diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-Board-ac5x-G3748.md5 b/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-Board-ac5x-G3748.md5
new file mode 100755
index 0000000000..e6272e216b
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-Board-ac5x-G3748.md5
@@ -0,0 +1 @@
+1dd040e3e3ec7740ad5778e9da49a59d
\ No newline at end of file
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-Board-ac5x-G3748.xml b/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-Board-ac5x-G3748.xml
new file mode 100755
index 0000000000..d927a18f3e
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-Board-ac5x-G3748.xml
@@ -0,0 +1,1607 @@
+
+
+
+
+
+ std-string
+ string
+ standard string.
+ 1
+ 100
+
+
+ board-callback-type
+ enumeration
+ Specifies os/ext drv callback types.
+
+ linux-static
+ Linux Static
+ 0
+
+
+ linux-shared
+ Linux Shared Lib mode
+ 1
+
+
+ external
+ External Os
+ 3
+
+
+ freeBsd
+ Free BSD
+ 4
+
+
+
+ board-pp-map-type
+ enumeration
+ Specifies pci info types.
+
+ fixed
+ Fixed
+ 0
+
+
+ autoscan
+ Auto scan
+ 1
+
+
+
+ board-pp-interface-channel-type
+ enumeration
+ Specifies interface tunnel.
+
+ pci
+ PCI
+ 0
+
+
+ smi
+ SMI
+ 1
+
+
+ pex
+ PEX
+ 3
+
+
+ pex_eagle
+ PEX EAGLE
+ 5
+
+
+ pex_falcon_z
+ PEX FALCON Z
+ 6
+
+
+
+ device-id-type
+ uint32
+ Device ID 0..1023
+ 0
+ 1023
+
+
+ port-mapping-type
+ enumeration
+ Specifies port map type.
+
+ ethernet_mac
+ ETHERNET_MAC
+ 0
+
+
+ cpu_sdma
+ CPU_SDMA
+ 1
+
+
+
+ interface-num-type
+ uint32
+ Interface number
+ 0
+ 1023
+
+
+ txq-port-number-type
+ uint32
+ 0 - 8 queues are configured per port (legacy mode),
+1...16 - the number of queues configured per port
+ SIP 5 : Bobcat2,BobK:0..71 ;Bobcat3: 0..576 ;Aldrin2:0..99
+ 0
+ 576
+
+
+ phy-smi-interface-type
+ uint32
+ Phy SMI interface type.
+ 0
+ 3
+
+
+ phy-xsmi-interface-type
+ uint32
+ Phy XSMI interface type.
+ 0
+ 15
+
+
+ phy-type
+ enumeration
+ Specifies the PHY Part Identifier.
+
+ NA
+ No Phy
+ 0
+
+
+ alaska-88E1543
+ Specifies PHY identifier 88E1543, used for Combo ports.
+ 1
+
+
+ alaska-88E1545
+ Specifies PHY identifier 88E1545, used for Copper GE with MAC on PHY support.
+ 2
+
+
+ alaska-88E1680
+ Specifies PHY identifier 88E1680, used for Copper with speeds of 10M/100M/1G.
+ 3
+
+
+ alaska-88E151X
+ Specifies PHY identifier 88E151X, used for Copper (HW supports combo and fiber).
+ 4
+
+
+ alaska-88E3140
+ Specifies PHY identifier 88E3140, used for Copper with speeds of 100M/1G/10G. Uses with FW SolarFlare next generation.
+ 5
+
+
+ alaska-88E3240
+ Specifies PHY identifier 88E3240, used for Copper with speeds of 100M/1G/10G. Uses with FW, SolarFlare next generation.
+ 6
+
+
+ alaska-88E3680
+ Specifies PHY identifier 88E3680, used for Octal Copper 100M.
+ 7
+
+
+ alaska-88E3220
+ Specifies PHY identifier 88E3220, used for Combo port with speeds of 100M/1G/10G. Uses FW, SolarFlare next generation.
+ 8
+
+
+ alaska-88E1680L
+ Specifies PHY identifier 88E1680L, used for Copper with speeds of 10M/100M/1G.
+ 9
+
+
+ alaska-88E33X0
+ Specifies PHY identifier 88E33X0, used for MGIG Combo.
+ 10
+
+
+ alaska-88E1548
+ Specifies PHY identifier 88E1548, used for Fiber GE.
+ 11
+
+
+ alaska-88E20X0
+ Specifies PHY identifier 88E20X0, used for Copper with speeds of 10M/100M/1G/2.5G/5G.
+ 12
+
+
+ alaska-88E1512
+ Specifies PHY identifier 88E1512, used for Copper with speeds of 10M/100M/1G.
+ 13
+
+
+ alaska-88E2180
+ Specifies PHY identifier 88E2180, used for Copper with speeds of 10M/100M/1G/2.5G/5G.
+ 14
+
+
+ alaska-88E1780
+ Specifies PHY identifier 88E1780, Integrated Octal 10/100/1000 Mbps Energy Efficient Ethernet Transceiver
+ 15
+
+
+ alaska-88E2540
+ Specifies PHY identifier 88E2540, 4 ports 10/100/1000/2.5G/5GBASE-T Ethernet Transceiver with IEEE 1588v2 PTP Support
+ 16
+
+
+ alaska-88E2580
+ Specifies PHY identifier 88E12580, Octal 10/100/1000/2.5G/5GBASE-T Ethernet Transceiver with IEEE 1588v2 PTP Support
+ 17
+
+
+
+ physical-port-num-type
+ uint32
+ PHYSICAL PORT NUM
+ 0
+ 1023
+
+
+ led-stream-port-type
+ enumeration
+ Specifies the ledstream port type.
+
+ PORT_TYPE_TRI_SPEED
+ tri-speed port.
+ 1
+
+
+ PORT_TYPE_XG
+ XG port.
+ 2
+
+
+
+ led-stream-blink-select-type
+ enumeration
+ Specifies the LED stream blink select type.
+
+ BLINK_SELECT_0
+ Blink 0 signal.
+ 1
+
+
+ BLINK_SELECT_1
+ Blink 1 signal
+ 2
+
+
+
+ led-stream-order-mode-type
+ enumeration
+ Specifies the LED stream ordering mode.
+
+ ORDER_MODE_BY_PORT
+ the indication order is arranged by port.
+ 1
+
+
+ ORDER_MODE_BY_CLASS
+ the indication order is arranged by class.
+ 2
+
+
+
+ led-stream-blink-duty-cycle-type
+ enumeration
+ Specifies the LED stream blink cycle duty cycle type.
+
+ BLINK_DUTY_CYCLE_0
+ 25% on, 75% off.
+ 1
+
+
+ BLINK_DUTY_CYCLE_1
+ 50% on, 50% off.
+ 2
+
+
+ BLINK_DUTY_CYCLE_2
+ 50% on, 50% off.
+ 3
+
+
+ BLINK_DUTY_CYCLE_3
+ 75% on, 25% off.
+ 4
+
+
+
+ led-stream-blink-duration-type
+ enumeration
+ Specifies the LED stream blink period type.
+
+ BLINK_DURATION_0
+ BLINK_DURATION_0.
+ 1
+
+
+ BLINK_DURATION_1
+ BLINK_DURATION_1.
+ 2
+
+
+ BLINK_DURATION_2
+ BLINK_DURATION_2.
+ 3
+
+
+ BLINK_DURATION_3
+ BLINK_DURATION_3.
+ 4
+
+
+ BLINK_DURATION_4
+ BLINK_DURATION_4.
+ 5
+
+
+ BLINK_DURATION_5
+ BLINK_DURATION_5.
+ 6
+
+
+ BLINK_DURATION_6
+ (APPLICABLE DEVICES: xCat3; AC5; Lion2; Bobcat2; Caelum; Aldrin; AC3X; Bobcat3; Aldrin2; Pipe) .
+ 7
+
+
+ BLINK_DURATION_7
+ APPLICABLE DEVICES: Bobcat2; Caelum; Aldrin; AC3X; Bobcat3; Aldrin2; Pipe).
+ 8
+
+
+
+ led-stream-pulse-stretch-type
+ enumeration
+ Specifies the LED stream length of stretching for dynamic signals.
+
+ PULSE_STRETCH_0_NO
+ PULSE_STRETCH_0_NO.
+ 1
+
+
+ PULSE_STRETCH_1
+ PULSE_STRETCH_1.
+ 2
+
+
+ PULSE_STRETCH_2
+ PULSE_STRETCH_2.
+ 3
+
+
+ PULSE_STRETCH_3
+ PULSE_STRETCH_3.
+ 4
+
+
+ PULSE_STRETCH_4
+ PULSE_STRETCH_4.
+ 5
+
+
+ PULSE_STRETCH_5
+ PULSE_STRETCH_5.
+ 6
+
+
+ PULSE_STRETCH_6
+ (APPLICABLE DEVICES: Bobcat2; Caelum; Aldrin; AC3X; Bobcat3; Aldrin2; Falcon; AC5P; Pipe).
+ 7
+
+
+ PULSE_STRETCH_7
+ (APPLICABLE DEVICES: Bobcat2; Caelum; Aldrin; AC3X; Bobcat3; Aldrin2; Falcon; AC5P; Pipe).
+ 8
+
+
+
+ led-stream-clock-out-frequency-type
+ enumeration
+ Specifies the LED stream blink cycle duty cycle type.
+
+ _CLOCK_OUT_FREQUENCY_500
+ 500 KHz LED clock frequency.
+ 1
+
+
+ CLOCK_OUT_FREQUENCY_1000
+ 1 MHz LED clock frequency.
+ 2
+
+
+ CLOCK_OUT_FREQUENCY_2000
+ 2 MHz LED clock frequency.
+ 3
+
+
+ CLOCK_OUT_FREQUENCY_3000
+ 3 MHz LED clock frequency.
+ 4
+
+
+
+ led-stream-class5-select-type
+ enumeration
+ Specifies the LED stream indication displayed on class5 (for dual-media port/phy).
+
+ CLASS_5_SELECT_HALF_DUPLEX
+ Half Duplex is displayed on class5.
+ 1
+
+
+ CLASS_5_SELECT_FIBER_LINK_UP
+ If port is a dual media port, Fiber Link Up is displayed on class5.
+ 2
+
+
+
+ led-stream-class13-select-type
+ enumeration
+ Specifies the LED stream indication displayed on class13 (for dual-media port/phy).
+
+ CLASS_13_SELECT_LINK_DOWN
+ Link Down is displayed on class13.
+ 1
+
+
+ CLASS_13_SELECT_COPPER_LINK_UP
+ If port is a dual media port, Copper Link Up is displayed on class13.
+ 2
+
+
+
+ led-class-num-type
+ uint32
+ Led Class number
+ 0
+ 11
+
+
+ boolean-type
+ enumeration
+ Boolean 32 bits , due to bing endian
+
+ false
+ False
+ 0
+
+
+ true
+ True
+ 1
+
+
+
+ bus-id-type
+ uint32
+ Bus Id Type, PCI/SMI
+ 0
+ 255
+
+
+ function-id-type
+ uint32
+ Function Id Type, PCI/SMI
+ 0
+ 255
+
+
+ domain-type
+ uint32
+ Domain, PCI/SMI
+ 0
+ 255
+
+
+ led-interface-type
+ uint32
+ Led interface
+ 0
+ 255
+
+
+ led-position-type
+ uint32
+ Led position
+ 0
+ 63
+
+
+ serdes-lane-type
+ uint32
+ serdes lane
+ 0
+ 255
+
+
+ cpu-type
+ enumeration
+ The CPU Internal/External
+
+ external
+ Extrenal connected CPU
+ 0
+
+
+ internal
+ Internal CPU
+ 1
+
+
+
+ led-stream-clock-frequency-type
+ uint32
+ Led Clock Frequency Sip6
+ 500
+ 80000
+
+
+ led-unit-type
+ uint32
+ Led units
+ 1
+ 16
+
+
+ led-unit-or-no-unit-type
+ uint32
+ Led units, 0 for no Unit
+ 0
+ 16
+
+
+ led-group-type
+ uint32
+ Led Group
+ 0
+ 1
+
+
+ led-stream-force-data-type
+ string
+ A hexadecimal string with octets represented as hex digits
+separated by colons. The canonical representation uses
+lowercase characters.
+ 3
+ 11
+
+
+ bit-type
+ uint32
+ Bit range 0..31
+ 0
+ 31
+
+
+ bit-size-type
+ uint32
+ Bit leng 1..32
+ 1
+ 32
+
+
+ led-sip-type
+ enumeration
+ The LED scehme
+
+ na
+ NA
+ 0
+
+
+ sip5
+ SIP5: AC5, AC3x
+ 5
+
+
+ sip6
+ SIP6: Falcon, AC5x, AC5P
+ 6
+
+
+
+ port-cscd-type
+ enumeration
+ Specifies the cascade port type.
+
+ DSA_1_WORD
+ DSA Regular
+ 0
+
+
+ DSA_2_WORDS
+ DSA Extended
+ 1
+
+
+ NETWORK
+ Network.
+ 2
+
+
+ DSA_3_WORDS
+ DSA 3 Words
+ 3
+
+
+ DSA_4_WORD
+ DSA 4 Words
+ 4
+
+
+
+ trunk-cscd-type
+ uint32
+ Specifies the Cascade Trunk id.
+ 0
+ 127
+
+
+ port-trunk-cscd-type
+ enumeration
+ Specifies the cascade port type.
+
+ cscdPort
+ Cascade port
+ 0
+
+
+ cscdTrunk
+ Csacde trunk
+ 1
+
+
+
+ hash-cscd-type
+ enumeration
+ Specifies the hash used by cascade trunk.
+
+ pkt
+ Hash based on packet
+ 0
+
+
+ srcPort
+ Hash based on source port
+ 1
+
+
+
+ AC5X-RD-G3748
+ linux-static
+ linux-static
+ autoscan
+ internal
+ pex_eagle
+
+ 0
+ 0
+ ASK-PP-AC5X-G3748.xml
+ ASK-L1-AC5X-G3748.xml
+ na
+
+ 0
+
+ ethernet_mac
+ 0
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 0
+ 0
+ 0
+
+
+
+
+ 1
+
+ ethernet_mac
+ 1
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 0
+ 1
+ 0
+
+
+
+
+ 2
+
+ ethernet_mac
+ 2
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 0
+ 2
+ 0
+
+
+
+
+ 3
+
+ ethernet_mac
+ 3
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 0
+ 3
+ 0
+
+
+
+
+ 4
+
+ ethernet_mac
+ 4
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 0
+ 4
+ 0
+
+
+
+
+ 5
+
+ ethernet_mac
+ 5
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 0
+ 5
+ 0
+
+
+
+
+ 6
+
+ ethernet_mac
+ 6
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 0
+ 6
+ 0
+
+
+
+
+ 7
+
+ ethernet_mac
+ 7
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 0
+ 7
+ 0
+
+
+
+
+ 8
+
+ ethernet_mac
+ 8
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 1
+ 8
+ 0
+
+
+
+
+ 9
+
+ ethernet_mac
+ 9
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 1
+ 9
+ 0
+
+
+
+
+ 10
+
+ ethernet_mac
+ 10
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 1
+ 10
+ 0
+
+
+
+
+ 11
+
+ ethernet_mac
+ 11
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 1
+ 11
+ 0
+
+
+
+
+ 12
+
+ ethernet_mac
+ 12
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 1
+ 12
+ 0
+
+
+
+
+ 13
+
+ ethernet_mac
+ 13
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 1
+ 13
+ 0
+
+
+
+
+ 14
+
+ ethernet_mac
+ 14
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 1
+ 14
+ 0
+
+
+
+
+ 15
+
+ ethernet_mac
+ 15
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 1
+ 15
+ 0
+
+
+
+
+ 16
+
+ ethernet_mac
+ 16
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 2
+ 16
+ 0
+
+
+
+
+ 17
+
+ ethernet_mac
+ 17
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 2
+ 17
+ 0
+
+
+
+
+ 18
+
+ ethernet_mac
+ 18
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 2
+ 18
+ 0
+
+
+
+
+ 19
+
+ ethernet_mac
+ 19
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 2
+ 19
+ 0
+
+
+
+
+ 20
+
+ ethernet_mac
+ 20
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 2
+ 20
+ 0
+
+
+
+
+ 21
+
+ ethernet_mac
+ 21
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 2
+ 21
+ 0
+
+
+
+
+ 22
+
+ ethernet_mac
+ 22
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 2
+ 22
+ 0
+
+
+
+
+ 23
+
+ ethernet_mac
+ 23
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 2
+ 23
+ 0
+
+
+
+
+ 24
+
+ ethernet_mac
+ 24
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 3
+ 0
+ 1
+
+
+
+
+ 25
+
+ ethernet_mac
+ 25
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 3
+ 1
+ 1
+
+
+
+
+ 26
+
+ ethernet_mac
+ 26
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 3
+ 2
+ 1
+
+
+
+
+ 27
+
+ ethernet_mac
+ 27
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 3
+ 3
+ 1
+
+
+
+
+ 28
+
+ ethernet_mac
+ 28
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 3
+ 4
+ 1
+
+
+
+
+ 29
+
+ ethernet_mac
+ 29
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 3
+ 5
+ 1
+
+
+
+
+ 30
+
+ ethernet_mac
+ 30
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 3
+ 6
+ 1
+
+
+
+
+ 31
+
+ ethernet_mac
+ 31
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 3
+ 7
+ 1
+
+
+
+
+ 32
+
+ ethernet_mac
+ 32
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 8
+ 1
+
+
+
+
+ 33
+
+ ethernet_mac
+ 33
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 9
+ 1
+
+
+
+
+ 34
+
+ ethernet_mac
+ 34
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 10
+ 1
+
+
+
+
+ 35
+
+ ethernet_mac
+ 35
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 11
+ 1
+
+
+
+
+ 36
+
+ ethernet_mac
+ 36
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 12
+ 1
+
+
+
+
+ 37
+
+ ethernet_mac
+ 37
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 5
+ 13
+ 1
+
+
+
+
+ 38
+
+ ethernet_mac
+ 38
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 5
+ 14
+ 1
+
+
+
+
+ 39
+
+ ethernet_mac
+ 39
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 5
+ 15
+ 1
+
+
+
+
+ 40
+
+ ethernet_mac
+ 40
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 5
+ 16
+ 1
+
+
+
+
+ 41
+
+ ethernet_mac
+ 41
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 17
+ 1
+
+
+
+
+ 42
+
+ ethernet_mac
+ 42
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 18
+ 1
+
+
+
+
+ 43
+
+ ethernet_mac
+ 43
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 19
+ 1
+
+
+
+
+ 44
+
+ ethernet_mac
+ 44
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 20
+ 1
+
+
+
+
+ 45
+
+ ethernet_mac
+ 45
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 21
+ 1
+
+
+
+
+ 46
+
+ ethernet_mac
+ 46
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 22
+ 1
+
+
+
+
+ 47
+
+ ethernet_mac
+ 47
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 23
+ 1
+
+
+
+
+ 48
+
+ ethernet_mac
+ 48
+ 0
+ false
+
+ NETWORK
+
+ NA
+
+
+
+
+ 53
+
+ ethernet_mac
+ 53
+ 0
+ false
+
+ NETWORK
+
+ NA
+
+
+
+
+ 52
+
+ ethernet_mac
+ 52
+ 0
+ false
+
+ NETWORK
+
+ NA
+
+
+
+
+ 51
+
+ ethernet_mac
+ 51
+ 0
+ false
+
+ NETWORK
+
+ NA
+
+
+
+
+ 50
+
+ ethernet_mac
+ 50
+ 0
+ false
+
+ NETWORK
+
+ NA
+
+
+
+
+ 49
+
+ ethernet_mac
+ 49
+ 0
+ false
+
+ NETWORK
+
+ NA
+
+
+
+
+ 63
+
+ cpu_sdma
+ 54
+ 0
+ false
+
+ NETWORK
+
+
+ 60
+
+ cpu_sdma
+ 55
+ 0
+ false
+
+ NETWORK
+
+
+ .
+
+ 1
+
+
+
\ No newline at end of file
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-L1-AC5X-G3748.md5 b/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-L1-AC5X-G3748.md5
new file mode 100755
index 0000000000..3f39c0bfe3
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-L1-AC5X-G3748.md5
@@ -0,0 +1 @@
+cccaf00bb8ea243d5c2884fb05bfd528
\ No newline at end of file
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-L1-AC5X-G3748.xml b/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-L1-AC5X-G3748.xml
new file mode 100755
index 0000000000..dd78325643
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-L1-AC5X-G3748.xml
@@ -0,0 +1,1219 @@
+
+
+
+
+
+ interface-mode-type
+ enumeration
+ Specifies supported Interface modes
+
+ 1000BASE_X
+ 1G
+ 6
+
+
+ SGMII
+ 1G , 2.5G
+ 3
+
+
+ QSGMII
+ 1G
+ 13
+
+
+ KR
+ 10G, 12G, 20G, 40G, 100G
+ 16
+
+
+ SR_LR
+ 5G, 10G, 12G, 20G, 40G
+ 20
+
+
+ KR2
+
+ 27
+
+
+ KR4
+
+ 28
+
+
+ SR_LR2
+
+ 29
+
+
+ SR_LR4
+ 100G
+ 30
+
+
+ KR_C
+ CONSORTIUM - 25G
+ 32
+
+
+ CR_C
+ CONSORTIUM - 25G
+ 33
+
+
+ KR2_C
+ CONSORTIUM - 50G
+ 34
+
+
+ CR2_C
+ CONSORTIUM - 50G
+ 35
+
+
+ CR
+
+ 36
+
+
+ CR2
+
+ 37
+
+
+ CR4
+
+ 38
+
+
+ KR_S
+
+ 39
+
+
+ CR_S
+
+ 40
+
+
+ KR8
+
+ 41
+
+
+ CR8
+
+ 42
+
+
+ SR_LR8
+
+ 43
+
+
+ USX_10G_QXGMII
+
+ 51
+
+
+ USX_20G_QXGMII
+
+ 52
+
+
+ USX_OUSGMII
+
+ 53
+
+
+ USX_20G_OXGMII
+
+ 54
+
+
+ NA
+
+ 57
+
+
+
+ port-speed-type
+ enumeration
+ Specifies supported speeds
+
+ 1G
+ 1G
+ 2
+
+
+ 10G
+ 10G
+ 3
+
+
+ 2500M
+ 2.5G
+ 5
+
+
+ 5G
+ 5G
+ 6
+
+
+ 25G
+ 25G, used in combination with CPSS_PORT_INTERFACE_MODE_KR_E, CPSS_PORT_INTERFACE_MODE_KR2_E
+ 21
+
+
+ 40G
+ 40G
+ 9
+
+
+ 50G
+ 50G
+ 14
+
+
+ 100G
+ 100G
+ 13
+
+
+ 200G
+ 200G
+ 24
+
+
+ 400G
+ 400G
+ 25
+
+
+ NA
+ NA
+ 35
+
+
+
+ fec-type
+ enumeration
+ Rx parameter type
+
+ enabled
+ Enabled
+ 0
+
+
+ disabled
+ Disabled
+ 1
+
+
+ rs_enabled
+ RS FEC enabled
+ 2
+
+
+ both_enabled
+ Both enabled
+ 3
+
+
+ rs_544_514_enabled
+ RS FEC 544 and 514
+ 4
+
+
+
+ physical-port-num-type
+ uint32
+ PHYSICAL PORT NUM
+ 0
+ 1023
+
+
+ tx-param-type
+ enumeration
+ Tx parameter type
+
+ atten
+ atten
+ 0
+
+
+ post
+ post
+ 1
+
+
+ pre
+ pre
+ 2
+
+
+ pre2
+ pre2
+ 3
+
+
+ pre3
+ pre3
+ 4
+
+
+ peak
+ peak
+ 5
+
+
+ main
+ main
+ 6
+
+
+ txAmpAdjEn
+ txAmpAdjEn
+ 7
+
+
+ emph0
+ emph0
+ 8
+
+
+ emph1
+ emph1
+ 9
+
+
+ txAmpShft
+ txAmpShft
+ 10
+
+
+ txEmphEn
+ txEmphEn
+ 11
+
+
+ txEmphEn1
+ txEmphEn1
+ 12
+
+
+ txAmpAdj
+ txAmpAdj
+ 13
+
+
+ slewCtrlEn
+ slewCtrlEn
+ 14
+
+
+ slewRate
+ slewRate
+ 15
+
+
+
+ rx-param-type
+ enumeration
+ Rx parameter type
+
+ sqlch
+ sqlch
+ 0
+
+
+ DC
+ DC
+ 1
+
+
+ LF
+ LF
+ 2
+
+
+ HF
+ HF
+ 3
+
+
+ gainShape1
+ gainShape1
+ 4
+
+
+ gainShape2
+ gainShape2
+ 5
+
+
+ shortChannelEn
+ shortChannelEn
+ 7
+
+
+ bfLf
+ bfLf
+ 8
+
+
+ bfHf
+ bfHf
+ 9
+
+
+ minLf
+ minLf
+ 10
+
+
+ maxLf
+ maxLf
+ 11
+
+
+ minHf
+ minHf
+ 12
+
+
+ maxHf
+ maxHf
+ 13
+
+
+ minPre1
+ minPre1
+ 14
+
+
+ maxPre1
+ maxPre1
+ 15
+
+
+ minPre2
+ minPre2
+ 16
+
+
+ maxPre2
+
+ 17
+
+
+ minPost
+ minPost
+ 18
+
+
+ maxPost
+ maxPost
+ 19
+
+
+ squelch
+ squelch
+ 20
+
+
+ termination
+ termination
+ 27
+
+
+ coldEnvelope
+ coldEnvelope
+ 35
+
+
+ hotEnvelope
+ hotEnvelope
+ 36
+
+
+ dcGain
+ dcGain
+ 37
+
+
+ bandWidth
+ bandWidth
+ 38
+
+
+ dfe
+ dfe
+ 39
+
+
+ ffeR
+ ffeR
+ 40
+
+
+ ffeC
+ ffeC
+ 41
+
+
+ sampler
+ sampler
+ 42
+
+
+ align90
+ align90
+ 43
+
+
+ ffeS
+ ffeS
+ 44
+
+
+ resSel
+ resSel
+ 45
+
+
+ resShift
+ resShift
+ 46
+
+
+ capSel
+ capSel
+ 47
+
+
+ ffeSettingForce
+ ffeSettingForce
+ 48
+
+
+ adaptedResSel
+ adaptedResSel
+ 49
+
+
+ adaptedCapSel
+ adaptedCapSel
+ 50
+
+
+ selmufi
+ selmufi
+ 51
+
+
+ selmuff
+ selmuff
+ 52
+
+
+ selmupi
+ selmupi
+ 53
+
+
+ selmupf
+ selmupf
+ 54
+
+
+ slewRateCtrl0
+ slewRateCtrl0
+ 55
+
+
+ slewRateCtrl1
+ slewRateCtrl1
+ 56
+
+
+ EO
+ EO
+ 57
+
+
+ dataRate
+ dataRate
+ 58
+
+
+ res1Sel
+ res1Sel
+ 59
+
+
+ res2Sel
+ res2Sel
+ 60
+
+
+ cap1Sel
+ cap1Sel
+ 61
+
+
+ cap2Sel
+ cap2Sel
+ 62
+
+
+ midpointLargeThresKLane
+ midpointLargeThresKLane
+ 63
+
+
+ midpointSmallThresKLane
+ midpointSmallThresKLane
+ 64
+
+
+ midpointLargeThresCLane
+ midpointLargeThresCLane
+ 65
+
+
+ midpointSmallThresCLane
+ midpointSmallThresCLane
+ 66
+
+
+ dfeResF0aHighThresInitLane
+ dfeResF0aHighThresInitLane
+ 67
+
+
+ dfeResF0aHighThresEndLane
+ dfeResF0aHighThresEndLane
+ 68
+
+
+ current1Sel
+ current1Sel
+ 69
+
+
+ rl1Sel
+ rl1Sel
+ 70
+
+
+ rl1Extra
+ rl1Extra
+ 71
+
+
+ cl1Ctrl
+ cl1Ctrl
+ 72
+
+
+ enMidFreq
+ enMidFreq
+ 73
+
+
+ cs1Mid
+ cs1Mid
+ 74
+
+
+ rs1Mid
+ rs1Mid
+ 75
+
+
+ rfCtrl
+ rfCtrl
+ 76
+
+
+ rl1TiaSel
+ rl1TiaSel
+ 77
+
+
+ rl1TiaExtra
+ rl1TiaExtra
+ 78
+
+
+ hpfRSel1st
+ hpfRSel1st
+ 79
+
+
+ current1TiaSel
+ current1TiaSel
+ 80
+
+
+ rl2Tune
+ rl2Tune
+ 81
+
+
+ rl2Sel
+ rl2Sel
+ 82
+
+
+ rs2Sel
+ rs2Sel
+ 83
+
+
+ current2Sel
+ current2Sel
+ 84
+
+
+ hpfRsel2nd
+ hpfRsel2nd
+ 85
+
+
+ BW
+ BW
+ 86
+
+
+ dfeGAIN
+ dfeGAIN
+ 87
+
+
+ dfeGAIN2
+ dfeGAIN2
+ 88
+
+
+ pre1
+ pre1
+ 89
+
+
+ pre2
+ pre2
+ 90
+
+
+ post1
+ post1
+ 91
+
+
+
+ boolean-type
+ enumeration
+ Boolean 32 bits , due to bing endian
+
+ false
+ False
+ 0
+
+
+ true
+ True
+ 1
+
+
+
+ serdes-type
+ enumeration
+ Serdes Type
+
+ NA
+ No serdes
+ 0
+
+
+ AVAGO
+ AVAGO
+ 1
+
+
+ COMPHY
+ COMPHY
+ 2
+
+
+ COMPHY_C12G
+ COMPHY_C12G
+ 3
+
+
+ COMPHY_C28G
+ COMPHY_C28G
+ 4
+
+
+ COMPHY_C112G
+ COMPHY_C112G
+ 5
+
+
+
+ uint8-type
+ uint32
+ Uint8 32 bits , due to bing endian
+ 0
+ 255
+
+
+ serdes-termination-type
+ enumeration
+ RX termination mode
+
+ GND
+ Enabled
+ 0
+
+
+ VDD
+ Disabled
+ 1
+
+
+ FLOATING
+ RS FEC enabled
+ 2
+
+
+
+ port-interconnect-profile-type
+ enumeration
+ Enumerator of interconnect profile.
+
+ profile_default
+ Profile Default
+ 0
+
+
+ profile_1
+ Profile 1
+ 1
+
+
+ profile_2
+ Profile 2
+ 2
+
+
+
+
+
+ 1000MR1
+
+ USX_OUSGMII
+ 1G
+ disabled
+
+
+ USX_OUSGMII
+ 1G
+ disabled
+ disabled
+
+
+
+ 2500MR1
+
+ USX_20G_OXGMII
+ 2500M
+ rs_enabled
+
+
+ USX_20G_OXGMII
+ 1G
+ rs_enabled
+
+
+ USX_20G_OXGMII
+ 2500M
+ rs_enabled
+ rs_enabled
+
+
+ USX_20G_OXGMII
+ 1G
+ rs_enabled
+ rs_enabled
+
+
+
+ 25GR1
+
+ CR
+ 25G
+ rs_enabled
+
+
+ KR
+ 25G
+ rs_enabled
+
+
+ KR
+ 10G
+ disabled
+
+
+ CR
+ 25G
+ rs_enabled
+ rs_enabled
+
+
+ KR
+ 25G
+ rs_enabled
+ rs_enabled
+
+
+ KR
+ 10G
+ disabled
+ disabled
+
+
+
+
+
+ 0
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 1
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 2
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 3
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 4
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 5
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 6
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 7
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 8
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 9
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 10
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 11
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 12
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 13
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 14
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 15
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 16
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 17
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 18
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 19
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 20
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 21
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 22
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 23
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 24
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 25
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 26
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 27
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 28
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 29
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 30
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 31
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 32
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 33
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 34
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 35
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 36
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 37
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 38
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 39
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 40
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 41
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 42
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 43
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 44
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 45
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 46
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 47
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 48
+ AVAGO
+ profile_default
+ 25GR1
+
+
+ 49
+ AVAGO
+ profile_default
+ 25GR1
+
+
+ 50
+ AVAGO
+ profile_default
+ 25GR1
+
+
+ 51
+ AVAGO
+ profile_default
+ 25GR1
+
+
+ 52
+ AVAGO
+ profile_default
+ 25GR1
+
+
+ 53
+ AVAGO
+ profile_default
+ 25GR1
+
+
+
+
\ No newline at end of file
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-PP-AC5X-G3748.md5 b/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-PP-AC5X-G3748.md5
new file mode 100755
index 0000000000..e0b9509d1d
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-PP-AC5X-G3748.md5
@@ -0,0 +1 @@
+75737f56687883d181ea3da8d1c24da6
\ No newline at end of file
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-PP-AC5X-G3748.xml b/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-PP-AC5X-G3748.xml
new file mode 100755
index 0000000000..50daefc694
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/ASK-PP-AC5X-G3748.xml
@@ -0,0 +1,871 @@
+
+
+
+
+
+ std-string
+ string
+ standard string.
+ 1
+ 100
+
+
+ queue-id-type
+ uint32
+ Queue id
+ 0
+ 7
+
+
+ precent-type
+ uint32
+ Precent
+ 0
+ 100
+
+
+ phaThreadId-type
+ uint32
+ Thread id
+ 1
+ 255
+
+
+ routing-mode-type
+ enumeration
+ Specifies routing mode.
+
+ POLICY_BASED_ROUTING_ONLY
+ PBR only
+ 0
+
+
+ TCAM_ROUTER_BASED
+ Router engine or PBR
+ 1
+
+
+
+ shared-table-mode-type
+ enumeration
+ Specifies table sharing modes for L3 (LPM), L2 (FDB), EM (Exact Match)
+
+ MID_L3_MID_L2_NO_EM
+ MID_L3_MID_L2_NO_EM
+ 0
+
+
+ MID_L3_MID_L2_MIN_EM
+ MID_L3_MID_L2_MIN_EM
+ 1
+
+
+ LOW_MAX_L3_MID_LOW_L2_NO_EM
+ LOW_MAX_L3_MID_LOW_L2_NO_EM
+ 2
+
+
+ MAX_L3_MIN_L2_NO_EM
+ MAX_L3_MIN_L2_NO_EM
+ 3
+
+
+
+ pha-firmware-image-id-type
+ enumeration
+ Specifies supported Pha image id
+
+ DEFAULT
+ Default PHA firmware image ID
+ 0
+
+
+ 01
+ 01 firmware image ID
+ 1
+
+
+ 02
+ 02 PHA firmware image ID
+ 2
+
+
+
+ pha-firmware-thread-type
+ enumeration
+ Specifies supported Pha thread type
+
+ IOAM_INGRESS_SWITCH_IPV4
+ IOAM_INGRESS_SWITCH_IPV4
+ 1
+
+
+ IOAM_INGRESS_SWITCH_IPV6
+ IOAM_INGRESS_SWITCH_IPV6
+ 2
+
+
+ IOAM_TRANSIT_SWITCH_IPV4
+ IOAM_TRANSIT_SWITCH_IPV4
+ 3
+
+
+ IOAM_TRANSIT_SWITCH_IPV6
+ IOAM_TRANSIT_SWITCH_IPV6
+ 4
+
+
+ INT_IOAM_MIRRORING
+ INT_IOAM_MIRRORING
+ 5
+
+
+ INT_IOAM_EGRESS_SWITCH
+ INT_IOAM_EGRESS_SWITCH
+ 6
+
+
+ MPLS_SR_NO_EL
+ MPLS_SR_NO_EL
+ 7
+
+
+ MPLS_SR_ONE_EL
+ MPLS_SR_ONE_EL
+ 8
+
+
+ MPLS_SR_TWO_EL
+ MPLS_SR_TWO_EL
+ 9
+
+
+ MPLS_SR_THREE_EL
+ MPLS_SR_THREE_EL
+ 10
+
+
+ UNIFIED_SR
+ UNIFIED_SR
+ 11
+
+
+ CLASSIFIER_NSH_OVER_ETHERNET
+ CLASSIFIER_NSH_OVER_ETHERNET
+ 12
+
+
+ CLASSIFIER_NSH_OVER_VXLAN_GPE
+ CLASSIFIER_NSH_OVER_VXLAN_GPE
+ 13
+
+
+ SFF_NSH_VXLAN_GPE_TO_ETHERNET
+ SFF_NSH_VXLAN_GPE_TO_ETHERNET
+ 14
+
+
+ SFF_NSH_ETHERNET_TO_VXLAN_GPE
+ SFF_NSH_ETHERNET_TO_VXLAN_GPE
+ 15
+
+
+ IOAM_EGRESS_SWITCH_IPV6
+ IOAM_EGRESS_SWITCH_IPV6
+ 16
+
+
+ SRV6_END_NODE
+ SRV6_END_NODE
+ 17
+
+
+ SRV6_PENULTIMATE_END_NODE
+ SRV6_PENULTIMATE_END_NODE
+ 18
+
+
+ SRV6_SRC_NODE_1_SEGMENT
+ SRV6_SRC_NODE_1_SEGMENT
+ 19
+
+
+ SRV6_SRC_NODE_FIRST_PASS_2_3_SEGMENTS
+ SRV6_SRC_NODE_FIRST_PASS_2_3_SEGMENTS
+ 20
+
+
+ SRV6_SRC_NODE_SECOND_PASS_3_SEGMENTS
+ SRV6_SRC_NODE_SECOND_PASS_3_SEGMENTS
+ 21
+
+
+ SRV6_SRC_NODE_SECOND_PASS_2_SEGMENTS
+ SRV6_SRC_NODE_SECOND_PASS_2_SEGMENTS
+ 22
+
+
+ SGT_NETWORK_ADD_MSB
+ SGT_NETWORK_ADD_MSB
+ 23
+
+
+ SGT_NETWORK_FIX
+ SGT_NETWORK_FIX
+ 24
+
+
+ SGT_NETWORK_REMOVE
+ SGT_NETWORK_REMOVE
+ 25
+
+
+ SGT_EDSA_FIX
+ SGT_EDSA_FIX
+ 26
+
+
+ SGT_EDSA_REMOVE
+ SGT_EDSA_REMOVE
+ 27
+
+
+ SGT_GBP_FIX_IPV4
+ SGT_GBP_FIX_IPV4
+ 28
+
+
+ SGT_GBP_FIX_IPV6
+ SGT_GBP_FIX_IPV6
+ 29
+
+
+ SGT_GBP_REMOVE_IPV4
+ SGT_GBP_REMOVE_IPV4
+ 30
+
+
+ SGT_GBP_REMOVE_IPV6
+ SGT_GBP_REMOVE_IPV6
+ 31
+
+
+ PTP_PHY_1_STEP
+ PTP_PHY_1_STEP
+ 32
+
+
+ EGRESS_MIRRORING_METADATA
+ EGRESS_MIRRORING_METADATA
+ 33
+
+
+ CC_ERSPAN_TYPE_II_TRG_DEV_LC_IPV4
+ CC_ERSPAN_TYPE_II_TRG_DEV_LC_IPV4
+ 34
+
+
+ CC_ERSPAN_TYPE_II_TRG_DEV_LC_IPV6
+ CC_ERSPAN_TYPE_II_TRG_DEV_LC_IPV6
+ 35
+
+
+ CC_ERSPAN_TYPE_II_TRG_DEV_DIRECT_IPV4
+ CC_ERSPAN_TYPE_II_TRG_DEV_DIRECT_IPV4
+ 36
+
+
+ CC_ERSPAN_TYPE_II_TRG_DEV_DIRECT_IPV6
+ CC_ERSPAN_TYPE_II_TRG_DEV_DIRECT_IPV6
+ 37
+
+
+ CC_ERSPAN_TYPE_II_SRC_DEV
+ CC_ERSPAN_TYPE_II_SRC_DEV
+ 38
+
+
+ VXLAN_GBP_SOURCE_GROUP_POLICY_ID
+ VXLAN_GBP_SOURCE_GROUP_POLICY_ID
+ 39
+
+
+ SRV6_BEST_EFFORT
+ SRV6_BEST_EFFORT
+ 40
+
+
+ SRV6_SRC_NODE_1_CONTAINER
+ SRV6_SRC_NODE_1_CONTAINER
+ 41
+
+
+ SRV6_SRC_NODE_FIRST_PASS_2_3_CONTAINERS
+ SRV6_SRC_NODE_FIRST_PASS_2_3_CONTAINERS
+ 42
+
+
+ SRV6_SRC_NODE_SECOND_PASS_2_CONTAINERS
+ SRV6_SRC_NODE_SECOND_PASS_2_CONTAINERS
+ 43
+
+
+ SRV6_SRC_NODE_SECOND_PASS_3_CONTAINERS
+ SRV6_SRC_NODE_SECOND_PASS_3_CONTAINERS
+ 44
+
+
+ SRV6_END_NODE_COC32_GSID
+ SRV6_END_NODE_COC32_GSID
+ 45
+
+
+ IPV4_TTL_INCREMENT
+ IPV4_TTL_INCREMENT
+ 46
+
+
+ IPV6_HOP_LIMIT_INCREMENT
+ IPV6_HOP_LIMIT_INCREMENT
+ 47
+
+
+ CLEAR_OUTGOING_MTAG_COMMAND
+ CLEAR_OUTGOING_MTAG_COMMAND
+ 48
+
+
+ SFLOW_V5_IPV4
+ SFLOW_V5_IPV4
+ 49
+
+
+ SFLOW_V5_IPV6
+ SFLOW_V5_IPV6
+ 50
+
+
+ SLS
+ SLS
+ 51
+
+
+
+ trunk-member-mode-type
+ enumeration
+ Specifies supported Pha image id
+
+ NATIVE
+ NATIVE
+ * the trunk members are filled
+ * according to the order given by application.
+ * Regular trunk may hold max of 8 members.
+ * Cascade trunk may hold :
+ * max of 64 members
+ 0
+
+
+ FLEX
+ FLEX
+ * A mode to allows flexibility for
+ * each Regular trunk to state it's max number of members (before starting to add members).
+ * (this mode not effect 'cascade trunk' members)
+ * Regular trunk may hold : max of 4K members. (each trunk set it's own limit)
+ * Cascade trunk may hold : max of 64 members.
+ 2
+
+
+
+ number-physical-port-type
+ enumeration
+ ac5x 128, falcon 64,128,256, 512, 1024
+
+ no-ports
+ no-ports
+ 0
+
+
+ 64-ports
+ 64-ports
+ 64
+
+
+ 128-ports
+ 128-ports
+ 128
+
+
+ 256-ports
+ 256-ports
+ 256
+
+
+ 512-ports
+ 512-ports
+ 512
+
+
+ 1024-ports
+ 1024-ports
+ 1024
+
+
+
+ serdes-ref-clock-type
+ enumeration
+ Specifies serdes refernce clock.
+
+ external_25_single_ended
+ EXTERNAL_25_SINGLE_ENDED
+ 0
+
+
+ external_125_single_ended
+ EXTERNAL_125_SINGLE_ENDED
+ 1
+
+
+ external_125_diff
+ EXTERNAL_125_DIFF
+ 2
+
+
+ external_156_25_single_ended
+ EXTERNAL_156_25_SINGLE_ENDED
+ 3
+
+
+ external_156_25_diff
+ EXTERNAL_156_25_DIFF
+ 4
+
+
+ internal_125
+ INTERNAL_125
+ 5
+
+
+
+ cpu-port-id-type
+ uint32
+ CPU port id
+ 0
+ 7
+
+
+ rx-buffer-size-type
+ uint32
+ Rx Buffer size
+ 64
+ 10240
+
+
+ tx-sdma-queue-mode-type
+ enumeration
+ Specifies TX queue mode.
+
+ Normal
+ Application
+ 0
+
+
+ Packet_Generator
+ Traffic generator
+ 1
+
+
+
+ alloc-method-type
+ enumeration
+ Specifies Buffers allocation method.
+
+ Dynamic_Alloc
+ Dynamic
+ 0
+
+
+ Static_Alloc
+ Static
+ 1
+
+
+
+ au_mesage_lenght-type
+ enumeration
+ Specifies Buffers allocation method.
+
+ 4_words
+ 4 Words
+ 0
+
+
+ 8_words
+ 8 Words
+ 1
+
+
+
+ boolean-type
+ enumeration
+ Boolean 32 bits , due to bing endian
+
+ false
+ False
+ 0
+
+
+ true
+ True
+ 1
+
+
+
+
+ AC5X-RD
+
+ 4294967295
+ external_25_single_ended
+ 2
+ 60
+ 128-ports
+ false
+ false
+ 0
+
+
+ true
+
+ 4096
+
+
+ 2048
+
+
+
+ 0
+ 0
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 1
+ 7
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 1
+ 6
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 1
+ 5
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 1
+ 4
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 1
+ 3
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 1
+ 2
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 1
+ 1
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 1
+ 0
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 0
+ 7
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 0
+ 6
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 0
+ 5
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 0
+ 4
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 0
+ 3
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 0
+ 2
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 0
+ 1
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 0
+ 0
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 0
+ 1
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 0
+ 2
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 0
+ 3
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 0
+ 4
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 0
+ 5
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 0
+ 6
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 0
+ 7
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 1
+ 0
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 1
+ 1
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 1
+ 2
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 1
+ 3
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 1
+ 4
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 1
+ 5
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 1
+ 6
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 1
+ 7
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+
+ false
+ false
+ false
+ 0
+ 8_words
+ false
+
+
+
+ TCAM_ROUTER_BASED
+ 0
+ MID_L3_MID_L2_NO_EM
+ true
+
+
+ true
+ true
+ true
+ true
+ true
+ true
+
+ 511
+ FLEX
+
+ true
+ true
+ true
+ true
+
+ false
+ 01
+ 0
+
+
+
+
+
\ No newline at end of file
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/SAI-AC5X-G3748.md5 b/device/supermicro/arm64-supermicro_sse_g3748-r0/SAI-AC5X-G3748.md5
new file mode 100755
index 0000000000..e06cc46bf9
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/SAI-AC5X-G3748.md5
@@ -0,0 +1 @@
+32fa759aabe89e7d76a2b8f35a9babc0
\ No newline at end of file
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/SAI-AC5X-G3748.xml b/device/supermicro/arm64-supermicro_sse_g3748-r0/SAI-AC5X-G3748.xml
new file mode 100755
index 0000000000..03d240255b
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/SAI-AC5X-G3748.xml
@@ -0,0 +1,346 @@
+
+
+
+
+
+ device-id-type
+ uint32
+ Device ID 0..1023
+ 0
+ 1023
+
+
+ port-id-type
+ uint32
+ Interface number
+ 0
+ 1023
+
+
+ logDest-type
+ enumeration
+ Logging Feature Options
+
+ SAI_LOG_SYSLOG
+ SYSLOG {Syslog service should be running to use this option}
+ 0
+
+
+ SAI_LOG_CONSOLE
+ CONSOLE
+ 1
+
+
+ SAI_LOG_FILE
+ FILE {Warning !!! Use with caution. Can cause disk full issues}
+ 2
+
+
+
+ log-dest-file-path-type
+ string
+ A string with path to file for logging feature
+ 2
+ 30
+
+
+ ASK-Board-ac5x-G3748.xml
+
+ false
+
+
+
+ 0
+ 0
+ 0
+
+
+ 1
+ 0
+ 1
+
+
+ 2
+ 0
+ 2
+
+
+ 3
+ 0
+ 3
+
+
+ 4
+ 0
+ 4
+
+
+ 5
+ 0
+ 5
+
+
+ 6
+ 0
+ 6
+
+
+ 7
+ 0
+ 7
+
+
+ 8
+ 0
+ 8
+
+
+ 9
+ 0
+ 9
+
+
+ 10
+ 0
+ 10
+
+
+ 11
+ 0
+ 11
+
+
+ 12
+ 0
+ 12
+
+
+ 13
+ 0
+ 13
+
+
+ 14
+ 0
+ 14
+
+
+ 15
+ 0
+ 15
+
+
+ 16
+ 0
+ 16
+
+
+ 17
+ 0
+ 17
+
+
+ 18
+ 0
+ 18
+
+
+ 19
+ 0
+ 19
+
+
+ 20
+ 0
+ 20
+
+
+ 21
+ 0
+ 21
+
+
+ 22
+ 0
+ 22
+
+
+ 23
+ 0
+ 23
+
+
+ 24
+ 0
+ 24
+
+
+ 25
+ 0
+ 25
+
+
+ 26
+ 0
+ 26
+
+
+ 27
+ 0
+ 27
+
+
+ 28
+ 0
+ 28
+
+
+ 29
+ 0
+ 29
+
+
+ 30
+ 0
+ 30
+
+
+ 31
+ 0
+ 31
+
+
+ 32
+ 0
+ 32
+
+
+ 33
+ 0
+ 33
+
+
+ 34
+ 0
+ 34
+
+
+ 35
+ 0
+ 35
+
+
+ 36
+ 0
+ 36
+
+
+ 37
+ 0
+ 37
+
+
+ 38
+ 0
+ 38
+
+
+ 39
+ 0
+ 39
+
+
+ 40
+ 0
+ 40
+
+
+ 41
+ 0
+ 41
+
+
+ 42
+ 0
+ 42
+
+
+ 43
+ 0
+ 43
+
+
+ 44
+ 0
+ 44
+
+
+ 45
+ 0
+ 45
+
+
+ 46
+ 0
+ 46
+
+
+ 47
+ 0
+ 47
+
+
+ 48
+ 0
+ 48
+
+
+ 49
+ 0
+ 49
+
+
+ 50
+ 0
+ 50
+
+
+ 51
+ 0
+ 51
+
+
+ 52
+ 0
+ 52
+
+
+ 53
+ 0
+ 53
+
+
+
+ 8
+ 0
+ 0
+ 64
+ 8
+ 8
+ 1024
+ 0
+ 0
+
+
+
+ 0
+
+
+ 2048
+
+
+
+ SAI_LOG_SYSLOG
+
+
+
\ No newline at end of file
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/default_sku b/device/supermicro/arm64-supermicro_sse_g3748-r0/default_sku
new file mode 100644
index 0000000000..9bde3d72ef
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/default_sku
@@ -0,0 +1 @@
+supermicro_sse_g3748 t1
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/pcie.yaml b/device/supermicro/arm64-supermicro_sse_g3748-r0/pcie.yaml
new file mode 100644
index 0000000000..fe51488c70
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/pcie.yaml
@@ -0,0 +1 @@
+[]
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/platform.json b/device/supermicro/arm64-supermicro_sse_g3748-r0/platform.json
new file mode 100644
index 0000000000..127ce8c955
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/platform.json
@@ -0,0 +1,116 @@
+{
+ "chassis": {
+ "name": "SSE-G3748",
+ "components": [
+ {
+ "name": "U-Boot"
+ },
+ {
+ "name": "ONIE-VERSION"
+ },
+ {
+ "name": "System-CPLD"
+ }
+ ],
+ "fans": [
+ {
+ "name": "Fan1",
+ "status_led": {
+ "controllable": true,
+ "colors": ["red", "green"]
+ }
+ },
+ {
+ "name": "Fan2",
+ "status_led": {
+ "controllable": true,
+ "colors": ["red", "green"]
+ }
+ }
+ ],
+ "fan_drawers": [
+ {
+ "name": "drawer1",
+ "status_led": {
+ "controllable": true,
+ "colors": ["red", "green"]
+ },
+ "max_consumed_power": false,
+ "fans": [
+ {
+ "name": "Fan1"
+ },
+ {
+ "name": "Fan2"
+ }
+ ]
+ }
+ ],
+ "psus": [
+ {
+ "name": "PSU1",
+ "status_led": {
+ "controllable": false
+ },
+ "current": false,
+ "power": false,
+ "max_power": false,
+ "voltage_high_threshold": false,
+ "voltage_low_threshold": false,
+ "temperature": false
+ },
+ {
+ "name": "PSU2",
+ "status_led": {
+ "controllable": false
+ },
+ "current": false,
+ "power": false,
+ "max_power": false,
+ "voltage_high_threshold": false,
+ "voltage_low_threshold": false,
+ "temperature": false
+ }
+ ],
+ "thermals": [
+ {
+ "name": "FRONT",
+ "controllable": false,
+ "low-threshold": false,
+ "high-threshold": false,
+ "low-crit-threshold": false,
+ "high-crit-threshold": false
+ },
+ {
+ "name": "REAR",
+ "controllable": false,
+ "low-threshold": false,
+ "high-threshold": false,
+ "low-crit-threshold": false,
+ "high-crit-threshold": false
+ }
+ ],
+ "sfps": [
+ {
+ "name": "Ethernet48"
+ },
+ {
+ "name": "Ethernet49"
+ },
+ {
+ "name": "Ethernet50"
+ },
+ {
+ "name": "Ethernet51"
+ },
+ {
+ "name": "Ethernet52"
+ },
+ {
+ "name": "Ethernet53"
+ }
+ ]
+ },
+ "interfaces": {}
+}
+
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/platform_asic b/device/supermicro/arm64-supermicro_sse_g3748-r0/platform_asic
new file mode 100644
index 0000000000..558e01e184
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/platform_asic
@@ -0,0 +1 @@
+marvell-arm64
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/platform_components.json b/device/supermicro/arm64-supermicro_sse_g3748-r0/platform_components.json
new file mode 100644
index 0000000000..eeb9e6edfd
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/platform_components.json
@@ -0,0 +1,21 @@
+{
+ "chassis": {
+ "SSE-G3748": {
+ "component": {
+ "U-Boot": { },
+ "ONIE-VERSION": { },
+ "System-CPLD": { }
+ }
+ }
+ },
+ "chassis": {
+ "SSE-G3748R": {
+ "component": {
+ "U-Boot": { },
+ "ONIE-VERSION": { },
+ "System-CPLD": { }
+ }
+ }
+ }
+
+}
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/platform_reboot b/device/supermicro/arm64-supermicro_sse_g3748-r0/platform_reboot
new file mode 100755
index 0000000000..a95459054c
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/platform_reboot
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+function SafePwrCycle() {
+ sync ; sync
+ umount -fa > /dev/null 2&>1
+
+ # Write CPLD register to initiate cold reboot
+ sudo i2cset -f -y 0 0x66 0x02 0x80
+}
+
+SafePwrCycle
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/plugins/eeprom.py b/device/supermicro/arm64-supermicro_sse_g3748-r0/plugins/eeprom.py
new file mode 100644
index 0000000000..b8d18f7ee9
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/plugins/eeprom.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+try:
+ from sonic_eeprom import eeprom_tlvinfo
+except ImportError as e:
+ raise ImportError (str(e) + "- required module not found")
+
+
+class board(eeprom_tlvinfo.TlvInfoDecoder):
+
+ def __init__(self, name, path, cpld_root, ro):
+ #self.eeprom_path = "/etc/sonic/eeprom"
+ self.eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0054/eeprom"
+ if not os.path.exists(self.eeprom_path):
+ os.system("echo 24c02 0x54 > /sys/class/i2c-adapter/i2c-0/new_device")
+ super(board, self).__init__(self.eeprom_path, 0, '', True)
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/plugins/led_control.py b/device/supermicro/arm64-supermicro_sse_g3748-r0/plugins/led_control.py
new file mode 100644
index 0000000000..c710eb6257
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/plugins/led_control.py
@@ -0,0 +1,225 @@
+#
+# led_control.py
+#
+# Platform-specific LED control functionality for SONiC
+#
+
+try:
+ from sonic_led.led_control_base import LedControlBase
+ import os
+ import time
+ import syslog
+ import sonic_platform.platform
+ import sonic_platform.chassis
+except ImportError as e:
+ raise ImportError(str(e) + " - required module not found")
+
+smbus_present = 1
+
+try:
+ import smbus
+except ImportError as e:
+ smbus_present = 0
+
+
+def DBG_PRINT(str):
+ syslog.openlog("sse-g3748-led")
+ syslog.syslog(syslog.LOG_INFO, str)
+ syslog.closelog()
+
+
+class LedControl(LedControlBase):
+ """Platform specific LED control class"""
+ SONIC_PORT_NAME_PREFIX = "Ethernet"
+
+ # Constructor
+ def __init__(self):
+ self.chassis = sonic_platform.platform.Platform().get_chassis()
+ self._initDefaultConfig()
+
+ def _initDefaultConfig(self):
+ # The fan tray leds and system led managed by new chassis class API
+ # leaving only a couple other front panel leds to be done old style
+ DBG_PRINT("starting system leds")
+ self._initSystemLed()
+ DBG_PRINT(" led done")
+
+ def _get_i2c_register(self, reg_file):
+ # On successful read, returns the value read from given
+ # reg_name and on failure returns 'ERR'
+ rv = 'ERR'
+
+ if (not os.path.isfile(reg_file)):
+ return rv
+ try:
+ with open(reg_file, 'r') as fd:
+ rv = fd.read()
+ except Exception as e:
+ rv = 'ERR'
+
+ rv = rv.rstrip('\r\n')
+ rv = rv.lstrip(" ")
+ return rv
+
+ def _set_i2c_register(self, reg_file, value):
+ # On successful write, the value read will be written on
+ # reg_name and on failure returns 'ERR'
+ rv = 'ERR'
+
+ if (not os.path.isfile(reg_file)):
+ return rv
+ try:
+ with open(reg_file, 'w') as fd:
+ rv = fd.write(str(value))
+ except Exception as e:
+ rv = 'ERR'
+
+ # Ensure that the write operation has succeeded
+ if (int(self._get_i2c_register(reg_file)) != value ):
+ time.sleep(3)
+ if (int(self._get_i2c_register(reg_file)) != value ):
+ rv = 'ERR'
+
+ return rv
+
+ def _initSystemLed(self):
+ # Front Panel System LEDs setting
+ oldfan = 0xf
+ oldpsu0 = 0xf
+ oldpsu1 = 0xf
+ G3748CPLD_I2C_DIR = "/sys/bus/i2c/devices/0-0066/"
+ self.fan_sys_frontled_reg = G3748CPLD_I2C_DIR+"fan_sys_frontled".format()
+ self.psu_frontled_reg = G3748CPLD_I2C_DIR+"psu_frontled".format()
+
+
+ # Write sys led
+ if smbus_present == 0:
+ DBG_PRINT(" PMON LED SET ERROR -> smbus present = 0 ")
+ else:
+ # System LED is controlled by CPLD (i2c 0x66) register 0x11 bits:3-0
+ #bus = smbus.SMBus(0)
+ #DEVICE_ADDRESS = 0x66
+ #DEVICEREG = 0x11
+ #register = bus.read_byte_data(DEVICE_ADDRESS, DEVICEREG)
+ ## write System LED Green
+ #register = register & 0xFC | 0x01
+ #bus.write_byte_data(DEVICE_ADDRESS, DEVICEREG, register)
+ #DBG_PRINT(" System LED set O.K. ")
+
+ register = self._get_i2c_register(self.fan_sys_frontled_reg)
+ # write System LED solid green
+ register = int(register) & 0xFC | 0x01
+ self._set_i2c_register(self.fan_sys_frontled_reg, register)
+
+ while True:
+ # Front Panel FAN Panel LED setting in CPLD (i2c 0x66) register 0x11 bits:7-4
+ if (self.chassis.get_fan(0).get_status() == self.chassis.get_fan(1).get_status() == True):
+ if oldfan != 0x1:
+ # Set Front Panel FAN LED to green
+ #bus = smbus.SMBus(0)
+ #DEVICE_ADDRESS = 0x66
+ #DEVICEREG = 0x11
+ #register = bus.read_byte_data(DEVICE_ADDRESS, DEVICEREG)
+ #register = register & 0xCF | 0x20
+ #bus.write_byte_data(DEVICE_ADDRESS, DEVICEREG, register)
+ register = self._get_i2c_register(self.fan_sys_frontled_reg)
+ register = int(register) & 0xCF | 0x20
+ self._set_i2c_register(self.fan_sys_frontled_reg, register)
+ oldfan = 0x1
+ DBG_PRINT(" Front panel LED FAN set green")
+ else:
+ if oldfan != 0x0:
+ # Set Front Panel FAN LED to red
+ #bus = smbus.SMBus(0)
+ #DEVICE_ADDRESS = 0x66
+ #DEVICEREG = 0x11
+ #register = bus.read_byte_data(DEVICE_ADDRESS, DEVICEREG)
+ #register = register & 0xCF | 0x10
+ #bus.write_byte_data(DEVICE_ADDRESS, DEVICEREG, register)
+ register = self._get_i2c_register(self.fan_sys_frontled_reg)
+ register = int(register) & 0xCF | 0x10
+ self._set_i2c_register(self.fan_sys_frontled_reg, register)
+ oldfan = 0x0
+ DBG_PRINT(" Front panel LED FAN set red")
+
+ # Front Panel PSU Panel LED setting in CPLD (i2c 0x66) register 0x12
+ # PSU0 -- bits: 1..0 PSU1 -- bits: 3..2
+ if (self.chassis.get_psu(0).get_status() == True):
+ if oldpsu0 != 0x1:
+ # Set PSU0 LED to green
+ #bus = smbus.SMBus(0)
+ #DEVICE_ADDRESS = 0x66
+ #DEVICEREG = 0x12
+ #register = bus.read_byte_data(DEVICE_ADDRESS, DEVICEREG)
+ #register = register & 0xFC | 0x02
+ #bus.write_byte_data(DEVICE_ADDRESS, DEVICEREG, register)
+ register = self._get_i2c_register(self.psu_frontled_reg)
+ register = int(register) & 0xFC | 0x02
+ self._set_i2c_register(self.psu_frontled_reg, register)
+ oldpsu0 = 0x1
+ DBG_PRINT(" Front panel LED PSU0 set green")
+ else:
+ if oldpsu0 != 0x0:
+ # Set PSU0 LED to red
+ #bus = smbus.SMBus(0)
+ #DEVICE_ADDRESS = 0x66
+ #DEVICEREG = 0x12
+ #register = bus.read_byte_data(DEVICE_ADDRESS, DEVICEREG)
+ #register = register & 0xFC | 0x01
+ #bus.write_byte_data(DEVICE_ADDRESS, DEVICEREG, register)
+ register = self._get_i2c_register(self.psu_frontled_reg)
+ register = int(register) & 0xFC | 0x01
+ self._set_i2c_register(self.psu_frontled_reg, register)
+ oldpsu0 = 0x0
+ DBG_PRINT(" Front panel LED PSU0 set red")
+
+ if (self.chassis.get_psu(1).get_status() == True):
+ if oldpsu1 != 0x1:
+ # Set PSU1 LED to green
+ #bus = smbus.SMBus(0)
+ #DEVICE_ADDRESS = 0x66
+ #DEVICEREG = 0x12
+ #register = bus.read_byte_data(DEVICE_ADDRESS, DEVICEREG)
+ #register = register & 0xF3 | 0x08
+ #bus.write_byte_data(DEVICE_ADDRESS, DEVICEREG, register)
+ register = self._get_i2c_register(self.psu_frontled_reg)
+ register = int(register) & 0xF3 | 0x08
+ self._set_i2c_register(self.psu_frontled_reg, register)
+ oldpsu1 = 0x1
+ DBG_PRINT(" Front panel LED PSU1 set green")
+ else:
+ if oldpsu1 != 0x0:
+ # Set PSU1 LED to red
+ #bus = smbus.SMBus(0)
+ #DEVICE_ADDRESS = 0x66
+ #DEVICEREG = 0x12
+ #register = bus.read_byte_data(DEVICE_ADDRESS, DEVICEREG)
+ #register = register & 0xF3 | 0x04
+ #bus.write_byte_data(DEVICE_ADDRESS, DEVICEREG, register)
+ register = self._get_i2c_register(self.psu_frontled_reg)
+ register = int(register) & 0xF3 | 0x04
+ self._set_i2c_register(self.psu_frontled_reg, register)
+ oldpsu1 = 0x0
+ DBG_PRINT(" Front panel LED PSU1 set red")
+
+ time.sleep(6)
+
+ # Helper method to map SONiC port name to index
+ def _port_name_to_index(self, port_name):
+ # Strip "Ethernet" off port name
+ if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX):
+ return -1
+
+ port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):])
+ return port_idx
+
+ def _port_state_to_mode(self, port_idx, state):
+ DBG_PRINT("_port_state_to_mode")
+
+ def _port_led_mode_update(self, port_idx, ledMode):
+ DBG_PRINT("_port_led_mode_update")
+
+ # called when port states change- implementation of port_link_state_change() method if needed
+ def port_link_state_change(self, portname, state):
+ # DBG_PRINT("port_link_state_change ")
+ return
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/plugins/psuutil.py b/device/supermicro/arm64-supermicro_sse_g3748-r0/plugins/psuutil.py
new file mode 100755
index 0000000000..513b3ae408
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/plugins/psuutil.py
@@ -0,0 +1,32 @@
+try:
+ import sonic_platform.platform
+ import sonic_platform.chassis
+ from sonic_psu.psu_base import PsuBase
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+
+class PsuUtil(PsuBase):
+ """Platform-specific PSUutil class"""
+
+ def __init__(self):
+ PsuBase.__init__(self)
+ self.chassis = sonic_platform.platform.Platform().get_chassis()
+
+ def get_num_psus(self):
+ MAX_PSUS = 2
+ return MAX_PSUS
+
+ def get_psu_status(self, index):
+ # print " psuUtil redirect to PMON 2.0 "
+ if self.chassis is not None:
+ return self.chassis.get_psu(index-1).get_status()
+ else:
+ return False
+
+ def get_psu_presence(self, index):
+ # print " psuUtil redirect to PMON 2.0 "
+ if self.chassis is not None:
+ return self.chassis.get_psu(index-1).get_presence()
+ else:
+ return False
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/plugins/sfputil.py b/device/supermicro/arm64-supermicro_sse_g3748-r0/plugins/sfputil.py
new file mode 100755
index 0000000000..5f2a061f94
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/plugins/sfputil.py
@@ -0,0 +1,118 @@
+try:
+ import glob
+ import sonic_platform.platform
+ import sonic_platform.chassis
+ from sonic_sfp.sfputilbase import SfpUtilBase
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+
+class SfpUtil(SfpUtilBase):
+ """Platform specific sfputil class"""
+
+ _port_start = 49
+ _port_end = 54
+ ports_in_block = 4
+
+ _port_to_eeprom_mapping = {}
+ port_to_i2c_mapping = {
+ 49: 2,
+ 50: 3,
+ 51: 4,
+ 52: 5,
+ 53: 6,
+ 54: 7
+ }
+ _changed_ports = [0, 0, 0, 0]
+
+ @property
+ def port_start(self):
+ return self._port_start
+
+ @property
+ def port_end(self):
+ return self._port_end
+
+ @property
+ def qsfp_ports(self):
+ return list(range(0, 0))
+
+ @property
+ def port_to_eeprom_mapping(self):
+ return self._port_to_eeprom_mapping
+
+ def __init__(self):
+ # Mux Ordering
+ mux_dev = sorted(glob.glob("/sys/class/i2c-adapter/i2c-1/i2c-[2-7]"))
+ eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"
+ y = 0
+ self.presence = {}
+ for x in range(self.port_start, self.port_end + 1):
+ mux_dev_num = mux_dev[y]
+ self.port_to_i2c_mapping[x] = mux_dev_num[-1]
+ y = y + 1
+ port_eeprom_path = eeprom_path.format(self.port_to_i2c_mapping[x])
+ self.port_to_eeprom_mapping[x] = port_eeprom_path
+ self._port_to_eeprom_mapping[x] = port_eeprom_path
+ self.presence[x] = False;
+
+ SfpUtilBase.__init__(self)
+
+ self.chassis = sonic_platform.platform.Platform().get_chassis()
+
+ def reset(self, port_num):
+ # print " SfpUtil(SfpUtilBase) re-directed to chassis PMON 2.0 "
+ if self.chassis is not None:
+ return self.chassis.get_sfp(port_num).reset()
+ else:
+ return False
+
+ def set_low_power_mode(self, port_nuM, lpmode):
+ # print " SfpUtil(SfpUtilBase) targeted for deprecation "
+ return False
+
+ def get_low_power_mode(self, port_num):
+ # print " SfpUtil(SfpUtilBase) targeted for deprecation "
+ return False
+
+ def get_presence(self, port_num):
+ # print " SfpUtil(SfpUtilBase) re-directed to chassis PMON 2.0 "
+ if self.chassis is not None:
+ return self.chassis.get_sfp(port_num).get_presence()
+ else:
+ return False
+
+ def get_transceiver_change_event(self, timeout):
+ # print " SfpUtil(SfpUtilBase) targeted for deprecation "
+#
+# raise NotImplementedError
+# eyen remove above line and add below. Refer to centec/arm64-centec_e530_48t4x_p-r0/plugins/sfputil.py
+
+ now = time.time()
+ port_dict = {}
+
+ if timeout < 1000:
+ timeout = 1000
+ timeout = (timeout) / float(1000) # Convert to secs
+
+ if now < (self.data['last'] + timeout) and self.data['valid']:
+ return True, {}
+
+ for x in range(self.port_start, self.port_end + 1):
+ presence = self.get_presence(x)
+ if presence != self.presence[x]:
+ self.presence[x] = presence
+ # index in port_config.ini
+ if presence:
+ port_dict[x] = SFP_STATUS_INSERTED
+ else:
+ port_dict[x] = SFP_STATUS_REMOVED
+
+ if bool(port_dict):
+ self.data['last'] = now
+ self.data['valid'] = 1
+ return True, port_dict
+ else:
+ time.sleep(0.5)
+ return True, {}
+
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/pmon_daemon_control.json b/device/supermicro/arm64-supermicro_sse_g3748-r0/pmon_daemon_control.json
new file mode 100644
index 0000000000..f2a407daaf
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/pmon_daemon_control.json
@@ -0,0 +1,4 @@
+{
+ "skip_ledd": false
+}
+
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/sensors.conf b/device/supermicro/arm64-supermicro_sse_g3748-r0/sensors.conf
new file mode 100644
index 0000000000..105d3dfff8
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/sensors.conf
@@ -0,0 +1,20 @@
+chip "lm75-i2c-*-48"
+ label temp1 "Board temp sensor 1"
+ set temp1_max 65
+ set temp1_max_hyst 50
+
+chip "lm75-i2c-*-49"
+ label temp1 "Board temp sensor 2"
+ set temp1_max 65
+ set temp1_max_hyst 50
+
+chip "7f022004mdiomii00-mdio-*"
+ label temp1 "Management ethernet port PHY temp"
+ set temp1_crit 50
+
+chip "g3748cpld-i2c-*-66"
+ label in1 "Power Supply Unit PSU1"
+ label in2 "Power Supply Unit PSU2"
+ label fan1 "Fan Module FAN1"
+ label fan2 "Fan Module FAN2"
+
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/soft-reboot_plugin b/device/supermicro/arm64-supermicro_sse_g3748-r0/soft-reboot_plugin
new file mode 100755
index 0000000000..1030cb07ba
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/soft-reboot_plugin
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+#echo "Issuing OS-level reboot .."
+exec /sbin/reboot -f
+
+
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-Board-ac5x-G3748.md5 b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-Board-ac5x-G3748.md5
new file mode 100644
index 0000000000..ad85b28162
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-Board-ac5x-G3748.md5
@@ -0,0 +1 @@
+a9434f801bdf89ef55e49be4ae288046
\ No newline at end of file
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-Board-ac5x-G3748.xml b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-Board-ac5x-G3748.xml
new file mode 100644
index 0000000000..a7bf814dc9
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-Board-ac5x-G3748.xml
@@ -0,0 +1,1607 @@
+
+
+
+
+
+ std-string
+ string
+ standard string.
+ 1
+ 100
+
+
+ board-callback-type
+ enumeration
+ Specifies os/ext drv callback types.
+
+ linux-static
+ Linux Static
+ 0
+
+
+ linux-shared
+ Linux Shared Lib mode
+ 1
+
+
+ external
+ External Os
+ 3
+
+
+ freeBsd
+ Free BSD
+ 4
+
+
+
+ board-pp-map-type
+ enumeration
+ Specifies pci info types.
+
+ fixed
+ Fixed
+ 0
+
+
+ autoscan
+ Auto scan
+ 1
+
+
+
+ board-pp-interface-channel-type
+ enumeration
+ Specifies interface tunnel.
+
+ pci
+ PCI
+ 0
+
+
+ smi
+ SMI
+ 1
+
+
+ pex
+ PEX
+ 3
+
+
+ pex_eagle
+ PEX EAGLE
+ 5
+
+
+ pex_falcon_z
+ PEX FALCON Z
+ 6
+
+
+
+ device-id-type
+ uint32
+ Device ID 0..1023
+ 0
+ 1023
+
+
+ port-mapping-type
+ enumeration
+ Specifies port map type.
+
+ ethernet_mac
+ ETHERNET_MAC
+ 0
+
+
+ cpu_sdma
+ CPU_SDMA
+ 1
+
+
+
+ interface-num-type
+ uint32
+ Interface number
+ 0
+ 1023
+
+
+ txq-port-number-type
+ uint32
+ 0 - 8 queues are configured per port (legacy mode),
+1...16 - the number of queues configured per port
+ SIP 5 : Bobcat2,BobK:0..71 ;Bobcat3: 0..576 ;Aldrin2:0..99
+ 0
+ 576
+
+
+ phy-smi-interface-type
+ uint32
+ Phy SMI interface type.
+ 0
+ 3
+
+
+ phy-xsmi-interface-type
+ uint32
+ Phy XSMI interface type.
+ 0
+ 15
+
+
+ phy-type
+ enumeration
+ Specifies the PHY Part Identifier.
+
+ NA
+ No Phy
+ 0
+
+
+ alaska-88E1543
+ Specifies PHY identifier 88E1543, used for Combo ports.
+ 1
+
+
+ alaska-88E1545
+ Specifies PHY identifier 88E1545, used for Copper GE with MAC on PHY support.
+ 2
+
+
+ alaska-88E1680
+ Specifies PHY identifier 88E1680, used for Copper with speeds of 10M/100M/1G.
+ 3
+
+
+ alaska-88E151X
+ Specifies PHY identifier 88E151X, used for Copper (HW supports combo and fiber).
+ 4
+
+
+ alaska-88E3140
+ Specifies PHY identifier 88E3140, used for Copper with speeds of 100M/1G/10G. Uses with FW SolarFlare next generation.
+ 5
+
+
+ alaska-88E3240
+ Specifies PHY identifier 88E3240, used for Copper with speeds of 100M/1G/10G. Uses with FW, SolarFlare next generation.
+ 6
+
+
+ alaska-88E3680
+ Specifies PHY identifier 88E3680, used for Octal Copper 100M.
+ 7
+
+
+ alaska-88E3220
+ Specifies PHY identifier 88E3220, used for Combo port with speeds of 100M/1G/10G. Uses FW, SolarFlare next generation.
+ 8
+
+
+ alaska-88E1680L
+ Specifies PHY identifier 88E1680L, used for Copper with speeds of 10M/100M/1G.
+ 9
+
+
+ alaska-88E33X0
+ Specifies PHY identifier 88E33X0, used for MGIG Combo.
+ 10
+
+
+ alaska-88E1548
+ Specifies PHY identifier 88E1548, used for Fiber GE.
+ 11
+
+
+ alaska-88E20X0
+ Specifies PHY identifier 88E20X0, used for Copper with speeds of 10M/100M/1G/2.5G/5G.
+ 12
+
+
+ alaska-88E1512
+ Specifies PHY identifier 88E1512, used for Copper with speeds of 10M/100M/1G.
+ 13
+
+
+ alaska-88E2180
+ Specifies PHY identifier 88E2180, used for Copper with speeds of 10M/100M/1G/2.5G/5G.
+ 14
+
+
+ alaska-88E1780
+ Specifies PHY identifier 88E1780, Integrated Octal 10/100/1000 Mbps Energy Efficient Ethernet Transceiver
+ 15
+
+
+ alaska-88E2540
+ Specifies PHY identifier 88E2540, 4 ports 10/100/1000/2.5G/5GBASE-T Ethernet Transceiver with IEEE 1588v2 PTP Support
+ 16
+
+
+ alaska-88E2580
+ Specifies PHY identifier 88E12580, Octal 10/100/1000/2.5G/5GBASE-T Ethernet Transceiver with IEEE 1588v2 PTP Support
+ 17
+
+
+
+ physical-port-num-type
+ uint32
+ PHYSICAL PORT NUM
+ 0
+ 1023
+
+
+ led-stream-port-type
+ enumeration
+ Specifies the ledstream port type.
+
+ PORT_TYPE_TRI_SPEED
+ tri-speed port.
+ 1
+
+
+ PORT_TYPE_XG
+ XG port.
+ 2
+
+
+
+ led-stream-blink-select-type
+ enumeration
+ Specifies the LED stream blink select type.
+
+ BLINK_SELECT_0
+ Blink 0 signal.
+ 1
+
+
+ BLINK_SELECT_1
+ Blink 1 signal
+ 2
+
+
+
+ led-stream-order-mode-type
+ enumeration
+ Specifies the LED stream ordering mode.
+
+ ORDER_MODE_BY_PORT
+ the indication order is arranged by port.
+ 1
+
+
+ ORDER_MODE_BY_CLASS
+ the indication order is arranged by class.
+ 2
+
+
+
+ led-stream-blink-duty-cycle-type
+ enumeration
+ Specifies the LED stream blink cycle duty cycle type.
+
+ BLINK_DUTY_CYCLE_0
+ 25% on, 75% off.
+ 1
+
+
+ BLINK_DUTY_CYCLE_1
+ 50% on, 50% off.
+ 2
+
+
+ BLINK_DUTY_CYCLE_2
+ 50% on, 50% off.
+ 3
+
+
+ BLINK_DUTY_CYCLE_3
+ 75% on, 25% off.
+ 4
+
+
+
+ led-stream-blink-duration-type
+ enumeration
+ Specifies the LED stream blink period type.
+
+ BLINK_DURATION_0
+ BLINK_DURATION_0.
+ 1
+
+
+ BLINK_DURATION_1
+ BLINK_DURATION_1.
+ 2
+
+
+ BLINK_DURATION_2
+ BLINK_DURATION_2.
+ 3
+
+
+ BLINK_DURATION_3
+ BLINK_DURATION_3.
+ 4
+
+
+ BLINK_DURATION_4
+ BLINK_DURATION_4.
+ 5
+
+
+ BLINK_DURATION_5
+ BLINK_DURATION_5.
+ 6
+
+
+ BLINK_DURATION_6
+ (APPLICABLE DEVICES: xCat3; AC5; Lion2; Bobcat2; Caelum; Aldrin; AC3X; Bobcat3; Aldrin2; Pipe) .
+ 7
+
+
+ BLINK_DURATION_7
+ APPLICABLE DEVICES: Bobcat2; Caelum; Aldrin; AC3X; Bobcat3; Aldrin2; Pipe).
+ 8
+
+
+
+ led-stream-pulse-stretch-type
+ enumeration
+ Specifies the LED stream length of stretching for dynamic signals.
+
+ PULSE_STRETCH_0_NO
+ PULSE_STRETCH_0_NO.
+ 1
+
+
+ PULSE_STRETCH_1
+ PULSE_STRETCH_1.
+ 2
+
+
+ PULSE_STRETCH_2
+ PULSE_STRETCH_2.
+ 3
+
+
+ PULSE_STRETCH_3
+ PULSE_STRETCH_3.
+ 4
+
+
+ PULSE_STRETCH_4
+ PULSE_STRETCH_4.
+ 5
+
+
+ PULSE_STRETCH_5
+ PULSE_STRETCH_5.
+ 6
+
+
+ PULSE_STRETCH_6
+ (APPLICABLE DEVICES: Bobcat2; Caelum; Aldrin; AC3X; Bobcat3; Aldrin2; Falcon; AC5P; Pipe).
+ 7
+
+
+ PULSE_STRETCH_7
+ (APPLICABLE DEVICES: Bobcat2; Caelum; Aldrin; AC3X; Bobcat3; Aldrin2; Falcon; AC5P; Pipe).
+ 8
+
+
+
+ led-stream-clock-out-frequency-type
+ enumeration
+ Specifies the LED stream blink cycle duty cycle type.
+
+ _CLOCK_OUT_FREQUENCY_500
+ 500 KHz LED clock frequency.
+ 1
+
+
+ CLOCK_OUT_FREQUENCY_1000
+ 1 MHz LED clock frequency.
+ 2
+
+
+ CLOCK_OUT_FREQUENCY_2000
+ 2 MHz LED clock frequency.
+ 3
+
+
+ CLOCK_OUT_FREQUENCY_3000
+ 3 MHz LED clock frequency.
+ 4
+
+
+
+ led-stream-class5-select-type
+ enumeration
+ Specifies the LED stream indication displayed on class5 (for dual-media port/phy).
+
+ CLASS_5_SELECT_HALF_DUPLEX
+ Half Duplex is displayed on class5.
+ 1
+
+
+ CLASS_5_SELECT_FIBER_LINK_UP
+ If port is a dual media port, Fiber Link Up is displayed on class5.
+ 2
+
+
+
+ led-stream-class13-select-type
+ enumeration
+ Specifies the LED stream indication displayed on class13 (for dual-media port/phy).
+
+ CLASS_13_SELECT_LINK_DOWN
+ Link Down is displayed on class13.
+ 1
+
+
+ CLASS_13_SELECT_COPPER_LINK_UP
+ If port is a dual media port, Copper Link Up is displayed on class13.
+ 2
+
+
+
+ led-class-num-type
+ uint32
+ Led Class number
+ 0
+ 11
+
+
+ boolean-type
+ enumeration
+ Boolean 32 bits , due to bing endian
+
+ false
+ False
+ 0
+
+
+ true
+ True
+ 1
+
+
+
+ bus-id-type
+ uint32
+ Bus Id Type, PCI/SMI
+ 0
+ 255
+
+
+ function-id-type
+ uint32
+ Function Id Type, PCI/SMI
+ 0
+ 255
+
+
+ domain-type
+ uint32
+ Domain, PCI/SMI
+ 0
+ 255
+
+
+ led-interface-type
+ uint32
+ Led interface
+ 0
+ 255
+
+
+ led-position-type
+ uint32
+ Led position
+ 0
+ 63
+
+
+ serdes-lane-type
+ uint32
+ serdes lane
+ 0
+ 255
+
+
+ cpu-type
+ enumeration
+ The CPU Internal/External
+
+ external
+ Extrenal connected CPU
+ 0
+
+
+ internal
+ Internal CPU
+ 1
+
+
+
+ led-stream-clock-frequency-type
+ uint32
+ Led Clock Frequency Sip6
+ 500
+ 80000
+
+
+ led-unit-type
+ uint32
+ Led units
+ 1
+ 16
+
+
+ led-unit-or-no-unit-type
+ uint32
+ Led units, 0 for no Unit
+ 0
+ 16
+
+
+ led-group-type
+ uint32
+ Led Group
+ 0
+ 1
+
+
+ led-stream-force-data-type
+ string
+ A hexadecimal string with octets represented as hex digits
+separated by colons. The canonical representation uses
+lowercase characters.
+ 3
+ 11
+
+
+ bit-type
+ uint32
+ Bit range 0..31
+ 0
+ 31
+
+
+ bit-size-type
+ uint32
+ Bit leng 1..32
+ 1
+ 32
+
+
+ led-sip-type
+ enumeration
+ The LED scehme
+
+ na
+ NA
+ 0
+
+
+ sip5
+ SIP5: AC5, AC3x
+ 5
+
+
+ sip6
+ SIP6: Falcon, AC5x, AC5P
+ 6
+
+
+
+ port-cscd-type
+ enumeration
+ Specifies the cascade port type.
+
+ DSA_1_WORD
+ DSA Regular
+ 0
+
+
+ DSA_2_WORDS
+ DSA Extended
+ 1
+
+
+ NETWORK
+ Network.
+ 2
+
+
+ DSA_3_WORDS
+ DSA 3 Words
+ 3
+
+
+ DSA_4_WORD
+ DSA 4 Words
+ 4
+
+
+
+ trunk-cscd-type
+ uint32
+ Specifies the Cascade Trunk id.
+ 0
+ 127
+
+
+ port-trunk-cscd-type
+ enumeration
+ Specifies the cascade port type.
+
+ cscdPort
+ Cascade port
+ 0
+
+
+ cscdTrunk
+ Csacde trunk
+ 1
+
+
+
+ hash-cscd-type
+ enumeration
+ Specifies the hash used by cascade trunk.
+
+ pkt
+ Hash based on packet
+ 0
+
+
+ srcPort
+ Hash based on source port
+ 1
+
+
+
+ AC5X-RD-G3748
+ linux-static
+ linux-static
+ autoscan
+ internal
+ pex_eagle
+
+ 0
+ 0
+ ASK-PP-AC5X-G3748.xml
+ ASK-L1-AC5X-G3748.xml
+ na
+
+ 0
+
+ ethernet_mac
+ 0
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 0
+ 0
+ 0
+
+
+
+
+ 1
+
+ ethernet_mac
+ 1
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 0
+ 1
+ 0
+
+
+
+
+ 2
+
+ ethernet_mac
+ 2
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 0
+ 2
+ 0
+
+
+
+
+ 3
+
+ ethernet_mac
+ 3
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 0
+ 3
+ 0
+
+
+
+
+ 4
+
+ ethernet_mac
+ 4
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 0
+ 4
+ 0
+
+
+
+
+ 5
+
+ ethernet_mac
+ 5
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 0
+ 5
+ 0
+
+
+
+
+ 6
+
+ ethernet_mac
+ 6
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 0
+ 6
+ 0
+
+
+
+
+ 7
+
+ ethernet_mac
+ 7
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 0
+ 7
+ 0
+
+
+
+
+ 8
+
+ ethernet_mac
+ 8
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 1
+ 8
+ 0
+
+
+
+
+ 9
+
+ ethernet_mac
+ 9
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 1
+ 9
+ 0
+
+
+
+
+ 10
+
+ ethernet_mac
+ 10
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 1
+ 10
+ 0
+
+
+
+
+ 11
+
+ ethernet_mac
+ 11
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 1
+ 11
+ 0
+
+
+
+
+ 12
+
+ ethernet_mac
+ 12
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 1
+ 12
+ 0
+
+
+
+
+ 13
+
+ ethernet_mac
+ 13
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 1
+ 13
+ 0
+
+
+
+
+ 14
+
+ ethernet_mac
+ 14
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 1
+ 14
+ 0
+
+
+
+
+ 15
+
+ ethernet_mac
+ 15
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 1
+ 15
+ 0
+
+
+
+
+ 16
+
+ ethernet_mac
+ 16
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 2
+ 16
+ 0
+
+
+
+
+ 17
+
+ ethernet_mac
+ 17
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 2
+ 17
+ 0
+
+
+
+
+ 18
+
+ ethernet_mac
+ 18
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 2
+ 18
+ 0
+
+
+
+
+ 19
+
+ ethernet_mac
+ 19
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 2
+ 19
+ 0
+
+
+
+
+ 20
+
+ ethernet_mac
+ 20
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 2
+ 20
+ 0
+
+
+
+
+ 21
+
+ ethernet_mac
+ 21
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 2
+ 21
+ 0
+
+
+
+
+ 22
+
+ ethernet_mac
+ 22
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 2
+ 22
+ 0
+
+
+
+
+ 23
+
+ ethernet_mac
+ 23
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 2
+ 23
+ 0
+
+
+
+
+ 24
+
+ ethernet_mac
+ 24
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 3
+ 0
+ 1
+
+
+
+
+ 25
+
+ ethernet_mac
+ 25
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 3
+ 1
+ 1
+
+
+
+
+ 26
+
+ ethernet_mac
+ 26
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 3
+ 2
+ 1
+
+
+
+
+ 27
+
+ ethernet_mac
+ 27
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 3
+ 3
+ 1
+
+
+
+
+ 28
+
+ ethernet_mac
+ 28
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 3
+ 4
+ 1
+
+
+
+
+ 29
+
+ ethernet_mac
+ 29
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 3
+ 5
+ 1
+
+
+
+
+ 30
+
+ ethernet_mac
+ 30
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 3
+ 6
+ 1
+
+
+
+
+ 31
+
+ ethernet_mac
+ 31
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 3
+ 7
+ 1
+
+
+
+
+ 32
+
+ ethernet_mac
+ 32
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 8
+ 1
+
+
+
+
+ 33
+
+ ethernet_mac
+ 33
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 9
+ 1
+
+
+
+
+ 34
+
+ ethernet_mac
+ 34
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 10
+ 1
+
+
+
+
+ 35
+
+ ethernet_mac
+ 35
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 11
+ 1
+
+
+
+
+ 36
+
+ ethernet_mac
+ 36
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 12
+ 1
+
+
+
+
+ 37
+
+ ethernet_mac
+ 37
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 5
+ 13
+ 1
+
+
+
+
+ 38
+
+ ethernet_mac
+ 38
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 5
+ 14
+ 1
+
+
+
+
+ 39
+
+ ethernet_mac
+ 39
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 5
+ 15
+ 1
+
+
+
+
+ 40
+
+ ethernet_mac
+ 40
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 5
+ 16
+ 1
+
+
+
+
+ 41
+
+ ethernet_mac
+ 41
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 17
+ 1
+
+
+
+
+ 42
+
+ ethernet_mac
+ 42
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 18
+ 1
+
+
+
+
+ 43
+
+ ethernet_mac
+ 43
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 19
+ 1
+
+
+
+
+ 44
+
+ ethernet_mac
+ 44
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 20
+ 1
+
+
+
+
+ 45
+
+ ethernet_mac
+ 45
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 21
+ 1
+
+
+
+
+ 46
+
+ ethernet_mac
+ 46
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 22
+ 1
+
+
+
+
+ 47
+
+ ethernet_mac
+ 47
+ 0
+ false
+
+ NETWORK
+
+ alaska-88E1780
+ 4
+ 23
+ 1
+
+
+
+
+ 48
+
+ ethernet_mac
+ 48
+ 0
+ false
+
+ NETWORK
+
+ NA
+
+
+
+
+ 53
+
+ ethernet_mac
+ 53
+ 0
+ false
+
+ NETWORK
+
+ NA
+
+
+
+
+ 52
+
+ ethernet_mac
+ 52
+ 0
+ false
+
+ NETWORK
+
+ NA
+
+
+
+
+ 51
+
+ ethernet_mac
+ 51
+ 0
+ false
+
+ NETWORK
+
+ NA
+
+
+
+
+ 50
+
+ ethernet_mac
+ 50
+ 0
+ false
+
+ NETWORK
+
+ NA
+
+
+
+
+ 49
+
+ ethernet_mac
+ 49
+ 0
+ false
+
+ NETWORK
+
+ NA
+
+
+
+
+ 63
+
+ cpu_sdma
+ 54
+ 0
+ false
+
+ NETWORK
+
+
+ 60
+
+ cpu_sdma
+ 55
+ 0
+ false
+
+ NETWORK
+
+
+ .
+
+ 1
+
+
+
\ No newline at end of file
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-L1-AC5X-G3748.md5 b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-L1-AC5X-G3748.md5
new file mode 100644
index 0000000000..0a8f542ec0
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-L1-AC5X-G3748.md5
@@ -0,0 +1 @@
+8e51017346a381613f8660e192883697
\ No newline at end of file
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-L1-AC5X-G3748.xml b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-L1-AC5X-G3748.xml
new file mode 100644
index 0000000000..f4622aa75c
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-L1-AC5X-G3748.xml
@@ -0,0 +1,1219 @@
+
+
+
+
+
+ interface-mode-type
+ enumeration
+ Specifies supported Interface modes
+
+ 1000BASE_X
+ 1G
+ 6
+
+
+ SGMII
+ 1G , 2.5G
+ 3
+
+
+ QSGMII
+ 1G
+ 13
+
+
+ KR
+ 10G, 12G, 20G, 40G, 100G
+ 16
+
+
+ SR_LR
+ 5G, 10G, 12G, 20G, 40G
+ 20
+
+
+ KR2
+
+ 27
+
+
+ KR4
+
+ 28
+
+
+ SR_LR2
+
+ 29
+
+
+ SR_LR4
+ 100G
+ 30
+
+
+ KR_C
+ CONSORTIUM - 25G
+ 32
+
+
+ CR_C
+ CONSORTIUM - 25G
+ 33
+
+
+ KR2_C
+ CONSORTIUM - 50G
+ 34
+
+
+ CR2_C
+ CONSORTIUM - 50G
+ 35
+
+
+ CR
+
+ 36
+
+
+ CR2
+
+ 37
+
+
+ CR4
+
+ 38
+
+
+ KR_S
+
+ 39
+
+
+ CR_S
+
+ 40
+
+
+ KR8
+
+ 41
+
+
+ CR8
+
+ 42
+
+
+ SR_LR8
+
+ 43
+
+
+ USX_10G_QXGMII
+
+ 51
+
+
+ USX_20G_QXGMII
+
+ 52
+
+
+ USX_OUSGMII
+
+ 53
+
+
+ USX_20G_OXGMII
+
+ 54
+
+
+ NA
+
+ 57
+
+
+
+ port-speed-type
+ enumeration
+ Specifies supported speeds
+
+ 1G
+ 1G
+ 2
+
+
+ 10G
+ 10G
+ 3
+
+
+ 2500M
+ 2.5G
+ 5
+
+
+ 5G
+ 5G
+ 6
+
+
+ 25G
+ 25G, used in combination with CPSS_PORT_INTERFACE_MODE_KR_E, CPSS_PORT_INTERFACE_MODE_KR2_E
+ 21
+
+
+ 40G
+ 40G
+ 9
+
+
+ 50G
+ 50G
+ 14
+
+
+ 100G
+ 100G
+ 13
+
+
+ 200G
+ 200G
+ 24
+
+
+ 400G
+ 400G
+ 25
+
+
+ NA
+ NA
+ 35
+
+
+
+ fec-type
+ enumeration
+ Rx parameter type
+
+ enabled
+ Enabled
+ 0
+
+
+ disabled
+ Disabled
+ 1
+
+
+ rs_enabled
+ RS FEC enabled
+ 2
+
+
+ both_enabled
+ Both enabled
+ 3
+
+
+ rs_544_514_enabled
+ RS FEC 544 and 514
+ 4
+
+
+
+ physical-port-num-type
+ uint32
+ PHYSICAL PORT NUM
+ 0
+ 1023
+
+
+ tx-param-type
+ enumeration
+ Tx parameter type
+
+ atten
+ atten
+ 0
+
+
+ post
+ post
+ 1
+
+
+ pre
+ pre
+ 2
+
+
+ pre2
+ pre2
+ 3
+
+
+ pre3
+ pre3
+ 4
+
+
+ peak
+ peak
+ 5
+
+
+ main
+ main
+ 6
+
+
+ txAmpAdjEn
+ txAmpAdjEn
+ 7
+
+
+ emph0
+ emph0
+ 8
+
+
+ emph1
+ emph1
+ 9
+
+
+ txAmpShft
+ txAmpShft
+ 10
+
+
+ txEmphEn
+ txEmphEn
+ 11
+
+
+ txEmphEn1
+ txEmphEn1
+ 12
+
+
+ txAmpAdj
+ txAmpAdj
+ 13
+
+
+ slewCtrlEn
+ slewCtrlEn
+ 14
+
+
+ slewRate
+ slewRate
+ 15
+
+
+
+ rx-param-type
+ enumeration
+ Rx parameter type
+
+ sqlch
+ sqlch
+ 0
+
+
+ DC
+ DC
+ 1
+
+
+ LF
+ LF
+ 2
+
+
+ HF
+ HF
+ 3
+
+
+ gainShape1
+ gainShape1
+ 4
+
+
+ gainShape2
+ gainShape2
+ 5
+
+
+ shortChannelEn
+ shortChannelEn
+ 7
+
+
+ bfLf
+ bfLf
+ 8
+
+
+ bfHf
+ bfHf
+ 9
+
+
+ minLf
+ minLf
+ 10
+
+
+ maxLf
+ maxLf
+ 11
+
+
+ minHf
+ minHf
+ 12
+
+
+ maxHf
+ maxHf
+ 13
+
+
+ minPre1
+ minPre1
+ 14
+
+
+ maxPre1
+ maxPre1
+ 15
+
+
+ minPre2
+ minPre2
+ 16
+
+
+ maxPre2
+
+ 17
+
+
+ minPost
+ minPost
+ 18
+
+
+ maxPost
+ maxPost
+ 19
+
+
+ squelch
+ squelch
+ 20
+
+
+ termination
+ termination
+ 27
+
+
+ coldEnvelope
+ coldEnvelope
+ 35
+
+
+ hotEnvelope
+ hotEnvelope
+ 36
+
+
+ dcGain
+ dcGain
+ 37
+
+
+ bandWidth
+ bandWidth
+ 38
+
+
+ dfe
+ dfe
+ 39
+
+
+ ffeR
+ ffeR
+ 40
+
+
+ ffeC
+ ffeC
+ 41
+
+
+ sampler
+ sampler
+ 42
+
+
+ align90
+ align90
+ 43
+
+
+ ffeS
+ ffeS
+ 44
+
+
+ resSel
+ resSel
+ 45
+
+
+ resShift
+ resShift
+ 46
+
+
+ capSel
+ capSel
+ 47
+
+
+ ffeSettingForce
+ ffeSettingForce
+ 48
+
+
+ adaptedResSel
+ adaptedResSel
+ 49
+
+
+ adaptedCapSel
+ adaptedCapSel
+ 50
+
+
+ selmufi
+ selmufi
+ 51
+
+
+ selmuff
+ selmuff
+ 52
+
+
+ selmupi
+ selmupi
+ 53
+
+
+ selmupf
+ selmupf
+ 54
+
+
+ slewRateCtrl0
+ slewRateCtrl0
+ 55
+
+
+ slewRateCtrl1
+ slewRateCtrl1
+ 56
+
+
+ EO
+ EO
+ 57
+
+
+ dataRate
+ dataRate
+ 58
+
+
+ res1Sel
+ res1Sel
+ 59
+
+
+ res2Sel
+ res2Sel
+ 60
+
+
+ cap1Sel
+ cap1Sel
+ 61
+
+
+ cap2Sel
+ cap2Sel
+ 62
+
+
+ midpointLargeThresKLane
+ midpointLargeThresKLane
+ 63
+
+
+ midpointSmallThresKLane
+ midpointSmallThresKLane
+ 64
+
+
+ midpointLargeThresCLane
+ midpointLargeThresCLane
+ 65
+
+
+ midpointSmallThresCLane
+ midpointSmallThresCLane
+ 66
+
+
+ dfeResF0aHighThresInitLane
+ dfeResF0aHighThresInitLane
+ 67
+
+
+ dfeResF0aHighThresEndLane
+ dfeResF0aHighThresEndLane
+ 68
+
+
+ current1Sel
+ current1Sel
+ 69
+
+
+ rl1Sel
+ rl1Sel
+ 70
+
+
+ rl1Extra
+ rl1Extra
+ 71
+
+
+ cl1Ctrl
+ cl1Ctrl
+ 72
+
+
+ enMidFreq
+ enMidFreq
+ 73
+
+
+ cs1Mid
+ cs1Mid
+ 74
+
+
+ rs1Mid
+ rs1Mid
+ 75
+
+
+ rfCtrl
+ rfCtrl
+ 76
+
+
+ rl1TiaSel
+ rl1TiaSel
+ 77
+
+
+ rl1TiaExtra
+ rl1TiaExtra
+ 78
+
+
+ hpfRSel1st
+ hpfRSel1st
+ 79
+
+
+ current1TiaSel
+ current1TiaSel
+ 80
+
+
+ rl2Tune
+ rl2Tune
+ 81
+
+
+ rl2Sel
+ rl2Sel
+ 82
+
+
+ rs2Sel
+ rs2Sel
+ 83
+
+
+ current2Sel
+ current2Sel
+ 84
+
+
+ hpfRsel2nd
+ hpfRsel2nd
+ 85
+
+
+ BW
+ BW
+ 86
+
+
+ dfeGAIN
+ dfeGAIN
+ 87
+
+
+ dfeGAIN2
+ dfeGAIN2
+ 88
+
+
+ pre1
+ pre1
+ 89
+
+
+ pre2
+ pre2
+ 90
+
+
+ post1
+ post1
+ 91
+
+
+
+ boolean-type
+ enumeration
+ Boolean 32 bits , due to bing endian
+
+ false
+ False
+ 0
+
+
+ true
+ True
+ 1
+
+
+
+ serdes-type
+ enumeration
+ Serdes Type
+
+ NA
+ No serdes
+ 0
+
+
+ AVAGO
+ AVAGO
+ 1
+
+
+ COMPHY
+ COMPHY
+ 2
+
+
+ COMPHY_C12G
+ COMPHY_C12G
+ 3
+
+
+ COMPHY_C28G
+ COMPHY_C28G
+ 4
+
+
+ COMPHY_C112G
+ COMPHY_C112G
+ 5
+
+
+
+ uint8-type
+ uint32
+ Uint8 32 bits , due to bing endian
+ 0
+ 255
+
+
+ serdes-termination-type
+ enumeration
+ RX termination mode
+
+ GND
+ Enabled
+ 0
+
+
+ VDD
+ Disabled
+ 1
+
+
+ FLOATING
+ RS FEC enabled
+ 2
+
+
+
+ port-interconnect-profile-type
+ enumeration
+ Enumerator of interconnect profile.
+
+ profile_default
+ Profile Default
+ 0
+
+
+ profile_1
+ Profile 1
+ 1
+
+
+ profile_2
+ Profile 2
+ 2
+
+
+
+
+
+ 1000MR1
+
+ USX_OUSGMII
+ 1G
+ disabled
+
+
+ USX_OUSGMII
+ 1G
+ disabled
+ disabled
+
+
+
+ 2500MR1
+
+ USX_20G_OXGMII
+ 2500M
+ rs_enabled
+
+
+ USX_20G_OXGMII
+ 1G
+ rs_enabled
+
+
+ USX_20G_OXGMII
+ 2500M
+ rs_enabled
+ rs_enabled
+
+
+ USX_20G_OXGMII
+ 1G
+ rs_enabled
+ rs_enabled
+
+
+
+ 25GR1
+
+ CR
+ 25G
+ rs_enabled
+
+
+ KR
+ 25G
+ rs_enabled
+
+
+ KR
+ 10G
+ disabled
+
+
+ CR
+ 25G
+ rs_enabled
+ rs_enabled
+
+
+ KR
+ 25G
+ rs_enabled
+ rs_enabled
+
+
+ KR
+ 10G
+ disabled
+ disabled
+
+
+
+
+
+ 0
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 1
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 2
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 3
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 4
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 5
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 6
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 7
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 8
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 9
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 10
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 11
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 12
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 13
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 14
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 15
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 16
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 17
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 18
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 19
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 20
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 21
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 22
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 23
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 24
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 25
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 26
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 27
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 28
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 29
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 30
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 31
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 32
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 33
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 34
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 35
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 36
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 37
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 38
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 39
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 40
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 41
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 42
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 43
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 44
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 45
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 46
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 47
+ AVAGO
+ profile_default
+ 1000MR1
+
+
+ 48
+ AVAGO
+ profile_default
+ 25GR1
+
+
+ 49
+ AVAGO
+ profile_default
+ 25GR1
+
+
+ 50
+ AVAGO
+ profile_default
+ 25GR1
+
+
+ 51
+ AVAGO
+ profile_default
+ 25GR1
+
+
+ 52
+ AVAGO
+ profile_default
+ 25GR1
+
+
+ 53
+ AVAGO
+ profile_default
+ 25GR1
+
+
+
+
\ No newline at end of file
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-PP-AC5X-G3748.md5 b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-PP-AC5X-G3748.md5
new file mode 100644
index 0000000000..18f55a9315
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-PP-AC5X-G3748.md5
@@ -0,0 +1 @@
+330bea15c5dc5dcc0bdabd95940b6bab
\ No newline at end of file
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-PP-AC5X-G3748.xml b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-PP-AC5X-G3748.xml
new file mode 100644
index 0000000000..6944bbcb42
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ASK-PP-AC5X-G3748.xml
@@ -0,0 +1,891 @@
+
+
+
+
+
+ std-string
+ string
+ standard string.
+ 1
+ 100
+
+
+ queue-id-type
+ uint32
+ Queue id
+ 0
+ 7
+
+
+ precent-type
+ uint32
+ Precent
+ 0
+ 100
+
+
+ phaThreadId-type
+ uint32
+ Thread id
+ 1
+ 255
+
+
+ routing-mode-type
+ enumeration
+ Specifies routing mode.
+
+ POLICY_BASED_ROUTING_ONLY
+ PBR only
+ 0
+
+
+ TCAM_ROUTER_BASED
+ Router engine or PBR
+ 1
+
+
+
+ shared-table-mode-type
+ enumeration
+ Specifies table sharing modes.
+
+ MAX_L3_MIN_L2_NO_EM
+ MAX_L3_MIN_L2_NO_EM
+ 0
+
+
+ MIN_L3_MAX_L2_NO_EM
+ MIN_L3_MAX_L2_NO_EM
+ 1
+
+
+ MID_L3_MID_L2_MIN_EM
+ MID_L3_MID_L2_MIN_EM
+ 2
+
+
+ MID_L3_MIN_L2_MAX_EM
+ MID_L3_MIN_L2_MAX_EM
+ 3
+
+
+ MID_LOW_L3_MID_LOW_L2_MAX_EM
+ MID_LOW_L3_MID_LOW_L2_MAX_EM
+ 4
+
+
+ MID_L3_MID_L2_NO_EM
+ MID_L3_MID_L2_NO_EM
+ 5
+
+
+ MID_LOW_L3_MID_L2_MID_EM
+ MID_LOW_L3_MID_L2_MID_EM
+ 6
+
+
+ MID_L3_MID_LOW_L2_MID_EM_MAX_ARP
+ MID_L3_MID_LOW_L2_MID_EM_MAX_ARP
+ 7
+
+
+
+ pha-firmware-image-id-type
+ enumeration
+ Specifies supported Pha image id
+
+ DEFAULT
+ Default PHA firmware image ID
+ 0
+
+
+ 01
+ 01 firmware image ID
+ 1
+
+
+ 02
+ 02 PHA firmware image ID
+ 2
+
+
+
+ pha-firmware-thread-type
+ enumeration
+ Specifies supported Pha thread type
+
+ IOAM_INGRESS_SWITCH_IPV4
+ IOAM_INGRESS_SWITCH_IPV4
+ 1
+
+
+ IOAM_INGRESS_SWITCH_IPV6
+ IOAM_INGRESS_SWITCH_IPV6
+ 2
+
+
+ IOAM_TRANSIT_SWITCH_IPV4
+ IOAM_TRANSIT_SWITCH_IPV4
+ 3
+
+
+ IOAM_TRANSIT_SWITCH_IPV6
+ IOAM_TRANSIT_SWITCH_IPV6
+ 4
+
+
+ INT_IOAM_MIRRORING
+ INT_IOAM_MIRRORING
+ 5
+
+
+ INT_IOAM_EGRESS_SWITCH
+ INT_IOAM_EGRESS_SWITCH
+ 6
+
+
+ MPLS_SR_NO_EL
+ MPLS_SR_NO_EL
+ 7
+
+
+ MPLS_SR_ONE_EL
+ MPLS_SR_ONE_EL
+ 8
+
+
+ MPLS_SR_TWO_EL
+ MPLS_SR_TWO_EL
+ 9
+
+
+ MPLS_SR_THREE_EL
+ MPLS_SR_THREE_EL
+ 10
+
+
+ UNIFIED_SR
+ UNIFIED_SR
+ 11
+
+
+ CLASSIFIER_NSH_OVER_ETHERNET
+ CLASSIFIER_NSH_OVER_ETHERNET
+ 12
+
+
+ CLASSIFIER_NSH_OVER_VXLAN_GPE
+ CLASSIFIER_NSH_OVER_VXLAN_GPE
+ 13
+
+
+ SFF_NSH_VXLAN_GPE_TO_ETHERNET
+ SFF_NSH_VXLAN_GPE_TO_ETHERNET
+ 14
+
+
+ SFF_NSH_ETHERNET_TO_VXLAN_GPE
+ SFF_NSH_ETHERNET_TO_VXLAN_GPE
+ 15
+
+
+ IOAM_EGRESS_SWITCH_IPV6
+ IOAM_EGRESS_SWITCH_IPV6
+ 16
+
+
+ SRV6_END_NODE
+ SRV6_END_NODE
+ 17
+
+
+ SRV6_PENULTIMATE_END_NODE
+ SRV6_PENULTIMATE_END_NODE
+ 18
+
+
+ SRV6_SRC_NODE_1_SEGMENT
+ SRV6_SRC_NODE_1_SEGMENT
+ 19
+
+
+ SRV6_SRC_NODE_FIRST_PASS_2_3_SEGMENTS
+ SRV6_SRC_NODE_FIRST_PASS_2_3_SEGMENTS
+ 20
+
+
+ SRV6_SRC_NODE_SECOND_PASS_3_SEGMENTS
+ SRV6_SRC_NODE_SECOND_PASS_3_SEGMENTS
+ 21
+
+
+ SRV6_SRC_NODE_SECOND_PASS_2_SEGMENTS
+ SRV6_SRC_NODE_SECOND_PASS_2_SEGMENTS
+ 22
+
+
+ SGT_NETWORK_ADD_MSB
+ SGT_NETWORK_ADD_MSB
+ 23
+
+
+ SGT_NETWORK_FIX
+ SGT_NETWORK_FIX
+ 24
+
+
+ SGT_NETWORK_REMOVE
+ SGT_NETWORK_REMOVE
+ 25
+
+
+ SGT_EDSA_FIX
+ SGT_EDSA_FIX
+ 26
+
+
+ SGT_EDSA_REMOVE
+ SGT_EDSA_REMOVE
+ 27
+
+
+ SGT_GBP_FIX_IPV4
+ SGT_GBP_FIX_IPV4
+ 28
+
+
+ SGT_GBP_FIX_IPV6
+ SGT_GBP_FIX_IPV6
+ 29
+
+
+ SGT_GBP_REMOVE_IPV4
+ SGT_GBP_REMOVE_IPV4
+ 30
+
+
+ SGT_GBP_REMOVE_IPV6
+ SGT_GBP_REMOVE_IPV6
+ 31
+
+
+ PTP_PHY_1_STEP
+ PTP_PHY_1_STEP
+ 32
+
+
+ EGRESS_MIRRORING_METADATA
+ EGRESS_MIRRORING_METADATA
+ 33
+
+
+ CC_ERSPAN_TYPE_II_TRG_DEV_LC_IPV4
+ CC_ERSPAN_TYPE_II_TRG_DEV_LC_IPV4
+ 34
+
+
+ CC_ERSPAN_TYPE_II_TRG_DEV_LC_IPV6
+ CC_ERSPAN_TYPE_II_TRG_DEV_LC_IPV6
+ 35
+
+
+ CC_ERSPAN_TYPE_II_TRG_DEV_DIRECT_IPV4
+ CC_ERSPAN_TYPE_II_TRG_DEV_DIRECT_IPV4
+ 36
+
+
+ CC_ERSPAN_TYPE_II_TRG_DEV_DIRECT_IPV6
+ CC_ERSPAN_TYPE_II_TRG_DEV_DIRECT_IPV6
+ 37
+
+
+ CC_ERSPAN_TYPE_II_SRC_DEV
+ CC_ERSPAN_TYPE_II_SRC_DEV
+ 38
+
+
+ VXLAN_GBP_SOURCE_GROUP_POLICY_ID
+ VXLAN_GBP_SOURCE_GROUP_POLICY_ID
+ 39
+
+
+ SRV6_BEST_EFFORT
+ SRV6_BEST_EFFORT
+ 40
+
+
+ SRV6_SRC_NODE_1_CONTAINER
+ SRV6_SRC_NODE_1_CONTAINER
+ 41
+
+
+ SRV6_SRC_NODE_FIRST_PASS_2_3_CONTAINERS
+ SRV6_SRC_NODE_FIRST_PASS_2_3_CONTAINERS
+ 42
+
+
+ SRV6_SRC_NODE_SECOND_PASS_2_CONTAINERS
+ SRV6_SRC_NODE_SECOND_PASS_2_CONTAINERS
+ 43
+
+
+ SRV6_SRC_NODE_SECOND_PASS_3_CONTAINERS
+ SRV6_SRC_NODE_SECOND_PASS_3_CONTAINERS
+ 44
+
+
+ SRV6_END_NODE_COC32_GSID
+ SRV6_END_NODE_COC32_GSID
+ 45
+
+
+ IPV4_TTL_INCREMENT
+ IPV4_TTL_INCREMENT
+ 46
+
+
+ IPV6_HOP_LIMIT_INCREMENT
+ IPV6_HOP_LIMIT_INCREMENT
+ 47
+
+
+ CLEAR_OUTGOING_MTAG_COMMAND
+ CLEAR_OUTGOING_MTAG_COMMAND
+ 48
+
+
+ SFLOW_V5_IPV4
+ SFLOW_V5_IPV4
+ 49
+
+
+ SFLOW_V5_IPV6
+ SFLOW_V5_IPV6
+ 50
+
+
+ SLS
+ SLS
+ 51
+
+
+
+ trunk-member-mode-type
+ enumeration
+ Specifies supported Pha image id
+
+ NATIVE
+ NATIVE
+ * the trunk members are filled
+ * according to the order given by application.
+ * Regular trunk may hold max of 8 members.
+ * Cascade trunk may hold :
+ * max of 64 members
+ 0
+
+
+ FLEX
+ FLEX
+ * A mode to allows flexibility for
+ * each Regular trunk to state it's max number of members (before starting to add members).
+ * (this mode not effect 'cascade trunk' members)
+ * Regular trunk may hold : max of 4K members. (each trunk set it's own limit)
+ * Cascade trunk may hold : max of 64 members.
+ 2
+
+
+
+ number-physical-port-type
+ enumeration
+ ac5x 128, falcon 64,128,256, 512, 1024
+
+ no-ports
+ no-ports
+ 0
+
+
+ 64-ports
+ 64-ports
+ 64
+
+
+ 128-ports
+ 128-ports
+ 128
+
+
+ 256-ports
+ 256-ports
+ 256
+
+
+ 512-ports
+ 512-ports
+ 512
+
+
+ 1024-ports
+ 1024-ports
+ 1024
+
+
+
+ serdes-ref-clock-type
+ enumeration
+ Specifies serdes refernce clock.
+
+ external_25_single_ended
+ EXTERNAL_25_SINGLE_ENDED
+ 0
+
+
+ external_125_single_ended
+ EXTERNAL_125_SINGLE_ENDED
+ 1
+
+
+ external_125_diff
+ EXTERNAL_125_DIFF
+ 2
+
+
+ external_156_25_single_ended
+ EXTERNAL_156_25_SINGLE_ENDED
+ 3
+
+
+ external_156_25_diff
+ EXTERNAL_156_25_DIFF
+ 4
+
+
+ internal_125
+ INTERNAL_125
+ 5
+
+
+
+ cpu-port-id-type
+ uint32
+ CPU port id
+ 0
+ 7
+
+
+ rx-buffer-size-type
+ uint32
+ Rx Buffer size
+ 64
+ 10240
+
+
+ tx-sdma-queue-mode-type
+ enumeration
+ Specifies TX queue mode.
+
+ Normal
+ Application
+ 0
+
+
+ Packet_Generator
+ Traffic generator
+ 1
+
+
+
+ alloc-method-type
+ enumeration
+ Specifies Buffers allocation method.
+
+ Dynamic_Alloc
+ Dynamic
+ 0
+
+
+ Static_Alloc
+ Static
+ 1
+
+
+
+ au_mesage_lenght-type
+ enumeration
+ Specifies Buffers allocation method.
+
+ 4_words
+ 4 Words
+ 0
+
+
+ 8_words
+ 8 Words
+ 1
+
+
+
+ boolean-type
+ enumeration
+ Boolean 32 bits , due to bing endian
+
+ false
+ False
+ 0
+
+
+ true
+ True
+ 1
+
+
+
+
+ AC5X-RD
+
+ 4294967295
+ external_25_single_ended
+ 2
+ 60
+ 128-ports
+ false
+ false
+ 0
+
+
+ true
+
+ 4096
+
+
+ 2048
+
+
+
+ 0
+ 0
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 1
+ 7
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 1
+ 6
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 1
+ 5
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 1
+ 4
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 1
+ 3
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 1
+ 2
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 1
+ 1
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 1
+ 0
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 0
+ 7
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 0
+ 6
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 0
+ 5
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 0
+ 4
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 0
+ 3
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 0
+ 2
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 0
+ 1
+ Static_Alloc
+ 20
+ 20
+ 2048
+ 0
+
+
+ 0
+ 0
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 0
+ 1
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 0
+ 2
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 0
+ 3
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 0
+ 4
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 0
+ 5
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 0
+ 6
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 0
+ 7
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 1
+ 0
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 1
+ 1
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 1
+ 2
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 1
+ 3
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 1
+ 4
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 1
+ 5
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 1
+ 6
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+ 1
+ 7
+ Static_Alloc
+ Normal
+ 20
+ 0
+ 128
+
+
+
+ false
+ false
+ false
+ 0
+ 8_words
+ false
+
+
+
+ TCAM_ROUTER_BASED
+ 0
+ MID_L3_MID_L2_NO_EM
+ true
+
+
+ true
+ true
+ true
+ true
+ true
+ true
+
+ 511
+ FLEX
+
+ true
+ true
+ true
+ true
+
+ false
+ 01
+ 0
+
+
+
+
+
\ No newline at end of file
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/SAI-AC5X-G3748.md5 b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/SAI-AC5X-G3748.md5
new file mode 100644
index 0000000000..6cdba7a1b7
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/SAI-AC5X-G3748.md5
@@ -0,0 +1 @@
+3ac4dbcd6e23c747318b7e7c27e08a02
\ No newline at end of file
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/SAI-AC5X-G3748.xml b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/SAI-AC5X-G3748.xml
new file mode 100644
index 0000000000..bb2f800047
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/SAI-AC5X-G3748.xml
@@ -0,0 +1,315 @@
+
+
+
+
+
+ device-id-type
+ uint32
+ Device ID 0..1023
+ 0
+ 1023
+
+
+ port-id-type
+ uint32
+ Interface number
+ 0
+ 1023
+
+
+ ASK-Board-ac5x-G3748.xml
+
+ false
+
+
+
+ 0
+ 0
+ 0
+
+
+ 1
+ 0
+ 1
+
+
+ 2
+ 0
+ 2
+
+
+ 3
+ 0
+ 3
+
+
+ 4
+ 0
+ 4
+
+
+ 5
+ 0
+ 5
+
+
+ 6
+ 0
+ 6
+
+
+ 7
+ 0
+ 7
+
+
+ 8
+ 0
+ 8
+
+
+ 9
+ 0
+ 9
+
+
+ 10
+ 0
+ 10
+
+
+ 11
+ 0
+ 11
+
+
+ 12
+ 0
+ 12
+
+
+ 13
+ 0
+ 13
+
+
+ 14
+ 0
+ 14
+
+
+ 15
+ 0
+ 15
+
+
+ 16
+ 0
+ 16
+
+
+ 17
+ 0
+ 17
+
+
+ 18
+ 0
+ 18
+
+
+ 19
+ 0
+ 19
+
+
+ 20
+ 0
+ 20
+
+
+ 21
+ 0
+ 21
+
+
+ 22
+ 0
+ 22
+
+
+ 23
+ 0
+ 23
+
+
+ 24
+ 0
+ 24
+
+
+ 25
+ 0
+ 25
+
+
+ 26
+ 0
+ 26
+
+
+ 27
+ 0
+ 27
+
+
+ 28
+ 0
+ 28
+
+
+ 29
+ 0
+ 29
+
+
+ 30
+ 0
+ 30
+
+
+ 31
+ 0
+ 31
+
+
+ 32
+ 0
+ 32
+
+
+ 33
+ 0
+ 33
+
+
+ 34
+ 0
+ 34
+
+
+ 35
+ 0
+ 35
+
+
+ 36
+ 0
+ 36
+
+
+ 37
+ 0
+ 37
+
+
+ 38
+ 0
+ 38
+
+
+ 39
+ 0
+ 39
+
+
+ 40
+ 0
+ 40
+
+
+ 41
+ 0
+ 41
+
+
+ 42
+ 0
+ 42
+
+
+ 43
+ 0
+ 43
+
+
+ 44
+ 0
+ 44
+
+
+ 45
+ 0
+ 45
+
+
+ 46
+ 0
+ 46
+
+
+ 47
+ 0
+ 47
+
+
+ 48
+ 0
+ 48
+
+
+ 49
+ 0
+ 49
+
+
+ 50
+ 0
+ 50
+
+
+ 51
+ 0
+ 51
+
+
+ 52
+ 0
+ 52
+
+
+ 53
+ 0
+ 53
+
+
+
+ 8
+ 0
+ 0
+ 64
+ 8
+ 8
+ 1024
+ 0
+
+
+
+ 0
+
+
+ 2048
+
+
+
+
\ No newline at end of file
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/hwsku.json b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/hwsku.json
new file mode 100644
index 0000000000..362f53a7c1
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/hwsku.json
@@ -0,0 +1,214 @@
+{
+ "interfaces": {
+ "Ethernet0": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet1": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet2": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet3": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet4": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet5": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet6": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet7": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet8": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet9": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet10": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet11": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet12": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet13": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet14": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet15": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet16": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet17": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet18": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet19": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet20": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet21": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet22": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet23": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet24": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet25": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet26": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet27": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet28": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet29": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet30": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet31": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet32": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet33": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet34": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet35": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet36": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet37": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet38": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet39": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet40": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet41": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet42": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet43": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet44": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet45": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet46": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet47": {
+ "default_brkout_mode": "1x1000[100,10]",
+ "port_type": "RJ45"
+ },
+ "Ethernet48": {
+ "default_brkout_mode": "1x25G[10G]"
+ },
+ "Ethernet49": {
+ "default_brkout_mode": "1x25G[10G]"
+ },
+ "Ethernet50": {
+ "default_brkout_mode": "1x25G[10G]"
+ },
+ "Ethernet51": {
+ "default_brkout_mode": "1x25G[10G]"
+ },
+ "Ethernet52": {
+ "default_brkout_mode": "1x25G[10G]"
+ },
+ "Ethernet53": {
+ "default_brkout_mode": "1x25G[10G]"
+ }
+ }
+}
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/platform.ini b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/platform.ini
new file mode 100644
index 0000000000..782144317a
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/platform.ini
@@ -0,0 +1 @@
+# Port lane speed DC BW HF LF sqlch minLf maxLf minHf maxHf
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/port_config.ini b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/port_config.ini
new file mode 100644
index 0000000000..003307d32f
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/port_config.ini
@@ -0,0 +1,55 @@
+# name lanes alias speed autoneg fec index
+Ethernet0 0 Gi0/1 1000 on none 1
+Ethernet1 1 Gi0/2 1000 on none 2
+Ethernet2 2 Gi0/3 1000 on none 3
+Ethernet3 3 Gi0/4 1000 on none 4
+Ethernet4 4 Gi0/5 1000 on none 5
+Ethernet5 5 Gi0/6 1000 on none 6
+Ethernet6 6 Gi0/7 1000 on none 7
+Ethernet7 7 Gi0/8 1000 on none 8
+Ethernet8 8 Gi0/9 1000 on none 9
+Ethernet9 9 Gi0/10 1000 on none 10
+Ethernet10 10 Gi0/11 1000 on none 11
+Ethernet11 11 Gi0/12 1000 on none 12
+Ethernet12 12 Gi0/13 1000 on none 13
+Ethernet13 13 Gi0/14 1000 on none 14
+Ethernet14 14 Gi0/15 1000 on none 15
+Ethernet15 15 Gi0/16 1000 on none 16
+Ethernet16 16 Gi0/17 1000 on none 17
+Ethernet17 17 Gi0/18 1000 on none 18
+Ethernet18 18 Gi0/19 1000 on none 19
+Ethernet19 19 Gi0/20 1000 on none 20
+Ethernet20 20 Gi0/21 1000 on none 21
+Ethernet21 21 Gi0/22 1000 on none 22
+Ethernet22 22 Gi0/23 1000 on none 23
+Ethernet23 23 Gi0/24 1000 on none 24
+Ethernet24 24 Gi0/25 1000 on none 25
+Ethernet25 25 Gi0/26 1000 on none 26
+Ethernet26 26 Gi0/27 1000 on none 27
+Ethernet27 27 Gi0/28 1000 on none 28
+Ethernet28 28 Gi0/29 1000 on none 29
+Ethernet29 29 Gi0/30 1000 on none 30
+Ethernet30 30 Gi0/31 1000 on none 31
+Ethernet31 31 Gi0/32 1000 on none 32
+Ethernet32 32 Gi0/33 1000 on none 33
+Ethernet33 33 Gi0/34 1000 on none 34
+Ethernet34 34 Gi0/35 1000 on none 35
+Ethernet35 35 Gi0/36 1000 on none 36
+Ethernet36 36 Gi0/37 1000 on none 37
+Ethernet37 37 Gi0/38 1000 on none 38
+Ethernet38 38 Gi0/39 1000 on none 39
+Ethernet39 39 Gi0/40 1000 on none 40
+Ethernet40 40 Gi0/41 1000 on none 41
+Ethernet41 41 Gi0/42 1000 on none 42
+Ethernet42 42 Gi0/43 1000 on none 43
+Ethernet43 43 Gi0/44 1000 on none 44
+Ethernet44 44 Gi0/45 1000 on none 45
+Ethernet45 45 Gi0/46 1000 on none 46
+Ethernet46 46 Gi0/47 1000 on none 47
+Ethernet47 47 Gi0/48 1000 on none 48
+Ethernet48 48 Fx0/1 25000 on rs 49
+Ethernet49 49 Fx0/2 25000 on rs 50
+Ethernet50 50 Fx0/3 25000 on rs 51
+Ethernet51 51 Fx0/4 25000 on rs 52
+Ethernet52 52 Fx0/5 25000 on rs 53
+Ethernet53 53 Fx0/6 25000 on rs 54
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/profile.ini b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/profile.ini
new file mode 100644
index 0000000000..16600d34e6
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/profile.ini
@@ -0,0 +1,7 @@
+switchMacAddress=00:01:02:03:04:05
+portListWithCableLen=000:1 001:1 002:1 003:1 004:1 005:1 006:1 007:1 008:1 009:1 010:1 011:1 012:1 013:1 014:1 015:1 016:1 017:1 018:1 019:1 020:1 021:1 022:1 023:1 024:1 025:1 026:1 027:1 028:1 029:1 030:1 031:1 032:1 033:1 034:1 035:1 036:1 037:1 038:1 039:1 040:1 041:1 042:1 043:1 044:1 045:1 046:1 047:1 048:1 049:1 050:1 051:1 052:1 053:1
+platformConfigFile=/usr/share/sonic/hwsku/platform.ini
+lpm_fdb_em_profile=MID_L3_MID_L2_NO_EM
+l3_counter_index_base=0 2K
+pbrMaxEntries=0
+SAI_NUM_ECMP_MEMBERS=64
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/sai.profile b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/sai.profile
new file mode 100644
index 0000000000..2f3febd68e
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/sai.profile
@@ -0,0 +1,4 @@
+mode=1
+hwId=AC5XG3748
+switchProfile=/usr/share/sonic/hwsku/SAI-AC5X-G3748.xml
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/profile.ini
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/system_health_monitoring_config.json b/device/supermicro/arm64-supermicro_sse_g3748-r0/system_health_monitoring_config.json
new file mode 100644
index 0000000000..d5f3a7b983
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/system_health_monitoring_config.json
@@ -0,0 +1,14 @@
+{
+ "services_to_ignore": [],
+ "devices_to_ignore": [
+ "asic",
+ "psu.temperature"
+ ],
+ "user_defined_checkers": [],
+ "polling_interval": 60,
+ "led_color": {
+ "fault": "amber",
+ "normal": "green",
+ "booting": "blinking green"
+ }
+}
diff --git a/device/supermicro/arm64-supermicro_sse_g3748-r0/thermal_policy.json b/device/supermicro/arm64-supermicro_sse_g3748-r0/thermal_policy.json
new file mode 100644
index 0000000000..7757303c54
--- /dev/null
+++ b/device/supermicro/arm64-supermicro_sse_g3748-r0/thermal_policy.json
@@ -0,0 +1,65 @@
+{
+ "thermal_control_algorithm": {
+ "run_at_boot_up": "false",
+ "fan_speed_when_suspend": "50"
+ },
+ "info_types": [
+ {
+ "type": "fan_info"
+ },
+ {
+ "type": "thermal_info"
+ },
+ {
+ "type": "chassis_info"
+ }
+ ],
+ "policies": [
+ {
+ "name": "any fan absence",
+ "conditions": [
+ {
+ "type": "fan.any.absence"
+ }
+ ],
+ "actions": [
+ {
+ "type": "thermal_control.control",
+ "status": "false"
+ },
+ {
+ "type": "fan.all.set_speed",
+ "speed": "100"
+ }
+ ]
+ },
+ {
+ "name": "all fan presence",
+ "conditions": [
+ {
+ "type": "fan.all.presence"
+ }
+ ],
+ "actions": [
+ {
+ "type": "thermal.temp_check_and_set_all_fan_speed",
+ "default_speed": "25",
+ "hightemp_speed": "100"
+ }
+ ]
+ },
+ {
+ "name": "temp over high critical threshold",
+ "conditions": [
+ {
+ "type": "thermal.over.high_critical_threshold"
+ }
+ ],
+ "actions": [
+ {
+ "type": "switch.shutdown"
+ }
+ ]
+ }
+ ]
+}
diff --git a/platform/marvell-arm64/one-image.mk b/platform/marvell-arm64/one-image.mk
index 1aa36f2b1d..41aa274c86 100644
--- a/platform/marvell-arm64/one-image.mk
+++ b/platform/marvell-arm64/one-image.mk
@@ -7,7 +7,8 @@ $(SONIC_ONE_IMAGE)_INSTALLS += $(SYSTEMD_SONIC_GENERATOR)
$(SONIC_ONE_IMAGE)_INSTALLS += $(MRVL_PRESTERA_DEB)
$(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(NOKIA_7215_PLATFORM) \
$(AC5X_RD98DX35xx_PLATFORM) \
- $(AC5X_RD98DX35xxCN9131_PLATFORM)
+ $(AC5X_RD98DX35xxCN9131_PLATFORM) \
+ $(SUPERMICRO_SSE_G3748_PLATFORM_MODULE)
ifeq ($(INSTALL_DEBUG_TOOLS),y)
$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES)
$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES))
diff --git a/platform/marvell-arm64/platform-modules-supermicro.mk b/platform/marvell-arm64/platform-modules-supermicro.mk
new file mode 100644
index 0000000000..874a1129bc
--- /dev/null
+++ b/platform/marvell-arm64/platform-modules-supermicro.mk
@@ -0,0 +1,12 @@
+# Supermicro SSE-G3748 (using AC5X) Platform modules
+
+SUPERMICRO_SSE_G3748_PLATFORM_MODULE_VERSION=1.0
+
+export SUPERMICRO_SSE_G3748_PLATFORM_MODULE_VERSION
+
+SUPERMICRO_SSE_G3748_PLATFORM_MODULE = sonic-platform-supermicro-sse-g3748_$(SUPERMICRO_SSE_G3748_PLATFORM_MODULE_VERSION)_$(CONFIGURED_ARCH).deb
+$(SUPERMICRO_SSE_G3748_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-supermicro
+$(SUPERMICRO_SSE_G3748_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_COMMON)
+$(SUPERMICRO_SSE_G3748_PLATFORM_MODULE)_PLATFORM = arm64-supermicro_sse_g3748-r0
+SONIC_DPKG_DEBS += $(SUPERMICRO_SSE_G3748_PLATFORM_MODULE)
+
diff --git a/platform/marvell-arm64/platform.conf b/platform/marvell-arm64/platform.conf
index a11314acf8..96c85f94f6 100644
--- a/platform/marvell-arm64/platform.conf
+++ b/platform/marvell-arm64/platform.conf
@@ -40,6 +40,9 @@ case $PLATFORM in
arm64-marvell_rd98DX35xx_cn9131-r0) PLATFORM_CN9131=1;
fdt_fname="/boot/cn9131-db-comexpress.dtb";
fit_conf_name="#conf_cn9131";;
+ arm64-supermicro_sse_g3748-r0) PLATFORM_AC5X=2;
+ fdt_fname="/usr/lib/linux-image-${kernel_version}/marvell/smc_sse-g3748.dtb";
+ fit_conf_name="#conf_smc_sse-g3748";;
esac
if [ $PLATFORM_AC5X -eq 1 ]; then
@@ -57,6 +60,39 @@ elif [ $PLATFORM_CN9131 -eq 1 ]; then
demo_part=2
FW_ENV_DEFAULT='/dev/mtd1 0x1F0000 0x10000 0x10000'
mmc_bus="mmc0:0001"
+lif [ $PLATFORM_AC5X -eq 2 ]; then
+ fdt_addr=0x201000000
+ fit_addr=0x210000000
+ initrd_addr=0x206000000
+
+ #---------------------------------------------------------------
+ # device name offset Env size sector size
+ # ----------- ------- -------- -----------
+ FW_ENV_DEFAULT='/dev/mtd1 0x000000 0x10000 0x10000'
+ demo_part=2
+ mmc_bus="mmc0:0001"
+
+ onie_part_size=168M
+ onie_part_num=1
+ onie_part_label=ONIE
+
+ sonic_part_num=2
+ sonic_part_label=SONiC-OS
+
+ swap_part_size=3G
+ swap_part_num=3
+ swap_part_label=swap
+
+ debug_part_size=2G
+ debug_swap_part_size=5G
+ debug_part_num=4
+ debug_part_label=DEBUG
+
+ current_image_dir=""
+ current_image_name=""
+ current_fdt_name=""
+ current_fit_name=""
+ current_sonic_version_1=""
else
fdt_addr=0x1000000
fit_addr=0x8000000
@@ -110,15 +146,86 @@ remove_dev_partitions() {
}
create_demo_partition() {
- # SD CARD
- remove_dev_partitions
+ if [ $PLATFORM_AC5X -eq 2 ]; then
+ onie_part=$(sgdisk -p "$blk_dev" | grep -e "$onie_part_label" | awk '{print $1}')
+ sonic_part=$(sgdisk -p "$blk_dev" | grep -e "$sonic_part_label" | awk '{print $1}')
+ swap_part=$(sgdisk -p "$blk_dev" | grep -e "$swap_part_label" | awk '{print $1}')
+ debug_part=$(sgdisk -p "$blk_dev" | grep -e "$debug_part_label" | awk '{print $1}')
- # Create sonic partition
- sgdisk --new ${demo_part}:: \
- --change-name=${demo_part}:${demo_volume_label} \
- --typecode=${demo_part}:8300 -p ${blk_dev}
+ if [ -z "$onie_part" ]
+ then
+ echo "Partitioning is Incorrect. Re-partitioning"
+ sgdisk -oZ ${blk_dev}
- partprobe
+ sgdisk --new ${onie_part_num}:0:+${onie_part_size} \
+ --change-name=${onie_part_num}:${onie_part_label} \
+ --typecode=${onie_part_num}:8300 -p ${blk_dev}
+
+ if [ $? -ne 0 ]; then
+ echo "Failed creating onie eMMC partition"
+ return 2
+ fi
+
+ mkfs.ext4 -F -L ${onie_part_label} ${blk_dev}p${onie_part_num}
+ else
+ fsck.ext4 -v -p ${blk_dev}p${onie_part_num}
+ fi
+
+ if [ -z "$debug_part" ]; then
+ # Create debug partition
+ sgdisk --new ${debug_part_num}:-${debug_part_size}: \
+ --change-name=${debug_part_num}:${debug_part_label} \
+ --typecode=${debug_part_num}:8300 -p ${blk_dev}
+
+ mkfs.ext4 -F -L ${debug_part_label} ${blk_dev}p${debug_part_num}
+ else
+ fsck.ext4 -v -p ${blk_dev}p${debug_part_num}
+ fi
+
+ if [ -z "$swap_part" ]; then
+ # Create swap partition
+ swap_start_num=-${debug_swap_part_size}
+ swap_end_num=-${debug_part_size}
+ #sgdisk --new ${swap_part_num}:-${swap_part_size}: \
+ sgdisk --new ${swap_part_num}:${swap_start_num}:${swap_end_num} \
+ --change-name=${swap_part_num}:${swap_part_label} \
+ --typecode=${swap_part_num}:8200 -p ${blk_dev}
+ fi
+
+ if [ -z "$sonic_part" ]; then
+ # Create sonic partition
+ start_num=$(sgdisk -F $blk_dev)
+ end_num=$(sgdisk -E $blk_dev)
+
+ sgdisk --new ${sonic_part_num}:${start_num}:${end_num} \
+ --change-name=${sonic_part_num}:${sonic_part_label} \
+ --typecode=${sonic_part_num}:8300 -p ${blk_dev}
+
+ mkfs.ext4 -F -L ${sonic_part_label} ${blk_dev}p${sonic_part_num}
+ else
+ mkfs.ext4 -F -L ${sonic_part_label} ${blk_dev}p${sonic_part_num}
+ fi
+
+ partprobe
+ sync
+
+ mkswap ${blk_dev}p${swap_part_num}
+ echo "${blk_dev}p${swap_part_num} swap swap defaults 0 0" > /etc/fstab
+ swapon -a
+
+ return 0
+
+ else
+ # SD CARD
+ remove_dev_partitions
+
+ # Create sonic partition
+ sgdisk --new ${demo_part}:: \
+ --change-name=${demo_part}:${demo_volume_label} \
+ --typecode=${demo_part}:8300 -p ${blk_dev}
+
+ partprobe
+ fi
}
create_partition() {
@@ -171,6 +278,13 @@ prepare_boot_menu() {
initrd_name=${image_dir}${initrd_fname}
fdt_name=${image_dir}${fdt_fname}
fit_name=${image_dir}${fit_fname}
+ if [ $PLATFORM_AC5X -eq 2 ]; then
+ current_image_dir="image-$running_sonic_revision"
+ current_image_name=${current_image_dir}${kernel_name}
+ current_fdt_name=${current_image_dir}${fdt_fname}
+ current_fit_name=${current_image_dir}${fit_fname}
+ current_sonic_version_1="${demo_volume_label}-${running_sonic_revision}"
+ fi
if [ "$install_env" = "onie" ]; then
FW_ARG="-f"
@@ -181,12 +295,55 @@ prepare_boot_menu() {
fit_name_old=""
sonic_version_2="None"
else
- image_dir_old=$(fw_printenv -n image_dir || true)
- image_name_old=$(fw_printenv -n image_name || true)
- initrd_name_old=$(fw_printenv -n initrd_name || true)
- fdt_name_old=$(fw_printenv -n fdt_name || true)
- fit_name_old=$(fw_printenv -n fit_name || true)
- sonic_version_2=$(fw_printenv -n sonic_version_1 || true)
+ if [ $PLATFORM_AC5X -eq 2 ]; then
+ sonic_version_1=$(fw_printenv -n sonic_version_1 || true)
+ sonic_version_2=$(fw_printenv -n sonic_version_2 || true)
+ if [ "$sonic_version_1" != "NONE" ] && [ "$sonic_version_1" != "None" ]
+ then
+ if [ "$running_sonic_revision" != "None" ]
+ then
+ image_dir_old=${current_image_dir}
+ image_name_old=${current_image_name}
+ initrd_name_old=${current_initrd_name}
+ fdt_name_old=${current_fdt_name}
+ fit_name_old=${current_fit_name}
+ sonic_version_2=${current_sonic_version_1}
+ else
+ image_dir_old=$(fw_printenv -n image_dir || true)
+ image_name_old=$(fw_printenv -n image_name || true)
+ initrd_name_old=$(fw_printenv -n initrd_name || true)
+ fdt_name_old=$(fw_printenv -n fdt_name || true)
+ fit_name_old=$(fw_printenv -n fit_name || true)
+ sonic_version_2=$(fw_printenv -n sonic_version_1 || true)
+ fi
+ else
+ if [ "$sonic_version_2" != "NONE" ] && [ "$sonic_version_2" != "None" ]
+ then
+ image_dir_old=$(fw_printenv -n image_dir_old || true)
+ image_name_old=$(fw_printenv -n image_name_old || true)
+ initrd_name_old=$(fw_printenv -n initrd_name_old || true)
+ fdt_name_old=$(fw_printenv -n fdt_name_old || true)
+ fit_name_old=$(fw_printenv -n fit_name_old || true)
+ fi
+ fi
+
+ if [ -z "$demo_dev" ]; then
+ get_install_device
+ if [ $? -ne 0 ]; then
+ echo "Error: Unable to detect $blk_dev $demo_dev"
+ exit 1
+ fi
+ demo_part=${sonic_part_num}
+ demo_dev=${blk_dev}p${sonic_part_num}
+ fi
+ else
+ image_dir_old=$(fw_printenv -n image_dir || true)
+ image_name_old=$(fw_printenv -n image_name || true)
+ initrd_name_old=$(fw_printenv -n initrd_name || true)
+ fdt_name_old=$(fw_printenv -n fdt_name || true)
+ fit_name_old=$(fw_printenv -n fit_name || true)
+ sonic_version_2=$(fw_printenv -n sonic_version_1 || true)
+ fi
fi
# Set boot variables
@@ -204,14 +361,27 @@ prepare_boot_menu() {
fw_setenv ${FW_ARG} sonic_version_2 $sonic_version_2 > /dev/null
BOOT1='echo " > Boot1: $sonic_version_1 - run sonic_image_1";echo;'
BOOT2='echo " > Boot2: $sonic_version_2 - run sonic_image_2";echo;'
- BOOT3='echo " > Boot3: ONIE - run onie_boot";echo;'
- BORDER='echo "---------------------------------------------------";echo;'
- fw_setenv ${FW_ARG} print_menu $BORDER $BOOT1 $BOOT2 $BOOT3 $BORDER > /dev/null
- fw_setenv ${FW_ARG} linuxargs "net.ifnames=0 loopfstype=squashfs loop=$image_dir/$FILESYSTEM_SQUASHFS systemd.unified_cgroup_hierarchy=0 varlog_size=$VAR_LOG ${ONIE_PLATFORM_EXTRA_CMDLINE_LINUX}" > /dev/null
- fw_setenv ${FW_ARG} linuxargs_old "net.ifnames=0 loopfstype=squashfs loop=$image_dir_old/$FILESYSTEM_SQUASHFS systemd.unified_cgroup_hierarchy=0 varlog_size=$VAR_LOG ${ONIE_PLATFORM_EXTRA_CMDLINE_LINUX}" > /dev/null
- sonic_bootargs_old='setenv bootargs root='$demo_dev' rw rootwait rootfstype=ext4 panic=1 console=ttyS0,${baudrate} ${othbootargs} ${mtdparts} ${linuxargs_old}'
- fw_setenv ${FW_ARG} sonic_bootargs_old $sonic_bootargs_old > /dev/null || true
+ if [ $PLATFORM -eq 2 ]; then
+ BOOT3='echo " > Boot3: ONIE - run onie_emmc_boot";echo;'
+ BORDER='echo "---------------------------------------------------";echo;'
+ fw_setenv ${FW_ARG} print_menu "$BORDER $BOOT1 $BOOT2 $BOOT3 $BORDER" > /dev/null
+
+ fw_setenv ${FW_ARG} linuxargs "net.ifnames=0 loopfstype=squashfs loop=$image_dir/$FILESYSTEM_SQUASHFS systemd.unified_cgroup_hierarchy=0 varlog_size=$VAR_LOG ${extra_cmdline_linux} loglevel=4" > /dev/null
+ fw_setenv ${FW_ARG} linuxargs_old "net.ifnames=0 loopfstype=squashfs loop=$image_dir_old/$FILESYSTEM_SQUASHFS systemd.unified_cgroup_hierarchy=0 varlog_size=$VAR_LOG loglevel=4" > /dev/null
+ sonic_bootargs_old='setenv bootargs root='$demo_dev' rw rootwait rootfstype=ext4 panic=1 console=ttyS0,${baudrate} ${othbootargs} ${mtdparts} ${linuxargs_old}'
+ fw_setenv ${FW_ARG} sonic_bootargs_old "$sonic_bootargs_old" > /dev/null || true
+ else
+ BOOT3='echo " > Boot3: ONIE - run onie_boot";echo;'
+ BORDER='echo "---------------------------------------------------";echo;'
+ fw_setenv ${FW_ARG} print_menu $BORDER $BOOT1 $BOOT2 $BOOT3 $BORDER > /dev/null
+
+ fw_setenv ${FW_ARG} linuxargs "net.ifnames=0 loopfstype=squashfs loop=$image_dir/$FILESYSTEM_SQUASHFS systemd.unified_cgroup_hierarchy=0 varlog_size=$VAR_LOG ${ONIE_PLATFORM_EXTRA_CMDLINE_LINUX}" > /dev/null
+ fw_setenv ${FW_ARG} linuxargs_old "net.ifnames=0 loopfstype=squashfs loop=$image_dir_old/$FILESYSTEM_SQUASHFS systemd.unified_cgroup_hierarchy=0 varlog_size=$VAR_LOG ${ONIE_PLATFORM_EXTRA_CMDLINE_LINUX}" > /dev/null
+ sonic_bootargs_old='setenv bootargs root='$demo_dev' rw rootwait rootfstype=ext4 panic=1 console=ttyS0,${baudrate} ${othbootargs} ${mtdparts} ${linuxargs_old}'
+ fw_setenv ${FW_ARG} sonic_bootargs_old $sonic_bootargs_old > /dev/null || true
+ fi
+
sonic_boot_load_old=$(fw_printenv -n sonic_boot_load || true)
old_str="_old"
fw_setenv ${FW_ARG} sonic_boot_load_old "$sonic_boot_load_old$old_str" > /dev/null || true
@@ -226,13 +396,24 @@ prepare_boot_menu() {
SONIC_BOOT_CMD='run sonic_bootargs; run sonic_boot_load; bootm $fit_addr${fit_conf_name}'
SONIC_BOOT_CMD_OLD='run sonic_bootargs_old; run sonic_boot_load_old; bootm $fit_addr${fit_conf_name}'
BOOTARGS='setenv bootargs root='$demo_dev' rw rootwait rootfstype=ext4 panic=1 console=ttyS0,${baudrate} ${othbootargs} ${mtdparts} ${linuxargs}'
- fw_setenv ${FW_ARG} sonic_bootargs $BOOTARGS > /dev/null
- fw_setenv ${FW_ARG} sonic_bootcmd $SONIC_BOOT_CMD > /dev/null
- fw_setenv ${FW_ARG} sonic_image_2 $SONIC_BOOT_CMD_OLD > /dev/null
+ if [ $PLATFORM -eq 2 ]; then
+ fw_setenv ${FW_ARG} sonic_bootargs "$BOOTARGS" > /dev/null
+ fw_setenv ${FW_ARG} sonic_bootcmd "$SONIC_BOOT_CMD" > /dev/null
+ fw_setenv ${FW_ARG} sonic_image_2 "$SONIC_BOOT_CMD_OLD" > /dev/null
+ else
+ fw_setenv ${FW_ARG} sonic_bootargs $BOOTARGS > /dev/null
+ fw_setenv ${FW_ARG} sonic_bootcmd $SONIC_BOOT_CMD > /dev/null
+ fw_setenv ${FW_ARG} sonic_image_2 $SONIC_BOOT_CMD_OLD > /dev/null
+ fi
fw_setenv ${FW_ARG} sonic_image_1 "$SONIC_BOOT_CMD" > /dev/null
fw_setenv ${FW_ARG} boot_next 'run sonic_image_1'> /dev/null
- fw_setenv ${FW_ARG} bootcmd 'run print_menu; usb start; test -n "$boot_once" && run boot_once; run boot_next' > /dev/null
-
+ if [ $PLATFORM -eq 2 ]; then
+ fw_setenv ${FW_ARG} boot_once > /dev/null
+ fw_setenv ${FW_ARG} nos_bootcmd 'run print_menu; usb start; test -n "$boot_once" && run boot_once; run boot_next' > /dev/null
+ fw_setenv ${FW_ARG} bootcmd 'run diag_bootcmd; run check_boot_reason; run nos_bootcmd; run onie_bootcmd' > /dev/null
+ else
+ fw_setenv ${FW_ARG} bootcmd 'run print_menu; usb start; test -n "$boot_once" && run boot_once; run boot_next' > /dev/null
+ fi
}
bootloader_menu_config() {
diff --git a/platform/marvell-arm64/rules.mk b/platform/marvell-arm64/rules.mk
index 882a9451e9..34fc7a0f1f 100644
--- a/platform/marvell-arm64/rules.mk
+++ b/platform/marvell-arm64/rules.mk
@@ -8,6 +8,7 @@ include $(PLATFORM_PATH)/one-image.mk
include $(PLATFORM_PATH)/mrvl-prestera.mk
include $(PLATFORM_PATH)/platform-nokia.mk
include $(PLATFORM_PATH)/platform-marvell.mk
+include $(PLATFORM_PATH)/platform-modules-supermicro.mk
SONIC_ALL += $(SONIC_ONE_IMAGE) \
$(DOCKER_FPM) \
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/changelog b/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/changelog
new file mode 100644
index 0000000000..1914959d83
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/changelog
@@ -0,0 +1,6 @@
+sonic-supermicro-platform-modules (1.0) unstable; urgency=low
+
+ * Add support for Supermicro SSE-G3748
+ * Initial release
+
+ -- Supermicro Team Wed, 03 Jan 2024 09:00:00 +0800
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/compat b/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/compat
new file mode 100644
index 0000000000..ec635144f6
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/compat
@@ -0,0 +1 @@
+9
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/control b/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/control
new file mode 100644
index 0000000000..c5aaa274cd
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/control
@@ -0,0 +1,13 @@
+Source: sonic-supermicro-platform-modules
+Section: main
+Priority: extra
+Maintainer: Supermicro Team
+Build-Depends: debhelper (>=9)
+Standards-Version: 3.9.6
+Homepage:
+
+Package: sonic-platform-supermicro-sse-g3748
+Architecture: arm64
+Depends: ${misc:Depends}
+Description: Kernel modules for platform devices such as fan, led, sfp
+
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/rules b/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/rules
new file mode 100755
index 0000000000..42e43c1a30
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/rules
@@ -0,0 +1,74 @@
+#!/usr/bin/make -f
+# See debhelper(7) (uncomment to enable)
+# output every command that modifies files on the build system.
+#export DH_VERBOSE = 1
+
+include /usr/share/dpkg/pkg-info.mk
+#--------------------------------------------------------
+
+export INSTALL_MOD_DIR:=extra
+
+PACKAGE_PRE_NAME := sonic-platform-supermicro
+KVERSION ?= $(shell uname -r)
+KERNEL_SRC ?= /lib/modules/$(KVERSION)
+MOD_SRC_DIR:= $(shell pwd)
+MODULE_DIRS:= sse-g3748
+MODULE_DIR:= modules
+UTILS_DIR := utils
+SERVICE_DIR := service
+
+%:
+ dh $@ --with systemd,python3 --buildsystem=pybuild
+
+clean:
+ dh_testdir
+ dh_testroot
+ dh_clean
+
+build:
+ (for mod in $(MODULE_DIRS); do \
+ if [ $$mod = "sse-g3748" ]; then \
+ make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \
+ python3 $${mod}/setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}; \
+ echo "Finished making whl package for $$mod"; \
+ fi; \
+ done)
+
+binary: binary-arch binary-indep
+ # Nothing to do
+
+binary-arch:
+ # Nothing to do
+
+binary-indep:
+ dh_testdir
+ dh_installdirs
+
+ # Custom package commands
+ (for mod in $(MODULE_DIRS); do \
+ dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} /usr/local/bin; \
+ dh_installdirs -p$(PACKAGE_PRE_NAME)-$${mod} $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
+ cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
+ cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \
+ python2 $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \
+ python3 $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \
+ done)
+
+ # Resuming debhelper scripts
+ dh_testroot
+ dh_install
+ dh_installchangelogs
+ dh_installdocs
+ dh_systemd_enable
+ dh_installinit
+ dh_systemd_start
+ dh_link
+ dh_fixperms
+ dh_compress
+ dh_strip
+ dh_installdeb
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+.PHONY: build binary binary-arch binary-indep clean
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/sonic-platform-supermicro-sse-g3748.install b/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/sonic-platform-supermicro-sse-g3748.install
new file mode 100644
index 0000000000..f826c9dc69
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/sonic-platform-supermicro-sse-g3748.install
@@ -0,0 +1,10 @@
+sse-g3748/scripts/setup_all_ports_l2.py usr/local/bin
+sse-g3748/scripts/show-techsupport usr/local/bin
+sse-g3748/scripts/techfile_v2.py usr/local/bin
+sse-g3748/scripts/sse-g3748_plt_setup.sh usr/local/bin
+sse-g3748/scripts/entropy.py etc/
+sse-g3748/scripts/sse-g3748-init.sh usr/local/bin
+sse-g3748/scripts/reset-to-factory-default usr/local/bin
+sse-g3748/service/sse-g3748-init.service etc/systemd/system
+sse-g3748/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/arm64-supermicro_sse_g3748-r0
+sse-g3748/scripts/add_port_range usr/local/bin
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/sonic-platform-supermicro-sse-g3748.postinst b/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/sonic-platform-supermicro-sse-g3748.postinst
new file mode 100644
index 0000000000..ad6cfcc41e
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/debian/sonic-platform-supermicro-sse-g3748.postinst
@@ -0,0 +1,47 @@
+#!/bin/sh
+# postinst script for platform-modules-sse-g3748
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+# * `configure'
+# * `abort-upgrade'
+# * `abort-remove' `in-favour'
+#
+# * `abort-remove'
+# * `abort-deconfigure' `in-favour'
+# `removing'
+#
+# for details, see https://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+ configure)
+ sh /usr/local/bin/sse-g3748_plt_setup.sh
+ chmod a+x /usr/local/bin/sse-g3748-init.sh
+ chmod a+x /usr/local/bin/setup_all_ports_l2.py
+ chmod a+x /usr/local/bin/add_port_range
+ chmod a+x /usr/local/bin/reset-to-factory-default
+ systemctl enable sse-g3748-init.service
+ systemctl start sse-g3748-init.service
+
+ ;;
+
+ abort-upgrade|abort-remove|abort-deconfigure)
+ ;;
+
+ *)
+ echo "postinst called with unknown argument \`$1'" >&2
+ exit 1
+ ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/modules/Makefile b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/modules/Makefile
new file mode 100644
index 0000000000..fea5efe53a
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/modules/Makefile
@@ -0,0 +1,2 @@
+obj-m := g3748cpld.o
+obj-m += smc-i2c-mux-pca954x.o
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/modules/g3748cpld.c b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/modules/g3748cpld.c
new file mode 100644
index 0000000000..db6a592721
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/modules/g3748cpld.c
@@ -0,0 +1,818 @@
+/*
+ * g3748cpld.c - A driver for control of SMC SSE-G3748 cpld based on lm75.c
+ *
+ * Copyright (c) 1998, 1999 Frodo Looijaard
+ * Copyright (c) 2023 Supermicro
+ *
+ * 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
+
+/* Addresses scanned */
+static const unsigned short normal_i2c[] = { 0x66, I2C_CLIENT_END };
+
+/* CPLD WDT global timeout */
+static u32 gTimeout = 0;
+
+/* Size of EEPROM in bytes */
+#define CPLD_SIZE 12
+
+#define FAN_NUM 2
+#define PSU_NUM 2
+#define DEFAULT_VOLTAGE_MIN 11000
+#define DEFAULT_VOLTAGE_MAX 13000
+#define DEFAULT_VOLTAGE_LCRIT 11500
+#define DEFAULT_VOLTAGE_CRIT 12500
+
+#define G3748_CPLD_VER_REG 0x09
+//#define G3748_POWER_GOOD_REG 0x0A
+//#define G3748_PSU_PRESENT_REG 0x0A
+#define G3748_PSU_STATUS_REG 0x0A
+#define G3748_FAN_STATUS_REG 0x3B
+#define G3748_FAN_CONTROL_REG 0x3C
+#define G3748_FAN_SPEED_REG 0x3E
+#define G3748_PSU_FRONTLED_REG 0x12
+#define G3748_FAN_SYS_FRONTLED_REG 0x11
+#define G3748_WDT_TIMER_REG 0x1B
+#define G3748_WDT_CTRL_REG 0x1C
+#define G3748_WDT_INTR_CNT_MASK_REG 0x1D
+#define G3748_WDT_INTR_FLAG_REG 0x1E
+
+/* Each client has this additional data */
+struct cpld_data {
+ struct device *hwmon_dev;
+ struct i2c_client *client;
+ struct mutex update_lock;
+ char valid; /* !=0 if registers are valid */
+ unsigned long last_updated; /* In jiffies */
+ u8 data[CPLD_SIZE]; /* Register value */
+
+ u32 in[PSU_NUM]; /* Register value for PSU Voltage input value */
+ u32 in_min[PSU_NUM]; /* Register value for PSU Voltage min value */
+ u32 in_max[PSU_NUM]; /* Register value for PSU Voltage max value */
+ u32 in_crit[PSU_NUM]; /* Register value for PSU Voltage critical max value */
+ u32 in_lcrit[PSU_NUM]; /* Register value for PSU Voltage critical min value */
+
+ u32 fan[FAN_NUM]; /* Register value for FAN speed(RPM) input value */
+ u32 fan_min[FAN_NUM]; /* Register value for FAN speed(RPM) min value */
+ u32 fan_max[FAN_NUM]; /* Register value for FAN speed(RPM) max value */
+ u32 fan_target[FAN_NUM]; /* Register value for FAN desired speed(RPM) value */
+ u8 pwm[FAN_NUM]; /* Register value for Pulse Width Modulation Ctrl 0-255 255:max(100%) */
+};
+
+static int g3748cpld_read (struct cpld_data *data, u8 reg)
+{
+ int ret = -EPERM;
+ //u8 high_reg = 0x00;
+
+ mutex_lock(&data->update_lock);
+ //ret = i2c_smbus_write_byte_data (data->client, high_reg, reg);
+ ret = i2c_smbus_read_byte_data (data->client, reg);
+ mutex_unlock(&data->update_lock);
+
+ return ret;
+}
+
+static int g3748cpld_write (struct cpld_data *data, u8 reg, u8 val)
+{
+ int ret = 0;
+
+ mutex_lock(&data->update_lock);
+ ret = i2c_smbus_write_byte_data (data->client, reg, val);
+ mutex_unlock(&data->update_lock);
+
+ return ret;
+}
+
+#if 0
+static ssize_t show_hwmon_value(struct device *dev, struct device_attribute *da, char *buf)
+{
+ struct cpld_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ int index = to_sensor_dev_attr_2(da)->index;
+
+ mutex_lock(&data->update_lock);
+ data->data[0] = i2c_smbus_read_byte_data(client, index);
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%d\n", data->data[0]);
+}
+
+static ssize_t show_sysfs_value(struct device *dev, struct device_attribute *da, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->update_lock);
+ data->data[0] = i2c_smbus_read_byte_data(client, attr->index);
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%02x\n", data->data[0]);
+}
+
+static ssize_t set_hwmon_value(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
+{
+ struct cpld_data *data = dev_get_drvdata(dev);
+ struct i2c_client *client = data->client;
+ int index = to_sensor_dev_attr_2(da)->index;
+ u8 temp;
+ int error;
+
+ error = kstrtou8(buf, 10, &temp);
+ if (error)
+ return error;
+
+ mutex_lock(&data->update_lock);
+ i2c_smbus_write_byte_data(client, index, temp);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+#endif
+
+static ssize_t get_cpld_ver(struct device *dev, struct device_attribute *da, char *buf)
+{
+ int ret;
+ u8 devdata = 0;
+ struct cpld_data *data = dev_get_drvdata(dev);
+
+ ret = g3748cpld_read (data, G3748_CPLD_VER_REG);
+ if (ret < 0)
+ return sprintf(buf, "cpld read error");
+
+ devdata = (u8)ret & 0xff;
+ return sprintf(buf, "0x%02X\n", devdata);
+}
+
+static ssize_t get_power_good(struct device *dev, struct device_attribute *da, char *buf)
+{
+ int ret;
+ u8 devdata = 0;
+ struct cpld_data *data = dev_get_drvdata(dev);
+ int index = to_sensor_dev_attr_2(da)->index;
+
+ //ret = g3748cpld_read (data, G3748_POWER_GOOD_REG);
+ ret = g3748cpld_read (data, G3748_PSU_STATUS_REG);
+ if (ret < 0)
+ return sprintf(buf, "cpld read error");
+
+ if (index == 1) {
+ devdata = (u8)ret & 0x04;
+ } else if (index == 2) {
+ devdata = (u8)ret & 0x08;
+ }
+
+ return sprintf(buf, "%s\n", (devdata == 0)? "12000":"0");
+}
+
+static ssize_t get_psu_status(struct device *dev, struct device_attribute *da, char *buf)
+{
+ int ret;
+ //u8 devdata = 0;
+ struct cpld_data *data = dev_get_drvdata(dev);
+ //int index = to_sensor_dev_attr_2(da)->index;
+
+ ret = g3748cpld_read (data, G3748_PSU_STATUS_REG);
+ if (ret < 0)
+ return sprintf(buf, "cpld psu status read error");
+
+ //if (index == 1) {
+ // devdata = (u8)ret & 0x01;
+ //} else if (index == 2) {
+ // devdata = (u8)ret & 0x02;
+ //}
+
+ return sprintf(buf, "%d\n", (u8)ret);
+}
+
+static void initCpldDataReg (struct cpld_data *data)
+{
+ if (data != NULL) {
+ data->in_min[0] = data->in_min[1] = DEFAULT_VOLTAGE_MIN;
+ data->in_max[0] = data->in_max[1] = DEFAULT_VOLTAGE_MAX;
+ data->in_lcrit[0] = data->in_lcrit[1] = DEFAULT_VOLTAGE_LCRIT;
+ data->in_crit[0] = data->in_crit[1] = DEFAULT_VOLTAGE_CRIT;
+ }
+}
+
+static ssize_t get_voltage_limit(struct device *dev, struct device_attribute *da, char *buf)
+{
+ struct cpld_data *data = dev_get_drvdata(dev);
+ int index = to_sensor_dev_attr_2(da)->index;
+ u32 inData = 0;
+ //ret = g3748cpld_read (data, G3748_PSU_PRESENT_REG);
+ //if (ret < 0)
+ // return sprintf(buf, "cpld read error");
+
+ /* Register data read from our cpld_data structure storage area */
+ if ((index == 11) || (index == 12)) {
+ /* Read for in1_min or in2_min */
+ inData = data->in_min[index - 11];
+ } else if ((index == 21) || (index == 22)) {
+ /* Read for in1_max or in2_max */
+ inData = data->in_max[index - 21];
+ } else if ((index == 31) || (index == 32)) {
+ /* Read for in1_lcrit or in2_lcrit */
+ inData = data->in_lcrit[index - 31];
+ } else if ((index == 41) || (index == 42)) {
+ /* Read for in1_crit or in2_crit */
+ inData = data->in_crit[index - 41];
+ }
+
+ return sprintf(buf, "%d\n", (int)inData);
+}
+
+static ssize_t set_voltage_limit(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
+{
+ struct cpld_data *data = dev_get_drvdata(dev);
+ int index = to_sensor_dev_attr_2(da)->index;
+ u32 inData = 0;
+ int error;
+
+ error = kstrtou32(buf, 10, &inData);
+ if (error)
+ return error;
+
+ /* Register data read from our cpld_data structure storage area */
+ if ((index == 11) || (index == 12)) {
+ /* write in1_min or in2_min */
+ data->in_min[index - 11] = inData;
+ } else if ((index == 21) || (index == 22)) {
+ /* write in1_max or in2_max */
+ data->in_max[index - 21] = inData;
+ } else if ((index == 31) || (index == 32)) {
+ /* write in1_lcrit or in2_lcrit */
+ data->in_lcrit[index - 31] = inData;
+ } else if ((index == 41) || (index == 42)) {
+ /* Read for in1_crit or in2_crit */
+ data->in_crit[index - 41] = inData;
+ }
+
+ return count;
+}
+
+static ssize_t get_fan_status(struct device *dev, struct device_attribute *da, char *buf)
+{
+ int ret = 0;
+ //u8 devdata = 0;
+ struct cpld_data *data = dev_get_drvdata(dev);
+ //int index = to_sensor_dev_attr_2(da)->index;
+
+ ret = g3748cpld_read (data, G3748_FAN_STATUS_REG);
+ if (ret < 0)
+ return sprintf(buf, "cpld fan status read error");
+
+ //if (index == 1) {
+ // devdata = (u8)ret & 0x04;
+ //} else if (index == 2) {
+ // devdata = (u8)ret & 0x08;
+ //}
+
+ return sprintf(buf, "%d\n", (u8)ret);
+}
+
+static ssize_t get_fan_fault(struct device *dev, struct device_attribute *da, char *buf)
+{
+ int ret = 0;
+ u8 fault = 0;
+ struct cpld_data *data = dev_get_drvdata(dev);
+ int index = to_sensor_dev_attr_2(da)->index;
+
+ ret = g3748cpld_read (data, G3748_FAN_STATUS_REG);
+ if (ret < 0)
+ return sprintf(buf, "ERR: fan status read");
+
+ if (index == 1) {
+ if (((u8)ret & 0x04) == 0) {
+ fault = 1; /* not present */
+ }
+ } else if (index == 2) {
+ if (((u8)ret & 0x084) == 0) {
+ fault = 1; /* not present */
+ }
+ }
+
+ return sprintf(buf, "%d\n", fault);
+}
+
+static ssize_t get_fan_speed(struct device *dev, struct device_attribute *da, char *buf)
+{
+ int ret, rpm;
+ //u8 devdata = 0;
+ struct cpld_data *data = dev_get_drvdata(dev);
+ int index = to_sensor_dev_attr_2(da)->index;
+
+ ret = g3748cpld_read (data, (G3748_FAN_SPEED_REG + index - 1));
+ if (ret < 0)
+ return sprintf(buf, "ERR");
+
+ rpm = (5000 * 60) / ret;
+
+ return sprintf(buf, "%d\n", rpm);
+}
+
+/* G3748 FAN Control Register:
+ * Register value -- total 32 steps (0-31(0x1f)) to control system FAN PWM value (0% to 100%)
+ * RPM -- 0x00:0rpm, 0x0F:8800rpm, 0x1F:17600rpm.
+ * PWM -- 0x00:0%, 0x0F:50%, 0x1F:100%
+ */
+static ssize_t get_fan_pwm(struct device *dev, struct device_attribute *da, char *buf)
+{
+ int ret;
+ //u8 devdata = 0;
+ struct cpld_data *data = dev_get_drvdata(dev);
+ int index = to_sensor_dev_attr_2(da)->index;
+ u8 pwm;
+
+ ret = g3748cpld_read (data, (G3748_FAN_CONTROL_REG + index - 1));
+ if (ret < 0)
+ return sprintf(buf, "cpld fan ctrl read error");
+
+ ret = ret & 0x1F;
+ if (ret == 0x1F) {
+ pwm = 100;
+ } else if (ret == 0) {
+ pwm = 0;
+ } else {
+ pwm = (u8)((ret * 100) / 31);
+ }
+
+ return sprintf(buf, "%d\n", pwm);
+}
+
+static ssize_t set_fan_pwm(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
+{
+ struct cpld_data *data = dev_get_drvdata(dev);
+ //struct i2c_client *client = data->client;
+ int index = to_sensor_dev_attr_2(da)->index;
+ u8 temp;
+ int error;
+ u8 regVal = 0;
+
+ error = kstrtou8(buf, 10, &temp);
+ if (error)
+ return error;
+ if (temp > 100) {
+ temp = 100;
+ } else if (temp < 0) {
+ temp = 0;
+ }
+ regVal = (u8)((int)temp * 31 / 100);
+
+ g3748cpld_write (data, (G3748_FAN_CONTROL_REG + index - 1), regVal);
+
+ return count;
+}
+
+static ssize_t get_fan_target(struct device *dev, struct device_attribute *da, char *buf)
+{
+ int ret;
+ //u8 devdata = 0;
+ struct cpld_data *data = dev_get_drvdata(dev);
+ int index = to_sensor_dev_attr_2(da)->index;
+ int rpm;
+
+ ret = g3748cpld_read (data, (G3748_FAN_CONTROL_REG + index - 1));
+ if (ret < 0)
+ return sprintf(buf, "cpld fan ctrl read error");
+
+ ret = ret & 0x1F;
+ if (ret == 0x1F) {
+ rpm = 17600;
+ } else if (ret == 0) {
+ rpm = 0;
+ } else {
+ rpm = (ret * 17600) / 31;
+ }
+
+ return sprintf(buf, "%d\n", rpm);
+}
+
+static ssize_t set_fan_target(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
+{
+ struct cpld_data *data = dev_get_drvdata(dev);
+ //struct i2c_client *client = data->client;
+ int index = to_sensor_dev_attr_2(da)->index;
+ int temp;
+ int error;
+ u8 regVal = 0;
+
+ error = kstrtou32(buf, 10, (u32 *)&temp);
+ if (error)
+ return error;
+ if (temp > 17600) {
+ temp = 17600;
+ } else if (temp < 0) {
+ temp = 0;
+ }
+ regVal = (u8)((temp * 31) / 17600);
+
+ g3748cpld_write (data, (G3748_FAN_CONTROL_REG + index - 1), regVal);
+
+ return count;
+}
+
+static ssize_t get_psu_frontled_reg(struct device *dev, struct device_attribute *da, char *buf)
+{
+ int ret;
+ struct cpld_data *data = dev_get_drvdata(dev);
+
+ ret = g3748cpld_read (data, G3748_PSU_FRONTLED_REG);
+ if (ret < 0) {
+ return sprintf(buf, "ERR: psu reg read");
+ }
+
+ return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t set_psu_frontled_reg(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
+{
+ struct cpld_data *data = dev_get_drvdata(dev);
+ u8 temp;
+ int error;
+
+ error = kstrtou8(buf, 10, &temp);
+ if (error) {
+ return error;
+ }
+
+ g3748cpld_write (data, G3748_PSU_FRONTLED_REG, temp);
+
+ return count;
+}
+
+static ssize_t get_fan_sys_frontled_reg(struct device *dev, struct device_attribute *da, char *buf)
+{
+ int ret;
+ struct cpld_data *data = dev_get_drvdata(dev);
+
+ ret = g3748cpld_read (data, G3748_FAN_SYS_FRONTLED_REG);
+ if (ret < 0) {
+ return sprintf(buf, "ERR: fan_sys reg read");
+ }
+
+ return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t set_fan_sys_frontled_reg(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
+{
+ struct cpld_data *data = dev_get_drvdata(dev);
+ u8 temp;
+ int error;
+
+ error = kstrtou8(buf, 10, &temp);
+ if (error) {
+ return error;
+ }
+
+ g3748cpld_write (data, G3748_FAN_SYS_FRONTLED_REG, temp);
+
+ return count;
+}
+
+static ssize_t get_wdt_timer_reg(struct device *dev, struct device_attribute *da, char *buf)
+{
+ int ret;
+ struct cpld_data *data = dev_get_drvdata(dev);
+
+ ret = g3748cpld_read (data, G3748_WDT_TIMER_REG);
+ if (ret < 0) {
+ return sprintf(buf, "ERR: WDT Timer reg read");
+ }
+
+ return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t set_wdt_timer_reg(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
+{
+ struct cpld_data *data = dev_get_drvdata(dev);
+ u8 temp;
+ int error;
+
+ error = kstrtou8(buf, 10, &temp);
+ if (error) {
+ return error;
+ }
+
+ g3748cpld_write (data, G3748_WDT_TIMER_REG, temp);
+
+ return count;
+}
+
+static ssize_t get_wdt_ctrl_reg(struct device *dev, struct device_attribute *da, char *buf)
+{
+ int ret;
+ struct cpld_data *data = dev_get_drvdata(dev);
+
+ ret = g3748cpld_read (data, G3748_WDT_CTRL_REG);
+ if (ret < 0) {
+ return sprintf(buf, "ERR: WDT Ctrl reg read");
+ }
+
+ return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t set_wdt_ctrl_reg(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
+{
+ struct cpld_data *data = dev_get_drvdata(dev);
+ u8 temp;
+ int error;
+
+ error = kstrtou8(buf, 10, &temp);
+ if (error) {
+ return error;
+ }
+
+ g3748cpld_write (data, G3748_WDT_CTRL_REG, temp);
+
+ return count;
+}
+
+static ssize_t get_wdt_intr_cnt_mask_reg(struct device *dev, struct device_attribute *da, char *buf)
+{
+ int ret;
+ struct cpld_data *data = dev_get_drvdata(dev);
+
+ ret = g3748cpld_read (data, G3748_WDT_INTR_CNT_MASK_REG);
+ if (ret < 0) {
+ return sprintf(buf, "ERR: WDT Intr Count Mask reg read");
+ }
+
+ return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t set_wdt_intr_cnt_mask_reg(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
+{
+ struct cpld_data *data = dev_get_drvdata(dev);
+ u8 temp;
+ int error;
+
+ error = kstrtou8(buf, 10, &temp);
+ if (error) {
+ return error;
+ }
+
+ g3748cpld_write (data, G3748_WDT_INTR_CNT_MASK_REG, temp);
+
+ return count;
+}
+
+static ssize_t get_wdt_intr_flag_reg(struct device *dev, struct device_attribute *da, char *buf)
+{
+ int ret;
+ struct cpld_data *data = dev_get_drvdata(dev);
+
+ ret = g3748cpld_read (data, G3748_WDT_INTR_FLAG_REG);
+ if (ret < 0) {
+ return sprintf(buf, "ERR: WDT Intr Flag reg read");
+ }
+
+ return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t set_wdt_intr_flag_reg(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
+{
+ struct cpld_data *data = dev_get_drvdata(dev);
+ u8 temp;
+ int error;
+
+ error = kstrtou8(buf, 10, &temp);
+ if (error) {
+ return error;
+ }
+
+ g3748cpld_write (data, G3748_WDT_INTR_FLAG_REG, temp);
+
+ return count;
+}
+
+static ssize_t get_wdt_timeout(struct device *dev, struct device_attribute *da, char *buf)
+{
+ return sprintf(buf, "%u\n", gTimeout);
+}
+
+static ssize_t set_wdt_timeout(struct device *dev, struct device_attribute *da, const char *buf, size_t count)
+{
+ struct cpld_data *data = dev_get_drvdata(dev);
+ u32 temp;
+ int error;
+
+ error = kstrtou32(buf, 10, &temp);
+ if (error) {
+ return error;
+ }
+
+ gTimeout = temp;
+
+ return count;
+}
+
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, get_power_good, NULL, 1); /* PSU1 voltage (power good) */
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, get_power_good, NULL, 2); /* PSU2 voltage (power good) */
+static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR, get_voltage_limit, set_voltage_limit, 11); /* PSU1 voltage min */
+static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO | S_IWUSR, get_voltage_limit, set_voltage_limit, 12); /* PSU2 voltage min */
+static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR, get_voltage_limit, set_voltage_limit, 21); /* PSU1 voltage max */
+static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO | S_IWUSR, get_voltage_limit, set_voltage_limit, 22); /* PSU2 voltage max */
+static SENSOR_DEVICE_ATTR(in1_lcrit, S_IRUGO | S_IWUSR, get_voltage_limit, set_voltage_limit, 31); /* PSU1 voltage lcrit */
+static SENSOR_DEVICE_ATTR(in2_lcrit, S_IRUGO | S_IWUSR, get_voltage_limit, set_voltage_limit, 32); /* PSU2 voltage lcrit */
+static SENSOR_DEVICE_ATTR(in1_crit, S_IRUGO | S_IWUSR, get_voltage_limit, set_voltage_limit, 41); /* PSU1 voltage crit */
+static SENSOR_DEVICE_ATTR(in2_crit, S_IRUGO | S_IWUSR, get_voltage_limit, set_voltage_limit, 42); /* PSU2 voltage crit */
+
+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_fan_pwm, set_fan_pwm, 1);
+static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, get_fan_pwm, set_fan_pwm, 1);
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan_speed, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan_speed, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, get_fan_target, set_fan_target, 1);
+static SENSOR_DEVICE_ATTR(fan2_target, S_IRUGO | S_IWUSR, get_fan_target, set_fan_target, 1);
+static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, get_fan_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, get_fan_fault, NULL, 2);
+
+static struct attribute *cpld_hwmon_attrs[] = {
+ &sensor_dev_attr_in1_input.dev_attr.attr,
+ &sensor_dev_attr_in2_input.dev_attr.attr,
+ &sensor_dev_attr_in1_min.dev_attr.attr,
+ &sensor_dev_attr_in2_min.dev_attr.attr,
+ &sensor_dev_attr_in1_max.dev_attr.attr,
+ &sensor_dev_attr_in2_max.dev_attr.attr,
+ &sensor_dev_attr_in1_lcrit.dev_attr.attr,
+ &sensor_dev_attr_in2_lcrit.dev_attr.attr,
+ &sensor_dev_attr_in1_crit.dev_attr.attr,
+ &sensor_dev_attr_in2_crit.dev_attr.attr,
+
+ &sensor_dev_attr_pwm1.dev_attr.attr,
+ &sensor_dev_attr_pwm2.dev_attr.attr,
+ &sensor_dev_attr_fan1_input.dev_attr.attr,
+ &sensor_dev_attr_fan2_input.dev_attr.attr,
+ &sensor_dev_attr_fan1_target.dev_attr.attr,
+ &sensor_dev_attr_fan2_target.dev_attr.attr,
+ &sensor_dev_attr_fan1_fault.dev_attr.attr,
+ &sensor_dev_attr_fan2_fault.dev_attr.attr,
+ NULL
+};
+
+ATTRIBUTE_GROUPS(cpld_hwmon);
+#if 0
+static const struct attribute_group cpld_hwmon_group = {
+ .attrs = cpld_hwmon_attrs,
+};
+#endif
+
+static SENSOR_DEVICE_ATTR(cpld_version, S_IRUGO, get_cpld_ver, NULL, 0x00);
+static SENSOR_DEVICE_ATTR(psu_status, S_IRUGO, get_psu_status, NULL, 0); /* PSU Status Register */
+static SENSOR_DEVICE_ATTR(fan_status, S_IRUGO, get_fan_status, NULL, 0); /* FAN Status Register */
+static SENSOR_DEVICE_ATTR(fan_sys_frontled, S_IRUGO | S_IWUSR, get_fan_sys_frontled_reg, set_fan_sys_frontled_reg, 0); /* FAN front panel LED */
+static SENSOR_DEVICE_ATTR(psu_frontled, S_IRUGO | S_IWUSR, get_psu_frontled_reg, set_psu_frontled_reg, 0); /* PSU front panel LED */
+
+static SENSOR_DEVICE_ATTR(wdt_timer, S_IRUGO | S_IWUSR, get_wdt_timer_reg, set_wdt_timer_reg, 0);
+static SENSOR_DEVICE_ATTR(wdt_ctrl, S_IRUGO | S_IWUSR, get_wdt_ctrl_reg, set_wdt_ctrl_reg, 0);
+static SENSOR_DEVICE_ATTR(wdt_intr_cnt_mask, S_IRUGO | S_IWUSR, get_wdt_intr_cnt_mask_reg, set_wdt_intr_cnt_mask_reg, 0);
+static SENSOR_DEVICE_ATTR(wdt_intr_flag, S_IRUGO | S_IWUSR, get_wdt_intr_flag_reg, set_wdt_intr_flag_reg, 0);
+static SENSOR_DEVICE_ATTR(wdt_timeout, S_IRUGO | S_IWUSR, get_wdt_timeout, set_wdt_timeout, 0);
+
+static struct attribute *cpld_sysfs_attrs[] = {
+ &sensor_dev_attr_cpld_version.dev_attr.attr,
+ &sensor_dev_attr_psu_status.dev_attr.attr,
+ &sensor_dev_attr_fan_status.dev_attr.attr,
+ &sensor_dev_attr_fan_sys_frontled.dev_attr.attr,
+ &sensor_dev_attr_psu_frontled.dev_attr.attr,
+
+ &sensor_dev_attr_wdt_timer.dev_attr.attr,
+ &sensor_dev_attr_wdt_ctrl.dev_attr.attr,
+ &sensor_dev_attr_wdt_intr_cnt_mask.dev_attr.attr,
+ &sensor_dev_attr_wdt_intr_flag.dev_attr.attr,
+ &sensor_dev_attr_wdt_timeout.dev_attr.attr,
+
+ NULL
+};
+
+static const struct attribute_group cpld_sysfs_group = {
+ .attrs = cpld_sysfs_attrs,
+};
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int g3748cpld_detect(struct i2c_client *new_client, struct i2c_board_info *info)
+{
+ struct i2c_adapter *adapter = new_client->adapter;
+ int conf;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
+
+ /* Unused bits */
+ conf = i2c_smbus_read_byte_data(new_client, 0);
+ if (!conf)
+ return -ENODEV;
+
+ return 0;
+}
+
+static void g3748cpld_add_client (struct i2c_client *client)
+{
+ struct cpld_data *data;
+
+ data = devm_kzalloc(&client->dev, sizeof(struct cpld_data), GFP_KERNEL);
+ if (!data) {
+ dev_info(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr);
+ return;
+ }
+
+ data->client = client;
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+}
+
+static int g3748cpld_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ int status;
+ struct cpld_data *data;
+ int err;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+ dev_info(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr);
+ status = -EIO;
+ return status;
+ }
+
+ dev_info(&client->dev, "chip found - CPLD\n");
+ g3748cpld_add_client(client);
+
+ /* Register sysfs hooks */
+ //printk(KERN_INFO "g3748cpld_probe: Register sysfs hooks\n");
+ status = sysfs_create_group(&client->dev.kobj, &cpld_sysfs_group);
+ if (status) {
+ printk(KERN_INFO "g3748cpld cannot create sysfs\n");
+ }
+
+ data = i2c_get_clientdata(client);
+ //data->hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, client->name, data, cpld_hwmon_groups);
+ data->hwmon_dev = hwmon_device_register_with_groups(&client->dev, client->name, data, cpld_hwmon_groups);
+
+ if (IS_ERR(data->hwmon_dev)) {
+ err = PTR_ERR(data->hwmon_dev);
+ goto exit_remove_files;
+ }
+
+ initCpldDataReg(data);
+ dev_info(&client->dev, "%s: sensor '%s'\n", dev_name(data->hwmon_dev), client->name);
+ return 0;
+
+exit_remove_files:
+ sysfs_remove_group(&client->dev.kobj, &cpld_sysfs_group);
+ return err;
+}
+
+static int g3748cpld_remove(struct i2c_client *client)
+{
+ struct cpld_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ //devm_hwmon_device_unregister(&client->dev);
+ sysfs_remove_group(&client->dev.kobj, &cpld_sysfs_group);
+ return 0;
+}
+
+static const struct i2c_device_id g3748cpld_id[] = {
+ { "g3748cpld", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, g3748cpld_id);
+
+static struct i2c_driver g3748cpld_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "g3748cpld",
+ },
+ .probe = g3748cpld_probe,
+ .remove = g3748cpld_remove,
+ .id_table = g3748cpld_id,
+ .detect = g3748cpld_detect,
+ .address_list = normal_i2c,
+};
+
+module_i2c_driver(g3748cpld_driver);
+
+MODULE_AUTHOR("SMC ");
+MODULE_DESCRIPTION("SMC SSE-G3748 CPLD driver");
+MODULE_LICENSE("GPL");
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/modules/smc-i2c-mux-pca954x.c b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/modules/smc-i2c-mux-pca954x.c
new file mode 100644
index 0000000000..80162bd9df
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/modules/smc-i2c-mux-pca954x.c
@@ -0,0 +1,591 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * I2C multiplexer
+ *
+ * Copyright (c) 2008-2009 Rodolfo Giometti
+ * Copyright (c) 2008-2009 Eurotech S.p.A.
+ *
+ * This module supports the PCA954x and PCA984x series of I2C multiplexer/switch
+ * chips made by NXP Semiconductors.
+ * This includes the:
+ * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547,
+ * PCA9548, PCA9846, PCA9847, PCA9848 and PCA9849.
+ *
+ * These chips are all controlled via the I2C bus itself, and all have a
+ * single 8-bit register. The upstream "parent" bus fans out to two,
+ * four, or eight downstream busses or channels; which of these
+ * are selected is determined by the chip type and register contents. A
+ * mux can select only one sub-bus at a time; a switch can select any
+ * combination simultaneously.
+ *
+ * Based on:
+ * pca954x.c from Kumar Gala
+ * Copyright (C) 2006
+ *
+ * Based on:
+ * pca954x.c from Ken Harrenstien
+ * Copyright (C) 2004 Google, Inc. (Ken Harrenstien)
+ *
+ * Based on:
+ * i2c-virtual_cb.c from Brian Kuschak
+ * and
+ * pca9540.c from Jean Delvare .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "smc-pca954x.h"
+
+#define PCA954X_MAX_NCHANS 8
+
+#define PCA954X_IRQ_OFFSET 4
+
+enum pca_type {
+ pca_9540,
+ pca_9542,
+ pca_9543,
+ pca_9544,
+ pca_9545,
+ pca_9546,
+ pca_9547,
+ pca_9548,
+ pca_9846,
+ pca_9847,
+ pca_9848,
+ pca_9849,
+};
+
+struct chip_desc {
+ u8 nchans;
+ u8 enable; /* used for muxes only */
+ u8 has_irq;
+ enum muxtype {
+ pca954x_ismux = 0,
+ pca954x_isswi
+ } muxtype;
+ struct i2c_device_identity id;
+};
+
+struct pca954x {
+ const struct chip_desc *chip;
+
+ u8 last_chan; /* last register value */
+ /* MUX_IDLE_AS_IS, MUX_IDLE_DISCONNECT or >= 0 for channel */
+ s32 idle_state;
+
+ struct i2c_client *client;
+
+ struct irq_domain *irq;
+ unsigned int irq_mask;
+ raw_spinlock_t lock;
+};
+
+/* Provide specs for the PCA954x types we know about */
+static const struct chip_desc chips[] = {
+ [pca_9540] = {
+ .nchans = 2,
+ .enable = 0x4,
+ .muxtype = pca954x_ismux,
+ .id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
+ },
+ [pca_9542] = {
+ .nchans = 2,
+ .enable = 0x4,
+ .has_irq = 1,
+ .muxtype = pca954x_ismux,
+ .id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
+ },
+ [pca_9543] = {
+ .nchans = 2,
+ .has_irq = 1,
+ .muxtype = pca954x_isswi,
+ .id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
+ },
+ [pca_9544] = {
+ .nchans = 4,
+ .enable = 0x4,
+ .has_irq = 1,
+ .muxtype = pca954x_ismux,
+ .id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
+ },
+ [pca_9545] = {
+ .nchans = 4,
+ .has_irq = 1,
+ .muxtype = pca954x_isswi,
+ .id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
+ },
+ [pca_9546] = {
+ .nchans = 4,
+ .muxtype = pca954x_isswi,
+ .id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
+ },
+ [pca_9547] = {
+ .nchans = 8,
+ .enable = 0x8,
+ .muxtype = pca954x_ismux,
+ .id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
+ },
+ [pca_9548] = {
+ .nchans = 8,
+ .muxtype = pca954x_isswi,
+ .id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
+ },
+ [pca_9846] = {
+ .nchans = 4,
+ .muxtype = pca954x_isswi,
+ .id = {
+ .manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS,
+ .part_id = 0x10b,
+ },
+ },
+ [pca_9847] = {
+ .nchans = 8,
+ .enable = 0x8,
+ .muxtype = pca954x_ismux,
+ .id = {
+ .manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS,
+ .part_id = 0x108,
+ },
+ },
+ [pca_9848] = {
+ .nchans = 8,
+ .muxtype = pca954x_isswi,
+ .id = {
+ .manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS,
+ .part_id = 0x10a,
+ },
+ },
+ [pca_9849] = {
+ .nchans = 4,
+ .enable = 0x4,
+ .muxtype = pca954x_ismux,
+ .id = {
+ .manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS,
+ .part_id = 0x109,
+ },
+ },
+};
+
+static const struct i2c_device_id pca954x_id[] = {
+ { "smc_pca9540", pca_9540 },
+ { "smc_pca9542", pca_9542 },
+ { "smc_pca9543", pca_9543 },
+ { "smc_pca9544", pca_9544 },
+ { "smc_pca9545", pca_9545 },
+ { "smc_pca9546", pca_9546 },
+ { "smc_pca9547", pca_9547 },
+ { "smc_pca9548", pca_9548 },
+ { "smc_pca9846", pca_9846 },
+ { "smc_pca9847", pca_9847 },
+ { "smc_pca9848", pca_9848 },
+ { "smc_pca9849", pca_9849 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, pca954x_id);
+
+/* Force deselect-on-exit feature for PCA954X devices. Default is disabled. */
+static unsigned int force_deselect_on_exit = 0;
+module_param(force_deselect_on_exit, uint, S_IRUGO);
+MODULE_PARM_DESC(force_deselect_on_exit, "Force deselect-on-exit feature for PCA954X devices. Default is disabled.");
+
+static const struct of_device_id pca954x_of_match[] = {
+ { .compatible = "nxp,smc_pca9540", .data = &chips[pca_9540] },
+ { .compatible = "nxp,smc_pca9542", .data = &chips[pca_9542] },
+ { .compatible = "nxp,smc_pca9543", .data = &chips[pca_9543] },
+ { .compatible = "nxp,smc_pca9544", .data = &chips[pca_9544] },
+ { .compatible = "nxp,smc_pca9545", .data = &chips[pca_9545] },
+ { .compatible = "nxp,smc_pca9546", .data = &chips[pca_9546] },
+ { .compatible = "nxp,smc_pca9547", .data = &chips[pca_9547] },
+ { .compatible = "nxp,smc_pca9548", .data = &chips[pca_9548] },
+ { .compatible = "nxp,smc_pca9846", .data = &chips[pca_9846] },
+ { .compatible = "nxp,smc_pca9847", .data = &chips[pca_9847] },
+ { .compatible = "nxp,smc_pca9848", .data = &chips[pca_9848] },
+ { .compatible = "nxp,smc_pca9849", .data = &chips[pca_9849] },
+ {}
+};
+MODULE_DEVICE_TABLE(of, pca954x_of_match);
+
+/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer()
+ for this as they will try to lock adapter a second time */
+static int pca954x_reg_write(struct i2c_adapter *adap,
+ struct i2c_client *client, u8 val)
+{
+ union i2c_smbus_data dummy;
+
+ return __i2c_smbus_xfer(adap, client->addr, client->flags,
+ I2C_SMBUS_WRITE, val,
+ I2C_SMBUS_BYTE, &dummy);
+}
+
+static u8 pca954x_regval(struct pca954x *data, u8 chan)
+{
+ /* We make switches look like muxes, not sure how to be smarter. */
+ if (data->chip->muxtype == pca954x_ismux)
+ return chan | data->chip->enable;
+ else
+ return 1 << chan;
+}
+
+static int pca954x_select_chan(struct i2c_mux_core *muxc, u32 chan)
+{
+ struct pca954x *data = i2c_mux_priv(muxc);
+ struct i2c_client *client = data->client;
+ u8 regval;
+ int ret = 0;
+
+ regval = pca954x_regval(data, chan);
+ /* Only select the channel if its different from the last channel */
+ if (data->last_chan != regval) {
+ ret = pca954x_reg_write(muxc->parent, client, regval);
+ data->last_chan = ret < 0 ? 0 : regval;
+ }
+
+ return ret;
+}
+
+static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan)
+{
+ struct pca954x *data = i2c_mux_priv(muxc);
+ struct i2c_client *client = data->client;
+ s32 idle_state;
+
+ idle_state = READ_ONCE(data->idle_state);
+ if (idle_state >= 0)
+ /* Set the mux back to a predetermined channel */
+ return pca954x_select_chan(muxc, idle_state);
+
+ if (idle_state == MUX_IDLE_DISCONNECT) {
+ /* Deselect active channel */
+ data->last_chan = 0;
+ return pca954x_reg_write(muxc->parent, client,
+ data->last_chan);
+ }
+
+ /* otherwise leave as-is */
+
+ return 0;
+}
+
+static ssize_t idle_state_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+ struct pca954x *data = i2c_mux_priv(muxc);
+
+ return sprintf(buf, "%d\n", READ_ONCE(data->idle_state));
+}
+
+static ssize_t idle_state_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+ struct pca954x *data = i2c_mux_priv(muxc);
+ int val;
+ int ret;
+
+ ret = kstrtoint(buf, 0, &val);
+ if (ret < 0)
+ return ret;
+
+ if (val != MUX_IDLE_AS_IS && val != MUX_IDLE_DISCONNECT &&
+ (val < 0 || val >= data->chip->nchans))
+ return -EINVAL;
+
+ i2c_lock_bus(muxc->parent, I2C_LOCK_SEGMENT);
+
+ WRITE_ONCE(data->idle_state, val);
+ /*
+ * Set the mux into a state consistent with the new
+ * idle_state.
+ */
+ if (data->last_chan || val != MUX_IDLE_DISCONNECT)
+ ret = pca954x_deselect_mux(muxc, 0);
+
+ i2c_unlock_bus(muxc->parent, I2C_LOCK_SEGMENT);
+
+ return ret < 0 ? ret : count;
+}
+
+static DEVICE_ATTR_RW(idle_state);
+
+static irqreturn_t pca954x_irq_handler(int irq, void *dev_id)
+{
+ struct pca954x *data = dev_id;
+ unsigned long pending;
+ int ret, i;
+
+ ret = i2c_smbus_read_byte(data->client);
+ if (ret < 0)
+ return IRQ_NONE;
+
+ pending = (ret >> PCA954X_IRQ_OFFSET) & (BIT(data->chip->nchans) - 1);
+ for_each_set_bit(i, &pending, data->chip->nchans)
+ handle_nested_irq(irq_linear_revmap(data->irq, i));
+
+ return IRQ_RETVAL(pending);
+}
+
+static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type)
+{
+ if ((type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_LEVEL_LOW)
+ return -EINVAL;
+ return 0;
+}
+
+static struct irq_chip pca954x_irq_chip = {
+ .name = "i2c-mux-pca954x",
+ .irq_set_type = pca954x_irq_set_type,
+};
+
+static int pca954x_irq_setup(struct i2c_mux_core *muxc)
+{
+ struct pca954x *data = i2c_mux_priv(muxc);
+ struct i2c_client *client = data->client;
+ int c, irq;
+
+ if (!data->chip->has_irq || client->irq <= 0)
+ return 0;
+
+ raw_spin_lock_init(&data->lock);
+
+ data->irq = irq_domain_add_linear(client->dev.of_node,
+ data->chip->nchans,
+ &irq_domain_simple_ops, data);
+ if (!data->irq)
+ return -ENODEV;
+
+ for (c = 0; c < data->chip->nchans; c++) {
+ irq = irq_create_mapping(data->irq, c);
+ if (!irq) {
+ dev_err(&client->dev, "failed irq create map\n");
+ return -EINVAL;
+ }
+ irq_set_chip_data(irq, data);
+ irq_set_chip_and_handler(irq, &pca954x_irq_chip,
+ handle_simple_irq);
+ }
+
+ return 0;
+}
+
+static void pca954x_cleanup(struct i2c_mux_core *muxc)
+{
+ struct pca954x *data = i2c_mux_priv(muxc);
+ int c, irq;
+
+ if (data->irq) {
+ for (c = 0; c < data->chip->nchans; c++) {
+ irq = irq_find_mapping(data->irq, c);
+ irq_dispose_mapping(irq);
+ }
+ irq_domain_remove(data->irq);
+ }
+ i2c_mux_del_adapters(muxc);
+}
+
+static int pca954x_init(struct i2c_client *client, struct pca954x *data)
+{
+ int ret;
+
+ printk("pca954x_init is called\n");
+ if (data->idle_state >= 0)
+ data->last_chan = pca954x_regval(data, data->idle_state);
+ else
+ data->last_chan = 0; /* Disconnect multiplexer */
+
+ ret = i2c_smbus_write_byte(client, data->last_chan);
+ if (ret < 0)
+ data->last_chan = 0;
+
+ return ret;
+}
+
+/*
+ * I2C init/probing/exit functions
+ */
+static int pca954x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adap = client->adapter;
+ struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev);
+ struct device *dev = &client->dev;
+ struct gpio_desc *gpio;
+ struct i2c_mux_core *muxc;
+ struct pca954x *data;
+ int num, force;
+ int ret;
+
+ printk("pca954x_probe is called\n");
+ if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
+ return -ENODEV;
+
+ muxc = i2c_mux_alloc(adap, dev, PCA954X_MAX_NCHANS, sizeof(*data), 0,
+ pca954x_select_chan, pca954x_deselect_mux);
+ if (!muxc)
+ return -ENOMEM;
+ data = i2c_mux_priv(muxc);
+
+ i2c_set_clientdata(client, muxc);
+ data->client = client;
+
+ /* Reset the mux if a reset GPIO is specified. */
+ gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(gpio))
+ return PTR_ERR(gpio);
+ if (gpio) {
+ udelay(1);
+ gpiod_set_value_cansleep(gpio, 0);
+ /* Give the chip some time to recover. */
+ udelay(1);
+ }
+
+ data->chip = device_get_match_data(dev);
+ if (!data->chip)
+ data->chip = &chips[id->driver_data];
+
+ if (data->chip->id.manufacturer_id != I2C_DEVICE_ID_NONE) {
+ struct i2c_device_identity id;
+
+ ret = i2c_get_device_id(client, &id);
+ if (ret && ret != -EOPNOTSUPP)
+ return ret;
+
+ if (!ret &&
+ (id.manufacturer_id != data->chip->id.manufacturer_id ||
+ id.part_id != data->chip->id.part_id)) {
+ dev_warn(dev, "unexpected device id %03x-%03x-%x\n",
+ id.manufacturer_id, id.part_id,
+ id.die_revision);
+ return -ENODEV;
+ }
+ }
+
+ data->idle_state = MUX_IDLE_AS_IS;
+ if (device_property_read_u32(dev, "idle-state", &data->idle_state)) {
+ if (device_property_read_bool(dev, "i2c-mux-idle-disconnect"))
+ data->idle_state = MUX_IDLE_DISCONNECT;
+ }
+ if (force_deselect_on_exit)
+ data->idle_state = MUX_IDLE_DISCONNECT;
+ printk("pca954x_probe: data->idle_state = %d\n", data->idle_state);
+
+ /*
+ * Write the mux register at addr to verify
+ * that the mux is in fact present. This also
+ * initializes the mux to a channel
+ * or disconnected state.
+ */
+ ret = pca954x_init(client, data);
+ if (ret < 0) {
+ dev_warn(dev, "probe failed\n");
+ return -ENODEV;
+ }
+
+ ret = pca954x_irq_setup(muxc);
+ if (ret)
+ goto fail_cleanup;
+
+ /* Now create an adapter for each channel */
+ for (num = 0; num < data->chip->nchans; num++) {
+ force = 0; /* dynamic adap number */
+ if (pdata) {
+ if (num < pdata->num_modes) {
+ /* force static number */
+ force = pdata->modes[num].adap_id;
+ } else
+ /* discard unconfigured channels */
+ break;
+ }
+
+ ret = i2c_mux_add_adapter(muxc, force, num, 0);
+ if (ret)
+ goto fail_cleanup;
+ }
+
+ if (data->irq) {
+ ret = devm_request_threaded_irq(dev, data->client->irq,
+ NULL, pca954x_irq_handler,
+ IRQF_ONESHOT | IRQF_SHARED,
+ "pca954x", data);
+ if (ret)
+ goto fail_cleanup;
+ }
+
+ /*
+ * The attr probably isn't going to be needed in most cases,
+ * so don't fail completely on error.
+ */
+ device_create_file(dev, &dev_attr_idle_state);
+
+ /* dev_info(dev, "registered %d multiplexed busses for I2C %s %s\n",
+ */
+ printk("registered %d multiplexed busses for I2C %s %s\n",
+ num, data->chip->muxtype == pca954x_ismux
+ ? "mux" : "switch", client->name);
+
+ return 0;
+
+fail_cleanup:
+ pca954x_cleanup(muxc);
+ return ret;
+}
+
+static int pca954x_remove(struct i2c_client *client)
+{
+ struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+
+ device_remove_file(&client->dev, &dev_attr_idle_state);
+
+ pca954x_cleanup(muxc);
+ return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int pca954x_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct i2c_mux_core *muxc = i2c_get_clientdata(client);
+ struct pca954x *data = i2c_mux_priv(muxc);
+ int ret;
+
+ ret = pca954x_init(client, data);
+ if (ret < 0)
+ dev_err(&client->dev, "failed to verify mux presence\n");
+
+ return ret;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pca954x_pm, NULL, pca954x_resume);
+
+static struct i2c_driver pca954x_driver = {
+ .driver = {
+ .name = "smc_pca954x",
+ .pm = &pca954x_pm,
+ .of_match_table = pca954x_of_match,
+ },
+ .probe = pca954x_probe,
+ .remove = pca954x_remove,
+ .id_table = pca954x_id,
+};
+
+module_i2c_driver(pca954x_driver);
+
+MODULE_AUTHOR("Rodolfo Giometti ");
+MODULE_DESCRIPTION("PCA954x I2C mux/switch driver");
+MODULE_LICENSE("GPL v2");
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/modules/smc-pca954x.h b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/modules/smc-pca954x.h
new file mode 100644
index 0000000000..15b9fe4146
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/modules/smc-pca954x.h
@@ -0,0 +1,44 @@
+/*
+ *
+ * cls-pca954x.h - I2C multiplexer/switch support
+ *
+ * Copyright (c) 2008-2009 Rodolfo Giometti
+ * Copyright (c) 2008-2009 Eurotech S.p.A.
+ * Michael Lawnick
+ *
+ * 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_I2C_PCA954X_H
+#define _LINUX_I2C_PCA954X_H
+
+/* Platform data for the PCA954x I2C multiplexers */
+
+/* Per channel initialisation data:
+ * @adap_id: bus number for the adapter. 0 = don't care
+ *
+ */
+struct pca954x_platform_mode {
+ int adap_id;
+};
+
+/* Per mux/switch data, used with i2c_register_board_info */
+struct pca954x_platform_data {
+ struct pca954x_platform_mode *modes;
+ int num_modes;
+};
+
+#endif /* _LINUX_I2C_PCA954X_H */
\ No newline at end of file
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/add_port_range b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/add_port_range
new file mode 100644
index 0000000000..9266e334b4
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/add_port_range
@@ -0,0 +1,73 @@
+#!/usr/bin/python
+import os
+import sys
+from sys import argv
+import re
+
+# Quit if user doesn't input all the required variables
+
+if len(argv) < 3 or len(argv) > 5:
+ print('\n' + 'Usage: add_port_range EthernetX-X vlan [OPTIONS] ' + '\n' + '\n' +
+ 'Add ports as Tagged/Untagged and configure VLAN onto them' + '\n' + '\n' +
+ 'OPTIONS:' + '\n' +
+ '-u, --untagged' + '\n' +
+ '-h, ?, -?, --help Show this message and exit' + '\n')
+ quit()
+
+
+# Quit if user inputs 'help' options
+
+if '?' in argv or '--help' in argv or '-help' in argv or 'help' in argv or '-?' in argv or '-h' in argv:
+ print('\n' + 'Usage: add_port_range EthernetX-X vlan [OPTIONS] ' + '\n' + '\n' +
+ 'Add ports as Tagged/Untagged and configure VLAN onto them' + '\n' + '\n' +
+ 'OPTIONS:' + '\n' +
+ '-u, --untagged' + '\n' +
+ '-h, ?, -?, --help Show this message and exit' + '\n')
+ quit()
+
+# User has to pass the VLAN argument using atleast the first two letters i.e. 'V/v' 'L/l'
+pattern = '[Vv]+[Ll]'
+
+def match(text):
+ if re.match(pattern,text):
+ return ('Yes')
+ else:
+ return('No')
+
+if ((match(argv[2]) == 'Yes') and (int(argv[3]) < 4094)):
+ command2 = 'sudo config vlan add ' + str(argv[3])
+ os.system(command2)
+else:
+ print('\n' + 'Usage: add_port_range EthernetX-X vlan [OPTIONS] ' + '\n' + '\n' +
+ 'Add ports as Tagged/Untagged and configure VLAN onto them' + '\n' + '\n' +
+ 'OPTIONS:' + '\n' +
+ '-u, --untagged' + '\n' +
+ '-h, ?, -?, --help Show this message and exit' + '\n')
+ quit()
+
+#Find and create a list of all the interfaces
+int_range1 = re.findall('[0-9]+-[0-9]+',argv[1])
+int_range = int_range1[0].split('-')
+
+#Add ports as untagged
+
+if ((match(argv[2]) == 'Yes') and ('-u' in argv)):
+
+ for interface in range(int(int_range[0]),int(int_range[1])):
+ os.system('sudo config vlan member add -u ' + str(argv[3]) + ' Ethernet' + str(interface))
+
+#Add ports as tagged
+
+elif ((match(argv[2]) == 'Yes') and len(argv)) == 4:
+
+ for interface in range(int(int_range[0]),int(int_range[1])):
+ os.system('sudo config vlan member add ' + str(argv[3]) + ' Ethernet' + str(interface))
+
+else:
+ print('\n' + 'Usage: add_port_range EthernetX-X vlan [OPTIONS] ' + '\n' + '\n' +
+ 'Add ports as Tagged/Untagged and configure VLAN onto them' + '\n' + '\n' +
+ 'OPTIONS:' + '\n' +
+ '-u, --untagged' + '\n' +
+ '-h, ?, -?, --help Show this message and exit' + '\n')
+ quit()
+
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/entropy.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/entropy.py
new file mode 100644
index 0000000000..338e2ad9bc
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/entropy.py
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+import fcntl, struct
+import time
+from os import path
+
+RNDADDENTROPY=0x40085203
+
+def avail():
+ with open("/proc/sys/kernel/random/entropy_avail", mode='r') as avail:
+ return int(avail.read())
+
+if path.exists("/proc/sys/kernel/random/entropy_avail"):
+ while 1:
+ while avail() < 2048:
+ with open('/dev/urandom', 'rb') as urnd, open("/dev/random", mode='wb') as rnd:
+ d = urnd.read(512)
+ t = struct.pack('ii', 4 * len(d), len(d)) + d
+ fcntl.ioctl(rnd, RNDADDENTROPY, t)
+ time.sleep(30)
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/reset-to-factory-default b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/reset-to-factory-default
new file mode 100644
index 0000000000..dea0ad7fe3
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/reset-to-factory-default
@@ -0,0 +1,84 @@
+#!/usr/bin/bash
+
+# This script is used to reset the current host file system and docker containers
+# to the initial state of the firmware.
+
+# Because this is a factory reset hook, execute the script only if the hook script is
+# either executed directorly or called as "config-setup factory" command
+if [ -n $CMD ] && [ "$CMD" != "" ]; then
+ if [ "$CMD" != "factory" ]; then
+ exit 0
+ fi
+fi
+
+# if called from the sonic cli, then python click has already confirmed
+# this, so just set var_yn to y here.
+
+if [ ! -r /tmp/sonic_cli_factory_reset ]; then
+# if called by the monitor script then no ask confirm
+PARENT_COMMAND=$(ps -o args= $PPID)
+if [[ "$PARENT_COMMAND" != *"reset_button_monitor.py"* ]]; then
+ cat << EOF
+This command will reset settings to factory defaults.
+After resetting to factory defaults, switch will be reloaded immediately.
+Do you really want to execute this command and reload the switch? [y/n]
+EOF
+
+ read var_yn
+ if [ "$var_yn" != "y" ]; then
+ exit 1
+ fi
+fi
+else
+ var_yn="y"
+fi
+
+
+if [ "$EUID" -ne 0 ]
+ then echo "Root privileges are required for this operation"
+ exit 2
+fi
+
+# PB issue: 156474: Enable ZTP back.-start
+ztp enable -y
+ztp run -y
+# PB issue: 156474: Enable ZTP back.-end
+
+# if there is any backup config saved via the command "config-setup backup"
+# then remove it during factory reset, else these configs will get applied
+# after factory reset.
+
+if [ -d /host/old_config ]; then
+ rm -rf /host/old_config
+fi
+
+# stop SONiC services to prevent docker restart
+# keep syslog for debugging
+grep -v @ /etc/sonic/generated_services.conf | grep -v rsyslog-config.service | xargs systemctl disable
+grep -v @ /etc/sonic/generated_services.conf | grep -v rsyslog-config.service | xargs systemctl stop
+
+# rm docker containers
+docker ps -aq | xargs docker rm -f
+
+# rm overlay upper dir, ex: /host/image-3.0.0.5/rw
+UPPER=`mount | grep "root-overlay on /" | sed 's/.*upperdir=\/root\([^,]*\),.*/\1/'`
+rm -rf $UPPER
+WORK=`mount | grep "root-overlay on /" | sed 's/.*workdir=\/root\([^)]*\)).*/\1/'`
+rm -rf $WORK
+sync;sync
+echo 3 > /proc/sys/vm/drop_caches
+
+# rm other files in /host/
+
+# create "image-xxx/platform/firsttime"
+IMGPATH=`dirname $UPPER`
+touch "$IMGPATH/platform/firsttime"
+sync;sync
+
+rm -f /etc/sonic/config_db.json
+
+# force reboot if called by user
+if [ "$var_yn" == "y" ]; then
+ shutdown -r now
+fi
+
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/setup_all_ports_l2.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/setup_all_ports_l2.py
new file mode 100644
index 0000000000..c1c9ba594e
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/setup_all_ports_l2.py
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+
+import os
+
+command1 = ""
+command2 = "sudo config vlan add 10"
+command3 = ""
+os.system(command2)
+for interface in range(0,54):
+ command1 = ('sudo config interface ip remove Ethernet' + str(interface) + " " + '10.0.0.' + str(interface*2) + '/31' + '\n')
+ os.system(command1)
+ command3 = "sudo config vlan member add -u 10 Ethernet" + str(interface) + '\n'
+ os.system(command3)
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/show-techsupport b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/show-techsupport
new file mode 100644
index 0000000000..1b19b7a33d
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/show-techsupport
@@ -0,0 +1,88 @@
+#!/usr/bin/python
+import os
+import sys
+import re
+import time
+import sys
+
+interface_output = str(os.popen('show interface stat').read())
+pattern_int = re.findall('Ethernet[0-9]+',interface_output)
+
+os.system('sudo config feature state iccpd enabled')
+mclag_output = str(os.popen('mclagdctl dump state').read())
+
+commands = []
+
+if not mclag_output:
+
+ commands = commands + ['show platform syseeprom', 'show version', 'show boot', 'show tacacs', 'show radius', 'show aaa',
+ 'show platform psustatus', 'show platform pcieinfo', 'show platform temp',
+ 'show platform summary', 'show platform firmware status',
+ 'show platform fan', 'show interface status', 'sudo ifconfig -a', 'show ip interface',
+ 'show vlan brief', 'show lldp neighbors' , 'show lldp table', 'show ztp status', 'show ip bgp summary', 'show ip bgp neighbors', 'show route-map',
+ 'show interface portchannel', 'show ip route', 'sudo route -n', 'show arp', 'sudo arp -n', 'show mac',
+ 'show acl rule', 'sudo aclshow -a -vv', 'show acl table', 'show interface counters -a', 'show int autoneg status',
+ 'mclagdctl dump state','sudo show system-health detail', 'show system-mem',
+ 'docker ps', 'top -n 1', 'show uptime', 'show reboot-cause history',
+ 'sudo show system-health summary','show int transceiver presence', 'show int transceiver eeprom', 'show int transceiver error-status',
+ 'show int transceiver lpmode', 'show clock', 'show ntp', 'sudo timedatectl status', 'show runningconfiguration all']
+
+else:
+
+ mclag_domain = re.findall('Domain id: [0-9]+',mclag_output)
+ mclag_final = mclag_domain[0].split(':')
+ commands = commands + ['show platform syseeprom', 'show version', 'show boot', 'show tacacs', 'show radius', 'show aaa',
+ 'show platform psustatus', 'show platform pcieinfo', 'show platform temp',
+ 'show platform summary', 'show platform firmware status',
+ 'show platform fan', 'show interface status', 'sudo ifconfig -a', 'show ip interface',
+ 'show vlan brief', 'show lldp neighbors' , 'show lldp table', 'show ztp status', 'show ip bgp summary', 'show ip bgp neighbors', 'show route-map',
+ 'show interface portchannel', 'show ip route', 'sudo route -n', 'show arp', 'sudo arp -n', 'show mac',
+ 'show acl rule', 'sudo aclshow -a -vv', 'show acl table', 'show interface counters -a', 'show int autoneg status',
+ 'mclagdctl dump state', ('mclagdctl dump mac -i ' + str(mclag_final[1])), ('mclagdctl dump arp -i ' + str(mclag_final[1])),
+ 'sudo show system-health detail', 'show system-mem',
+ 'docker ps', 'top -n 1', 'show uptime', 'show reboot-cause history',
+ 'sudo show system-health summary','show int transceiver presence', 'show int transceiver eeprom', 'show int transceiver error-status',
+ 'show int transceiver lpmode', 'show clock', 'show ntp', 'sudo timedatectl status', 'show runningconfiguration all']
+
+output = ''
+
+print('Fetching data....This might take a few minutes...')
+
+toolbar_width = 83
+
+# setup toolbar
+sys.stdout.write("[%s]" % (" " * toolbar_width))
+sys.stdout.flush()
+sys.stdout.write("\b" * (toolbar_width+1)) # return to start of line, after '['
+
+for command in commands:
+ time.sleep(0.1)
+ output = output + str(command) + '\n'
+ output = output + os.popen(str(command)).read() + '\n'
+ output = str(output)
+# update the bar
+ sys.stdout.write("-")
+ sys.stdout.flush()
+
+for interface in pattern_int:
+ time.sleep(0.1)
+ int_command = '\n' + 'show interface counters detailed ' + str(interface) + '\n'
+ output = '\n' + output + int_command + '\n'
+ output = output + os.popen(str(int_command)).read()
+ output = str(output)
+# update the bar
+ sys.stdout.write("-")
+ sys.stdout.flush()
+
+# end the progress bar
+sys.stdout.write("\n")
+
+print('Generated a text file techsupport.txt in the tmp directory')
+orig_stdout = sys.stdout
+f = open('/tmp/techsupport.txt', 'w')
+sys.stdout = f
+
+print(output)
+
+sys.stdout = orig_stdout
+f.close()
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/sse-g3748-init.sh b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/sse-g3748-init.sh
new file mode 100644
index 0000000000..8b58a17efe
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/sse-g3748-init.sh
@@ -0,0 +1,342 @@
+#!/bin/bash
+
+# Platform init script
+
+NUM_I2C_1_DEVICE=1
+
+# MAIN MUX PCA9548 0x71
+NUM_MUX_9548_CH0=$(( ${NUM_I2C_DEVICE} + 1 )) # MUX #1 SFP28 Port1 EEPROM 0x50
+NUM_MUX_9548_CH1=$(( ${NUM_I2C_DEVICE} + 2 )) # MUX #2 SFP28 Port2 EEPROM 0x50
+NUM_MUX_9548_CH2=$(( ${NUM_I2C_DEVICE} + 3 )) # MUX #3 SFP28 Port3 EEPROM 0x50
+NUM_MUX_9548_CH3=$(( ${NUM_I2C_DEVICE} + 4 )) # MUX #4 SFP28 Port4 EEPROM 0x50
+NUM_MUX_9548_CH4=$(( ${NUM_I2C_DEVICE} + 5 )) # MUX #5 SFP28 Port5 EEPROM 0x50
+NUM_MUX_9548_CH5=$(( ${NUM_I2C_DEVICE} + 6 )) # MUX #6 SFP28 Port6 EEPROM 0x50
+NUM_MUX_9548_CH6=$(( ${NUM_I2C_DEVICE} + 7 )) # MUX #7 FAN EEPROM (0x56, 0x57)
+NUM_MUX_9548_CH7=$(( ${NUM_I2C_DEVICE} + 8 )) # MUX #8 PSU EEPROM (0x56, 0x57)
+
+PATH_SYS_I2C_DEVICES="/sys/bus/i2c/devices"
+PATH_I2C_1_DEVICE="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_I2C_1_DEVICE}"
+PATH_MUX_9548_CH0="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_CH0}"
+PATH_MUX_9548_CH1="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_CH1}"
+PATH_MUX_9548_CH2="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_CH2}"
+PATH_MUX_9548_CH3="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_CH3}"
+PATH_MUX_9548_CH4="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_CH4}"
+PATH_MUX_9548_CH5="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_CH5}"
+PATH_MUX_9548_CH6="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_CH6}"
+PATH_MUX_9548_CH7="${PATH_SYS_I2C_DEVICES}/i2c-${NUM_MUX_9548_CH7}"
+
+# I2C Address
+### I2C MUX PCA9548
+I2C_ADDR_MUX_9548_CH0=0x71 # SFP28 MUX #1 EEPROM
+I2C_ADDR_MUX_9548_CH1=0x71 # SFP28 MUX #2 EEPROM
+I2C_ADDR_MUX_9548_CH2=0x71 # SFP28 MUX #3 EEPROM
+I2C_ADDR_MUX_9548_CH3=0x71 # SFP28 MUX #4 EEPROM
+I2C_ADDR_MUX_9548_CH4=0x71 # SFP28 MUX #5 EEPROM
+I2C_ADDR_MUX_9548_CH5=0x71 # SFP28 MUX #6 EEPROM
+I2C_ADDR_MUX_9548_CH6=0x71 # FAN MUX #7 EEPROM
+I2C_ADDR_MUX_9548_CH7=0x71 # PSU MUX #8 EEPROM
+### GPIO Expander
+I2C_ADDR_IO_PCAL6416=0x20 # GPIO Expander PCAL6416A
+I2C_ADDR_IO_PCAL6524=0x22 # GPIO Expander PCAL6524
+### peripheral
+I2C_ADDR_FAN1_EEPROM=0x56 # FAN1 EEPROM
+I2C_ADDR_FAN2_EEPROM=0x57 # FAN2 EEPROM
+I2C_ADDR_PSU1_EEPROM=0x56 # PSU1 EEPROM
+I2C_ADDR_PSU2_EEPROM=0x57 # PSU2 EEPROM
+I2C_ADDR_TMP75_1=0x48 # LM75 temperature sensor 1
+I2C_ADDR_TMP75_2=0x49 # LM75 temperature sensor 2
+I2C_ADDR_QSFP_EEPROM=0x50 # SFP28 port EEPROM
+
+# IO Expander Register
+# direction
+PCAL6524_REG_PORT0_DIR=0x0C
+PCAL6524_REG_PORT1_DIR=0x0D
+PCAL6524_REG_PORT2_DIR=0x0E
+
+PCAL6416_REG_PORT0_DIR=6
+PCAL6416_REG_PORT1_DIR=7
+
+# polarity
+PCAL6524_REG_PORT0_POL=0x08
+PCAL6524_REG_PORT1_POL=0x09
+PCAL6524_REG_PORT2_POL=0x0A
+
+PCAL6416_REG_PORT0_POL=4
+PCAL6416_REG_PORT1_POL=5
+
+# output
+PCAL6524_REG_PORT0_OUT=0x04
+PCAL6524_REG_PORT1_OUT=0x05
+PCAL6524_REG_PORT2_OUT=0x06
+
+PCAL6416_REG_PORT0_OUT=2
+PCAL6416_REG_PORT1_OUT=3
+
+# input
+PCAL6524_REG_PORT0_IN=0x00
+PCAL6524_REG_PORT1_IN=0x01
+PCAL6524_REG_PORT2_IN=0x02
+
+PCAL6416_REG_PORT0_IN=0
+PCAL6416_REG_PORT1_IN=1
+
+# Load required kernel-mode drivers
+load_kernel_drivers() {
+ echo "Load SSE-G3748 Linux kernel drivers ...\n"
+ # Remove modules loaded during Linux init
+ # FIX-ME: This will be removed in the future when Linux init no longer loads these
+ rmmod i2c_dev
+ rmmod i2c_mv64xxx
+ rmmod smc_i2c_mux_pca954x
+
+ # Carefully control the load order here to ensure consistent i2c bus numbering
+ depmod -a
+ modprobe g3748cpld
+ modprobe smc_i2c_mux_pca954x force_deselect_on_exit=1
+ modprobe i2c_mv64xxx
+ modprobe i2c_dev
+ modprobe eeprom
+ modprobe mvMbusDrv
+}
+
+# i2c MUX PCA9548 init
+i2c_mux_init() {
+ # add MUX PCA9548 on I2C_1, assume to be i2c-2~9
+ if [ ! -e ${PATH_MUX_9548_CH0} ]; then
+ _retry "echo 'pca9548 ${I2C_ADDR_MUX_9548_CH0}' > ${PATH_I2C_1_DEVICE}/new_device"
+ else
+ echo "pca9548 ${I2C_ADDR_MUX_9548_CH0} already init."
+ fi
+
+}
+
+# I/O Expander init
+#----------------------------------------------------------------------------
+# PCAL6524 -- [I2C 0x22] 24 bits I/O for SFP status and TX_DIS
+# Port 0 -- 7 6 5 4 3 2 1 0
+# TX_FAULT TX_DIS LOS PRESENT TX_FAULT TX_DIS LOS PRESENT
+# SFP1 SFP1 SFP1 SFP1 SFP0 SFP0 SFP0 SFP0
+#
+# Port 1 -- 7 6 5 4 3 2 1 0
+# TX_FAULT TX_DIS LOS PRESENT TX_FAULT TX_DIS LOS PRESENT
+# SFP3 SFP3 SFP3 SFP3 SFP2 SFP2 SFP2 SFP2
+#
+# Port 1 -- 7 6 5 4 3 2 1 0
+# TX_FAULT TX_DIS LOS PRESENT TX_FAULT TX_DIS LOS PRESENT
+# SFP5 SFP5 SFP5 SFP5 SFP4 SFP4 SFP4 SFP4
+# [TX_DIS bit is output, all other bits are input]
+#---------------------------------------------------------------------------
+# PCAL6416A -- [I2C 0x20] 16 bits I/) Expander SFP RS0 and RS1
+# Port 0 -- 7 6 5 4 3 2 1 0
+# RS0 RS1 RS0 RS1 RS0 RS1 RS0 RS1
+# SF2 SF3 SF0 SF1
+#
+# Port 0 -- 7 6 5 4 3 2 1 0
+# N/A N/A N/A N/A RS0 RS1 RS0 RS1
+# SF4 SF5
+# [ All bits are output]
+# According to SFF-8431
+# RS0 - low : RX signalling rate less than or equal to 4.25GBd
+# high: RX signalling rate greater than 4.25GBd
+# RS1 - low : TX signalling rate less than or equal to 4.25GBd
+# high: TX signalling rate greater than 4.25GBd
+#---------------------------------------------------------------------------
+
+i2c_io_exp_init() {
+ echo "Init SFP status and ctrl IO Expander"
+ sudo i2cset -y -r ${NUM_I2C_1_DEVICE} ${I2C_ADDR_IO_PCAL6524} ${PCAL6524_REG_PORT0_DIR} 0xBB
+ sudo i2cset -y -r ${NUM_I2C_1_DEVICE} ${I2C_ADDR_IO_PCAL6524} ${PCAL6524_REG_PORT1_DIR} 0xBB
+ sudo i2cset -y -r ${NUM_I2C_1_DEVICE} ${I2C_ADDR_IO_PCAL6524} ${PCAL6524_REG_PORT2_DIR} 0xBB
+ sudo i2cset -y -r ${NUM_I2C_1_DEVICE} ${I2C_ADDR_IO_PCAL6524} ${PCAL6524_REG_PORT0_POL} 0x00
+ sudo i2cset -y -r ${NUM_I2C_1_DEVICE} ${I2C_ADDR_IO_PCAL6524} ${PCAL6524_REG_PORT1_POL} 0x00
+ sudo i2cset -y -r ${NUM_I2C_1_DEVICE} ${I2C_ADDR_IO_PCAL6524} ${PCAL6524_REG_PORT2_POL} 0x00
+
+ echo "Init SFP RS0 and RS1 IO Expander"
+ sudo i2cset -y -r ${NUM_I2C_1_DEVICE} ${I2C_ADDR_IO_PCAL6416} ${PCAL6416_REG_PORT0_DIR} 0x00
+ sudo i2cset -y -r ${NUM_I2C_1_DEVICE} ${I2C_ADDR_IO_PCAL6416} ${PCAL6416_REG_PORT1_DIR} 0x00
+ sudo i2cset -y -r ${NUM_I2C_1_DEVICE} ${I2C_ADDR_IO_PCAL6416} ${PCAL6416_REG_PORT0_POL} 0x00
+ sudo i2cset -y -r ${NUM_I2C_1_DEVICE} ${I2C_ADDR_IO_PCAL6416} ${PCAL6416_REG_PORT1_POL} 0x00
+ sudo i2cset -y -r ${NUM_I2C_1_DEVICE} ${I2C_ADDR_IO_PCAL6416} ${PCAL6416_REG_PORT0_OUT} 0xFF
+ sudo i2cset -y -r ${NUM_I2C_1_DEVICE} ${I2C_ADDR_IO_PCAL6416} ${PCAL6416_REG_PORT1_OUT} 0xFF
+}
+
+update_share_password()
+{
+ echo "Update shared password !!!"
+ SONIC_VERSION=$(cat /etc/sonic/sonic_version.yml | grep "build_version" | sed -e "s/build_version: //g;s/'//g")
+ image_dir=$(cat /proc/cmdline | sed -e 's/.*loop=\(\S*\)\/.*/\1/')
+ if [ -f /host/reboot-cause/platform/last_boot_image ]; then
+ last_image_ver=$(cat /host/reboot-cause/platform/last_boot_image)
+ else
+ last_image_ver=""
+ fi
+ echo "last_image_ver=${last_image_ver}"
+
+ find /host -name "*image-*" | sed -e 's/\/host\/image-//' | while read var ; do
+ #echo "var=${var} image_dir=${image_dir}"
+ if [ "image-${var}" != "$image_dir" ] && [ "$last_image_ver" != "${SONIC_VERSION}" ]; then
+ cp /host/image-${var}/rw/etc/shadow /host/${image_dir}/rw/etc/shadow
+ cp /host/image-${var}/rw/etc/passwd /host/${image_dir}/rw/etc/passwd
+ cp /host/image-${var}/rw/etc/gshadow /host/${image_dir}/rw/etc/gshadow
+ cp /host/image-${var}/rw/etc/group /host/${image_dir}/rw/etc/group
+ fi
+ done
+
+ if [ -d /host/reboot-cause/platform ]; then
+ echo "${SONIC_VERSION}" | sudo tee /host/reboot-cause/platform/last_boot_image > /dev/null
+ fi
+}
+
+check_and_install_certificate_key_for_telemetry()
+{
+ echo "Check and install certificate and key for telemetry."
+ if [ ! -d /etc/sonic/telemetry ]; then
+ sudo mkdir -p /etc/sonic/telemetry
+ fi
+ if [ -d /etc/sonic/telemetry ]; then
+ if [ ! -f /etc/sonic/telemetry/dsmsroot.key ] || [ ! -f /etc/sonic/telemetry/dsmsroot.cer ]; then
+ echo "Create dsmsroot.key and dsmsroot.cer in /etc/sonic/telemetry/"
+ sudo openssl req -x509 -newkey rsa:4096 -keyout /etc/sonic/telemetry/dsmsroot.key \
+ -out /etc/sonic/telemetry/dsmsroot.cer -sha256 -days 365 -nodes -subj '/CN=lab-ca'
+ fi
+
+ if [ ! -f /etc/sonic/telemetry/streamingtelemetryserver.csr ] || [ ! -f /etc/sonic/telemetry/streamingtelemetryserver.key ]; then
+ echo "Create streamingtelemetryserver.key, streamingtelemetryserver.csr in /etc/sonic/telemetry/"
+ sudo openssl req -new -newkey rsa:4096 -nodes \
+ -keyout /etc/sonic/telemetry/streamingtelemetryserver.key -out /etc/sonic/telemetry/streamingtelemetryserver.csr \
+ -subj "/CN=dev-pygnmi-sonic-003"
+ fi
+
+ if [ ! -f /etc/sonic/telemetry/streamingtelemetryserver.cer ] || [ ! -f /etc/sonic/telemetry/dsmsroot.srl ]; then
+ echo "Create streamingtelemetryserver.cer, dsmsroot.srl in /etc/sonic/telemetry/"
+ sudo openssl x509 -req -in /etc/sonic/telemetry/streamingtelemetryserver.csr \
+ -CA /etc/sonic/telemetry/dsmsroot.cer -CAkey /etc/sonic/telemetry/dsmsroot.key \
+ -CAcreateserial -out /etc/sonic/telemetry/streamingtelemetryserver.cer \
+ -days 365 -sha512
+ fi
+ fi
+}
+
+# - Main entry
+
+# Install kernel drivers required for i2c bus access
+load_kernel_drivers
+#entropy setting
+#python /etc/entropy.py
+
+# LOGIC to enumerate SFP eeprom devices - send 0x50 to kernel i2c driver - initialize devices
+# the mux may be enumerated at number 4 or 5 so we check for the mux and skip if needed
+echo pca9548 ${I2C_ADDR_MUX_9548_CH0} > ${PATH_I2C_1_DEVICE}/new_device
+sleep 2
+
+# Get list of the mux channels
+ismux_bus=$(i2cdetect -l|grep mux|cut -f1)
+
+# Enumerate the SFP eeprom device on each mux channel
+#echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-0/new_device
+for mux in ${ismux_bus}
+do
+ if [[ "${mux}" != "i2c-8" ]] && [[ "${mux}" != "i2c-9" ]]; then
+ echo optoe2 ${I2C_ADDR_QSFP_EEPROM} > /sys/class/i2c-adapter/${mux}/new_device
+ mux_num=$(echo ${mux} | cut -b5)
+ #sleep 1
+ chmod 644 /sys/class/i2c-adapter/${mux}/${mux_num}-0050/eeprom
+ fi
+
+ if [ "${mux}" == "i2c-8" ]; then
+ # Enumerate fan eeprom devices
+ echo eeprom 0x56 > /sys/class/i2c-adapter/i2c-8/new_device
+ #sleep 1
+ chmod 644 /sys/class/i2c-adapter/i2c-8/8-0056/eeprom
+
+ echo eeprom 0x57 > /sys/class/i2c-adapter/i2c-8/new_device
+ #sleep 1
+ chmod 644 /sys/class/i2c-adapter/i2c-8/8-0057/eeprom
+ fi
+
+ if [ "${mux}" == "i2c-9" ]; then
+ # Enumerate fan eeprom devices
+ echo eeprom 0x56 > /sys/class/i2c-adapter/i2c-9/new_device
+ #sleep 1
+ chmod 644 /sys/class/i2c-adapter/i2c-9/9-0056/eeprom
+
+ echo eeprom 0x57 > /sys/class/i2c-adapter/i2c-9/new_device
+ #sleep 1
+ chmod 644 /sys/class/i2c-adapter/i2c-9/9-0057/eeprom
+ fi
+done
+
+# Enumerate rtc
+echo pcf8563 0x51 > /sys/bus/i2c/devices/i2c-0/new_device
+# Enumerate system eeprom
+echo 24c02 0x54 > /sys/class/i2c-adapter/i2c-0/new_device
+#sleep 1
+#chmod 644 /sys/class/i2c-adapter/i2c-0/0-0054/eeprom
+
+# Enumerate PD eeprom
+echo 24c02 0x52 > /sys/class/i2c-adapter/i2c-0/new_device
+#sleep 1
+#chmod 644 /sys/class/i2c-adapter/i2c-0/0-0052/eeprom
+
+# Enumerate AC5X eeprom
+echo 24c64 0x53 > /sys/class/i2c-adapter/i2c-0/new_device
+#sleep 1
+#chmod 644 /sys/class/i2c-adapter/i2c-0/0-0053/eeprom
+
+# Enumerate temperature sensors
+echo lm75 0x48 > /sys/class/i2c-adapter/i2c-0/new_device
+sleep 1
+#chmod 644 /sys/class/i2c-adapter/i2c-0/0-0048/eeprom
+
+echo lm75 0x49 > /sys/class/i2c-adapter/i2c-0/new_device
+sleep 1
+#chmod 644 /sys/class/i2c-adapter/i2c-0/0-0049/eeprom
+
+# Enumerate cpld
+echo g3748cpld 0x66 > /sys/bus/i2c/devices/i2c-0/new_device
+sleep 1
+
+# Enumerate gpio
+echo gpio 0x22 > /sys/class/i2c-adapter/i2c-1/new_device
+#sleep 1
+#chmod 644 /sys/class/i2c-adapter/i2c-1/1-0022/
+echo gpio 0x20 > /sys/class/i2c-adapter/i2c-1/new_device
+#sleep 1
+#chmod 644 /sys/class/i2c-adapter/i2c-1/1-0020/
+
+sleep 1
+chmod 644 /sys/class/i2c-adapter/i2c-0/0-0054/eeprom
+chmod 644 /sys/class/i2c-adapter/i2c-0/0-0052/eeprom
+chmod 644 /sys/class/i2c-adapter/i2c-0/0-0053/eeprom
+
+i2c_io_exp_init
+
+# Updating password for each installed image
+update_share_password
+
+# Check and setup certificate and key for telemetry
+check_and_install_certificate_key_for_telemetry
+
+#setting boot_once to undefined everytime after reboot
+/usr/bin/fw_setenv boot_once
+
+
+#Handle 202211 image install from 202106 release image. ie. if platform
+#directory sse_g3748 exists, this config is coming from 202106 code,
+#the corresponding directory in 202211 is supermicro_sse_g3748.
+# So we have to create a soft link from sse_g3748 to supermicro_sse_g3748.
+# So let us delete the sse_g3748 directory first.
+
+sed "s/\/supermicro_sse_g3748/" /etc/sonic/sonic-enviornment -i
+
+tmp=$(mktemp)
+jq '.DEVICE_METADATA.localhost.hwsku = "supermicro_sse_g3748"' /etc/sonic/config_db.json > "$tmp" && mv "$tmp" /etc/sonic/config_db.json
+
+if [ -d /usr/share/sonic/device/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748 ]; then
+ rm -rf /usr/share/sonic/device/arm64-supermicro_sse_g3748-r0/sse_g3748
+ ln -s /usr/share/sonic/device/arm64-supermicro_sse_g3748-r0/supermicro_sse_g3748/ /usr/share/sonic/device/arm64-supermicro_sse_g3748-r0/sse_g3748
+fi
+
+hwclock -s
+
+exit 0
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/sse-g3748_plt_setup.sh b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/sse-g3748_plt_setup.sh
new file mode 100644
index 0000000000..dfbd649f30
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/sse-g3748_plt_setup.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+fw_uboot_env_cfg()
+{
+ echo "Setting up U-Boot environment..."
+ MACH_FILE="/host/machine.conf"
+ PLATFORM=`sed -n 's/onie_platform=\(.*\)/\1/p' $MACH_FILE`
+
+ FW_ENV_DEFAULT='/dev/mtd1 0 0x10000 0x10000'
+
+ echo $FW_ENV_DEFAULT
+ echo $FW_ENV_DEFAULT > /etc/fw_env.config
+}
+
+sse_g3748_profile()
+{
+ MAC_ADDR=$(fw_printenv -n ethaddr)
+ find /usr/share/sonic/device/*sse_g3748* -name profile.ini | xargs sed -i "s/switchMacAddress=.*/switchMacAddress=$MAC_ADDR/g"
+ echo "SSE-G3748 Updating switch mac address ${MAC_ADDR}"
+}
+
+update_modulelist()
+{
+ MODULE_FILE="/etc/modules-load.d/supermicro.conf"
+
+ echo "# Module list to load during the boot" > $MODULE_FILE
+ echo "mvIntDrv" >> $MODULE_FILE
+ echo "psample" >> $MODULE_FILE
+}
+
+haveged_service_cfg()
+{
+ # Workaround for failing haveged.service
+ sed -i 's/^DAEMON_ARGS=.*/DAEMON_ARGS="-w 1024 -d 16"/' /etc/default/haveged
+}
+
+main()
+{
+ echo "Executing sse-g3748_plt_setup.sh ....."
+ fw_uboot_env_cfg
+ sse_g3748_profile
+ update_modulelist
+ haveged_service_cfg
+}
+
+main $@
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/techfile_v2.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/techfile_v2.py
new file mode 100644
index 0000000000..1b19b7a33d
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/scripts/techfile_v2.py
@@ -0,0 +1,88 @@
+#!/usr/bin/python
+import os
+import sys
+import re
+import time
+import sys
+
+interface_output = str(os.popen('show interface stat').read())
+pattern_int = re.findall('Ethernet[0-9]+',interface_output)
+
+os.system('sudo config feature state iccpd enabled')
+mclag_output = str(os.popen('mclagdctl dump state').read())
+
+commands = []
+
+if not mclag_output:
+
+ commands = commands + ['show platform syseeprom', 'show version', 'show boot', 'show tacacs', 'show radius', 'show aaa',
+ 'show platform psustatus', 'show platform pcieinfo', 'show platform temp',
+ 'show platform summary', 'show platform firmware status',
+ 'show platform fan', 'show interface status', 'sudo ifconfig -a', 'show ip interface',
+ 'show vlan brief', 'show lldp neighbors' , 'show lldp table', 'show ztp status', 'show ip bgp summary', 'show ip bgp neighbors', 'show route-map',
+ 'show interface portchannel', 'show ip route', 'sudo route -n', 'show arp', 'sudo arp -n', 'show mac',
+ 'show acl rule', 'sudo aclshow -a -vv', 'show acl table', 'show interface counters -a', 'show int autoneg status',
+ 'mclagdctl dump state','sudo show system-health detail', 'show system-mem',
+ 'docker ps', 'top -n 1', 'show uptime', 'show reboot-cause history',
+ 'sudo show system-health summary','show int transceiver presence', 'show int transceiver eeprom', 'show int transceiver error-status',
+ 'show int transceiver lpmode', 'show clock', 'show ntp', 'sudo timedatectl status', 'show runningconfiguration all']
+
+else:
+
+ mclag_domain = re.findall('Domain id: [0-9]+',mclag_output)
+ mclag_final = mclag_domain[0].split(':')
+ commands = commands + ['show platform syseeprom', 'show version', 'show boot', 'show tacacs', 'show radius', 'show aaa',
+ 'show platform psustatus', 'show platform pcieinfo', 'show platform temp',
+ 'show platform summary', 'show platform firmware status',
+ 'show platform fan', 'show interface status', 'sudo ifconfig -a', 'show ip interface',
+ 'show vlan brief', 'show lldp neighbors' , 'show lldp table', 'show ztp status', 'show ip bgp summary', 'show ip bgp neighbors', 'show route-map',
+ 'show interface portchannel', 'show ip route', 'sudo route -n', 'show arp', 'sudo arp -n', 'show mac',
+ 'show acl rule', 'sudo aclshow -a -vv', 'show acl table', 'show interface counters -a', 'show int autoneg status',
+ 'mclagdctl dump state', ('mclagdctl dump mac -i ' + str(mclag_final[1])), ('mclagdctl dump arp -i ' + str(mclag_final[1])),
+ 'sudo show system-health detail', 'show system-mem',
+ 'docker ps', 'top -n 1', 'show uptime', 'show reboot-cause history',
+ 'sudo show system-health summary','show int transceiver presence', 'show int transceiver eeprom', 'show int transceiver error-status',
+ 'show int transceiver lpmode', 'show clock', 'show ntp', 'sudo timedatectl status', 'show runningconfiguration all']
+
+output = ''
+
+print('Fetching data....This might take a few minutes...')
+
+toolbar_width = 83
+
+# setup toolbar
+sys.stdout.write("[%s]" % (" " * toolbar_width))
+sys.stdout.flush()
+sys.stdout.write("\b" * (toolbar_width+1)) # return to start of line, after '['
+
+for command in commands:
+ time.sleep(0.1)
+ output = output + str(command) + '\n'
+ output = output + os.popen(str(command)).read() + '\n'
+ output = str(output)
+# update the bar
+ sys.stdout.write("-")
+ sys.stdout.flush()
+
+for interface in pattern_int:
+ time.sleep(0.1)
+ int_command = '\n' + 'show interface counters detailed ' + str(interface) + '\n'
+ output = '\n' + output + int_command + '\n'
+ output = output + os.popen(str(int_command)).read()
+ output = str(output)
+# update the bar
+ sys.stdout.write("-")
+ sys.stdout.flush()
+
+# end the progress bar
+sys.stdout.write("\n")
+
+print('Generated a text file techsupport.txt in the tmp directory')
+orig_stdout = sys.stdout
+f = open('/tmp/techsupport.txt', 'w')
+sys.stdout = f
+
+print(output)
+
+sys.stdout = orig_stdout
+f.close()
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/service/sse-g3748-init.service b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/service/sse-g3748-init.service
new file mode 100644
index 0000000000..201f60ada7
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/service/sse-g3748-init.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Platform SSE-G3748 Service
+Before=pmon.service
+After=sysinit.target
+DefaultDependencies=no
+
+[Service]
+ExecStart=/usr/local/bin/sse-g3748-init.sh
+KillSignal=SIGKILL
+SuccessExitStatus=SIGKILL
+#StandardOutput=tty
+
+[Install]
+WantedBy=multi-user.target
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/setup.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/setup.py
new file mode 100644
index 0000000000..bc44c7ddd7
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/setup.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+
+import os
+from setuptools import setup
+os.listdir
+
+setup(
+ name='sonic_platform',
+ version='1.0',
+ description='Module to initialize Supermicro SSE-G3748 platforms',
+
+ packages=['sonic_platform','sonic_platform.test'],
+ package_dir={'sonic_platform': 'sse-g3748/sonic_platform'},
+)
+
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/__init__.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/__init__.py
new file mode 100644
index 0000000000..4bfefa0fb6
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/__init__.py
@@ -0,0 +1,3 @@
+__all__ = ["platform", "chassis"]
+from sonic_platform import *
+
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/chassis.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/chassis.py
new file mode 100644
index 0000000000..975e843216
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/chassis.py
@@ -0,0 +1,548 @@
+#!/usr/bin/env python
+##################################################################
+# Module contains an implementation of SONiC Platform Base API and
+# provides the platform information
+##################################################################
+
+try:
+ import os
+ import sys
+ import glob
+ from sonic_platform_base.chassis_base import ChassisBase
+ from sonic_platform.sfp import Sfp
+ from sonic_platform.eeprom import Eeprom
+ from sonic_platform.fan import Fan
+ from .fan_drawer import RealDrawer
+ from sonic_platform.psu import Psu
+ from sonic_platform.thermal import Thermal
+ from sonic_py_common import logger
+ from sonic_platform.component import Component
+
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+smbus_present = 1
+try:
+ import smbus
+except ImportError as e:
+ smbus_present = 0
+
+if sys.version_info[0] < 3:
+ import commands as cmd
+else:
+ import subprocess as cmd
+
+
+MAX_SELECT_DELAY = 3600
+COPPER_PORT_START = 1
+COPPER_PORT_END = 48
+SFP_PORT_START =49
+SFP_PORT_END = 54
+PORT_END = 54
+MAX_COMPONENT=3
+
+# Device counts
+MAX_G3748_FAN_DRAWERS = 1
+MAX_G3748_FANS_PER_DRAWER = 2
+MAX_G3748_PSU = 2
+MAX_G3748_THERMAL = 2
+
+SYSLOG_IDENTIFIER = "chassis"
+sonic_logger=logger.Logger(SYSLOG_IDENTIFIER)
+
+class Chassis(ChassisBase):
+ """
+ Platform-specific Chassis class
+ derived from Dell S6000 platform.
+ customized for the platform.
+ """
+ reset_reason_dict = {}
+ reset_reason_dict[0x02] = ChassisBase.REBOOT_CAUSE_POWER_LOSS
+ reset_reason_dict[0x20] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC
+
+ reset_reason_dict[0x08] = ChassisBase.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU
+ reset_reason_dict[0x10] = ChassisBase.REBOOT_CAUSE_WATCHDOG
+ PLATFORM_ROOT_PATH = "/usr/share/sonic/device"
+ PMON_HWSKU_PATH = "/usr/share/sonic/hwsku"
+ HOST_CHK_CMD = "docker > /dev/null 2>&1"
+ PLATFORM = "arm64-supermicro_sse_g3748-r0"
+ HWSKU = "supermicro_sse_g3748"
+
+ I2C_CLASS_DIR = "/sys/class/i2c-adapter/"
+ I2C_DEV_MAPPING = (['i2c-0/0-0066/hwmon/', 1])
+
+ def __init__(self):
+ ChassisBase.__init__(self)
+ self.system_led_supported_color = ['off', 'green', 'amber', 'blue', 'blinking green', 'blinking amber', 'blinking blue']
+ # Port numbers for Initialize SFP list
+ self.COPPER_PORT_START = COPPER_PORT_START
+ self.COPPER_PORT_END = COPPER_PORT_END
+ self.SFP_PORT_START = SFP_PORT_START
+ self.SFP_PORT_END = SFP_PORT_END
+ self.PORT_END = PORT_END
+
+ G3748CPLD_I2C_DIR = "/sys/bus/i2c/devices/0-0066/"
+
+ # for non-sfp ports create dummy objects for copper / non-sfp ports
+ for index in range(self.COPPER_PORT_START, self.COPPER_PORT_END+1):
+ sfp_node = Sfp(index, 'RJ45', 'N/A', 'N/A')
+ self._sfp_list.append(sfp_node)
+
+ # Verify optoe2 driver SFP eeprom devices were enumerated and exist
+ # then create the sfp nodes
+ eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"
+ mux_dev = sorted(glob.glob("/sys/class/i2c-adapter/i2c-[2-7]"))
+ y = 0
+ for index in range(self.SFP_PORT_START, self.SFP_PORT_END+1):
+ mux_dev_num = mux_dev[y]
+ port_i2c_map = mux_dev_num[-1]
+ y = y + 1
+ port_eeprom_path = eeprom_path.format(port_i2c_map)
+ if not os.path.exists(port_eeprom_path):
+ sonic_logger.log_info("path %s didnt exist" % port_eeprom_path)
+ sfp_node = Sfp(index, 'SFP', port_eeprom_path, port_i2c_map)
+ self._sfp_list.append(sfp_node)
+ self.sfp_event_initialized = False
+
+ # Instantiate ONIE system eeprom object
+ self._eeprom = Eeprom()
+
+ # Construct lists fans, power supplies, thermals & components
+ drawer_num = MAX_G3748_FAN_DRAWERS
+ fan_num_per_drawer = MAX_G3748_FANS_PER_DRAWER
+ drawer_ctor = RealDrawer
+ fan_index = 0
+ for drawer_index in range(drawer_num):
+ drawer = drawer_ctor(drawer_index)
+ self._fan_drawer_list.append(drawer)
+ for index in range(fan_num_per_drawer):
+ fan = Fan(fan_index, drawer)
+ fan_index += 1
+ drawer._fan_list.append(fan)
+ self._fan_list.append(fan)
+
+ for i in range(MAX_G3748_PSU):
+ psu = Psu(i)
+ self._psu_list.append(psu)
+
+ for i in range(MAX_G3748_THERMAL):
+ thermal = Thermal(i)
+ self._thermal_list.append(thermal)
+
+ for i in range(MAX_COMPONENT):
+ component = Component(i)
+ self._component_list.append(component)
+
+ self.fan_sys_frontled_reg = G3748CPLD_I2C_DIR+"fan_sys_frontled".format()
+
+ def _get_i2c_register(self, reg_file):
+ # On successful read, returns the value read from given
+ # reg_name and on failure returns 'ERR'
+ rv = 'ERR'
+
+ if (not os.path.isfile(reg_file)):
+ return rv
+
+ try:
+ with open(reg_file, 'r') as fd:
+ rv = fd.read()
+ except Exception as e:
+ rv = 'ERR'
+
+ rv = rv.rstrip('\r\n')
+ rv = rv.lstrip(" ")
+ return rv
+
+ def _set_i2c_register(self, reg_file, value):
+ # On successful write, the value read will be written on
+ # reg_name and on failure returns 'ERR'
+ rv = 'ERR'
+
+ if (not os.path.isfile(reg_file)):
+ return rv
+
+ try:
+ with open(reg_file, 'w') as fd:
+ rv = fd.write(str(value))
+ except Exception as e:
+ rv = 'ERR'
+
+ # Ensure that the write operation has succeeded
+ if (int(self._get_i2c_register(reg_file)) != value ):
+ time.sleep(3)
+ if (int(self._get_i2c_register(reg_file)) != value ):
+ rv = 'ERR'
+
+ return rv
+
+ def __is_host(self):
+ return os.system(self.HOST_CHK_CMD) == 0
+
+ def get_presence(self):
+ """
+ Retrieves the presence of the chassis
+ Returns:
+ bool: True if chassis is present, False if not
+ """
+ return True
+
+ def get_status(self):
+ """
+ Retrieves the operational status of the chassis
+ Returns:
+ bool: A boolean value, True if chassis is operating properly
+ False if not
+ """
+ return True
+
+ ##############################################
+ # EEPROM methods
+ ##############################################
+
+ def get_eeprom(self):
+ """
+ Retreives eeprom device on this chassis
+ Returns:
+ An object representing the hardware eeprom device
+ """
+ return self._eeprom
+
+ def get_name(self):
+ """
+ Retrieves the name of the chassis
+ Returns:
+ string: The name of the chassis
+ """
+ return self._eeprom.modelstr()
+
+ def get_model(self):
+ """
+ Retrieves the model number (or part number) of the chassis
+ Returns:
+ string: Model/part number of chassis
+ """
+ return self._eeprom.part_number_str()
+
+ def get_serial(self):
+ """
+ Retrieves the serial number of the chassis (Service tag)
+ Returns:
+ string: Serial number of chassis
+ """
+ return self._eeprom.serial_str()
+
+ def get_revision(self):
+ """
+ Retrieves the device version of the chassis
+ Returns:
+ string: device version of chassis
+ """
+ return self._eeprom.device_version()
+
+ def get_base_mac(self):
+ """
+ Retrieves the base MAC address for the chassis
+
+ Returns:
+ A string containing the MAC address in the format
+ 'XX:XX:XX:XX:XX:XX'
+ """
+ return self._eeprom.base_mac_addr()
+
+ def get_serial_number(self):
+ """
+ Retrieves the hardware serial number for the chassis
+
+ Returns:
+ A string containing the hardware serial number for this
+ chassis.
+ """
+ return self._eeprom.serial_number_str()
+
+ def get_system_eeprom_info(self):
+ """
+ Retrieves the full content of system EEPROM information for the
+ chassis
+
+ Returns:
+ A dictionary where keys are the type code defined in
+ OCP ONIE TlvInfo EEPROM format and values are their
+ corresponding values.
+ """
+ return self._eeprom.system_eeprom_info()
+
+ ##############################################
+ # SFP methods
+ ##############################################
+
+ def get_sfp(self, index):
+ """
+ Retrieves sfp represented by (1-based) index
+ Args:
+ index: An integer, the index (1-based) of the sfp to retrieve.
+ The index should be the sequence of physical SFP ports in a chassis,
+ starting from 1.
+ For example, 1 for first SFP port in the chassis and so on.
+ Returns:
+ An object dervied from SfpBase representing the specified sfp
+ """
+ sfp = None
+ try:
+ # The index will start from 1
+ sfp = self._sfp_list[index-1]
+ except IndexError:
+ sys.stderr.write("SFP index {} out of range (1-{})\n".format(
+ index, len(self._sfp_list)))
+ return sfp
+
+ #index = index - 1
+ #return super(Chassis, self).get_sfp(index)
+
+ def get_port_or_cage_type(self, index):
+ """
+ Retrieves sfp port or cage type corresponding to physical port
+
+ Args:
+ index: An integer (>=0), the index of the sfp to retrieve.
+ The index should correspond to the physical port in a chassis.
+ For example:-
+ 1 for Ethernet0, 2 for Ethernet4 and so on for one platform.
+ 0 for Ethernet0, 1 for Ethernet4 and so on for another platform.
+ Returns:
+ The masks of all types of port or cage that can be supported on the port
+ Types are defined in sfp_base.py
+ Eg.
+ Both SFP and SFP+ are supported on the port, the return value should be 0x0a
+ which is 0x02 | 0x08
+ """
+ #if index in range(self.COPPER_PORT_START, self.COPPER_PORT_END):
+ if (index >= self.COPPER_PORT_START and index <= self.COPPER_PORT_END):
+ from sonic_platform_base.sfp_base import SfpBase
+ return SfpBase.SFP_PORT_TYPE_BIT_RJ45
+ raise NotImplementedError
+
+ def get_change_event(self, timeout=0):
+ """
+ Returns a nested dictionary containing all devices which have
+ experienced a change at chassis level
+ Args:
+ timeout: Timeout in milliseconds (optional). If timeout == 0,
+ this method will block until a change is detected.
+ Returns:
+ (bool, dict):
+ - True if call successful, False if not;
+ - A nested dictionary where key is a device type,
+ value is a dictionary with key:value pairs in the format of
+ {'device_id':'device_event'},
+ where device_id is the device ID for this device and
+ device_event,
+ status='1' represents device inserted,
+ status='0' represents device removed.
+ Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
+ indicates that fan 0 has been removed, fan 2
+ has been inserted and sfp 11 has been removed.
+ """
+ # Initialize SFP event first
+ if not self.sfp_event_initialized:
+ from sonic_platform.sfp_event import sfp_event
+ self.sfp_event = sfp_event()
+ self.sfp_event.initialize()
+ self.MAX_SELECT_EVENT_RETURNED = self.PORT_END
+ self.sfp_event_initialized = True
+
+ wait_for_ever = (timeout == 0)
+ port_dict = {}
+ if wait_for_ever:
+ # xrcvd will call this monitor loop in the "SYSTEM_READY" state
+ # logger.log_info(" wait_for_ever get_change_event %d" % timeout)
+ timeout = MAX_SELECT_DELAY
+ while True:
+ status = self.sfp_event.check_sfp_status( port_dict, timeout)
+ if not port_dict == {}:
+ break
+ else:
+ # At boot up and in "INIT" state call from xrcvd will have a timeout value
+ # return true without change after timeout and will transition to "SYSTEM_READY"
+ # logger.log_info(" initial get_change_event %d" % timeout )
+ status = self.sfp_event.check_sfp_status( port_dict, timeout)
+
+ if status:
+ return True, {'sfp':port_dict}
+ else:
+ return True, {'sfp':{}}
+
+ ##############################################
+ # THERMAL methods
+ ##############################################
+
+ def get_thermal_manager(self):
+ from .thermal_manager import ThermalManager
+ return ThermalManager
+
+ ##############################################
+ # System LED methods
+ ##############################################
+
+ def initizalize_system_led(self):
+ return True
+
+ def set_status_led(self, color):
+ """
+ Sets the state of the system LED
+
+ Args:
+ color: A string representing the color with which to set the
+ system LED
+
+ Returns:
+ bool: True if system LED state is set successfully, False if not
+ """
+ #sonic_logger.log_warning(" System LED set_status_led color:{}".format(color))
+ if color not in self.system_led_supported_color:
+ return False
+
+ if (color == 'off'):
+ setbits = 0x00
+ elif (color == 'blue'):
+ setbits = 0x03
+ elif (color == 'amber'):
+ setbits = 0x02
+ elif (color == 'green'):
+ setbits = 0x01
+ elif (color == 'blinking blue'):
+ setbits = 0x07
+ elif (color == 'blinking amber'):
+ setbits = 0x06
+ elif (color == 'blinking green'):
+ setbits = 0x05
+ else:
+ return False
+
+ #sonic_logger.log_warning(" System LED set_status_led setbits:{}".format(setbits))
+ # Write sys led
+ #if smbus_present == 0: # called from host (e.g. 'show system-health')
+ # cmdstatus, value = cmd.getstatusoutput('sudo i2cget -y 0 0x66 0x11')
+ # value = int(value, 16)
+ # value = value & 0xF0 | setbits
+ # sonic_logger.log_warning(" System LED set color:{} value:{}".format(color, value))
+ # cmdstatus, value = cmd.getstatusoutput('sudo i2cset -y 0 0x66 0x11 %d' % value)
+ # if cmdstatus:
+ # sonic_logger.log_warning(" System LED set %s failed" % value)
+ # return False
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICEREG = 0x11
+ # value = bus.read_byte_data(DEVICE_ADDRESS, DEVICEREG)
+ # value = value & 0xF0 | setbits
+ # bus.write_byte_data(DEVICE_ADDRESS, DEVICEREG, value)
+ # sonic_logger.log_warning(" System LED set color:{} value:{}".format(color, value))
+
+ value = self._get_i2c_register(self.fan_sys_frontled_reg)
+ value = int(value) & 0xF0 | setbits
+ self._set_i2c_register(self.fan_sys_frontled_reg, value)
+ sonic_logger.log_warning(" System LED set color:{} value:{}".format(color, value))
+
+ return True
+
+ def get_status_led(self):
+ """
+ Gets the state of the system LED
+
+ Returns:
+ A string, one of the valid LED color strings which could be vendor
+ specified.
+ """
+ # Read sys led
+ #if smbus_present == 0: # called from host
+ # cmdstatus, value = cmd.getstatusoutput('sudo i2cget -y 0 0x66 0x11')
+ # value = int(value, 16)
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICE_REG = 0x11
+ # value = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)
+ #value = value & 0x07
+ value = self._get_i2c_register(self.fan_sys_frontled_reg)
+ value = int(value) & 0x07
+
+ if value == 0x00:
+ color = 'off'
+ elif value == 0x01:
+ color = 'green'
+ elif value == 0x02:
+ color = 'amber'
+ elif value == 0x06:
+ color = 'amber_blink'
+ elif value == 0x05:
+ color = 'green_blink'
+ elif value == 0x04:
+ color = 'off'
+ else:
+ return None
+
+ sonic_logger.log_warning(" System LED get color %s" % color)
+ return color
+
+ def get_position_in_parent(self):
+ """
+ Prasanna : This method is added, since M0 test named below fails without this method.
+ platform_tests/api/test_chassis.py::TestChassisApi::test_get_position_in_parent[lab-inno-01]
+ As done in other platforms such as nokia etc, return -1.
+
+ Retrieves 1-based relative physical position in parent device.
+ Returns:
+ integer: The 1-based relative physical position in parent
+ device or -1 if cannot determine the position
+ """
+ return -1
+
+ def is_replaceable(self):
+ """
+ Prasanna : This method is added, since M0 test named below fails without this method.
+ platform_tests/api/test_chassis.py::TestChassisApi::test_is_replaceable[lab-inno-01]
+ As done in other platforms such as nokia etc, return False.
+
+ Indicate whether Chassis is replaceable.
+ Returns:
+ bool: True if it is replaceable.
+ """
+ return False
+
+ def get_reboot_cause(self):
+ """
+ Retrieves the cause of the previous reboot
+ Returns:
+ A tuple (string, string) where the first element is a string
+ containing the cause of the previous reboot. This string must be
+ one of the predefined strings in this class. If the first string
+ is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
+ to pass a description of the reboot cause.
+ """
+ #lrr = self._get_cpld_register('mb_reboot_cause')
+ #if (lrr != 'ERR'):
+ # reset_reason = lrr
+ # if (reset_reason in self.reset_reason_dict):
+ # return (self.reset_reason_dict[reset_reason], None)
+ #
+ return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)
+
+ def get_watchdog(self):
+ """
+ Retrieves hardware watchdog device on this chassis
+
+ Returns:
+ An object derived from WatchdogBase representing the hardware
+ watchdog device
+ """
+ try:
+ if self._watchdog is None:
+ from sonic_platform.watchdog import WatchdogImplBase
+ watchdog_device_path = "/dev/watchdog0"
+ self._watchdog = WatchdogImplBase(watchdog_device_path)
+ except Exception as e:
+ sonic_logger.log_warning(" Fail to load watchdog {}".format(repr(e)))
+
+ return self._watchdog
+
+
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/component.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/component.py
new file mode 100644
index 0000000000..6cbaf70ace
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/component.py
@@ -0,0 +1,166 @@
+########################################################################
+#
+# Module contains an implementation of SONiC Platform Base API and
+# provides the Components' (e.g., BIOS, CPLD, FPGA, etc.) available in
+# the platform
+#
+########################################################################
+
+try:
+ import sys
+ import subprocess
+ from sonic_platform_base.component_base import ComponentBase
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+
+if sys.version_info[0] < 3:
+ import commands as cmd
+else:
+ import subprocess as cmd
+
+
+class Component(ComponentBase):
+ """platform-specific Component class"""
+
+ CHASSIS_COMPONENTS = [
+ ["U-Boot", "Performs initialization during booting"],
+ ["ONIE-VERSION", "ONIE - Open Network Install Environment"],
+ ["System-CPLD", "System - CPLD"],
+ ]
+
+ def __init__(self, component_index):
+ self.index = component_index
+ self.name = self.CHASSIS_COMPONENTS[self.index][0]
+ self.description = self.CHASSIS_COMPONENTS[self.index][1]
+
+ def _get_command_result(self, cmdline):
+ try:
+ proc = subprocess.Popen(cmdline.split(), stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ stdout = proc.communicate()[0]
+ proc.wait()
+ result = stdout.rstrip('\n')
+ except OSError:
+ result = None
+
+ return result
+
+
+ def get_name(self):
+ """
+ Retrieves the name of the component
+
+ Returns:
+ A string containing the name of the component
+ """
+ return self.name
+ def get_model(self):
+ """
+ Retrieves the part number of the component
+
+ Returns:
+ string: Part number of component
+ """
+ return 'NA'
+
+ def get_serial(self):
+ """
+ Retrieves the serial number of the component
+
+ Returns:
+ string: Serial number of component
+ """
+ return 'NA'
+
+ def get_presence(self):
+ """
+ Retrieves the presence of the component
+
+ Returns:
+ bool: True if component is operating properly, False if not
+ """
+ return True
+
+ def get_status(self):
+ """
+ Retrieves the presence of the component
+
+ Returns:
+ bool: True if component is operating properly, False if not
+ """
+ return True
+
+ def get_position_in_parent(self):
+ """
+ Retrieves 1-based relative physical position in parent device.
+ Returns:
+ integer: The 1-based relative physical position in parent
+ device or -1 if cannot determine the position
+ """
+ return -1
+
+ def is_replaceable(self):
+ """
+ Indicate whether Chassis is replaceable.
+ Returns:
+ bool: True if it is replaceable.
+ """
+ return False
+
+ def get_description(self):
+ """
+ Retrieves the description of the component
+
+ Returns:
+ A string containing the description of the component
+ """
+ return self.description
+
+ def get_firmware_version(self):
+ """
+ Retrieves the firmware version of the component
+
+ Returns:
+ A string containing the firmware version of the component
+ """
+
+ if self.index == 0:
+ cmdstatus, uboot_version = cmd.getstatusoutput('grep --null-data ^U-Boot /dev/mtd0ro | cut -d" " -f2')
+ return uboot_version
+
+ if self.index == 1:
+ cmdstatus, onie_version = cmd.getstatusoutput('grep ^onie_version /host/machine.conf | cut -f2 -d"="')
+ return onie_version
+
+ if self.index == 2:
+ cmdstatus, cpld_version = cmd.getstatusoutput('cat /sys/bus/i2c/devices/0-0066/cpld_version')
+ return cpld_version
+
+ def install_firmware(self, image_path):
+ """
+ Installs firmware to the component
+
+ Args:
+ image_path: A string, path to firmware image
+
+ Returns:
+ A boolean, True if install was successful, False if not
+ """
+ return False
+
+
+ def get_available_firmware_version(self, image_path):
+ """
+ Fix for issue: 160170:(SONIC-MGMT) platform_tests post /platform/chassis/component/
+ returns empty reply.
+
+ Retrieves the available firmware version of the component
+ Note: the firmware version will be read from image.
+ Args:
+ image_path: A string, path to firmware image
+ Returns:
+ A string containing the available firmware version of the component
+ """
+ return "N/A"
+
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/eeprom.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/eeprom.py
new file mode 100644
index 0000000000..1fb8adf599
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/eeprom.py
@@ -0,0 +1,321 @@
+#!/usr/bin/env python
+
+########################################################################
+# Supermicro SSE-G3748
+#
+# Module contains platform specific implementation of SONiC Platform
+# Base API and provides the EEPROMs' information.
+#
+# The different EEPROMs available are as follows:
+# - System EEPROM : Contains Serial number, Service tag, Base MA
+# address, etc. in ONIE TlvInfo EEPROM format.
+# - PSU EEPROM : Contains Serial number, Part number, Service Tag,
+# PSU type, Revision.
+# - Fan EEPROM : Contains Serial number, Part number, Service Tag,
+# Fan type, Number of Fans in Fantray, Revision.
+########################################################################
+
+
+try:
+ from sonic_platform_base.sonic_eeprom.eeprom_base import EepromDecoder
+ from sonic_platform_base.sonic_eeprom.eeprom_tlvinfo import TlvInfoDecoder
+ from sonic_py_common import logger
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+
+# PSU eeprom fields in format required by EepromDecoder
+psu_eeprom_format = [
+ ('Frame Head', 's', 1), ('PSU Rev', 's', 3), ('Reserved_1', 's', 3),
+ ('Checksum', 's', 1), ('Reserved_2', 's', 2),
+ ('Part Number', 's', 17), ('Vendor', 's', 7), ('Serial Number', 's', 25),
+ ('Specification', 's', 141), ('Power', 's', 10), ('Mfg Date', 's', 3),
+ ('Reserved_3', 's', 43)
+ ]
+
+# Fan eeprom fields in format required by EepromDecoder
+fan_eeprom_format = [
+ ('Common Head', 's', 8),
+ ('Board Area Ver', 's', 1), ('Board Area Len', 's', 1), ('Language Code', 's', 1),
+ ('Mfg Date', 's', 3), ('Mfg TypeLen', 's', 1), ('Mfg Name', 's', 3),
+ ('Model TypeLen', 's', 1), ('Model', 's', 13),
+ ('Serial Number TypeLen', 's', 1), ('Serial Number', 's', 15),
+ ('Part Number TypeLen', 's',1), ('Part Number', 's', 12),
+ ('FRU TypeLen', 's', 1), ('FRU Id', 's', 1),
+ ('PCB Part Number TypeLen', 's', 1), ('PCB Part Number', 's', 12),
+ ('End Encoder', 's', 1),
+ ('Reserved', 's', 179)
+ ]
+
+sonic_logger = logger.Logger('eeprom')
+
+class Eeprom(TlvInfoDecoder):
+ """Supermicro SSE-G3748 platform-specific EEPROM class"""
+
+ I2C_DIR = "/sys/class/i2c-adapter/"
+
+ def __init__(self, is_psu=False, psu_index=0, is_fan=False, fan_index=0):
+ self.is_psu_eeprom = is_psu
+ self.is_fan_eeprom = is_fan
+ self.is_sys_eeprom = not (is_psu | is_fan)
+
+ if self.is_sys_eeprom:
+ self.start_offset = 0
+ #self.eeprom_path = "/etc/sonic/eeprom"
+ self.eeprom_path = self.I2C_DIR + "i2c-0/0-0054/eeprom"
+ # System EEPROM is in ONIE TlvInfo EEPROM format
+ super(Eeprom, self).__init__(self.eeprom_path,
+ self.start_offset, '', True)
+ self._load_system_eeprom()
+ else:
+ #print ("No other eeprom")
+ if self.is_psu_eeprom:
+ self.index = psu_index
+ self.start_offset = 0
+ self.eeprom_path = self.I2C_DIR + "i2c-9/9-005{}/eeprom".format(self.index + 5)
+ self.format = psu_eeprom_format
+
+ # Decode device eeprom as per specified format
+ EepromDecoder.__init__(self, self.eeprom_path, self.format, self.start_offset, '', True)
+ #sonic_logger.log_warning("_load_device_eeprom PSU##{}".format(self.index))
+ #sonic_logger.log_warning("eeprom_path for PSU## is {}".format(self.eeprom_path))
+ else:
+ self.index = fan_index
+ self.start_offset = 0
+ self.eeprom_path = self.I2C_DIR + "i2c-8/8-005{}/eeprom".format(self.index + 5)
+ self.format = fan_eeprom_format
+
+ # Fan EEPROM is in ONIE TlvInfo EEPROM format
+ EepromDecoder.__init__(self, self.eeprom_path, self.format, self.start_offset, '', True)
+ #sonic_logger.log_warning("_load_device_eeprom FAN##{}".format(self.index))
+ #sonic_logger.log_warning("eeprom_path for FAN## is {}".format(self.eeprom_path))
+
+ self._load_device_eeprom()
+
+ def _load_system_eeprom(self):
+ """
+ Reads the system EEPROM and retrieves the values corresponding
+ to the codes defined as per ONIE TlvInfo EEPROM format and fills
+ them in a dictionary.
+ """
+ try:
+ # Read System EEPROM as per ONIE TlvInfo EEPROM format.
+ self.eeprom_data = self.read_eeprom()
+ except Exception as e:
+ self.base_mac = 'NA'
+ self.serial_number = 'NA'
+ self.part_number = 'NA'
+ self.model_str = 'NA'
+ self.serial = 'NA'
+ self.device_ver = 'NA'
+ self.eeprom_tlv_dict = dict()
+ else:
+ eeprom = self.eeprom_data
+ self.eeprom_tlv_dict = dict()
+
+ if not self.is_valid_tlvinfo_header(eeprom):
+ self.base_mac = 'NA'
+ self.serial_number = 'NA'
+ self.part_number = 'NA'
+ self.model_str = 'NA'
+ self.serial = 'NA'
+ self.device_ver = 'NA'
+ return
+
+ total_length = (eeprom[9] << 8) | eeprom[10]
+ tlv_index = self._TLV_INFO_HDR_LEN
+ tlv_end = self._TLV_INFO_HDR_LEN + total_length
+
+ # Construct dictionary of eeprom TLV entries
+ while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end:
+ if not self.is_valid_tlv(eeprom[tlv_index:]):
+ break
+
+ tlv = eeprom[tlv_index:tlv_index + 2
+ + eeprom[tlv_index + 1]]
+ code = "0x%02X" % (tlv[0])
+
+ if tlv[0] == self._TLV_CODE_VENDOR_EXT:
+ value = str((tlv[2] << 24) | (tlv[3] << 16) |
+ (tlv[4]<< 8) | tlv[5])
+ value += str(tlv[6:6 + tlv[1]])
+ else:
+ name, value = self.decoder(None, tlv)
+
+ self.eeprom_tlv_dict[code] = value
+ if eeprom[tlv_index] == self._TLV_CODE_CRC_32:
+ break
+
+ tlv_index += eeprom[tlv_index+1] + 2
+
+ self.base_mac = self.eeprom_tlv_dict.get(
+ "0x%X" % (self._TLV_CODE_MAC_BASE), 'NA')
+ self.serial_number = self.eeprom_tlv_dict.get(
+ "0x%X" % (self._TLV_CODE_SERIAL_NUMBER), 'NA')
+ self.part_number = self.eeprom_tlv_dict.get(
+ "0x%X" % (self._TLV_CODE_PART_NUMBER), 'NA')
+ self.model_str = self.eeprom_tlv_dict.get(
+ "0x%X" % (self._TLV_CODE_PRODUCT_NAME), 'NA')
+ #self.serial = self.eeprom_tlv_dict.get(
+ # "0x%X" % (self._TLV_CODE_SERVICE_TAG), 'NA')
+ self.serial = self.eeprom_tlv_dict.get(
+ "0x%X" % (self._TLV_CODE_SERIAL_NUMBER), 'NA')
+ self.device_ver = self.eeprom_tlv_dict.get(
+ "0x%X" % (self._TLV_CODE_DEVICE_VERSION), 'NA')
+
+ def _load_device_eeprom(self):
+ """
+ Reads the Fan/PSU EEPROM and interprets as per the specified format
+ """
+ self.serial_number = 'NA'
+ self.part_number = 'NA'
+ self.model_str = 'NA'
+ self.service_tag = 'NA'
+ self.mfg_date = 'NA'
+ self.hw_rev = 'NA'
+
+ # PSU device eeproms use proprietary format
+ if self.is_psu_eeprom:
+ try:
+ # Read Fan/PSU EEPROM as per the specified format.
+ self.eeprom_data = EepromDecoder.read_eeprom(self)
+ except Exception as e:
+ sonic_logger.log_warning("Unable to read device eeprom for PSU#{}".format(self.index))
+ return
+
+ # Bail out if PSU eeprom unavailable
+ if self.eeprom_data[0] == 255:
+ sonic_logger.log_warning("Uninitialized device eeprom for PSU#{}".format(self.index))
+ return
+
+ (valid, data) = self._get_eeprom_field("Model")
+ if valid:
+ self.model_str = data.decode()
+
+ (valid, data) = self._get_eeprom_field("Part Number")
+ if valid:
+ self.part_number = data.decode()
+
+ (valid, data) = self._get_eeprom_field("PSU Rev")
+ if valid:
+ self.hw_rev = data.decode()
+
+ # Early PSU device eeproms were not programmed with serial #
+ try:
+ (valid, data) = self._get_eeprom_field("Serial Number")
+ if valid:
+ self.serial_number = data.decode()
+ except Exception as e:
+ sonic_logger.log_warning("Unable to read serial# of PSU#{}".format(self.index))
+ return
+
+ # Fan device eeproms use proprietary proformat
+ else:
+ # Temporary hardcoded due to no eeprom data in FAN module
+ self.model_str = 'NA'
+ self.part_number = 'NA'
+ self.serial_number = 'NA'
+
+ try:
+ # Read Fan EEPROM as per ONIE TlvInfo EEPROM format.
+ self.eeprom_data = EepromDecoder.read_eeprom(self)
+ except Exception as e:
+ sonic_logger.log_warning("Unable to read device eeprom for Fan#{}".format(self.index))
+ return
+
+ # Bail out if FAN eeprom unavailable
+ if self.eeprom_data[0] == 255 or self.eeprom_data[0] == 15:
+ sonic_logger.log_warning("Uninitialized device eeprom for Fan#{}".format(self.index))
+ return
+
+ (valid, data) = self._get_eeprom_field("Model")
+ if valid:
+ self.model_str = data.decode()
+
+ (valid, data) = self._get_eeprom_field("Part Number")
+ if valid:
+ self.part_number = data.decode()
+
+ # Early FAN device eeproms were not programmed with serial #
+ try:
+ (valid, data) = self._get_eeprom_field("Serial Number")
+ if valid:
+ self.serial_number = data.decode()
+ except Exception as e:
+ sonic_logger.log_warning("Unable to read serial# of FAN#{}".format(self.index))
+ return
+
+ def _get_eeprom_field(self, field_name):
+ """
+ For a field name specified in the EEPROM format, returns the
+ presence of the field and the value for the same.
+ """
+ field_start = 0
+ for field in self.format:
+ field_end = field_start + field[2]
+ if field[0] == field_name:
+ return (True, self.eeprom_data[field_start:field_end])
+ field_start = field_end
+
+ return (False, None)
+
+ def serial_number_str(self):
+ """
+ Returns the serial number.
+ """
+ return self.serial_number
+
+ def part_number_str(self):
+ """
+ Returns the part number.
+ """
+ return self.part_number
+
+ def revision_str(self):
+ """
+ Return revision number
+ """
+ return self.hw_rev
+
+ def airflow_fan_type(self):
+ """
+ Returns the airflow fan type.
+ """
+ if self.is_psu_eeprom:
+ return int(self.psu_type.encode('hex'), 16)
+ if self.is_fan_eeprom:
+ return int(self.fan_type.encode('hex'), 16)
+
+ # System EEPROM specific methods
+ def base_mac_addr(self):
+ """
+ Returns the base MAC address found in the system EEPROM.
+ """
+ return self.base_mac
+
+ def modelstr(self):
+ """
+ Returns the Model name.
+ """
+ return self.model_str
+
+ def serial_str(self):
+ """
+ Returns the servicetag number.
+ Currently, we treat it as serial number from syseeprom
+ """
+ return self.serial
+
+ def device_version(self):
+ """
+ Returns the device version.
+ """
+ return self.device_ver
+
+ def system_eeprom_info(self):
+ """
+ Returns a dictionary, where keys are the type code defined in
+ ONIE EEPROM format and values are their corresponding values
+ found in the system EEPROM.
+ """
+ return self.eeprom_tlv_dict
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/fan.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/fan.py
new file mode 100644
index 0000000000..155e5f9439
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/fan.py
@@ -0,0 +1,576 @@
+########################################################################
+# Supermicro SSE-G3748
+#
+# Module contains an implementation of SONiC Platform Base API and
+# provides the Fans' information which are available in the platform
+#
+########################################################################
+
+
+try:
+ import math
+ import os
+ import sys
+ import time
+ from sonic_platform_base.fan_base import FanBase
+ from sonic_platform.eeprom import Eeprom
+ from sonic_py_common import logger
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+if sys.version_info[0] < 3:
+ import commands as cmd
+else:
+ import subprocess as cmd
+
+smbus_present = 1
+try:
+ import smbus
+except ImportError as e:
+ smbus_present = 0
+
+sonic_logger = logger.Logger('fan')
+
+
+MAX_G3748_FAN_SPEED = 17600
+WORKING_G3748_FAN_SPEED = 960
+
+CPLD_I2C_ADDR = 0x66
+CPLD_FAN_STATUS_REG = 0x3B
+CPLD_FAN_SPEED_PWM_REG = 0x3C
+CPLD_FAN1_SPEED_CNT_REG = 0x3E
+CPLD_FAN2_SPEED_CNT_REG = 0x3F
+
+#FAN_DIRECTION_EXHAUST = 'exhaust'
+#FAN_DIRECTION_INTAKE = 'intake'
+
+class Fan(FanBase):
+ """Supermicro SSE-G3748 platform-specific Fan class"""
+ I2C_CLASS_DIR = "/sys/class/i2c-adapter/"
+ I2C_DEV_MAPPING = (['i2c-0/0-0066/hwmon/', 1])
+
+ def __init__(self, fan_index, fan_drawer, psu_fan=False, dependency=None):
+ self.is_psu_fan = psu_fan
+ G3748CPLD_I2C_DIR = "/sys/bus/i2c/devices/0-0066/"
+
+ if not self.is_psu_fan:
+ # Fan is 1-based in Supermicro SSE-G3748 platforms
+ self.index = fan_index + 1
+ self.fan_drawer = fan_drawer
+
+ self.set_fan_pwm_reg = G3748CPLD_I2C_DIR+"hwmon/hwmon3/pwm{}".format(self.index)
+ self.get_fan_pwm_reg = G3748CPLD_I2C_DIR+"hwmon/hwmon3/pwm{}".format(self.index)
+ self.get_fan_speed_reg = G3748CPLD_I2C_DIR+"hwmon/hwmon3/fan{}_input".format(self.index)
+ self.get_fan_target_reg = G3748CPLD_I2C_DIR+"hwmon/hwmon3/fan{}_target".format(self.index)
+ self.set_fan_target_reg = G3748CPLD_I2C_DIR+"hwmon/hwmon3/fan{}_target".format(self.index)
+ self.get_fan_status_reg = G3748CPLD_I2C_DIR+"fan_status".format()
+ self.fan_sys_frontled_reg = G3748CPLD_I2C_DIR+"fan_sys_frontled".format()
+
+ #self.fan_speed_cnt_reg = [ CPLD_FAN1_SPEED_CNT_REG, CPLD_FAN2_SPEED_CNT_REG]
+ self.max_fan_speed = MAX_G3748_FAN_SPEED
+ self.supported_led_color = ['off', 'green', 'red']
+
+ # Fan eeprom
+ self.eeprom = Eeprom(is_fan=True, fan_index=self.index)
+ else:
+ # this is a PSU Fan
+ self.index = fan_index
+ self.dependency = dependency
+
+ def _get_i2c_register(self, reg_file):
+ # On successful read, returns the value read from given
+ # reg_name and on failure returns 'ERR'
+ rv = 'ERR'
+
+ if (not os.path.isfile(reg_file)):
+ return rv
+
+ try:
+ with open(reg_file, 'r') as fd:
+ rv = fd.read()
+ except Exception as e:
+ rv = 'ERR'
+
+ rv = rv.rstrip('\r\n')
+ rv = rv.lstrip(" ")
+ return rv
+
+ def _set_i2c_register(self, reg_file, value):
+ # On successful write, the value read will be written on
+ # reg_name and on failure returns 'ERR'
+ rv = 'ERR'
+
+ if (not os.path.isfile(reg_file)):
+ return rv
+
+ try:
+ with open(reg_file, 'w') as fd:
+ rv = fd.write(str(value))
+ except Exception as e:
+ rv = 'ERR'
+
+ # Ensure that the write operation has succeeded
+ if (int(self._get_i2c_register(reg_file)) != value ):
+ time.sleep(3)
+ if (int(self._get_i2c_register(reg_file)) != value ):
+ rv = 'ERR'
+
+ return rv
+
+ def get_name(self):
+ """
+ Retrieves the name of the Fan
+
+ Returns:
+ string: The name of the Fan
+ """
+ if not self.is_psu_fan:
+ return "Fan{}".format(self.index)
+ else:
+ return "PSU{} Fan".format(self.index)
+
+ def get_presence(self):
+ """
+ Retrieves the presence of the Fan Unit
+
+ Returns:
+ bool: True if Fan is present, False if not
+ """
+ #if smbus_present == 0:
+ # #sonic_logger.log_info("PMON fan-smbus ERROR - presence ")
+ # cmdstatus, fanstatus = cmd.getstatusoutput('sudo i2cget -y 0 0x66 0x3B')
+ # fanstatus = int(fanstatus, 16)
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICE_REG = 0x3B
+ # fanstatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)
+ #
+ #if self.index == 1:
+ # fanstatus = fanstatus & 4
+ # if fanstatus == 4:
+ # return True
+ #if self.index == 2:
+ # fanstatus = fanstatus & 8
+ # if fanstatus == 8:
+ # return True
+ #return False
+ fanstatus = self._get_i2c_register(self.get_fan_status_reg)
+
+ if self.index == 1:
+ fanstatus = int(fanstatus) & 4
+ if fanstatus == 4:
+ return True
+ if self.index == 2:
+ fanstatus = int(fanstatus) & 8
+ if fanstatus == 8:
+ return True
+ return False
+
+ def get_model(self):
+ """
+ Retrieves the model number of the Fan
+
+ Returns:
+ string: Model number of Fan.
+ """
+ return self.eeprom.modelstr()
+
+ def get_serial(self):
+ """
+ Retrieves the serial number of the Fan
+
+ Returns:
+ string: Serial number of Fan
+ """
+ return self.eeprom.serial_number_str()
+
+ def get_part_number(self):
+ """
+ Retrieves the part number of the Fan
+
+ Returns:
+ string: Part number of Fan
+ """
+ return self.eeprom.part_number_str()
+
+ def get_service_tag(self):
+ """
+ Retrieves the service tag of the Fan
+
+ Returns:
+ string: Service Tag of Fan
+ """
+ #return self.eeprom.service_tag_str()
+ return 'N/A'
+
+ def get_status(self):
+ """
+ Retrieves the operational status of the Fan
+
+ Returns:
+ bool: True if Fan is operating properly, False if not
+ """
+
+ #if smbus_present == 0:
+ # cmdstatus, fanstatus = cmd.getstatusoutput('sudo i2cget -y 0 0x66 0x3B')
+ # fanstatus = int(fanstatus, 16)
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICE_REG = 0x3B
+ # fanstatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)
+ #if self.index == 1:
+ # fanstatus = fanstatus & 0x10
+ # if fanstatus == 0:
+ # return True
+ #if self.index == 2:
+ # fanstatus = fanstatus & 0x20
+ # if fanstatus == 0:
+ # return True
+ #return False
+ fanstatus = self._get_i2c_register(self.get_fan_status_reg)
+
+ if self.index == 1:
+ fanstatus = int(fanstatus) & 0x10
+ if fanstatus == 0:
+ return True
+ if self.index == 2:
+ fanstatus = int(fanstatus) & 0x20
+ if fanstatus == 0:
+ return True
+ return False
+
+ def get_direction(self):
+ """
+ Retrieves the fan airflow direction
+ Possible fan directions (relative to port-side of device)
+ Returns:
+ A string, either FAN_DIRECTION_INTAKE or
+ FAN_DIRECTION_EXHAUST depending on fan direction
+ """
+
+ #if smbus_present == 0:
+ # cmdstatus, fandir = cmd.getstatusoutput('sudo i2cget -y 0 0x66 0x3B')
+ # fandir = int(fandir, 16)
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICE_REG = 0x3B
+ # fandir = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)
+ #if self.index == 1:
+ # fandir = fandir & 0x01
+ # if fandir == 0:
+ # return self.FAN_DIRECTION_EXHAUST
+ #if self.index == 2:
+ # fandir = fandir & 0x02
+ # if fandir == 0:
+ # return self.FAN_DIRECTION_EXHAUST
+ fandir = self._get_i2c_register(self.get_fan_status_reg)
+
+ if self.index == 1:
+ fandir = int(fandir) & 0x01
+ if fandir == 0:
+ return self.FAN_DIRECTION_EXHAUST
+ if self.index == 2:
+ fandir = int(fandir) & 0x02
+ if fandir == 0:
+ return self.FAN_DIRECTION_EXHAUST
+
+ #return 'intake'
+ return self.FAN_DIRECTION_INTAKE
+
+ def get_position_in_parent(self):
+ """
+ Retrieves 1-based relative physical position in parent device
+ Returns:
+ integer: The 1-based relative physical position in parent device
+ """
+ return self.index
+
+ def is_replaceable(self):
+ """
+ Indicate whether this device is replaceable.
+ Returns:
+ bool: True if it is replaceable.
+ """
+ return True
+
+
+ def get_speed(self):
+ """
+ Retrieves the speed of a Front FAN in the tray in revolutions per
+ minute defined by 1-based index
+ :param index: An integer, 1-based index of the FAN to query speed
+ :return: integer, denoting front FAN speed
+ """
+ speed = 0
+
+ #if smbus_present == 0:
+ # cmdstatus, speedcnt = cmd.getstatusoutput('sudo i2cget -y 0 0x66 %d' % self.fan_speed_cnt_reg[self.index - 1])
+ # speedcnt = int(speedcnt, 16)
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICE_REG = self.fan_speed_cnt_reg[self.index - 1]
+ # speedcnt = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)
+
+ #speed_in_rpm = (5000 * 60) / speedcnt
+ #speed = 100*speed_in_rpm/MAX_G3748_FAN_SPEED
+
+ speed_in_rpm = int(self._get_i2c_register(self.get_fan_speed_reg))
+
+ speed = 100*int(speed_in_rpm)/MAX_G3748_FAN_SPEED
+ if speed > 100:
+ speed = 100
+
+ #sonic_logger.log_warning("fan get_speed speed is %d" % speed )
+ #sonic_logger.log_warning("get_speed FAN{} FAN_RPM={} FAN_PWM={}".format(self.index, speed_in_rpm, speed))
+ return int(speed)
+
+ def get_speed_tolerance(self):
+ """
+ Retrieves the speed tolerance of the fan
+
+ Returns:
+ An integer, the percentage of variance from target speed
+ which is considered tolerable
+ """
+ if self.get_presence():
+ # The tolerance value is fixed as 25% for this platform
+ tolerance = 25
+ else:
+ tolerance = 0
+
+ return tolerance
+
+ def set_speed(self, speed):
+ """
+ Set fan speed to expected value
+ Args:
+ speed: An integer, the percentage of full fan speed to set
+ fan to, in the range 0 (off) to 100 (full speed)
+ Returns:
+ bool: True if set success, False if fail.
+ """
+ if self.is_psu_fan:
+ return False
+
+ # Set current fan duty cycle
+ # - 0x00 : fan off (0 rpm)
+ # - 0x0F : 50% duty cycle (8800 rpm)
+ # - 0x1F : 100% duty cycle (17600 rpm)
+ #fan_speed_pwm_reg_val = int((speed * 31) / 100)
+
+ #if smbus_present == 0:
+ # cmdstatus, rv = cmd.getstatusoutput('sudo i2cset -y 0 0x66 0x3C %d' % fan_speed_pwm_reg_val)
+ # if cmdstatus:
+ # sonic_logger.log_warning("fan set_speed cmdstatus i2c write failed %s" % rv )
+ # return False
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICE_REG = 0x3C
+ # bus.write_byte_data(DEVICE_ADDRESS, DEVICE_REG, fan_speed_pwm_reg_val)
+
+ rv = self._set_i2c_register(self.set_fan_pwm_reg, speed)
+ #sonic_logger.log_warning("fan set_speed PWM reg is %d" % speed )
+ #sonic_logger.log_warning("set_speed FAN{} FAN_PWM_REG={}".format(self.index, speed))
+
+ return True
+
+ ## - 0x00 : fan off
+ ## - 0x40 : 25% duty cycle
+ ## - 0x80 : 50% duty cycle (default)
+ ## - 0xff : 100% duty cycle (full speed)
+ #if speed in range(0, 6):
+ # fandutycycle = 0x00
+ #elif speed in range(6, 41):
+ # fandutycycle = 64
+ #elif speed in range(41, 76):
+ # fandutycycle = 128
+ #elif speed in range(76, 101):
+ # fandutycycle = 255
+ #else:
+ # return False
+
+ #rv = self._set_i2c_register(self.set_fan_speed_reg, fandutycycle)
+ #sonic_logger.log_warning("fan set_speed PWM reg is %d" % speed )
+ #if (rv != 'ERR'):
+ # return True
+ #else:
+ # return False
+
+ def set_status_led(self, color):
+ """
+ Set led to expected color
+ Args:
+ color: A string representing the color with which to set the
+ fan module status LED
+ Returns:
+ bool: True if set success, False if fail.
+
+ off , red and green are the only settings 7215 fans
+ """
+
+ if self.is_psu_fan or (color not in self.supported_led_color):
+ return False
+ if (color == self.STATUS_LED_COLOR_AMBER):
+ return False
+ if (color == self.STATUS_LED_COLOR_RED):
+ value = 0x10
+ elif (color == self.STATUS_LED_COLOR_GREEN):
+ value = 0x20
+ elif (color == self.STATUS_LED_COLOR_OFF):
+ value = 0x00
+ else:
+ return False
+
+ #if smbus_present == 0:
+ # return False
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICEREG = 0x11
+ # original = bus.read_byte_data(DEVICE_ADDRESS, DEVICEREG)
+ # original = original & 0xCF
+ # ledstatus = original | value
+ # if (self.index == 1):
+ # if (color == self.STATUS_LED_COLOR_GREEN):
+ # ledstatus = ledstatus | 0x40
+ # else:
+ # ledstatus = ledstatus & 0xBF
+ # elif self.index == 2:
+ # if (color == self.STATUS_LED_COLOR_GREEN):
+ # ledstatus = ledstatus | 0x80
+ # else:
+ # ledstatus = ledstatus & 0x7F
+ # else:
+ # return False
+
+ # bus.write_byte_data(DEVICE_ADDRESS, DEVICEREG, ledstatus)
+ # #sonic_logger.log_warning("fan set_status_led FAN{} FAN_LED_REG={}".format(self.index, ledstatus))
+
+ original = self._get_i2c_register(self.fan_sys_frontled_reg)
+ original = int(original) & 0xCF
+ ledstatus = original | value
+ if (self.index == 1):
+ if (color == self.STATUS_LED_COLOR_GREEN):
+ ledstatus = ledstatus | 0x40
+ else:
+ ledstatus = ledstatus & 0xBF
+ elif self.index == 2:
+ if (color == self.STATUS_LED_COLOR_GREEN):
+ ledstatus = ledstatus | 0x80
+ else:
+ ledstatus = ledstatus & 0x7F
+ else:
+ return False
+
+ self._set_i2c_register(self.fan_sys_frontled_reg, ledstatus)
+ #sonic_logger.log_warning("set_status_led FAN{} FAN_SYS_LED_REG={} color={}".format(self.index, ledstatus, color))
+
+ return True
+
+ def get_status_led(self):
+ """
+ Gets the state of the fan status LED
+
+ Returns:
+ A string, one of the predefined STATUS_LED_COLOR_* strings.
+ """
+
+ if self.is_psu_fan:
+ return None
+
+ #if smbus_present == 0:
+ # return None
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICE_REG = 0x11
+ # ledstatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)
+ ledstatus = int(self._get_i2c_register(self.fan_sys_frontled_reg))
+ #sonic_logger.log_warning("get_status_led FAN{} FAN_SYS_LED_REG={}".format(self.index, ledstatus))
+
+ if ledstatus & 0x30 == 0x20:
+ if self.index == 1:
+ if ledstatus & 0x40 == 0x40:
+ return self.STATUS_LED_COLOR_GREEN
+ else:
+ return self.STATUS_LED_COLOR_OFF
+ elif self.index == 2:
+ if ledstatus & 0x80 == 0x80:
+ return self.STATUS_LED_COLOR_GREEN
+ else:
+ return self.STATUS_LED_COLOR_OFF
+ else:
+ return self.STATUS_LED_COLOR_OFF
+ elif ledstatus & 0x30 == 0x10:
+ return self.STATUS_LED_COLOR_RED
+ elif ledstatus & 0x30 == 0x00:
+ return self.STATUS_LED_COLOR_OFF
+
+ #elif ledstatus & 0x30 == 0x20:
+ # return self.STATUS_LED_COLOR_RED
+ #elif ledstatus & 0x30 == 0x00:
+ # return self.STATUS_LED_COLOR_OFF
+
+ #if self.index == 1:
+ # ledstatus = (ledstatus & 0x40)
+ # ledstatus = ledstatus >> 4
+ #elif self.index == 2:
+ # ledstatus = (ledstatus & 0x80)
+ # ledstatus = ledstatus >> 6
+ #if ledstatus == 0x02:
+ # return self.STATUS_LED_COLOR_RED
+ #elif ledstatus == 0x1:
+ # return self.STATUS_LED_COLOR_GREEN
+ #else:
+ # return self.STATUS_LED_COLOR_OFF
+
+ def get_target_speed(self):
+ """
+ Retrieves the target (expected) speed of the fan
+
+ Returns:
+ An integer, the percentage of full fan speed, in the range 0
+ (off) to 100 (full speed)
+ """
+ #speed = 0
+
+ #if smbus_present == 0:
+ # cmdstatus, rv = cmd.getstatusoutput('sudo i2cget -y 0 0x66 0x3C')
+ # if cmdstatus:
+ # sonic_logger.log_warning("fan get_target_speed cmdstatus i2c get failed %s" % rv )
+ # return speed
+ # rv = int(rv, 16)
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICE_REG = 0x3C
+ # rv = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)
+
+ #if rv > 0x1F:
+ # sonic_logger.log_warning("fan get_target_speed return value out of boundry")
+ # return speed
+ #speed = rv * 100 / 0x1F
+ speed = int(self._get_i2c_register(self.get_fan_pwm_reg))
+
+ #sonic_logger.log_warning("get_target_speed FAN{} FAN_PWM_REG={}".format(self.index, speed))
+ #sonic_logger.log_warning("fan get_target_speed speed is %d" % int(speed) )
+ return int(speed)
+
+ #fan_duty = self._get_i2c_register(self.set_fan_speed_reg)
+ #if (fan_duty != 'ERR'):
+ # dutyspeed = int(fan_duty)
+ # if dutyspeed == 0:
+ # speed = 0
+ # elif dutyspeed == 64:
+ # speed = 25
+ # elif dutyspeed == 128:
+ # speed = 50
+ # elif dutyspeed == 255:
+ # speed = 100
+ #
+ #return speed
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/fan_drawer.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/fan_drawer.py
new file mode 100644
index 0000000000..e19c6ee385
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/fan_drawer.py
@@ -0,0 +1,102 @@
+#############################################################################
+# Supermicro SSE-G3748
+#
+# Module contains an implementation of SONiC Platform Base API and
+# provides the Fan Drawer status which is available in the platform
+#
+#############################################################################
+
+try:
+ from sonic_platform_base.fan_drawer_base import FanDrawerBase
+ from sonic_py_common import logger
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+sonic_logger = logger.Logger('fan_drawer')
+
+class G3748FanDrawer(FanDrawerBase):
+ def __init__(self, index):
+ super(G3748FanDrawer, self).__init__()
+ self._index = index + 1
+ self._led = None
+
+ def get_index(self):
+ return self._index
+
+ def get_presence(self):
+ return self._fan_list[0].get_presence()
+
+ def get_model(self):
+ """
+ Retrieves the model number of the Fan Drawer
+ Returns:
+ string: Part number of Fan Drawer
+ """
+ return self._fan_list[0].get_model()
+
+ def get_serial(self):
+ """
+ Retrieves the serial number of the Fan Drawer
+ Returns:
+ string: Serial number of Fan
+ """
+ return self._fan_list[0].get_serial()
+
+ def get_status(self):
+ """
+ Retrieves the operational status of the Fan Drawer
+ Returns:
+ bool: True if Fan is operating properly, False if not
+ """
+ return self._fan_list[0].get_status()
+
+ def get_direction(self):
+ return 'intake'
+
+ def set_status_led(self, color):
+ """
+ Sets the state of the fan drawer status LED
+
+ Args:
+ color: A string representing the color with which to set the
+ fan drawer status LED
+
+ Returns:
+ bool: True if status LED state is set successfully, False if not
+ """
+ return self._fan_list[0].set_status_led(color)
+
+ def get_status_led(self):
+ """
+ Gets the state of the fan drawer LED
+
+ Returns:
+ A string, one of the predefined STATUS_LED_COLOR_* strings
+ """
+ return self._fan_list[0].get_status_led()
+
+ def is_replaceable(self):
+ """
+ Indicate whether this device is replaceable.
+ Returns:
+ bool: True if it is replaceable.
+ """
+ return True
+
+ def get_position_in_parent(self):
+ """
+ Retrieves 1-based relative physical position in parent device
+ Returns:
+ integer: The 1-based relative physical position in parent device
+ """
+ return self._index
+
+
+# For Supermicro SSE-G3748 platforms with fan drawer(s)
+class RealDrawer(G3748FanDrawer):
+ def __init__(self, index):
+ super(RealDrawer, self).__init__(index)
+ self._name = 'drawer{}'.format(self._index)
+
+ def get_name(self):
+ return self._name
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/pcie.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/pcie.py
new file mode 100644
index 0000000000..195a6098fd
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/pcie.py
@@ -0,0 +1,57 @@
+#######################################################################
+# Module contains a platform specific implementation of SONiC Platform
+# Base PCIe class
+#######################################################################
+import os
+import re
+
+try:
+ from sonic_platform_base.sonic_pcie.pcie_common import PcieUtil
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+SYSFS_PCI_DEVICE_PATH = '/sys/bus/pci/devices/'
+
+class Pcie(PcieUtil):
+ # Check the current PCIe device with config file and return the result.
+ # It uses bus from _device_id_to_bus_map instead of from default in yaml file.
+ def get_pcie_check(self):
+ self.load_config_file()
+ for item_conf in self.confInfo:
+ id_conf = item_conf["id"]
+ dev_conf = item_conf["dev"]
+ fn_conf = item_conf["fn"]
+ bus_conf = self._device_id_to_bus_map.get(str(id_conf))
+ if bus_conf and self.check_pcie_sysfs(bus=int(bus_conf, base=16), device=int(dev_conf, base=16),
+ func=int(fn_conf, base=16)):
+ item_conf["result"] = "Passed"
+ else:
+ item_conf["result"] = "Failed"
+ return self.confInfo
+
+ # Create bus from device id and store in self._device_id_to_bus_map
+ def _create_device_id_to_bus_map(self):
+ self._device_id_to_bus_map = {}
+ self.load_config_file()
+ device_folders = os.listdir(SYSFS_PCI_DEVICE_PATH)
+ # Search for device folder name pattern in sysfs tree.
+ # If there is a matching pattern found, create an id to bus mapping.
+ # Save the mapping in self._device_id_to_bus_map[ ].
+ # Device folder name pattern: dddd:bb:ii:f
+ # where dddd - 4 hex digit of domain
+ # bb - 2 hex digit of bus
+ # ii - 2 hex digit of id
+ # f - 1 digit of fn
+ for folder in device_folders:
+ pattern_for_device_folder = re.search('....:(..):..\..', folder)
+ if pattern_for_device_folder:
+ bus = pattern_for_device_folder.group(1)
+ with open(os.path.join('/sys/bus/pci/devices', folder, 'device'), 'r') as device_file:
+ # The 'device' file contain an hex repesantaion of the id key in the yaml file.
+ # We will strip the new line character, and remove the 0x prefix that is not needed.
+ device_id = device_file.read().strip().replace('0x', '')
+ self._device_id_to_bus_map[device_id] = bus
+
+ def __init__(self, platform_path):
+ PcieUtil.__init__(self, platform_path)
+ self._create_device_id_to_bus_map()
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/platform.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/platform.py
new file mode 100644
index 0000000000..0b67a68b86
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/platform.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+
+#############################################################################
+#
+# Module contains an implementation of SONiC Platform Base API and
+# provides the platform information
+#
+#############################################################################
+
+try:
+ from sonic_platform_base.platform_base import PlatformBase
+ from sonic_platform.chassis import Chassis
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+
+class Platform(PlatformBase):
+
+ def __init__(self):
+ PlatformBase.__init__(self)
+ self._chassis = Chassis()
+
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/psu.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/psu.py
new file mode 100644
index 0000000000..dc7443afff
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/psu.py
@@ -0,0 +1,527 @@
+#######################################################################
+# Supermicro SSE-G3748
+#
+# Module contains an implementation of SONiC Platform Base API and
+# provides the PSUs' information which are available in the platform
+#
+########################################################################
+
+try:
+ import os
+ import sys
+ from sonic_platform_base.psu_base import PsuBase
+ from sonic_py_common import logger
+ from sonic_platform.eeprom import Eeprom
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+if sys.version_info[0] < 3:
+ import commands as cmd
+else:
+ import subprocess as cmd
+
+smbus_present = 1
+try:
+ import smbus
+except ImportError as e:
+ smbus_present = 0
+
+sonic_logger = logger.Logger('psu')
+
+class Psu(PsuBase):
+ """Supermicro platform-specific PSU class for SSE-G3748 """
+ def __init__(self, psu_index):
+ PsuBase.__init__(self)
+ self.PSU_OUTPUT_VOLTAGE_MIN = 11
+ self.PSU_OUTPUT_VOLTAGE_MAX = 13
+ G3748CPLD_I2C_DIR = "/sys/bus/i2c/devices/0-0066/"
+ # PSU is 1-based in SMC G3748 platforms
+ self.index = psu_index + 1
+ self._fan_list = []
+
+ self.get_psu_voltage_reg = G3748CPLD_I2C_DIR+"hwmon/hwmon3/in{}_input".format(self.index)
+ self.get_psu_status_reg = G3748CPLD_I2C_DIR+"psu_status".format()
+ self.psu_frontled_reg = G3748CPLD_I2C_DIR+"psu_frontled".format()
+
+ # PSU eeprom
+ self.eeprom = Eeprom(is_psu=True, psu_index=self.index)
+
+ def _read_sysfs_file(self, sysfs_file):
+ rv = 'ERR'
+
+ if (not os.path.isfile(sysfs_file)):
+ return rv
+ try:
+ with open(sysfs_file, 'r') as fd:
+ rv = fd.read()
+ except Exception as e:
+ rv = 'ERR'
+
+ rv = rv.rstrip('\r\n')
+ rv = rv.lstrip(" ")
+ return rv
+
+ def _write_sysfs_file(self, sysfs_file, value):
+ rv = 'ERR'
+
+ if (not os.path.isfile(sysfs_file)):
+ return rv
+ try:
+ with open(sysfs_file, 'w') as fd:
+ rv = fd.write(str(value))
+ except Exception as e:
+ rv = 'ERR'
+
+ # Ensure that the write operation has succeeded
+ if (int(self._read_sysfs_file(sysfs_file)) != value ):
+ time.sleep(3)
+ if (int(self._read_sysfs_file(sysfs_file)) != value ):
+ rv = 'ERR'
+
+ return rv
+
+ def get_name(self):
+ """
+ Retrieves the name of the device
+
+ Returns:
+ string: The name of the device
+ """
+ return "PSU{}".format(self.index)
+
+ def get_presence(self):
+ """
+ Retrieves the presence of the Power Supply Unit (PSU)
+
+ Returns:
+ bool: True if PSU is present, False if not
+ """
+
+ #if smbus_present == 0: # if called from psuutil outside of pmon
+ # cmdstatus, psustatus = cmd.getstatusoutput('sudo i2cget -y 0 0x66 0xa')
+ # psustatus = int(psustatus, 16)
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICE_REG = 0xa
+ # psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)
+ #
+ #if self.index == 1:
+ # psustatus = psustatus & 1
+ # if psustatus == 1:
+ # return True
+ #if self.index == 2:
+ # psustatus = psustatus & 2
+ # if psustatus == 2:
+ # return True
+ psustatus = self._read_sysfs_file(self.get_psu_status_reg)
+
+ if self.index == 1:
+ psustatus = int(psustatus) & 1
+ if psustatus == 1:
+ return True
+ if self.index == 2:
+ psustatus = int(psustatus) & 2
+ if psustatus == 2:
+ return True
+
+ return False
+
+ def get_model(self):
+ """
+ Retrieves the model of the PSU
+
+ Returns:
+ string: Model name of PSU.
+ Part number of PSU if model name is not available.
+ """
+ if self.eeprom.modelstr() == "NA":
+ return self.eeprom.part_number_str()
+ else:
+ return self.eeprom.modelstr()
+
+
+ def get_serial(self):
+ """
+ Retrieves the serial number of the PSU
+
+ Returns:
+ string: Serial number of PSU
+ """
+ return self.eeprom.serial_number_str()
+
+
+ def get_part_number(self):
+ """
+ Retrieves the part number of the PSU
+
+ Returns:
+ string: Part number of PSU
+ """
+ return self.eeprom.part_number_str()
+
+ def get_revision(self):
+ """
+ Retrieves the hardware revision number of the PSU
+
+ Returns:
+ string: Revision number of PSU
+ """
+ return self.eeprom.revision_str()
+
+
+ def get_status(self):
+ """
+ Retrieves the operational status of the PSU
+
+ Returns:
+ bool: True if PSU is operating properly, False if not
+ """
+
+ #if smbus_present == 0:
+ # cmdstatus, psustatus = cmd.getstatusoutput('sudo i2cget -y 0 0x66 0xa')
+ # psustatus = int(psustatus, 16)
+ # sonic_logger.log_warning("PMON psu-smbus - presence = 0 ")
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICE_REG = 0xa
+ # psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)
+ #
+ #if self.index == 1:
+ # psustatus = psustatus & 4
+ # if psustatus == 4:
+ # return False
+ #if self.index == 2:
+ # psustatus = psustatus & 8
+ # if psustatus == 8:
+ # return False
+ psustatus = self._read_sysfs_file(self.get_psu_status_reg)
+
+ if self.index == 1:
+ psustatus = int(psustatus) & 4
+ if psustatus == 4:
+ return False
+ if self.index == 2:
+ psustatus = int(psustatus) & 8
+ if psustatus == 8:
+ return False
+
+ return True
+
+ def get_voltage(self):
+ """
+ Retrieves current PSU voltage output
+
+ Returns:
+ A float number, the output voltage in volts,
+ e.g. 12.1
+ """
+ #if smbus_present == 0:
+ # cmdstatus, psustatus = cmd.getstatusoutput('sudo i2cget -y 0 0x66 0xa')
+ # psustatus = int(psustatus, 16)
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICE_REG = 0xa
+ # psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)
+ #if self.index == 1:
+ # psustatus = psustatus & 4
+ # if psustatus == 0:
+ # psu_voltage = 12.0
+ # return psu_voltage
+ #if self.index == 2:
+ # psustatus = psustatus & 8
+ # if psustatus == 0:
+ # psu_voltage = 12.0
+ # return psu_voltage
+ psustatus = self._read_sysfs_file(self.get_psu_status_reg)
+
+ if self.index == 1:
+ psustatus = int(psustatus) & 4
+ if psustatus == 0:
+ psu_voltage = 12.0
+ return psu_voltage
+ if self.index == 2:
+ psustatus = int(psustatus) & 8
+ if psustatus == 0:
+ psu_voltage = 12.0
+ return psu_voltage
+
+ psu_voltage = 0.0
+ return psu_voltage
+
+ def get_position_in_parent(self):
+ """
+ Retrieves 1-based relative physical position in parent device
+ Returns:
+ integer: The 1-based relative physical position in parent device
+ """
+ return self.index
+
+ def is_replaceable(self):
+ """
+ Indicate whether this device is replaceable.
+ Returns:
+ bool: True if it is replaceable.
+ """
+ return True
+
+ def get_powergood_status(self):
+ """
+ Retrieves the powergood status of PSU
+ Returns:
+ A boolean, True if PSU has stablized its output voltages and
+ passed all its internal self-tests, False if not.
+ """
+
+ #if smbus_present == 0:
+ # cmdstatus, psustatus = cmd.getstatusoutput('sudo i2cget -y 0 0x66 0xa')
+ # psustatus = int(psustatus, 16)
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICE_REG = 0xa
+ # psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)
+ #if self.index == 1:
+ # psustatus = psustatus & 4
+ # if psustatus == 0:
+ # return True
+ #if self.index == 2:
+ # psustatus = psustatus & 8
+ # if psustatus == 0:
+ # return True
+ psustatus = self._read_sysfs_file(self.get_psu_status_reg)
+
+ if self.index == 1:
+ psustatus = int(psustatus) & 4
+ if psustatus == 0:
+ return True
+ if self.index == 2:
+ psustatus = int(psustatus) & 8
+ if psustatus == 0:
+ return True
+
+ return False
+
+ def get_status_led(self):
+ """
+ Gets the state of the PSU status LED
+
+ Returns:
+ A string, one of the predefined STATUS_LED_COLOR_* strings.
+ """
+ if self.get_powergood_status():
+ return self.STATUS_LED_COLOR_GREEN
+ else:
+ return self.STATUS_LED_COLOR_OFF
+
+ def set_status_led(self, color):
+ """
+ Sets the state of the PSU status LED
+ Args:
+ color: A string representing the color with which to set the
+ PSU status LED
+ Returns:
+ bool: True if status LED state is set successfully, False if
+ not
+ """
+ # The firmware running in the PSU controls the LED
+ # and the PSU LED state cannot be changed from CPU.
+
+ # Read current psu led register
+ #if smbus_present == 0:
+ # cmdstatus, psuled = cmd.getstatusoutput('sudo i2cget -y 0 0x66 0x12')
+ # psuled = int(psuled, 16)
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICE_REG = 0x12
+ # psuled = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)
+ psuled = self._read_sysfs_file(self.psu_frontled_reg)
+
+ if color == self.STATUS_LED_COLOR_GREEN:
+ if self.index == 1:
+ psuled = int(psuled) & 0x0C | 0x02
+ if self.index == 2:
+ psuled = int(psuled) & 0x03 | 0x08
+ if color == self.STATUS_LED_COLOR_RED:
+ if self.index == 1:
+ psuled = int(psuled) & 0x0C | 0x01
+ if self.index == 2:
+ psuled = int(psuled) & 0x03 | 0x04
+ if color == self.STATUS_LED_COLOR_OFF:
+ if self.index == 1:
+ psuled = int(psuled) & 0x0C
+ if self.index == 2:
+ psuled = int(psuled) & 0x03
+
+ #if smbus_present == 0:
+ # cmdstatus, psustatus = cmd.getstatusoutput('sudo i2cset -y 0 0x66 0x12 %d' % psuled)
+ # psustatus = int(psustatus, 16)
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICE_REG = 0x12
+ # psustatus = bus.write_byte_data(DEVICE_ADDRESS, DEVICE_REG, psuled)
+
+ self._write_sysfs_file(self.psu_frontled_reg, psuled)
+ #sonic_logger.log_warning("set_status_led PSU{} color={} PSU_LED_REG={}".format(self.index, color, psuled))
+
+ return True
+
+ def get_status_master_led(self):
+ """
+ Gets the state of the front panel PSU status LED
+
+ Returns:
+ A string, one of the predefined STATUS_LED_COLOR_* strings.
+ """
+ if (not os.path.isfile("/sys/class/gpio/psuLedGreen/value") or
+ not os.path.isfile("/sys/class/gpio/psuLedAmber/value")):
+ return None
+
+ green = self._read_sysfs_file("/sys/class/gpio/psuLedGreen/value")
+ amber = self._read_sysfs_file("/sys/class/gpio/psuLedAmber/value")
+ if green == "ERR" or amber == "ERR":
+ return None
+ if green == "1":
+ return self.STATUS_LED_COLOR_GREEN
+ elif amber == "1":
+ return self.STATUS_LED_COLOR_AMBER
+ else:
+ return None
+
+ def set_status_master_led(self, color):
+ """
+ Sets the state of the front panel PSU status LED
+
+ Returns:
+ bool: True if status LED state is set successfully, False if
+ not
+ """
+ if (not os.path.isfile("/sys/class/gpio/psuLedGreen/value") or
+ not os.path.isfile("/sys/class/gpio/psuLedAmber/value")):
+ return False
+
+ if color == self.STATUS_LED_COLOR_GREEN:
+ rvg = self._write_sysfs_file("/sys/class/gpio/psuLedGreen/value", 1)
+ if rvg != "ERR":
+ rva = self._write_sysfs_file("/sys/class/gpio/psuLedAmber/value", 0)
+ elif color == self.STATUS_LED_COLOR_AMBER:
+ rvg = self._write_sysfs_file("/sys/class/gpio/psuLedGreen/value", 0)
+ if rvg != "ERR":
+ rva = self._write_sysfs_file("/sys/class/gpio/psuLedAmber/value", 1)
+ else:
+ return False
+
+ if rvg == "ERR" or rva == "ERR":
+ return False
+
+ return True
+
+ def get_power(self):
+ """
+ Retrieves the output power of the PSU
+
+ Returns:
+ string: output power of PSU
+ """
+ #return self.eeprom.power_str()
+ #if smbus_present == 0:
+ # cmdstatus, psustatus = cmd.getstatusoutput('sudo i2cget -y 0 0x66 0xa')
+ # psustatus = int(psustatus, 16)
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICE_REG = 0xa
+ # psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)
+ #
+ #if self.index == 1:
+ # psustatus = psustatus & 4
+ # if psustatus == 0:
+ # psu_power = 150
+ # return psu_power
+ #if self.index == 2:
+ # psustatus = psustatus & 8
+ # if psustatus == 0:
+ # psu_power = 150
+ # return psu_power
+ psustatus = self._read_sysfs_file(self.get_psu_status_reg)
+
+ if self.index == 1:
+ psustatus = int(psustatus) & 4
+ if psustatus == 0:
+ psu_power = 150
+ return psu_power
+ if self.index == 2:
+ psustatus = int(psustatus) & 8
+ if psustatus == 0:
+ psu_power = 150
+ return psu_power
+
+ psu_power = 0
+ return psu_power
+
+ def get_current(self):
+ """
+ Retrieves the output current of the PSU
+
+ Returns:
+ string: output current of PSU
+ """
+ #return self.eeprom.current_str()
+ #if smbus_present == 0:
+ # cmdstatus, psustatus = cmd.getstatusoutput('sudo i2cget -y 0 0x66 0xa')
+ # psustatus = int(psustatus, 16)
+ #else:
+ # bus = smbus.SMBus(0)
+ # DEVICE_ADDRESS = 0x66
+ # DEVICE_REG = 0xa
+ # psustatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)
+ #
+ #if self.index == 1:
+ # psustatus = psustatus & 4
+ # if psustatus == 0:
+ # psu_current = 12.5
+ # return psu_current
+ #if self.index == 2:
+ # psustatus = psustatus & 8
+ # if psustatus == 0:
+ # psu_current = 12.5
+ # return psu_current
+ psustatus = self._read_sysfs_file(self.get_psu_status_reg)
+
+ if self.index == 1:
+ psustatus = int(psustatus) & 4
+ if psustatus == 0:
+ psu_current = 12.5
+ return psu_current
+ if self.index == 2:
+ psustatus = int(psustatus) & 8
+ if psustatus == 0:
+ psu_current = 12.5
+ return psu_current
+
+ psu_current = 0.0
+ return psu_current
+
+ def get_voltage_high_threshold(self):
+ """
+ Retrieves the high threshold PSU voltage output
+ Returns:
+ A float number, the high threshold output voltage in volts,
+ e.g. 12.1
+ """
+ return float(self.PSU_OUTPUT_VOLTAGE_MAX)
+
+ def get_voltage_low_threshold(self):
+ """
+ Retrieves the low threshold PSU voltage output
+ Returns:
+ A float number, the low threshold output voltage in volts,
+ e.g. 12.1
+ """
+ return float(self.PSU_OUTPUT_VOLTAGE_MIN)
+
+
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/sfp.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/sfp.py
new file mode 100644
index 0000000000..cccffc4cef
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/sfp.py
@@ -0,0 +1,573 @@
+#############################################################################
+# Supermicro SSE-G3748
+#
+# Module contains an implementation of SONiC Platform Base API and
+# provides the platform information by using sfp refactor spec
+#
+#############################################################################
+#
+# There are 2 IO Expander connect to SFP transceiver status/control
+#---------------------------------------------------------------------------
+#
+# SFP transceiver status:
+#
+# PCAL6524 -- [I2C 0x22] 24 bits I/O for SFP status and TX_DIS
+# Port 0 -- 7 6 5 4 3 2 1 0
+# TX_FAULT TX_DIS LOS PRESENT TX_FAULT TX_DIS LOS PRESENT
+# SFP1 SFP1 SFP1 SFP1 SFP0 SFP0 SFP0 SFP0
+#
+# Port 1 -- 7 6 5 4 3 2 1 0
+# TX_FAULT TX_DIS LOS PRESENT TX_FAULT TX_DIS LOS PRESENT
+# SFP3 SFP3 SFP3 SFP3 SFP2 SFP2 SFP2 SFP2
+#
+# Port 2 -- 7 6 5 4 3 2 1 0
+# TX_FAULT TX_DIS LOS PRESENT TX_FAULT TX_DIS LOS PRESENT
+# SFP5 SFP5 SFP5 SFP5 SFP4 SFP4 SFP4 SFP4
+# [TX_DIS bit is output, all other bits are input]
+#---------------------------------------------------------------------------
+#
+# SFP transceiver control:
+#
+# PCAL6416A -- [I2C 0x20] 16 bits I/) Expander SFP RS0 and RS1
+# Port 0 -- 7 6 5 4 3 2 1 0
+# RS0 RS1 RS0 RS1 RS0 RS1 RS0 RS1
+# SF2 SF3 SF0 SF1
+#
+# Port 0 -- 7 6 5 4 3 2 1 0
+# N/A N/A N/A N/A RS0 RS1 RS0 RS1
+# SF4 SF5
+# [ All bits are output]
+#
+#############################################################################
+
+try:
+ import os
+ import sys
+ import time
+ import subprocess
+ from sonic_platform_base.sonic_xcvr.sfp_optoe_base import SfpOptoeBase
+ from sonic_platform_base.sfp_base import SfpBase
+
+ from sonic_py_common import logger
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+if sys.version_info[0] < 3:
+ import commands as cmd
+else:
+ import subprocess as cmd
+
+smbus_present = 1
+
+try:
+ import smbus
+except ImportError as e:
+ smbus_present = 0
+
+QSFP_INFO_OFFSET = 128
+SFP_INFO_OFFSET = 0
+QSFP_DD_PAGE0 = 0
+
+SFP_TYPE_LIST = [
+ '0x3' # SFP/SFP+/SFP28 and later
+]
+QSFP_TYPE_LIST = [
+ '0x0c', # QSFP
+ '0x0d', # QSFP+ or later
+ '0x11' # QSFP28 or later
+]
+QSFP_DD_TYPE_LIST = [
+ '0x18' #QSFP_DD Type
+]
+
+OSFP_TYPE_LIST = [
+ '0x19' # OSFP 8X Type
+]
+
+COPPER_TYPE = "COPPER"
+SFP_TYPE = "SFP"
+RJ45_TYPE = "RJ45"
+
+# SFP PORT numbers
+SFP_PORT_START = 49
+SFP_PORT_END = 54
+
+SYSLOG_IDENTIFIER = "xcvrd"
+sonic_logger = logger.Logger(SYSLOG_IDENTIFIER)
+
+class Sfp(SfpOptoeBase):
+ """
+ Supermicro SSE-G3748 refactor Platform-specific Sfp class
+ """
+
+ def __init__(self, index, sfp_type, eeprom_path, port_i2c_map):
+ SfpOptoeBase.__init__(self)
+ self.index = index
+ self.port_num = index
+ self.eeprom_path = eeprom_path
+ self.sfp_eeprom_path = eeprom_path
+ #port_type is the native port type and sfp_type is the transceiver type
+ #sfp_type will be detected in get_transceiver_info
+ self.port_type = sfp_type
+ if (self.index < SFP_PORT_START):
+ self.port_type = RJ45_TYPE
+ self.sfp_type = self.port_type
+
+ self._port_to_i2c_mapping = port_i2c_map
+ self.port_name = sfp_type + str(index)
+
+ self._initialize_media(delay=False)
+
+# def __is_host(self):
+# return os.system(self.HOST_CHK_CMD) == 0
+#
+# def __get_path_to_port_config_file(self):
+# platform_path = "/".join([self.PLATFORM_ROOT_PATH, self.PLATFORM])
+# hwsku_path = "/".join([platform_path, self.HWSKU]
+# ) if self.__is_host() else self.PMON_HWSKU_PATH
+# sonic_logger.log_warning("sfp __get_path_to_port_config_file hwsku_path = %s" % hwsku_path)
+
+ def sfp_status_get_value(self, port_off):
+ reg_in = [0x00, 0x00, 0x01, 0x01, 0x02, 0x02]
+
+ if smbus_present == 0: # if called from sfputil outside of pmon
+ regin = reg_in[port_off]
+ cmdstatus, sfpstatus = cmd.getstatusoutput('sudo i2cget -y 1 0x22 %d' % regin)
+ if cmdstatus:
+ sonic_logger.log_warning("sfp cmdstatus i2c get failed %s" % status)
+ return False
+ sfpStatus = int(sfpstatus, 16)
+ else:
+ bus = smbus.SMBus(1)
+ DEVICE_ADDRESS = 0x22
+ DEVICE_REG = reg_in[port_off]
+ sfpStatus = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)
+
+ return sfpStatus
+
+ def sfp_status_set_value(self, port_off, val):
+ reg_out = [0x04, 0x04, 0x05, 0x05, 0x06, 0x06]
+
+ if smbus_present == 0: # if called from sfputil outside of pmon
+ regout = reg_out[port_off]
+ i2csetcmd = "i2cset -y 1 0x22 " + hex(regout) + hex(val)
+ cmdstatus, output = cmd.getstatusoutput(i2csetcmd)
+ if cmdstatus:
+ sonic_logger.log_warning("sfp cmdstatus i2c write failed %s" % output )
+ return False
+ else:
+ bus = smbus.SMBus(1)
+ DEVICE_ADDRESS = 0x22
+ DEVICE_REG = reg_out[port_off]
+ bus.write_byte_data(DEVICE_ADDRESS, DEVICE_REG, val)
+
+ return True
+
+ def _initialize_media(self, delay=False):
+ """
+ Initialize the media type and eeprom driver for SFP
+ """
+ if delay:
+ time.sleep(1)
+ self._xcvr_api = None
+ self.get_xcvr_api()
+
+ self.set_media_type()
+ self.reinit_sfp_driver()
+
+ def set_media_type(self):
+ """
+ Reads optic eeprom byte to determine media type inserted
+ """
+ eeprom_raw = []
+ eeprom_raw = self._xcvr_api_factory._get_id()
+ if eeprom_raw is not None:
+ eeprom_raw = hex(eeprom_raw)
+ if eeprom_raw in SFP_TYPE_LIST:
+ self.sfp_type = 'SFP'
+ elif eeprom_raw in QSFP_TYPE_LIST:
+ self.sfp_type = 'QSFP'
+ elif eeprom_raw in QSFP_DD_TYPE_LIST:
+ self.sfp_type = 'QSFP_DD'
+ else:
+ #Set native port type if EEPROM type is not recognized/readable
+ self.sfp_type = self.port_type
+ else:
+ self.sfp_type = self.port_type
+
+ return self.sfp_type
+
+ def reinit_sfp_driver(self):
+ """
+ Changes the driver based on media type detected
+ """
+ """
+ del_sfp_path = "/sys/class/i2c-adapter/i2c-{0}/delete_device".format(
+ self._port_to_i2c_mapping[self.index])
+ new_sfp_path = "/sys/class/i2c-adapter/i2c-{0}/new_device".format(
+ self._port_to_i2c_mapping[self.index])
+ driver_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/name".format(
+ self._port_to_i2c_mapping[self.index])
+ """
+ i2c_bus = self.sfp_eeprom_path[27:].split('/')[0]
+ del_sfp_path = "/sys/class/i2c-adapter/i2c-{0}/delete_device".format(i2c_bus)
+ new_sfp_path = "/sys/class/i2c-adapter/i2c-{0}/new_device".format(i2c_bus)
+ driver_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/name".format(i2c_bus)
+ delete_device = "echo 0x50 >" + del_sfp_path
+
+ if not os.path.isfile(driver_path):
+ #print(driver_path, "does not exist")
+ return False
+
+ try:
+ with os.fdopen(os.open(driver_path, os.O_RDONLY)) as filed:
+ driver_name = filed.read()
+ driver_name = driver_name.rstrip('\r\n')
+ driver_name = driver_name.lstrip(" ")
+
+ #Avoid re-initialization of the QSFP/SFP optic on QSFP/SFP port.
+ if self.sfp_type == 'SFP' and driver_name in ['optoe1', 'optoe3']:
+ subprocess.Popen(delete_device, shell=True, stdout=subprocess.PIPE)
+ time.sleep(0.2)
+ new_device = "echo optoe2 0x50 >" + new_sfp_path
+ subprocess.Popen(new_device, shell=True, stdout=subprocess.PIPE)
+ time.sleep(2)
+ elif self.sfp_type == 'QSFP' and driver_name in ['optoe2', 'optoe3']:
+ subprocess.Popen(delete_device, shell=True, stdout=subprocess.PIPE)
+ time.sleep(0.2)
+ new_device = "echo optoe1 0x50 >" + new_sfp_path
+ subprocess.Popen(new_device, shell=True, stdout=subprocess.PIPE)
+ time.sleep(2)
+ elif self.sfp_type == 'QSFP_DD' and driver_name in ['optoe1', 'optoe2']:
+ subprocess.Popen(delete_device, shell=True, stdout=subprocess.PIPE)
+ time.sleep(0.2)
+ new_device = "echo optoe3 0x50 >" + new_sfp_path
+ subprocess.Popen(new_device, shell=True, stdout=subprocess.PIPE)
+ time.sleep(2)
+
+ except IOError as err:
+ print("Error: Unable to open file: %s" %str(err))
+ return False
+
+ return True
+
+# Implemented in sfp_optoe_base
+# def get_model(self):
+# def get_serial(self):
+# def get_transceiver_info(self):
+# def get_transceiver_bulk_status(self):
+# def get_transceiver_threshold_info(self):
+
+ def get_transceiver_status(self):
+ return {}
+
+ def get_transceiver_info(self):
+ if self.sfp_type == COPPER_TYPE or self.sfp_type == RJ45_TYPE:
+ transceiver_info_keys = ['manufacturer',
+ 'model',
+ 'vendor_rev',
+ 'serial',
+ 'vendor_oui',
+ 'vendor_date',
+ 'connector',
+ 'encoding',
+ 'ext_identifier',
+ 'ext_rateselect_compliance',
+ 'cable_type',
+ 'cable_length',
+ 'specification_compliance',
+ 'nominal_bit_rate',
+ 'application_advertisement']
+ transceiver_info_dict = dict.fromkeys(transceiver_info_keys, 'N/A')
+ transceiver_info_dict['type'] = self.sfp_type
+ return transceiver_info_dict
+ else:
+ return super(Sfp, self).get_transceiver_info()
+
+ def get_transceiver_bulk_status(self):
+ if self.sfp_type == COPPER_TYPE or self.sfp_type == RJ45_TYPE:
+ transceiver_dom_info_dict = {}
+ dom_info_dict_keys = ['temperature', 'voltage',
+ 'rx1power', 'rx2power',
+ 'rx3power', 'rx4power',
+ 'rx5power', 'rx6power',
+ 'rx7power', 'rx8power',
+ 'tx1bias', 'tx2bias',
+ 'tx3bias', 'tx4bias',
+ 'tx5bias', 'tx6bias',
+ 'tx7bias', 'tx8bias',
+ 'tx1power', 'tx2power',
+ 'tx3power', 'tx4power',
+ 'tx5power', 'tx6power',
+ 'tx7power', 'tx8power'
+ ]
+ transceiver_dom_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A')
+ return transceiver_dom_info_dict
+ else:
+ return super(Sfp, self).get_transceiver_bulk_status()
+
+ def get_transceiver_threshold_info(self):
+ if self.sfp_type == COPPER_TYPE or self.sfp_type == RJ45_TYPE:
+ transceiver_dom_threshold_info_dict = {}
+ dom_info_dict_keys = ['temphighalarm', 'temphighwarning',
+ 'templowalarm', 'templowwarning',
+ 'vcchighalarm', 'vcchighwarning',
+ 'vcclowalarm', 'vcclowwarning',
+ 'rxpowerhighalarm', 'rxpowerhighwarning',
+ 'rxpowerlowalarm', 'rxpowerlowwarning',
+ 'txpowerhighalarm', 'txpowerhighwarning',
+ 'txpowerlowalarm', 'txpowerlowwarning',
+ 'txbiashighalarm', 'txbiashighwarning',
+ 'txbiaslowalarm', 'txbiaslowwarning'
+ ]
+ transceiver_dom_threshold_info_dict = dict.fromkeys(dom_info_dict_keys, 'N/A')
+ return transceiver_dom_threshold_info_dict
+ else:
+ return super(Sfp, self).get_transceiver_threshold_info()
+
+# def get_transceiver_loopback(self):
+# def is_coherent_module(self):
+# def get_transceiver_pm(self):
+# def get_rx_los(self):
+# def get_tx_fault(self):
+# def get_tx_disable(self):
+# def get_tx_disable_channel(self):
+# def get_temperature(self):
+# def get_voltage(self):
+# def get_tx_bias(self):
+# def get_rx_power(self):
+# def get_tx_power(self):
+
+ def tx_disable(self, tx_disable):
+ """
+ Disable SFP TX
+ Args:
+ tx_disable : A Boolean, True to enable tx_disable mode, False to disable
+ tx_disable mode.
+ Returns:
+ A boolean, True if tx_disable is set successfully, False if not
+ """
+
+ if self.sfp_type == COPPER_TYPE or self.sfp_type == RJ45_TYPE:
+ return False
+
+ port_offset = self.index-SFP_PORT_START
+ sfpstatus=self.sfp_status_get_value(port_offset)
+
+ tx_dis_bit = [0x04, 0x40, 0x04, 0x40, 0x04, 0x40]
+ tx_en_bit = [0xFB, 0xBF, 0xFB, 0xBF, 0xFB, 0xBF]
+
+ if tx_disable == True:
+ setbits = sfpstatus | tx_dis_bit[port_offset]
+ else:
+ setbits = sfpstatus & tx_en_bit[port_offset]
+
+ self.sfp_status_set_value(port_offset, setbits)
+
+ return True
+
+# Implemented in sfp_optoe_base
+# def tx_disable_channel(self, channel, disable):
+# """
+# Sets the tx_disable for specified SFP channels
+# Args:
+# channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3,
+# e.g. 0x5 for channel 0 and channel 2.
+# disable : A boolean, True to disable TX channels specified in channel,
+# False to enable
+# Returns:
+# A boolean, True if successful, False if not
+# """
+#
+# return NotImplementedError
+
+ def get_power_override(self):
+ """
+ Retrieves the power-override status of this SFP
+ Returns:
+ A Boolean, True if power-override is enabled, False if disabled
+ """
+ if self.sfp_type == COPPER_TYPE or self.sfp_type == RJ45_TYPE:
+ return False
+ if self.sfp_type == SFP_TYPE:
+ return False
+
+# Implemented in sfp_optoe_base
+# def set_power_override(self, power_override, power_set):
+# """
+# Sets SFP power level using power_override and power_set
+# Args:
+# power_override :
+# A Boolean, True to override set_lpmode and use power_set
+# to control SFP power, False to disable SFP power control
+# through power_override/power_set and use set_lpmode
+# to control SFP power.
+# power_set :
+# Only valid when power_override is True.
+# A Boolean, True to set SFP to low power mode, False to set
+# SFP to high power mode.
+# Returns:
+# A boolean, True if power-override and power_set are set successfully,
+# False if not
+# """
+#
+# return NotImplementedError
+
+ def get_eeprom_path(self):
+ """
+ Returns SFP eeprom path
+ """
+ return self.eeprom_path
+
+ def get_lpmode(self):
+ """
+ Retrieves the lpmode (low power mode) status of this SFP
+ Returns:
+ A Boolean, True if lpmode is enabled, False if disabled
+ """
+ if self.sfp_type == COPPER_TYPE or self.sfp_type == RJ45_TYPE:
+ return False
+ if self.sfp_type == SFP_TYPE:
+ return False
+
+ def set_lpmode(self, lpmode):
+ """
+ Sets the lpmode (low power mode) of SFP
+ Args:
+ lpmode: A Boolean, True to enable lpmode, False to disable it
+ Note : lpmode can be overridden by set_power_override
+ Returns:
+ A boolean, True if lpmode is set successfully, False if not
+ """
+ if self.sfp_type == COPPER_TYPE or self.sfp_type == RJ45_TYPE:
+ return False
+ if self.sfp_type == SFP_TYPE:
+ return False
+
+# def read_eeprom(self, offset, num_bytes):
+# def write_eeprom(self, offset, num_bytes, write_buffer):
+
+ def reset(self):
+ """
+ Reset SFP.
+ Returns:
+ A boolean, True if successful, False if not
+ """
+ # RJ45 and SFP ports not resettable
+ return False
+
+ def get_error_description(self):
+ """
+ Retrives the error descriptions of the SFP module
+
+ Returns:
+ String that represents the current error descriptions of vendor specific errors
+ In case there are multiple errors, they should be joined by '|',
+ like: "Bad EEPROM|Unsupported cable"
+ """
+ if self.sfp_type == COPPER_TYPE or self.sfp_type == RJ45_TYPE:
+ return super(Sfp, self).get_error_description()
+
+ if not self.get_presence():
+ return self.SFP_STATUS_UNPLUGGED
+ else:
+ if not os.path.isfile(self.eeprom_path):
+ return "EEPROM driver is not attached"
+
+ if self.sfp_type == 'SFP':
+ offset = SFP_INFO_OFFSET
+ elif self.sfp_type == 'QSFP':
+ offset = QSFP_INFO_OFFSET
+ elif self.sfp_type == 'QSFP_DD':
+ offset = QSFP_DD_PAGE0
+
+ try:
+ with open(self.eeprom_path, mode="rb", buffering=0) as eeprom:
+ eeprom.seek(offset)
+ eeprom.read(1)
+ except OSError as e:
+ return "EEPROM read failed ({})".format(e.strerror)
+
+ return self.SFP_STATUS_OK
+
+ def get_name(self):
+ """
+ Returns native transceiver type
+ Returns: string - The name of the device
+ """
+ return RJ45_TYPE if self.index < SFP_PORT_START else "SFP/SFP+/SFP28"
+
+# def get_name(self):
+# """
+# Retrieves the name of the device
+# Returns:
+# string: The name of the device
+# """
+# sfputil_helper = SfpUtilHelper()
+# sfputil_helper.read_porttab_mappings(
+# self.__get_path_to_port_config_file())
+# name = sfputil_helper.logical[self.index-1] or "Unknown"
+# return name
+
+ def get_presence(self):
+ """
+ Retrieves the presence
+ Returns:
+ bool: True if is present, False if not
+ """
+ if self.sfp_type == COPPER_TYPE or self.sfp_type == RJ45_TYPE:
+ return False
+
+ port_offset = self.index-SFP_PORT_START
+ sfpstatus = self.sfp_status_get_value(port_offset)
+
+ if ((port_offset%2) == 1):
+ sfpstatus = (sfpstatus >> 4) & 0X01
+ else:
+ sfpstatus = sfpstatus & 0x01
+
+ if sfpstatus == 0:
+ # Present. Turn off tx_disable
+ self.tx_disable(False)
+ return True
+
+ # Not present. Turn on tx_disable
+ self.tx_disable(True)
+ return False
+
+ def get_reset_status(self):
+ """
+ Retrives the reset status of SFP
+ """
+ reset_status = False
+ return reset_status
+
+
+ def get_status(self):
+ """
+ Retrieves the operational status of the device
+ Returns:
+ A boolean value, True if device is operating properly, False if not
+ """
+ return self.get_presence()
+
+ def is_replaceable(self):
+ """
+ Indicate whether this device is replaceable.
+ Returns:
+ bool: True if it is replaceable.
+ """
+
+ if self.sfp_type == "SFP":
+ return True
+ else:
+ return False
+
+ def get_position_in_parent(self):
+ """
+ Retrieves 1-based relative physical position in parent device
+ Returns:
+ integer: The 1-based relative physical position in parent device
+ """
+ return self.index
+
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/sfp_event.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/sfp_event.py
new file mode 100644
index 0000000000..53e0099c62
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/sfp_event.py
@@ -0,0 +1,141 @@
+############################################################
+# listen for the SFP change event and return to chassis.
+############################################################
+
+import math
+import os
+import sys
+import time
+from sonic_py_common import logger
+
+smbus_present = 1
+
+try:
+ import smbus
+except ImportError as e:
+ smbus_present = 0
+
+if sys.version_info[0] < 3:
+ import commands as cmd
+else:
+ import subprocess as cmd
+
+# system level event/error
+EVENT_ON_ALL_SFP = '-1'
+SYSTEM_NOT_READY = 'system_not_ready'
+SYSTEM_READY = 'system_become_ready'
+SYSTEM_FAIL = 'system_fail'
+
+# SFP PORT numbers
+SFP_PORT_START = 49
+SFP_PORT_END = 54
+RJ45_PORT_START = 1
+RJ45_PORT_END = 48
+
+SYSLOG_IDENTIFIER = "sfp_event"
+sonic_logger = logger.Logger(SYSLOG_IDENTIFIER)
+
+
+class sfp_event:
+ ''' Listen to plugin/plugout cable events '''
+
+ def __init__(self):
+ self.handle = None
+
+ def initialize(self):
+ self.modprs_register = 0
+ # Get Transceiver status
+ time.sleep(5)
+ self.modprs_register = self._get_transceiver_status()
+ sonic_logger.log_info("Initial SFP presence=%d" % self.modprs_register)
+
+ def deinitialize(self):
+ if self.handle is None:
+ return
+
+ def _get_transceiver_status(self):
+
+ reg_in = [0x00, 0x00, 0x01, 0x01, 0x02, 0x02]
+ port = SFP_PORT_START
+
+ sfpstatus = 0
+ while (port >= SFP_PORT_START and port <= SFP_PORT_END):
+ if smbus_present == 0:
+ sonic_logger.log_info(" PMON - smbus ERROR - DEBUG sfp_event ")
+ regin = reg_in[port-SFP_PORT_START]
+ cmdstatus, sfpreg = cmd.getstatusoutput('sudo i2cget -y 0 0x22 %d' % regin)
+ sfpreg = int(sfpreg, 16)
+ else:
+ bus = smbus.SMBus(1)
+ DEVICE_ADDRESS = 0x22
+ DEVICE_REG = reg_in[port-SFP_PORT_START]
+ sfpreg = bus.read_byte_data(DEVICE_ADDRESS, DEVICE_REG)
+
+ if ((port-SFP_PORT_START)%2) == 1:
+ sfpreg = (sfpreg >> 4) & 0x01
+ else:
+ sfpreg = sfpreg & 0x01
+ sfpstatus = sfpstatus | (sfpreg << (port-SFP_PORT_START))
+ port += 1
+
+ return sfpstatus
+
+ def check_sfp_status(self, port_change, timeout):
+ """
+ check_sfp_status called from get_change_event, this will return correct
+ status of all 6 SFP ports if there is a change in any of them
+ """
+ start_time = time.time()
+ #port = SFP_PORT_START
+ port = RJ45_PORT_START
+ forever = False
+
+ if timeout == 0:
+ forever = True
+ elif timeout > 0:
+ timeout = timeout / float(1000) # Convert to secs
+ else:
+ return False, {}
+ end_time = start_time + timeout
+
+ if (start_time > end_time):
+ return False, {} # Time wrap or possibly incorrect timeout
+
+ while (timeout >= 0):
+ while (port >= RJ45_PORT_START and port <= RJ45_PORT_END):
+ port_change[port] = '1'
+ port += 1
+
+ # Check for OIR events and return updated port_change
+ reg_value = self._get_transceiver_status()
+ if (reg_value != self.modprs_register):
+ changed_ports = (self.modprs_register ^ reg_value)
+ while (port >= SFP_PORT_START and port <= SFP_PORT_END):
+ # Mask off the bit corresponding to our port
+ mask = (1 << port-SFP_PORT_START)
+ if (changed_ports & mask):
+ # ModPrsL is active high
+ if reg_value & mask == 0:
+ #G3748 reg_value==0 is inserted. In port_change 1 is inserted
+ port_change[port] = '1'
+ else:
+ #G3748 reg_value==1 is removed. In port_change 0 is removed
+ port_change[port] = '0'
+ port += 1
+
+ # Update reg value
+ self.modprs_register = reg_value
+ #return True, port_change
+ return True, port_change
+
+ 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, {}
+ return False, {}
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/README b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/README
new file mode 100644
index 0000000000..3efc8fabce
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/README
@@ -0,0 +1 @@
+This directory contains unit tests of the Platform API 2.0
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-chassis.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-chassis.py
new file mode 100644
index 0000000000..772cf6d88d
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-chassis.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python3
+
+#import sonic_platform
+#from sonic_platform.chassis import Chassis
+
+
+try:
+ import sonic_platform.platform
+ import sonic_platform.chassis
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+
+def main():
+ print("-----------------")
+ print("Chassis Unit Test")
+ print("-----------------")
+
+ chassis = sonic_platform.platform.Platform().get_chassis()
+ print(" Chassis name: {}".format(chassis.get_name()))
+
+ print(" Chassis presence: {}".format(chassis.get_presence()))
+
+ print(" Chassis model: {}".format(chassis.get_model()))
+
+ print(" Chassis serial: {}".format(chassis.get_serial()))
+
+ print(" Chassis status: {}".format(chassis.get_status()))
+
+ print(" Chassis base_mac: {}".format(chassis.get_base_mac()))
+
+ print(" Chassis reboot cause: {}\n".format(chassis.get_reboot_cause()))
+
+ print(" Chassis watchdog: {}".format(chassis.get_watchdog()))
+
+ print(" Chassis num_components: {}".format(chassis.get_num_components()))
+
+ print(" Chassis all_components: {}\n".format(chassis.get_all_components()))
+
+ print(" Chassis num_modules: {}".format(chassis.get_num_modules()))
+
+ print(" Chassis all_modules: {}\n".format(chassis.get_all_modules()))
+
+ print(" Chassis num_fans: {}".format(chassis.get_num_fans()))
+
+ print(" Chassis all_fans: {}\n".format(chassis.get_all_fans()))
+
+ print(" Chassis num_psus: {}".format(chassis.get_num_psus()))
+
+ print(" Chassis all_psus: {}\n".format(chassis.get_all_psus()))
+
+ print(" Chassis num_thermals: {}".format(chassis.get_num_thermals()))
+
+ print(" Chassis all_thermals: {}\n".format(chassis.get_all_thermals()))
+
+ print(" Chassis num_sfps: {}".format(chassis.get_num_sfps()))
+
+ print(" Chassis all_sfps: {}\n".format(chassis.get_all_sfps()))
+
+ print(" Chassis eeprom: {}".format(chassis.get_eeprom()))
+
+ print(" Chassis system_eeprom_info: {}\n".format(chassis.get_system_eeprom_info()))
+
+ print(" Chassis get_status_led start : {}\n".format(chassis.get_status_led()))
+ chassis.set_status_led('amber')
+ print(" Chassis get_status_led amber: {}\n".format(chassis.get_status_led()))
+ chassis.set_status_led('green')
+ print(" Chassis get_status_led green: {}\n".format(chassis.get_status_led()))
+
+ print(" Chassis thermal_manager: {}\n".format(chassis.get_thermal_manager()))
+
+ return
+
+
+if __name__ == '__main__':
+ main()
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-component.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-component.py
new file mode 100644
index 0000000000..1116cc7b58
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-component.py
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+
+from sonic_platform.chassis import Chassis
+
+
+def main():
+ print("---------------------------")
+ print("Chassis Component Unit Test")
+ print("---------------------------")
+
+ chassis = Chassis()
+
+ for component in chassis.get_all_components():
+ print(" Name: {}".format(component.get_name()))
+ print(" Description: {}".format(component.get_description()))
+ print(" FW version: {}\n".format(component.get_firmware_version()))
+
+ return
+
+
+if __name__ == '__main__':
+ main()
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-eeprom.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-eeprom.py
new file mode 100644
index 0000000000..4083661169
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-eeprom.py
@@ -0,0 +1,25 @@
+#!/usr/bin/python
+
+from sonic_platform.chassis import Chassis
+
+
+def main():
+ print("------------------------")
+ print("Chassis eeprom Unit Test")
+ print("------------------------")
+
+ chassis = Chassis()
+
+ eeprom = chassis.get_eeprom()
+
+ print(" Model: {}, Service Tag: {}".format(eeprom.modelstr(),
+ eeprom.service_tag_str()))
+ print(" Part#: {}, Serial#: {}".format(eeprom.part_number_str(),
+ eeprom.serial_number_str()))
+ print(" Base MAC: {}".format(eeprom.base_mac_addr()))
+
+ return
+
+
+if __name__ == '__main__':
+ main()
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-fan.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-fan.py
new file mode 100644
index 0000000000..5844e25b55
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-fan.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+
+import sonic_platform
+from sonic_platform.chassis import Chassis
+
+
+def main():
+ print("---------------------")
+ print("Chassis Fan Unit Test")
+ print("---------------------")
+
+ chassis = Chassis()
+
+ for fan in chassis.get_all_fans():
+ if not fan.get_presence():
+ print(" Name: {} not present".format(fan.get_name()))
+ else:
+ print(" Name:", fan.get_name())
+ print(" Presence: {}, Status: {}, LED: {}".format(fan.get_presence(),
+ fan.get_status(),
+ fan.get_status_led()))
+ print(" Model: {}, Serial#: {}".format(fan.get_model(),
+ fan.get_serial()))
+ print(" Part#: {}, Service Tag: {}".format(fan.get_part_number(),
+ fan.get_service_tag()))
+ print(" Direction: {}, Speed: {}RPM, Target Speed: {}, Speed Tolerance: {}%\n".format(fan.get_direction(),
+ str(fan.get_speed()),
+ str(fan.get_target_speed()),
+ str(fan.get_speed_tolerance()))
+ return
+
+
+if __name__ == '__main__':
+ main()
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-psu.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-psu.py
new file mode 100644
index 0000000000..ac04f06f93
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-psu.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python3
+
+import sonic_platform
+from sonic_platform.chassis import Chassis
+
+
+def main():
+ print("---------------------")
+ print("Chassis PSU Unit Test")
+ print("---------------------")
+
+ chassis = Chassis()
+
+ for psu in chassis.get_all_psus():
+ if not psu.get_presence():
+ print(" Name: {} not present".format(psu.get_name()))
+ else:
+ print(" Name:", psu.get_name())
+ print(" Presence: {}, Status: {}, LED: {}".format(psu.get_presence(),
+ psu.get_status(),
+ psu.get_status_led()))
+ print(" Model: {}, Serial#: {}, Part#: {}".format(psu.get_model(),
+ psu.get_serial(),
+ psu.get_part_number()))
+ try:
+ current = psu.get_current()
+ except NotImplementedError:
+ current = "NA"
+ try:
+ power = psu.get_power()
+ except NotImplementedError:
+ power = "NA"
+
+ print(" Voltage: {}, Current: {}, Power: {}\n".format(psu.get_voltage(),
+ current,
+ power))
+ return
+
+
+if __name__ == '__main__':
+ main()
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-sfp.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-sfp.py
new file mode 100644
index 0000000000..f5f2283f17
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-sfp.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+
+import sonic_platform
+
+try:
+ from sonic_platform.chassis import Chassis
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+
+def main():
+ print("---------------------")
+ print("Chassis SFP Unit Test")
+ print("---------------------")
+
+ chassis = Chassis()
+
+ PORT_START = 1
+ PORT_END = 52
+
+ for physical_port in range(PORT_START, PORT_END+1):
+ print(" ")
+ print(" SFP transceiver tests PORT = ", physical_port)
+ name = chassis.get_sfp(physical_port).get_name()
+ print(" SFP transceiver tests NAME = ", name)
+
+ presence = chassis.get_sfp(physical_port).get_presence()
+ print("TEST 1 - sfp presence [ True ] ", physical_port, presence)
+
+ status = chassis.get_sfp(physical_port).get_reset_status()
+ print("TEST 2 - sfp reset status [ False ] ", physical_port, status)
+
+ txdisable = chassis.get_sfp(physical_port).get_tx_disable()
+ print("TEST 3 - sfp tx_disable [ False ] ", physical_port, txdisable)
+
+ rxlos = chassis.get_sfp(physical_port).get_rx_los()
+ print("TEST 4 - sfp status rxlos [ False ] ", physical_port, rxlos)
+
+ txfault = chassis.get_sfp(physical_port).get_tx_fault()
+ print("TEST 5 - sfp status txfault [ False ] ", physical_port, txfault)
+
+ lpmode = chassis.get_sfp(physical_port).get_lpmode()
+ print("TEST 6 - sfp enable lpmode [ False ] ", physical_port, lpmode)
+
+ trans_info = chassis.get_sfp(physical_port).get_transceiver_info()
+ print("TEST 7 - sfp transceiver info for port:", physical_port, trans_info)
+
+ trans_status = chassis.get_sfp(physical_port).get_transceiver_bulk_status()
+ print("TEST 8 - sfp bulk status for port:", physical_port, trans_status)
+
+ threshold = chassis.get_sfp(physical_port).get_transceiver_threshold_info()
+ print("TEST 9 - sfp bulk status for port:", physical_port, threshold)
+
+ return
+
+
+if __name__ == '__main__':
+ main()
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-thermal.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-thermal.py
new file mode 100644
index 0000000000..91ef75d8f9
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-thermal.py
@@ -0,0 +1,50 @@
+#!/usr/bin/python
+
+from sonic_platform.chassis import Chassis
+
+def main():
+ print("-------------------------")
+ print("Chassis Thermal Unit Test")
+ print("-------------------------")
+
+ chassis = Chassis()
+
+ for thermal in chassis.get_all_thermals():
+ if not thermal.get_presence():
+ print(" Name: {} not present".format(thermal.get_name()))
+ else:
+ print(" Name:", thermal.get_name())
+ print(" Presence: {}, Status: {}".format(thermal.get_presence(),
+ thermal.get_status()))
+ print(" Model: {}, Serial#: {}".format(thermal.get_model(),
+ thermal.get_serial()))
+ print(" Temperature(C): {}".format(thermal.get_temperature()))
+
+ try:
+ low_thresh = thermal.get_low_threshold()
+ except NotImplementedError:
+ low_thresh = "NA"
+ try:
+ high_thresh = thermal.get_high_threshold()
+ except NotImplementedError:
+ high_thresh = "NA"
+
+ print(" Low Threshold(C): {}, High Threshold(C): {}".format(low_thresh,
+ high_thresh))
+
+ try:
+ crit_low_thresh = thermal.get_low_critical_threshold()
+ except NotImplementedError:
+ crit_low_thresh = "NA"
+ try:
+ crit_high_thresh = thermal.get_high_critical_threshold()
+ except NotImplementedError:
+ crit_high_thresh = "NA"
+
+ print(" Crit Low Threshold(C): {}, Crit High Threshold(C): {}\n".format(crit_low_thresh,
+ crit_high_thresh))
+ return
+
+
+if __name__ == '__main__':
+ main()
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-watchdog.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-watchdog.py
new file mode 100644
index 0000000000..20805e04ed
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/test/test-watchdog.py
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+
+from sonic_platform.chassis import Chassis
+
+
+def main():
+ print("---------------------")
+ print("Chassis Watchdog Test")
+ print("---------------------")
+
+ chassis = Chassis()
+
+ watchdog = chassis.get_watchdog()
+
+ print(" Armed: {}".format(watchdog.is_armed()))
+ print(" Time Left: {}".format(watchdog.get_remaining_time()))
+
+ return
+
+
+if __name__ == '__main__':
+ main()
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/thermal.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/thermal.py
new file mode 100644
index 0000000000..76410f7c44
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/thermal.py
@@ -0,0 +1,245 @@
+########################################################################
+# Supermicro SSE-G3748
+#
+# Module contains an implementation of SONiC Platform Base API and
+# provides the Thermals' information which are available in the platform
+#
+########################################################################
+
+
+try:
+ import os
+ from sonic_platform_base.thermal_base import ThermalBase
+ from sonic_py_common import logger
+except ImportError as e:
+ raise ImportError(str(e) + "- required module not found")
+
+sonic_logger = logger.Logger('thermal')
+
+class Thermal(ThermalBase):
+ """sse-g3748 platform-specific Thermal class"""
+
+ I2C_CLASS_DIR = "/sys/class/i2c-adapter/"
+ I2C_DEV_MAPPING = (['i2c-0/0-0048/hwmon/', 1],
+ ['i2c-0/0-0049/hwmon/', 1])
+
+ HWMON_CLASS_DIR = "/sys/class/hwmon/"
+
+ THERMAL_NAME = ("FRONT", "REAR")
+
+ def __init__(self, thermal_index):
+ ThermalBase.__init__(self)
+ self.index = thermal_index + 1
+ self.is_psu_thermal = False
+ self.dependency = None
+ self._minimum = None
+ self._maximum = None
+ self.thermal_high_threshold_file = None
+ # PCB temperature sensors
+ if self.index < 3:
+ i2c_path = self.I2C_CLASS_DIR + self.I2C_DEV_MAPPING[self.index - 1][0]
+ sensor_index = self.I2C_DEV_MAPPING[self.index - 1][1]
+ sensor_max_suffix = "max"
+ sensor_crit_suffix = "max_hyst"
+ hwmon_node = os.listdir(i2c_path)[0]
+ self.SENSOR_DIR = i2c_path + hwmon_node + '/'
+
+ # Armada 38x SOC temperature sensor
+ else:
+ dev_path = self.HWMON_CLASS_DIR
+ sensor_index = 1
+ sensor_max_suffix = None
+ sensor_crit_suffix = None
+ hwmon_node = os.listdir(dev_path)[0]
+ self.SENSOR_DIR = dev_path + hwmon_node + '/'
+
+ # sysfs file for current temperature value
+ self.thermal_temperature_file = self.SENSOR_DIR \
+ + "temp{}_input".format(sensor_index)
+
+ # sysfs file for high threshold value if supported for this sensor
+ if sensor_max_suffix:
+ self.thermal_high_threshold_file = self.SENSOR_DIR \
+ + "temp{}_{}".format(sensor_index, sensor_max_suffix)
+ else:
+ self.thermal_high_threshold_file = None
+
+ # sysfs file for crit high threshold value if supported for this sensor
+ if sensor_crit_suffix:
+ self.thermal_high_crit_threshold_file = self.SENSOR_DIR \
+ + "temp{}_{}".format(sensor_index, sensor_crit_suffix)
+ else:
+ self.thermal_high_crit_threshold_file = None
+
+ def _read_sysfs_file(self, sysfs_file):
+ # On successful read, returns the value read from given
+ # sysfs_file and on failure returns 'ERR'
+ rv = 'ERR'
+
+ if (not os.path.isfile(sysfs_file)):
+ return rv
+
+ try:
+ with open(sysfs_file, 'r') as fd:
+ rv = fd.read()
+ except Exception as e:
+ rv = 'ERR'
+
+ rv = rv.rstrip('\r\n')
+ rv = rv.lstrip(" ")
+ return rv
+
+ def get_name(self):
+ """
+ Retrieves the name of the thermal
+
+ Returns:
+ string: The name of the thermal
+ """
+ return self.THERMAL_NAME[self.index - 1]
+
+ def get_presence(self):
+ """
+ Retrieves the presence of the thermal
+
+ Returns:
+ bool: True if thermal is present, False if not
+ """
+ if self.dependency:
+ return self.dependency.get_presence()
+ else:
+ return True
+
+ def get_model(self):
+ """
+ Retrieves the model number (or part number) of the Thermal
+
+ Returns:
+ string: Model/part number of Thermal
+ """
+ return 'NA'
+
+ def get_serial(self):
+ """
+ Retrieves the serial number of the Thermal
+
+ Returns:
+ string: Serial number of Thermal
+ """
+ return 'NA'
+
+ def get_status(self):
+ """
+ Retrieves the operational status of the thermal
+
+ Returns:
+ A boolean value, True if thermal is operating properly,
+ False if not
+ """
+ if self.dependency:
+ return self.dependency.get_status()
+ else:
+ return True
+
+ def get_temperature(self):
+ """
+ Retrieves current temperature reading from thermal
+
+ Returns:
+ A float number of current temperature in Celsius up to
+ nearest thousandth of one degree Celsius, e.g. 30.125
+ """
+ thermal_temperature = self._read_sysfs_file(
+ self.thermal_temperature_file)
+ if (thermal_temperature != 'ERR'):
+ thermal_temperature = float(thermal_temperature) / 1000
+ if self._minimum is None or self._minimum > thermal_temperature:
+ self._minimum = thermal_temperature
+ if self._maximum is None or self._maximum < thermal_temperature:
+ self._maximum = thermal_temperature
+ else:
+ thermal_temperature = 0
+
+ return float("{:.3f}".format(thermal_temperature))
+
+ def get_high_threshold(self):
+ """
+ Retrieves the high threshold temperature of thermal
+
+ Returns:
+ A float number, the high threshold temperature of thermal in
+ Celsius up to nearest thousandth of one degree Celsius,
+ e.g. 30.125
+ """
+ # Not implemented for this sensor
+ if not self.thermal_high_threshold_file:
+ raise NotImplementedError
+
+ thermal_high_threshold = self._read_sysfs_file(
+ self.thermal_high_threshold_file)
+ if (thermal_high_threshold != 'ERR'):
+ thermal_high_threshold = float(thermal_high_threshold) / 1000
+ else:
+ thermal_high_threshold = 0.0
+
+ return float("{:.3f}".format(thermal_high_threshold))
+
+ def set_high_threshold(self, temperature):
+ """
+ Sets the high threshold temperature of thermal
+
+ Args :
+ temperature: A float number up to nearest thousandth of one
+ degree Celsius, e.g. 30.125
+ Returns:
+ A boolean, True if threshold is set successfully, False if
+ not
+ """
+ # Thermal threshold values are pre-defined based on HW.
+ return False
+
+ def get_high_critical_threshold(self):
+ """
+ Retrieves the high critical threshold temperature of thermal
+
+ Returns:
+ A float number, the high critical threshold temperature of thermal in Celsius
+ up to nearest thousandth of one degree Celsius, e.g. 30.125
+ """
+
+ # Not implemented for this sensor
+ if not self.thermal_high_crit_threshold_file:
+ raise NotImplementedError
+
+ thermal_high_crit_threshold = self._read_sysfs_file(
+ self.thermal_high_crit_threshold_file)
+ if (thermal_high_crit_threshold != 'ERR'):
+ thermal_high_crit_threshold = float(thermal_high_crit_threshold) / 1000
+ else:
+ thermal_high_crit_threshold = 0.0
+
+ return float("{:.3f}".format(thermal_high_crit_threshold))
+
+ def get_minimum_recorded(self):
+ self.get_temperature()
+ return self._minimum
+
+ def get_maximum_recorded(self):
+ self.get_temperature()
+ return self._maximum
+
+ def get_position_in_parent(self):
+ """
+ Retrieves 1-based relative physical position in parent device
+ Returns:
+ integer: The 1-based relative physical position in parent device
+ """
+ return self.index
+
+ def is_replaceable(self):
+ """
+ Indicate whether this device is replaceable.
+ Returns:
+ bool: True if it is replaceable.
+ """
+ return False
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/thermal_actions.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/thermal_actions.py
new file mode 100644
index 0000000000..4bf1502ae3
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/thermal_actions.py
@@ -0,0 +1,200 @@
+#try:
+# import os
+# from sonic_platform_base.sonic_thermal_control.thermal_action_base import ThermalPolicyActionBase
+# from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object
+#except ImportError as e:
+# raise ImportError(str(e) + "- required module not found")
+
+import os
+from sonic_platform_base.sonic_thermal_control.thermal_action_base import ThermalPolicyActionBase
+from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object
+
+from sonic_py_common import logger
+
+sonic_logger = logger.Logger('thermal_actions')
+
+
+class SetFanSpeedAction(ThermalPolicyActionBase):
+ """
+ Base thermal action class to set speed for fans
+ """
+ # JSON field definition
+ JSON_FIELD_SPEED = 'speed'
+ JSON_FIELD_DEFAULT_SPEED = 'default_speed'
+ JSON_FIELD_HIGHTEMP_SPEED = 'hightemp_speed'
+
+ def __init__(self):
+ """
+ Constructor of SetFanSpeedAction
+ """
+ self.default_speed = 50
+ self.hightemp_speed = 100
+ self.speed = self.default_speed
+
+ def load_from_json(self, json_obj):
+ """
+ Construct SetFanSpeedAction via JSON. JSON example:
+ {
+ "type": "fan.all.set_speed"
+ "speed": "100"
+ }
+ :param json_obj: A JSON object representing a SetFanSpeedAction action.
+ :return:
+ """
+ if SetFanSpeedAction.JSON_FIELD_SPEED in json_obj:
+ speed = int(json_obj[SetFanSpeedAction.JSON_FIELD_SPEED])
+ if speed < 0 or speed > 100:
+ raise ValueError('SetFanSpeedAction invalid speed value {} in JSON policy file, valid value should be [0, 100]'.
+ format(speed))
+ self.speed = int(json_obj[SetFanSpeedAction.JSON_FIELD_SPEED])
+ else:
+ raise ValueError('SetFanSpeedAction missing mandatory field {} in JSON policy file'.
+ format(SetFanSpeedAction.JSON_FIELD_SPEED))
+
+ @classmethod
+ def set_all_fan_speed(cls, thermal_info_dict, speed):
+ from .thermal_infos import FanInfo
+ if FanInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[FanInfo.INFO_NAME], FanInfo):
+ fan_info_obj = thermal_info_dict[FanInfo.INFO_NAME]
+ for fan in fan_info_obj.get_presence_fans():
+ fan.set_speed(int(speed))
+
+
+@thermal_json_object('fan.all.set_speed')
+class SetAllFanSpeedAction(SetFanSpeedAction):
+ """
+ Action to set speed for all fans
+ """
+ def execute(self, thermal_info_dict):
+ """
+ Set speed for all fans
+ :param thermal_info_dict: A dictionary stores all thermal information.
+ :return:
+ """
+ SetAllFanSpeedAction.set_all_fan_speed(thermal_info_dict, self.speed)
+
+
+@thermal_json_object('thermal.temp_check_and_set_all_fan_speed')
+class ThermalRecoverAction(SetFanSpeedAction):
+ """
+ Action to check thermal sensor temperature change status and set speed for all fans
+ """
+
+ def load_from_json(self, json_obj):
+ """
+ Construct ThermalRecoverAction via JSON. JSON example:
+ {
+ "type": "thermal.temp_check_and_set_all_fan_speed"
+ "default_speed": "50"
+ "hightemp_speed": "100"
+ }
+ :param json_obj: A JSON object representing a ThermalRecoverAction action.
+ :return:
+ """
+ if SetFanSpeedAction.JSON_FIELD_DEFAULT_SPEED in json_obj:
+ default_speed = int(json_obj[SetFanSpeedAction.JSON_FIELD_DEFAULT_SPEED])
+ if default_speed < 0 or default_speed > 100:
+ raise ValueError('SetFanSpeedAction invalid default speed value {} in JSON policy file, valid value should be [0, 100]'.
+ format(default_speed))
+ self.default_speed = int(json_obj[SetFanSpeedAction.JSON_FIELD_DEFAULT_SPEED])
+ else:
+ raise ValueError('SetFanSpeedAction missing mandatory field {} in JSON policy file'.
+ format(SetFanSpeedAction.JSON_FIELD_DEFAULT_SPEED))
+
+ if SetFanSpeedAction.JSON_FIELD_HIGHTEMP_SPEED in json_obj:
+ hightemp_speed = int(json_obj[SetFanSpeedAction.JSON_FIELD_HIGHTEMP_SPEED])
+ if hightemp_speed < 0 or hightemp_speed > 100:
+ raise ValueError('SetFanSpeedAction invalid hightemp speed value {} in JSON policy file, valid value should be [0, 100]'.
+ format(hightemp_speed))
+ self.hightemp_speed = int(json_obj[SetFanSpeedAction.JSON_FIELD_HIGHTEMP_SPEED])
+ else:
+ raise ValueError('SetFanSpeedAction missing mandatory field {} in JSON policy file'.
+ format(SetFanSpeedAction.JSON_FIELD_HIGHTEMP_SPEED))
+
+ sonic_logger.log_warning("ThermalRecoverAction: default: {}, hightemp: {}".format(self.default_speed, self.hightemp_speed))
+
+ def execute(self, thermal_info_dict):
+ """
+ Check check thermal sensor temperature change status and set speed for all fans
+ :param thermal_info_dict: A dictionary stores all thermal information.
+ :return:
+ """
+ from .thermal_infos import ThermalInfo
+ if ThermalInfo.INFO_NAME in thermal_info_dict and \
+ isinstance(thermal_info_dict[ThermalInfo.INFO_NAME], ThermalInfo):
+
+ thermal_info_obj = thermal_info_dict[ThermalInfo.INFO_NAME]
+ if thermal_info_obj.is_warm_up_and_over_high_threshold():
+ ThermalRecoverAction.set_all_fan_speed(thermal_info_dict, self.hightemp_speed)
+ elif thermal_info_obj.is_cool_down_and_below_low_threshold():
+ ThermalRecoverAction.set_all_fan_speed(thermal_info_dict, self.default_speed)
+
+
+@thermal_json_object('switch.shutdown')
+class SwitchPolicyAction(ThermalPolicyActionBase):
+ """
+ Base class for thermal action. Once all thermal conditions in a thermal policy are matched,
+ all predefined thermal action will be executed.
+ """
+ def execute(self, thermal_info_dict):
+ """
+ Take action when thermal condition matches. For example, adjust speed of fan or shut
+ down the switch.
+ :param thermal_info_dict: A dictionary stores all thermal information.
+ :return:
+ """
+ sonic_logger.log_warning("Alarm for temperature critical is detected, reboot Device")
+ # import os
+ # os.system('reboot')
+
+
+@thermal_json_object('thermal_control.control')
+class ControlThermalAlgoAction(ThermalPolicyActionBase):
+ """
+ Action to control the thermal control algorithm
+ """
+ # JSON field definition
+ JSON_FIELD_STATUS = 'status'
+
+ def __init__(self):
+ self.status = True
+
+ def load_from_json(self, json_obj):
+ """
+ Construct ControlThermalAlgoAction via JSON. JSON example:
+ {
+ "type": "thermal_control.control"
+ "status": "true"
+ }
+ :param json_obj: A JSON object representing a ControlThermalAlgoAction action.
+ :return:
+ """
+ if ControlThermalAlgoAction.JSON_FIELD_STATUS in json_obj:
+ status_str = json_obj[ControlThermalAlgoAction.JSON_FIELD_STATUS].lower()
+ if status_str == 'true':
+ self.status = True
+ elif status_str == 'false':
+ self.status = False
+ else:
+ raise ValueError('Invalid {} field value, please specify true of false'.
+ format(ControlThermalAlgoAction.JSON_FIELD_STATUS))
+ else:
+ raise ValueError('ControlThermalAlgoAction '
+ 'missing mandatory field {} in JSON policy file'.
+ format(ControlThermalAlgoAction.JSON_FIELD_STATUS))
+
+ def execute(self, thermal_info_dict):
+ """
+ Disable thermal control algorithm
+ :param thermal_info_dict: A dictionary stores all thermal information.
+ :return:
+ """
+ from .thermal_infos import ChassisInfo
+ if ChassisInfo.INFO_NAME in thermal_info_dict:
+ chassis_info_obj = thermal_info_dict[ChassisInfo.INFO_NAME]
+ chassis = chassis_info_obj.get_chassis()
+ thermal_manager = chassis.get_thermal_manager()
+ if self.status:
+ thermal_manager.start_thermal_control_algorithm()
+ else:
+ thermal_manager.stop_thermal_control_algorithm()
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/thermal_conditions.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/thermal_conditions.py
new file mode 100644
index 0000000000..4923d63d74
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/thermal_conditions.py
@@ -0,0 +1,81 @@
+from sonic_platform_base.sonic_thermal_control.thermal_condition_base import ThermalPolicyConditionBase
+from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object
+
+
+class FanCondition(ThermalPolicyConditionBase):
+ def get_fan_info(self, thermal_info_dict):
+ from .thermal_infos import FanInfo
+ if FanInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[FanInfo.INFO_NAME], FanInfo):
+ return thermal_info_dict[FanInfo.INFO_NAME]
+ else:
+ return None
+
+
+@thermal_json_object('fan.any.absence')
+class AnyFanAbsenceCondition(FanCondition):
+ def is_match(self, thermal_info_dict):
+ fan_info_obj = self.get_fan_info(thermal_info_dict)
+ return len(fan_info_obj.get_absence_fans()) > 0 if fan_info_obj else False
+
+
+@thermal_json_object('fan.all.absence')
+class AllFanAbsenceCondition(FanCondition):
+ def is_match(self, thermal_info_dict):
+ fan_info_obj = self.get_fan_info(thermal_info_dict)
+ return len(fan_info_obj.get_presence_fans()) == 0 if fan_info_obj else False
+
+
+@thermal_json_object('fan.all.presence')
+class AllFanPresenceCondition(FanCondition):
+ def is_match(self, thermal_info_dict):
+ fan_info_obj = self.get_fan_info(thermal_info_dict)
+ return len(fan_info_obj.get_absence_fans()) == 0 if fan_info_obj else False
+
+
+class ThermalCondition(ThermalPolicyConditionBase):
+ def get_thermal_info(self, thermal_info_dict):
+ from .thermal_infos import ThermalInfo
+ if ThermalInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[ThermalInfo.INFO_NAME], ThermalInfo):
+ return thermal_info_dict[ThermalInfo.INFO_NAME]
+ else:
+ return None
+
+
+@thermal_json_object('thermal.over.high_critical_threshold')
+class ThermalOverHighCriticalCondition(ThermalCondition):
+ def is_match(self, thermal_info_dict):
+ thermal_info_obj = self.get_thermal_info(thermal_info_dict)
+ if thermal_info_obj:
+ return thermal_info_obj.is_over_high_critical_threshold()
+ else:
+ return False
+
+
+class PsuCondition(ThermalPolicyConditionBase):
+ def get_psu_info(self, thermal_info_dict):
+ from .thermal_infos import PsuInfo
+ if PsuInfo.INFO_NAME in thermal_info_dict and isinstance(thermal_info_dict[PsuInfo.INFO_NAME], PsuInfo):
+ return thermal_info_dict[PsuInfo.INFO_NAME]
+ else:
+ return None
+
+
+@thermal_json_object('psu.any.absence')
+class AnyPsuAbsenceCondition(PsuCondition):
+ def is_match(self, thermal_info_dict):
+ psu_info_obj = self.get_psu_info(thermal_info_dict)
+ return len(psu_info_obj.get_absence_psus()) > 0 if psu_info_obj else False
+
+
+@thermal_json_object('psu.all.absence')
+class AllPsuAbsenceCondition(PsuCondition):
+ def is_match(self, thermal_info_dict):
+ psu_info_obj = self.get_psu_info(thermal_info_dict)
+ return len(psu_info_obj.get_presence_psus()) == 0 if psu_info_obj else False
+
+
+@thermal_json_object('psu.all.presence')
+class AllPsuPresenceCondition(PsuCondition):
+ def is_match(self, thermal_info_dict):
+ psu_info_obj = self.get_psu_info(thermal_info_dict)
+ return len(psu_info_obj.get_absence_psus()) == 0 if psu_info_obj else False
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/thermal_infos.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/thermal_infos.py
new file mode 100644
index 0000000000..cd0a0591cd
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/thermal_infos.py
@@ -0,0 +1,210 @@
+from sonic_platform_base.sonic_thermal_control.thermal_info_base import ThermalPolicyInfoBase
+from sonic_platform_base.sonic_thermal_control.thermal_json_object import thermal_json_object
+
+
+@thermal_json_object('fan_info')
+class FanInfo(ThermalPolicyInfoBase):
+ """
+ Fan information needed by thermal policy
+ """
+
+ # Fan information name
+ INFO_NAME = 'fan_info'
+
+ def __init__(self):
+ self._absence_fans = set()
+ self._presence_fans = set()
+ self._status_changed = False
+
+ def collect(self, chassis):
+ """
+ Collect absence and presence fans.
+ :param chassis: The chassis object
+ :return:
+ """
+ self._status_changed = False
+ for fan in chassis.get_all_fans():
+ if fan.get_presence() and fan not in self._presence_fans:
+ self._presence_fans.add(fan)
+ self._status_changed = True
+ if fan in self._absence_fans:
+ self._absence_fans.remove(fan)
+ elif not fan.get_presence() and fan not in self._absence_fans:
+ self._absence_fans.add(fan)
+ self._status_changed = True
+ if fan in self._presence_fans:
+ self._presence_fans.remove(fan)
+
+ def get_absence_fans(self):
+ """
+ Retrieves absence fans
+ :return: A set of absence fans
+ """
+ return self._absence_fans
+
+ def get_presence_fans(self):
+ """
+ Retrieves presence fans
+ :return: A set of presence fans
+ """
+ return self._presence_fans
+
+ def is_status_changed(self):
+ """
+ Retrieves if the status of fan information changed
+ :return: True if status changed else False
+ """
+ return self._status_changed
+
+
+@thermal_json_object('thermal_info')
+class ThermalInfo(ThermalPolicyInfoBase):
+ """
+ Thermal information needed by thermal policy
+ """
+
+ # Fan information name
+ INFO_NAME = 'thermal_info'
+
+ def __init__(self):
+ self.init = False
+ self._old_avg_temp = 0
+ self._current_avg_temp = 0
+ self._high_crital_threshold = 75
+ self._high_threshold = 45
+ self._low_threshold = 40
+
+ def collect(self, chassis):
+ """
+ Collect thermal sensor temperature change status
+ :param chassis: The chassis object
+ :return:
+ """
+ self._temps = []
+ self._over_high_critical_threshold = False
+ self._warm_up_and_over_high_threshold = False
+ self._cool_down_and_below_low_threshold = False
+
+ # Calculate average temp within the device
+ temp = 0
+ num_of_thermals = chassis.get_num_thermals()
+ for index in range(num_of_thermals):
+ self._temps.insert(index, chassis.get_thermal(index).get_temperature())
+ temp += self._temps[index]
+
+ self._current_avg_temp = temp / num_of_thermals
+
+ # Special case if first time
+ if self.init is False:
+ self._old_avg_temp = self._current_avg_temp
+ self.init = True
+
+ # Check if new average temp exceeds high threshold value
+ if self._current_avg_temp >= self._old_avg_temp and self._current_avg_temp >= self._high_threshold:
+ self._warm_up_and_over_high_threshold = True
+
+ # Check if new average temp exceeds low threshold value
+ if self._current_avg_temp <= self._old_avg_temp and self._current_avg_temp <= self._low_threshold:
+ self._cool_down_and_below_low_threshold = True
+
+ self._old_avg_temp = self._current_avg_temp
+
+ def is_warm_up_and_over_high_threshold(self):
+ """
+ Retrieves if the temperature is warm up and over high threshold
+ :return: True if the temperature is warm up and over high threshold else False
+ """
+ return self._warm_up_and_over_high_threshold
+
+ def is_cool_down_and_below_low_threshold(self):
+ """
+ Retrieves if the temperature is cold down and below low threshold
+ :return: True if the temperature is cold down and below low threshold else False
+ """
+ return self._cool_down_and_below_low_threshold
+
+ def is_over_high_critical_threshold(self):
+ """
+ Retrieves if the temperature is over high critical threshold
+ :return: True if the temperature is over high critical threshold else False
+ """
+ return self._over_high_critical_threshold
+
+
+@thermal_json_object('psu_info')
+class PsuInfo(ThermalPolicyInfoBase):
+ """
+ PSU information needed by thermal policy
+ """
+ INFO_NAME = 'psu_info'
+
+ def __init__(self):
+ self._absence_psus = set()
+ self._presence_psus = set()
+ self._status_changed = False
+
+ def collect(self, chassis):
+ """
+ Collect absence and presence PSUs.
+ :param chassis: The chassis object
+ :return:
+ """
+ self._status_changed = False
+ for psu in chassis.get_all_psus():
+ if psu.get_presence() and psu.get_powergood_status() and psu not in self._presence_psus:
+ self._presence_psus.add(psu)
+ self._status_changed = True
+ if psu in self._absence_psus:
+ self._absence_psus.remove(psu)
+ elif (not psu.get_presence() or not psu.get_powergood_status()) and psu not in self._absence_psus:
+ self._absence_psus.add(psu)
+ self._status_changed = True
+ if psu in self._presence_psus:
+ self._presence_psus.remove(psu)
+
+ def get_absence_psus(self):
+ """
+ Retrieves presence PSUs
+ :return: A set of absence PSUs
+ """
+ return self._absence_psus
+
+ def get_presence_psus(self):
+ """
+ Retrieves presence PSUs
+ :return: A set of presence fans
+ """
+ return self._presence_psus
+
+ def is_status_changed(self):
+ """
+ Retrieves if the status of PSU information changed
+ :return: True if status changed else False
+ """
+ return self._status_changed
+
+
+@thermal_json_object('chassis_info')
+class ChassisInfo(ThermalPolicyInfoBase):
+ """
+ Chassis information needed by thermal policy
+ """
+ INFO_NAME = 'chassis_info'
+
+ def __init__(self):
+ self._chassis = None
+
+ def collect(self, chassis):
+ """
+ Collect platform chassis.
+ :param chassis: The chassis object
+ :return:
+ """
+ self._chassis = chassis
+
+ def get_chassis(self):
+ """
+ Retrieves platform chassis object
+ :return: A platform chassis object.
+ """
+ return self._chassis
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/thermal_manager.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/thermal_manager.py
new file mode 100644
index 0000000000..10c3b67433
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/thermal_manager.py
@@ -0,0 +1,68 @@
+
+#try:
+# import os
+# from sonic_platform_base.sonic_thermal_control.thermal_manager_base import ThermalManagerBase
+# from .thermal_actions import *
+# from .thermal_conditions import *
+# from .thermal_infos import *
+#except ImportError as e:
+# raise ImportError(str(e) + "- required module not found")
+
+import os
+from sonic_platform_base.sonic_thermal_control.thermal_manager_base import ThermalManagerBase
+from sonic_py_common import logger
+from .thermal_actions import *
+from .thermal_conditions import *
+from .thermal_infos import *
+
+sonic_logger = logger.Logger('thermal_manager')
+
+class ThermalManager(ThermalManagerBase):
+ THERMAL_ALGORITHM_CONTROL_PATH = '/var/run/hw-management/config/suspend'
+
+ @classmethod
+ def initialize(cls):
+ cls.logger=sonic_logger
+ cls.logger.set_min_log_priority_info()
+ cls.logger.log_warning('ThermalManager initialize')
+
+ @classmethod
+ def start_thermal_control_algorithm(cls):
+ """
+ Start thermal control algorithm
+
+ Returns:
+ bool: True if set success, False if fail.
+ """
+ cls._control_thermal_control_algorithm(False)
+
+ @classmethod
+ def stop_thermal_control_algorithm(cls):
+ """
+ Stop thermal control algorithm
+
+ Returns:
+ bool: True if set success, False if fail.
+ """
+ cls._control_thermal_control_algorithm(True)
+
+ @classmethod
+ def _control_thermal_control_algorithm(cls, suspend):
+ """
+ Control thermal control algorithm
+
+ Args:
+ suspend: Bool, indicate suspend the algorithm or not
+
+ Returns:
+ bool: True if set success, False if fail.
+ """
+ status = True
+ write_value = 1 if suspend else 0
+ try:
+ with open(cls.THERMAL_ALGORITHM_CONTROL_PATH, 'w') as control_file:
+ control_file.write(str(write_value))
+ except (ValueError, IOError):
+ status = False
+
+ return status
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/watchdog.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/watchdog.py
new file mode 100644
index 0000000000..53edc60fa9
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/sonic_platform/watchdog.py
@@ -0,0 +1,289 @@
+"""
+Module contains an implementation of SONiC Platform Base API and
+provides access to hardware watchdog
+"""
+
+import os
+import fcntl
+import array
+import time
+
+from sonic_platform_base.watchdog_base import WatchdogBase
+from sonic_py_common import logger
+
+WD_COMMON_ERROR = -1
+
+sonic_logger = logger.Logger()
+
+# CPLD Watchdog Timer CTRL register bits
+WDT_CTRL_INTR_EN_BIT = 0x80
+WDT_CTRL_RSET_EN_BIT = 0x40
+WDT_CTRL_CNTR_EN_BIT = 0x20
+
+WDT_CTRL_FREQ_SEL_16HZ = 0x00
+WDT_CTRL_FREQ_SEL_4HZ = 0x01
+WDT_CTRL_FREQ_SEL_1HZ = 0x02
+WDT_CTRL_FREQ_SEL_0_25HZ = 0x03
+
+WDT_MAX_TIMEOUT = 867
+
+class WatchdogImplBase(WatchdogBase):
+ """
+ Base class that implements common logic for interacting
+ with watchdog using ioctl commands
+ """
+
+ def __init__(self, wd_device_path):
+ """
+ Open a watchdog handle
+ @param wd_device_path Path to watchdog device
+ """
+
+ G3748CPLD_I2C_DIR = "/sys/bus/i2c/devices/0-0066/"
+ #sonic_logger.log_info(" WatchdogImplBase: __init__")
+
+ self.watchdog_path = wd_device_path
+ #self.watchdog = os.open(self.watchdog_path, os.O_WRONLY)
+ self.wdt_timer_reg = G3748CPLD_I2C_DIR+"wdt_timer".format()
+ self.wdt_ctrl_reg = G3748CPLD_I2C_DIR+"wdt_ctrl".format()
+ self.wdt_intr_cnt_mask_reg = G3748CPLD_I2C_DIR+"wdt_intr_cnt_mask".format()
+ self.wdt_intr_flag_reg = G3748CPLD_I2C_DIR+"wdt_intr_flag".format()
+ self.wdt_timeout = G3748CPLD_I2C_DIR+"wdt_timeout".format()
+
+ self.armed = self._is_cpld_wd_armed()
+ self.timeout = self._gettimeout()
+ self.max_timeout = WDT_MAX_TIMEOUT
+
+ def _read_cpld_reg(self, reg_file):
+ # On successful read, returns the value read from given
+ # reg_name and on failure returns 'ERR'
+ rv = 'ERR'
+ if (not os.path.isfile(reg_file)):
+ return rv
+ try:
+ with open(reg_file, 'r') as fd:
+ rv = fd.read()
+ except Exception as e:
+ rv = 'ERR'
+ rv = rv.rstrip('\r\n')
+ rv = rv.lstrip(" ")
+ return rv
+
+ def _write_cpld_reg(self, reg_file, value):
+ # On successful write, the value read will be written on
+ # reg_name and on failure returns 'ERR'
+ rv = 'ERR'
+ if (not os.path.isfile(reg_file)):
+ return rv
+ try:
+ with open(reg_file, 'w') as fd:
+ rv = fd.write(str(value))
+ except Exception as e:
+ rv = 'ERR'
+ # Ensure that the write operation has succeeded
+ if (int(self._read_cpld_reg(reg_file)) != value ):
+ time.sleep(3)
+ if (int(self._read_cpld_reg(reg_file)) != value ):
+ rv = 'ERR'
+ return rv
+
+ def _is_cpld_wd_armed(self):
+ reg = self._read_cpld_reg(self.wdt_ctrl_reg)
+ state = (int(reg) & 0x20) >> 5
+ #sonic_logger.log_warning(" state = {}".format(state))
+ if (state == 0):
+ return False # Disabled
+ return True # Enabled
+
+ def _disablewatchdog(self):
+ """
+ Turn off the watchdog timer
+ """
+ #sonic_logger.log_info(" _disablewatchdog")
+ reg = self._read_cpld_reg(self.wdt_ctrl_reg)
+ # Set reg bit(7-5) to 0 to disable timer
+ reg_val = int(reg)
+ reg_val = reg_val & ~(WDT_CTRL_INTR_EN_BIT | WDT_CTRL_RSET_EN_BIT | WDT_CTRL_CNTR_EN_BIT)
+ self._write_cpld_reg(self.wdt_ctrl_reg, reg_val)
+ # Reset timer counter to 0
+ self._write_cpld_reg(self.wdt_timer_reg, 0)
+
+ def _enablewatchdog(self):
+ """
+ Turn on the watchdog timer
+ """
+ #sonic_logger.log_info(" _enablewatchdog")
+ reg = self._read_cpld_reg(self.wdt_ctrl_reg)
+ # Set reg bit(5) to 1 to enable timer
+ reg_val = int(reg) | (WDT_CTRL_INTR_EN_BIT | WDT_CTRL_RSET_EN_BIT | WDT_CTRL_CNTR_EN_BIT)
+ self._write_cpld_reg(self.wdt_ctrl_reg, reg_val)
+
+ def _settimeout(self, seconds):
+ """
+ Set watchdog timer timeout
+ 1. The watchdog timer can be set to an initial value from 0 through 0xff.
+ Writing 0xff would generate an immediate watchdog reset.
+ 2. The watchdog timer will increment from the initial value after enabling
+ the watchdog timer reset function or the watchdog interrupt function.
+ 3. Writing a value to the watchdog timer register will restart the timer count.
+ 4. The watchdog timer will generate an interrupt when the watchdog timer
+ interrupt function is enabled by software and the current timer value
+ reaches watchdog interrupt count mask register value (power on default = 0X7f).
+ 5. The PLD will reset the whole system when watchdog timer reset function is enabled
+ by software and the current timer value is 0XFF.
+
+ @param seconds - timeout in seconds
+ @return is the actual set timeout
+ """
+ #sonic_logger.log_info(" _settimeout")
+ if (seconds > self.max_timeout or seconds < 0):
+ sonic_logger.log_warning("Error: WDT timeout value is out of range.")
+ return WD_COMMON_ERROR
+ # Save the timeout (seconds) value
+ self._write_cpld_reg(self.wdt_timeout, seconds)
+ # Configure the initial timer value to CPLD registor
+ if (seconds >= 0 and seconds <= self.max_timeout):
+ # Use 3.4 sec instead of 4 sec, to be more closer to real time
+ count = (seconds / 3.4)
+ clkval = WDT_CTRL_FREQ_SEL_0_25HZ # frequency 0.25 Hz
+ #elif (seconds >= 0 and seconds < 256):
+ # count = (seconds / 1)
+ # clkval = WDT_CTRL_FREQ_SEL_1HZ # frequency 1 Hz
+
+ init_timer = int(255 - count)
+ if (init_timer > 1):
+ init_timer = init_timer - 1
+ #sonic_logger.log_warning("_settimeout: init_timer = {}".format(init_timer))
+ # Set initial timer count
+ self._write_cpld_reg(self.wdt_timer_reg, init_timer)
+ # Set clock frequency selector
+ # If Bit7 - Bit5 of fval has one bit '1', the timer will be restarted
+ reg = self._read_cpld_reg(self.wdt_ctrl_reg)
+ fval = (int(reg) & 0xF0) | clkval
+ self._write_cpld_reg(self.wdt_ctrl_reg, fval)
+
+ return seconds
+
+ def _gettimeout(self):
+ """
+ Get watchdog timeout
+ @return watchdog timeout
+ """
+ #sonic_logger.log_info(" _gettimeout")
+ timeout = self._read_cpld_reg(self.wdt_timeout)
+ return int(timeout)
+
+ def _gettimeleft(self):
+ """
+ Get time left before watchdog timer expires
+ @return time left in seconds
+ """
+ #sonic_logger.log_info(" _gettimeleft")
+ timer_cnt = int(self._read_cpld_reg(self.wdt_timer_reg))
+ if (timer_cnt < 254):
+ timer_cnt = timer_cnt + 1
+ freq_sel = int(self._read_cpld_reg(self.wdt_ctrl_reg)) & 0x03
+ timer_cnt_left = 0xFF - int(timer_cnt)
+ if (freq_sel == WDT_CTRL_FREQ_SEL_16HZ):
+ timeleft = timer_cnt_left / 16
+ elif (freq_sel == WDT_CTRL_FREQ_SEL_4HZ):
+ timeleft = timer_cnt_left / 4
+ elif (freq_sel == WDT_CTRL_FREQ_SEL_1HZ):
+ timeleft = timer_cnt_left / 1
+ elif (freq_sel == WDT_CTRL_FREQ_SEL_0_25HZ):
+ #timeleft = timer_cnt_left * 4
+ # Change from 4 sec to 3.4 sec to be more closer to real time.
+ timeleft = timer_cnt_left * 3.4
+
+ return int(timeleft)
+
+ def _keepalive(self):
+ """
+ Keep alive watchdog timer
+ """
+ #sonic_logger.log_warning(" _keepalive")
+ self._disablewatchdog()
+ timeout = self._gettimeout()
+ self._settimeout(timeout)
+ self._enablewatchdog()
+
+ def is_armed(self):
+ """
+ Implements is_armed WatchdogBase API
+ """
+ return self.armed
+
+ def get_remaining_time(self):
+ """
+ Implements get_remaining_time WatchdogBase API
+ """
+ #sonic_logger.log_warning("get_remaining_time")
+ timeleft = WD_COMMON_ERROR
+
+ if self.armed:
+ try:
+ timeleft = self._gettimeleft()
+ except IOError:
+ pass
+
+ return timeleft
+
+ def disarm(self):
+ """
+ Disarm the hardware watchdog
+ Returns:
+ A boolean, True if watchdog is disarmed successfully, False
+ if not
+ """
+ #sonic_logger.log_info(" Debug disarm watchdog ")
+
+ disarmed = False
+
+ if self.is_armed():
+ try:
+ self._disablewatchdog()
+ self.armed = False
+ disarmed = True
+ self.timeout = 0
+ self._write_cpld_reg(self.wdt_timeout, self.timeout)
+ except IOError:
+ pass
+
+ return disarmed
+
+ def arm(self, seconds):
+ """
+ Arm the hardware watchdog with a timeout of seconds.
+ If the watchdog is currently armed, calling this function will
+ simply reset the timer to the provided value. If the underlying
+ hardware does not support the value provided in , this
+ method should arm the watchdog with the *next greater* available
+ value.
+ Returns:
+ An integer specifying the *actual* number of seconds the watchdog
+ was armed with. On failure returns -1.
+ """
+ #sonic_logger.log_info(" Debug arm ")
+
+ ret = WD_COMMON_ERROR
+ if seconds < 0:
+ return ret
+ if seconds > self.max_timeout:
+ return ret
+
+ try:
+ self._disablewatchdog()
+ #if self._gettimeout() != seconds:
+ #sonic_logger.log_info(" Debug arm-settimeout")
+ self.timeout = self._settimeout(seconds)
+ #sonic_logger.log_info(" Debug arm-enable ")
+ self._enablewatchdog()
+ self.armed = True
+ ret = self.timeout
+ except IOError as e:
+ pass
+
+ return ret
+
+
+
diff --git a/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/utils/get-base-mac.py b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/utils/get-base-mac.py
new file mode 100644
index 0000000000..fe271d04a9
--- /dev/null
+++ b/platform/marvell-arm64/sonic-platform-modules-supermicro/sse-g3748/utils/get-base-mac.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+
+def main():
+ try:
+ import sonic_platform.platform
+ import sonic_platform.chassis
+ except ImportError, e:
+ raise ImportError (str(e) + "- required module not found")
+
+ chassis = sonic_platform.platform.Platform().get_chassis()
+ if chassis is None:
+ print "DEBUG chassis was None "
+
+ base_mac = chassis.get_base_mac()
+ print base_mac
+
+ return
+
+if __name__ == '__main__':
+ main()
diff --git a/platform/marvell-arm64/sonic_fit.its b/platform/marvell-arm64/sonic_fit.its
index e0d1e7b5d3..2879ff4f43 100644
--- a/platform/marvell-arm64/sonic_fit.its
+++ b/platform/marvell-arm64/sonic_fit.its
@@ -91,6 +91,17 @@
algo = "sha1";
};
};
+ fdt_smc_sse-g3748 {
+ description = "Flattened Device Tree blob for Supermicro SSE-G3748";
+ data = /incbin/("/usr/lib/linux-image-5.10.0-23-2-arm64/marvell/smc_sse-g3748.dtb");
+ type = "flat_dt";
+ arch = "arm64";
+ compression = "none";
+ load = <0x2 0x1000000>;
+ hash@1 {
+ algo = "sha1";
+ };
+ };
};
configurations {
default = "conf_ac5x";
@@ -121,5 +132,14 @@
algo = "sha1";
};
};
+ conf_smc_sse-g3748 {
+ description = "Boot Linux kernel with FDT blob + ramdisk for Supermicro SSE-G3748";
+ kernel = "kernel_ac5x";
+ fdt = "fdt_smc_sse-g3748";
+ ramdisk = "ramdisk_ac5x";
+ hash@1 {
+ algo = "sha1";
+ };
+ };
};
};