diff --git a/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/port_config.ini b/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/port_config.ini
new file mode 100644
index 0000000000..2e128a4fde
--- /dev/null
+++ b/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/port_config.ini
@@ -0,0 +1,55 @@
+# name lanes alias index speed
+Ethernet0 2 tenGigE1 1 10000
+Ethernet1 1 tenGigE2 2 10000
+Ethernet2 4 tenGigE3 3 10000
+Ethernet3 3 tenGigE4 4 10000
+Ethernet4 6 tenGigE5 5 10000
+Ethernet5 5 tenGigE6 6 10000
+Ethernet6 8 tenGigE7 7 10000
+Ethernet7 7 tenGigE8 8 10000
+Ethernet8 10 tenGigE9 9 10000
+Ethernet9 9 tenGigE10 10 10000
+Ethernet10 12 tenGigE11 11 10000
+Ethernet11 11 tenGigE12 12 10000
+Ethernet12 14 tenGigE13 13 10000
+Ethernet13 13 tenGigE14 14 10000
+Ethernet14 16 tenGigE15 15 10000
+Ethernet15 15 tenGigE16 16 10000
+Ethernet16 18 tenGigE17 17 10000
+Ethernet17 17 tenGigE18 18 10000
+Ethernet18 20 tenGigE19 19 10000
+Ethernet19 19 tenGigE20 20 10000
+Ethernet20 22 tenGigE21 21 10000
+Ethernet21 21 tenGigE22 22 10000
+Ethernet22 24 tenGigE23 23 10000
+Ethernet23 23 tenGigE24 24 10000
+Ethernet24 54 tenGigE25 25 10000
+Ethernet25 53 tenGigE26 26 10000
+Ethernet26 56 tenGigE27 27 10000
+Ethernet27 55 tenGigE28 28 10000
+Ethernet28 58 tenGigE29 29 10000
+Ethernet29 57 tenGigE30 30 10000
+Ethernet30 60 tenGigE31 31 10000
+Ethernet31 59 tenGigE32 32 10000
+Ethernet32 62 tenGigE33 33 10000
+Ethernet33 61 tenGigE34 34 10000
+Ethernet34 64 tenGigE35 35 10000
+Ethernet35 63 tenGigE36 36 10000
+Ethernet36 66 tenGigE37 37 10000
+Ethernet37 65 tenGigE38 38 10000
+Ethernet38 68 tenGigE39 39 10000
+Ethernet39 67 tenGigE40 40 10000
+Ethernet40 70 tenGigE41 41 10000
+Ethernet41 69 tenGigE42 42 10000
+Ethernet42 72 tenGigE43 43 10000
+Ethernet43 71 tenGigE44 44 10000
+Ethernet44 74 tenGigE45 45 10000
+Ethernet45 73 tenGigE46 46 10000
+Ethernet46 76 tenGigE47 47 10000
+Ethernet47 75 tenGigE48 48 10000
+Ethernet48 29,30,31,32 hundredGigE49 49 100000
+Ethernet52 33,34,35,36 hundredGigE50 53 100000
+Ethernet56 37,38,39,40 hundredGigE51 57 100000
+Ethernet60 41,42,43,44 hundredGigE52 61 100000
+Ethernet64 45,46,47,48 hundredGigE53 65 100000
+Ethernet68 49,50,51,52 hundredGigE54 69 100000
diff --git a/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/sai.profile b/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/sai.profile
new file mode 100644
index 0000000000..952c87a00e
--- /dev/null
+++ b/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/sai.profile
@@ -0,0 +1 @@
+SAI_INIT_CONFIG_FILE=/etc/bcm/td3-as5835t-48x10G+6x100G.config.bcm
diff --git a/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/td3-as5835t-48x10G+6x100G.config.bcm b/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/td3-as5835t-48x10G+6x100G.config.bcm
new file mode 100644
index 0000000000..4b73e8c29d
--- /dev/null
+++ b/device/accton/x86_64-accton_as5835_54t-r0/Accton-AS5835-54T/td3-as5835t-48x10G+6x100G.config.bcm
@@ -0,0 +1,515 @@
+#polarity/lanemap is using TH2 style.
+core_clock_frequency=1525
+dpp_clock_ratio=2:3
+
+ptp_ts_pll_fref=50000000
+ptp_bs_fref_0=50000000
+ptp_bs_fref_1=50000000
+
+oversubscribe_mode=1
+
+pbmp_xport_xe=0x1FFFFFFFFFFFFFFFE
+
+parity_enable=0
+mem_cache_enable=0
+
+l2_mem_entries=32768
+#l3_mem_entries=49152
+#fpem_mem_entries=16384
+l2xmsg_mode=1
+
+#FC0
+dport_map_port_1=2
+dport_map_port_2=1
+dport_map_port_3=4
+dport_map_port_4=3
+portmap_1=1:10
+portmap_2=2:10
+portmap_3=3:10
+portmap_4=4:10
+#port_phy_addr_1=0x00
+#port_phy_addr_2=0x01
+#port_phy_addr_3=0x02
+#port_phy_addr_4=0x03
+phy_chain_rx_lane_map_physical{1.0}=0x0123
+phy_chain_rx_lane_map_physical{2.0}=0x0123
+phy_chain_rx_lane_map_physical{3.0}=0x0123
+phy_chain_rx_lane_map_physical{4.0}=0x0123
+phy_chain_tx_lane_map_physical{1.0}=0x0123
+phy_chain_tx_lane_map_physical{2.0}=0x0123
+phy_chain_tx_lane_map_physical{3.0}=0x0123
+phy_chain_tx_lane_map_physical{4.0}=0x0123
+phy_chain_rx_polarity_flip_physical{1.0}=0x1
+phy_chain_rx_polarity_flip_physical{2.0}=0x1
+phy_chain_rx_polarity_flip_physical{3.0}=0x1
+phy_chain_rx_polarity_flip_physical{4.0}=0x1
+phy_chain_tx_polarity_flip_physical{1.0}=0x0
+phy_chain_tx_polarity_flip_physical{2.0}=0x0
+phy_chain_tx_polarity_flip_physical{3.0}=0x0
+phy_chain_tx_polarity_flip_physical{4.0}=0x0
+
+#FC1
+dport_map_port_5=6
+dport_map_port_6=5
+dport_map_port_7=8
+dport_map_port_8=7
+portmap_5=5:10
+portmap_6=6:10
+portmap_7=7:10
+portmap_8=8:10
+#port_phy_addr_5=0x04
+#port_phy_addr_6=0x05
+#port_phy_addr_7=0x06
+#port_phy_addr_8=0x07
+phy_chain_rx_lane_map_physical{5.0}=0x0123
+phy_chain_rx_lane_map_physical{6.0}=0x0123
+phy_chain_rx_lane_map_physical{7.0}=0x0123
+phy_chain_rx_lane_map_physical{8.0}=0x0123
+phy_chain_tx_lane_map_physical{5.0}=0x0123
+phy_chain_tx_lane_map_physical{6.0}=0x0123
+phy_chain_tx_lane_map_physical{7.0}=0x0123
+phy_chain_tx_lane_map_physical{8.0}=0x0123
+phy_chain_rx_polarity_flip_physical{5.0}=0x0
+phy_chain_rx_polarity_flip_physical{6.0}=0x0
+phy_chain_rx_polarity_flip_physical{7.0}=0x0
+phy_chain_rx_polarity_flip_physical{8.0}=0x0
+phy_chain_tx_polarity_flip_physical{5.0}=0x0
+phy_chain_tx_polarity_flip_physical{6.0}=0x0
+phy_chain_tx_polarity_flip_physical{7.0}=0x0
+phy_chain_tx_polarity_flip_physical{8.0}=0x0
+
+#FC2
+dport_map_port_9=10
+dport_map_port_10=9
+dport_map_port_11=12
+dport_map_port_12=11
+portmap_9=9:10
+portmap_10=10:10
+portmap_11=11:10
+portmap_12=12:10
+#port_phy_addr_9=0x20
+#port_phy_addr_10=0x21
+#port_phy_addr_11=0x22
+#port_phy_addr_12=0x23
+phy_chain_rx_lane_map_physical{9.0}=0x0123
+phy_chain_rx_lane_map_physical{10.0}=0x0123
+phy_chain_rx_lane_map_physical{11.0}=0x0123
+phy_chain_rx_lane_map_physical{12.0}=0x0123
+phy_chain_tx_lane_map_physical{9.0}=0x0123
+phy_chain_tx_lane_map_physical{10.0}=0x0123
+phy_chain_tx_lane_map_physical{11.0}=0x0123
+phy_chain_tx_lane_map_physical{12.0}=0x0123
+phy_chain_rx_polarity_flip_physical{9.0}=0x0
+phy_chain_rx_polarity_flip_physical{10.0}=0x0
+phy_chain_rx_polarity_flip_physical{11.0}=0x0
+phy_chain_rx_polarity_flip_physical{12.0}=0x0
+phy_chain_tx_polarity_flip_physical{9.0}=0x0
+phy_chain_tx_polarity_flip_physical{10.0}=0x0
+phy_chain_tx_polarity_flip_physical{11.0}=0x0
+phy_chain_tx_polarity_flip_physical{12.0}=0x0
+
+#FC3
+dport_map_port_13=14
+dport_map_port_14=13
+dport_map_port_15=16
+dport_map_port_16=15
+portmap_13=13:10
+portmap_14=14:10
+portmap_15=15:10
+portmap_16=16:10
+#port_phy_addr_13=0x24
+#port_phy_addr_14=0x25
+#port_phy_addr_15=0x26
+#port_phy_addr_16=0x27
+phy_chain_rx_lane_map_physical{13.0}=0x0123
+phy_chain_rx_lane_map_physical{14.0}=0x0123
+phy_chain_rx_lane_map_physical{15.0}=0x0123
+phy_chain_rx_lane_map_physical{16.0}=0x0123
+phy_chain_tx_lane_map_physical{13.0}=0x0123
+phy_chain_tx_lane_map_physical{14.0}=0x0123
+phy_chain_tx_lane_map_physical{15.0}=0x0123
+phy_chain_tx_lane_map_physical{16.0}=0x0123
+phy_chain_rx_polarity_flip_physical{13.0}=0x0
+phy_chain_rx_polarity_flip_physical{14.0}=0x0
+phy_chain_rx_polarity_flip_physical{15.0}=0x0
+phy_chain_rx_polarity_flip_physical{16.0}=0x0
+phy_chain_tx_polarity_flip_physical{13.0}=0x0
+phy_chain_tx_polarity_flip_physical{14.0}=0x0
+phy_chain_tx_polarity_flip_physical{15.0}=0x0
+phy_chain_tx_polarity_flip_physical{16.0}=0x0
+
+#FC4
+dport_map_port_17=18
+dport_map_port_18=17
+dport_map_port_19=20
+dport_map_port_20=19
+portmap_17=17:10
+portmap_18=18:10
+portmap_19=19:10
+portmap_20=20:10
+#port_phy_addr_17=0x40
+#port_phy_addr_18=0x41
+#port_phy_addr_19=0x42
+#port_phy_addr_20=0x43
+phy_chain_rx_lane_map_physical{17.0}=0x0123
+phy_chain_rx_lane_map_physical{18.0}=0x0123
+phy_chain_rx_lane_map_physical{19.0}=0x0123
+phy_chain_rx_lane_map_physical{20.0}=0x0123
+phy_chain_tx_lane_map_physical{17.0}=0x0123
+phy_chain_tx_lane_map_physical{18.0}=0x0123
+phy_chain_tx_lane_map_physical{19.0}=0x0123
+phy_chain_tx_lane_map_physical{20.0}=0x0123
+phy_chain_rx_polarity_flip_physical{17.0}=0x1
+phy_chain_rx_polarity_flip_physical{18.0}=0x1
+phy_chain_rx_polarity_flip_physical{19.0}=0x1
+phy_chain_rx_polarity_flip_physical{20.0}=0x1
+phy_chain_tx_polarity_flip_physical{17.0}=0x0
+phy_chain_tx_polarity_flip_physical{18.0}=0x0
+phy_chain_tx_polarity_flip_physical{19.0}=0x0
+phy_chain_tx_polarity_flip_physical{20.0}=0x0
+
+#FC5
+dport_map_port_21=22
+dport_map_port_22=21
+dport_map_port_23=24
+dport_map_port_24=23
+portmap_21=21:10
+portmap_22=22:10
+portmap_23=23:10
+portmap_24=24:10
+#port_phy_addr_21=0x44
+#port_phy_addr_22=0x45
+#port_phy_addr_23=0x46
+#port_phy_addr_24=0x47
+phy_chain_rx_lane_map_physical{21.0}=0x0123
+phy_chain_rx_lane_map_physical{22.0}=0x0123
+phy_chain_rx_lane_map_physical{23.0}=0x0123
+phy_chain_rx_lane_map_physical{24.0}=0x0123
+phy_chain_tx_lane_map_physical{21.0}=0x0123
+phy_chain_tx_lane_map_physical{22.0}=0x0123
+phy_chain_tx_lane_map_physical{23.0}=0x0123
+phy_chain_tx_lane_map_physical{24.0}=0x0123
+phy_chain_rx_polarity_flip_physical{21.0}=0x0
+phy_chain_rx_polarity_flip_physical{22.0}=0x0
+phy_chain_rx_polarity_flip_physical{23.0}=0x0
+phy_chain_rx_polarity_flip_physical{24.0}=0x0
+phy_chain_tx_polarity_flip_physical{21.0}=0x0
+phy_chain_tx_polarity_flip_physical{22.0}=0x0
+phy_chain_tx_polarity_flip_physical{23.0}=0x0
+phy_chain_tx_polarity_flip_physical{24.0}=0x0
+
+#FC6
+
+#FC7
+dport_map_port_25=50
+portmap_25=29:100:4
+phy_chain_rx_lane_map_physical{29.0}=0x1302
+phy_chain_rx_lane_map_physical{30.0}=0x1302
+phy_chain_rx_lane_map_physical{31.0}=0x1302
+phy_chain_rx_lane_map_physical{32.0}=0x1302
+phy_chain_tx_lane_map_physical{29.0}=0x2031
+phy_chain_tx_lane_map_physical{30.0}=0x2031
+phy_chain_tx_lane_map_physical{31.0}=0x2031
+phy_chain_tx_lane_map_physical{32.0}=0x2031
+phy_chain_rx_polarity_flip_physical{29.0}=0x0
+phy_chain_rx_polarity_flip_physical{30.0}=0x0
+phy_chain_rx_polarity_flip_physical{31.0}=0x0
+phy_chain_rx_polarity_flip_physical{32.0}=0x1
+phy_chain_tx_polarity_flip_physical{29.0}=0x1
+phy_chain_tx_polarity_flip_physical{30.0}=0x1
+phy_chain_tx_polarity_flip_physical{31.0}=0x1
+phy_chain_tx_polarity_flip_physical{32.0}=0x1
+
+#FC8
+dport_map_port_26=51
+portmap_26=33:100:4
+phy_chain_rx_lane_map_physical{33.0}=0x0123
+phy_chain_rx_lane_map_physical{34.0}=0x0123
+phy_chain_rx_lane_map_physical{35.0}=0x0123
+phy_chain_rx_lane_map_physical{36.0}=0x0123
+phy_chain_tx_lane_map_physical{33.0}=0x0123
+phy_chain_tx_lane_map_physical{34.0}=0x0123
+phy_chain_tx_lane_map_physical{35.0}=0x0123
+phy_chain_tx_lane_map_physical{36.0}=0x0123
+phy_chain_rx_polarity_flip_physical{33.0}=0x0
+phy_chain_rx_polarity_flip_physical{34.0}=0x1
+phy_chain_rx_polarity_flip_physical{35.0}=0x0
+phy_chain_rx_polarity_flip_physical{36.0}=0x1
+phy_chain_tx_polarity_flip_physical{33.0}=0x0
+phy_chain_tx_polarity_flip_physical{34.0}=0x0
+phy_chain_tx_polarity_flip_physical{35.0}=0x0
+phy_chain_tx_polarity_flip_physical{36.0}=0x0
+
+#FC9
+dport_map_port_27=49
+dport_map_port_28=52
+dport_map_port_29=53
+dport_map_port_30=54
+portmap_27=37:100:4
+phy_chain_rx_lane_map_physical{37.0}=0x1023
+phy_chain_rx_lane_map_physical{38.0}=0x1023
+phy_chain_rx_lane_map_physical{39.0}=0x1023
+phy_chain_rx_lane_map_physical{40.0}=0x1023
+phy_chain_tx_lane_map_physical{37.0}=0x3210
+phy_chain_tx_lane_map_physical{38.0}=0x3210
+phy_chain_tx_lane_map_physical{39.0}=0x3210
+phy_chain_tx_lane_map_physical{40.0}=0x3210
+phy_chain_rx_polarity_flip_physical{37.0}=0x0
+phy_chain_rx_polarity_flip_physical{38.0}=0x1
+phy_chain_rx_polarity_flip_physical{39.0}=0x0
+phy_chain_rx_polarity_flip_physical{40.0}=0x0
+phy_chain_tx_polarity_flip_physical{37.0}=0x0
+phy_chain_tx_polarity_flip_physical{38.0}=0x1
+phy_chain_tx_polarity_flip_physical{39.0}=0x0
+phy_chain_tx_polarity_flip_physical{40.0}=0x0
+
+#FC10
+dport_map_port_33=57
+portmap_33=41:100:4
+phy_chain_rx_lane_map_physical{41.0}=0x3210
+phy_chain_rx_lane_map_physical{42.0}=0x3210
+phy_chain_rx_lane_map_physical{43.0}=0x3210
+phy_chain_rx_lane_map_physical{44.0}=0x3210
+phy_chain_tx_lane_map_physical{41.0}=0x3210
+phy_chain_tx_lane_map_physical{42.0}=0x3210
+phy_chain_tx_lane_map_physical{43.0}=0x3210
+phy_chain_tx_lane_map_physical{44.0}=0x3210
+phy_chain_rx_polarity_flip_physical{41.0}=0x0
+phy_chain_rx_polarity_flip_physical{42.0}=0x1
+phy_chain_rx_polarity_flip_physical{43.0}=0x0
+phy_chain_rx_polarity_flip_physical{44.0}=0x1
+phy_chain_tx_polarity_flip_physical{41.0}=0x1
+phy_chain_tx_polarity_flip_physical{42.0}=0x0
+phy_chain_tx_polarity_flip_physical{43.0}=0x0
+phy_chain_tx_polarity_flip_physical{44.0}=0x0
+
+#FC11
+dport_map_port_34=56
+portmap_34=45:100:4
+phy_chain_rx_lane_map_physical{45.0}=0x3210
+phy_chain_rx_lane_map_physical{46.0}=0x3210
+phy_chain_rx_lane_map_physical{47.0}=0x3210
+phy_chain_rx_lane_map_physical{48.0}=0x3210
+phy_chain_tx_lane_map_physical{45.0}=0x3210
+phy_chain_tx_lane_map_physical{46.0}=0x3210
+phy_chain_tx_lane_map_physical{47.0}=0x3210
+phy_chain_tx_lane_map_physical{48.0}=0x3210
+phy_chain_rx_polarity_flip_physical{45.0}=0x0
+phy_chain_rx_polarity_flip_physical{46.0}=0x0
+phy_chain_rx_polarity_flip_physical{47.0}=0x0
+phy_chain_rx_polarity_flip_physical{48.0}=0x0
+phy_chain_tx_polarity_flip_physical{45.0}=0x0
+phy_chain_tx_polarity_flip_physical{46.0}=0x0
+phy_chain_tx_polarity_flip_physical{47.0}=0x1
+phy_chain_tx_polarity_flip_physical{48.0}=0x0
+
+#FC12
+dport_map_port_35=55
+dport_map_port_36=58
+dport_map_port_37=59
+dport_map_port_38=60
+portmap_35=49:100:4
+phy_chain_rx_lane_map_physical{49.0}=0x3210
+phy_chain_rx_lane_map_physical{50.0}=0x3210
+phy_chain_rx_lane_map_physical{51.0}=0x3210
+phy_chain_rx_lane_map_physical{52.0}=0x3210
+phy_chain_tx_lane_map_physical{49.0}=0x3210
+phy_chain_tx_lane_map_physical{50.0}=0x3210
+phy_chain_tx_lane_map_physical{51.0}=0x3210
+phy_chain_tx_lane_map_physical{52.0}=0x3210
+phy_chain_rx_polarity_flip_physical{49.0}=0x0
+phy_chain_rx_polarity_flip_physical{50.0}=0x0
+phy_chain_rx_polarity_flip_physical{51.0}=0x0
+phy_chain_rx_polarity_flip_physical{52.0}=0x0
+phy_chain_tx_polarity_flip_physical{49.0}=0x1
+phy_chain_tx_polarity_flip_physical{50.0}=0x0
+phy_chain_tx_polarity_flip_physical{51.0}=0x0
+phy_chain_tx_polarity_flip_physical{52.0}=0x1
+
+#FC13
+dport_map_port_39=26
+dport_map_port_40=25
+dport_map_port_41=28
+dport_map_port_42=27
+portmap_39=53:10
+portmap_40=54:10
+portmap_41=55:10
+portmap_42=56:10
+#port_phy_addr_39=0x60
+#port_phy_addr_40=0x61
+#port_phy_addr_41=0x62
+#port_phy_addr_42=0x63
+phy_chain_rx_lane_map_physical{53.0}=0x3120
+phy_chain_rx_lane_map_physical{54.0}=0x3120
+phy_chain_rx_lane_map_physical{55.0}=0x3120
+phy_chain_rx_lane_map_physical{56.0}=0x3120
+phy_chain_tx_lane_map_physical{53.0}=0x3102
+phy_chain_tx_lane_map_physical{54.0}=0x3102
+phy_chain_tx_lane_map_physical{55.0}=0x3102
+phy_chain_tx_lane_map_physical{56.0}=0x3102
+phy_chain_rx_polarity_flip_physical{53.0}=0x0
+phy_chain_rx_polarity_flip_physical{54.0}=0x1
+phy_chain_rx_polarity_flip_physical{55.0}=0x1
+phy_chain_rx_polarity_flip_physical{56.0}=0x0
+phy_chain_tx_polarity_flip_physical{53.0}=0x0
+phy_chain_tx_polarity_flip_physical{54.0}=0x1
+phy_chain_tx_polarity_flip_physical{55.0}=0x1
+phy_chain_tx_polarity_flip_physical{56.0}=0x0
+
+#FC14
+dport_map_port_43=30
+dport_map_port_44=29
+dport_map_port_45=32
+dport_map_port_46=31
+portmap_43=57:10
+portmap_44=58:10
+portmap_45=59:10
+portmap_46=60:10
+#port_phy_addr_43=0x64
+#port_phy_addr_44=0x65
+#port_phy_addr_45=0x66
+#port_phy_addr_46=0x67
+phy_chain_rx_lane_map_physical{57.0}=0x3210
+phy_chain_rx_lane_map_physical{58.0}=0x3210
+phy_chain_rx_lane_map_physical{59.0}=0x3210
+phy_chain_rx_lane_map_physical{60.0}=0x3210
+phy_chain_tx_lane_map_physical{57.0}=0x3210
+phy_chain_tx_lane_map_physical{58.0}=0x3210
+phy_chain_tx_lane_map_physical{59.0}=0x3210
+phy_chain_tx_lane_map_physical{60.0}=0x3210
+phy_chain_rx_polarity_flip_physical{57.0}=0x1
+phy_chain_rx_polarity_flip_physical{58.0}=0x0
+phy_chain_rx_polarity_flip_physical{59.0}=0x1
+phy_chain_rx_polarity_flip_physical{60.0}=0x0
+phy_chain_tx_polarity_flip_physical{57.0}=0x0
+phy_chain_tx_polarity_flip_physical{58.0}=0x0
+phy_chain_tx_polarity_flip_physical{59.0}=0x0
+phy_chain_tx_polarity_flip_physical{60.0}=0x0
+
+#FC15
+dport_map_port_47=34
+dport_map_port_48=33
+dport_map_port_49=36
+dport_map_port_50=35
+portmap_47=61:10
+portmap_48=62:10
+portmap_49=63:10
+portmap_50=64:10
+#port_phy_addr_47=0x100
+#port_phy_addr_48=0x101
+#port_phy_addr_49=0x102
+#port_phy_addr_50=0x103
+phy_chain_rx_lane_map_physical{61.0}=0x3210
+phy_chain_rx_lane_map_physical{62.0}=0x3210
+phy_chain_rx_lane_map_physical{63.0}=0x3210
+phy_chain_rx_lane_map_physical{64.0}=0x3210
+phy_chain_tx_lane_map_physical{61.0}=0x3210
+phy_chain_tx_lane_map_physical{62.0}=0x3210
+phy_chain_tx_lane_map_physical{63.0}=0x3210
+phy_chain_tx_lane_map_physical{64.0}=0x3210
+phy_chain_rx_polarity_flip_physical{61.0}=0x1
+phy_chain_rx_polarity_flip_physical{62.0}=0x1
+phy_chain_rx_polarity_flip_physical{63.0}=0x1
+phy_chain_rx_polarity_flip_physical{64.0}=0x1
+phy_chain_tx_polarity_flip_physical{61.0}=0x0
+phy_chain_tx_polarity_flip_physical{62.0}=0x0
+phy_chain_tx_polarity_flip_physical{63.0}=0x0
+phy_chain_tx_polarity_flip_physical{64.0}=0x0
+
+#FC16
+dport_map_port_51=38
+dport_map_port_52=37
+dport_map_port_53=40
+dport_map_port_54=39
+portmap_51=65:10
+portmap_52=66:10
+portmap_53=67:10
+portmap_54=68:10
+#port_phy_addr_51=0x104
+#port_phy_addr_52=0x105
+#port_phy_addr_53=0x106
+#port_phy_addr_54=0x107
+phy_chain_rx_lane_map_physical{65.0}=0x3210
+phy_chain_rx_lane_map_physical{66.0}=0x3210
+phy_chain_rx_lane_map_physical{67.0}=0x3210
+phy_chain_rx_lane_map_physical{68.0}=0x3210
+phy_chain_tx_lane_map_physical{65.0}=0x3210
+phy_chain_tx_lane_map_physical{66.0}=0x3210
+phy_chain_tx_lane_map_physical{67.0}=0x3210
+phy_chain_tx_lane_map_physical{68.0}=0x3210
+phy_chain_rx_polarity_flip_physical{65.0}=0x0
+phy_chain_rx_polarity_flip_physical{66.0}=0x0
+phy_chain_rx_polarity_flip_physical{67.0}=0x0
+phy_chain_rx_polarity_flip_physical{68.0}=0x0
+phy_chain_tx_polarity_flip_physical{65.0}=0x0
+phy_chain_tx_polarity_flip_physical{66.0}=0x0
+phy_chain_tx_polarity_flip_physical{67.0}=0x0
+phy_chain_tx_polarity_flip_physical{68.0}=0x0
+
+#FC17
+dport_map_port_55=42
+dport_map_port_56=41
+dport_map_port_57=44
+dport_map_port_58=43
+portmap_55=69:10
+portmap_56=70:10
+portmap_57=71:10
+portmap_58=72:10
+#port_phy_addr_55=0x120
+#port_phy_addr_56=0x121
+#port_phy_addr_57=0x122
+#port_phy_addr_58=0x123
+phy_chain_rx_lane_map_physical{69.0}=0x3210
+phy_chain_rx_lane_map_physical{70.0}=0x3210
+phy_chain_rx_lane_map_physical{71.0}=0x3210
+phy_chain_rx_lane_map_physical{72.0}=0x3210
+phy_chain_tx_lane_map_physical{69.0}=0x3210
+phy_chain_tx_lane_map_physical{70.0}=0x3210
+phy_chain_tx_lane_map_physical{71.0}=0x3210
+phy_chain_tx_lane_map_physical{72.0}=0x3210
+phy_chain_rx_polarity_flip_physical{69.0}=0x0
+phy_chain_rx_polarity_flip_physical{70.0}=0x0
+phy_chain_rx_polarity_flip_physical{71.0}=0x0
+phy_chain_rx_polarity_flip_physical{72.0}=0x0
+phy_chain_tx_polarity_flip_physical{69.0}=0x0
+phy_chain_tx_polarity_flip_physical{70.0}=0x0
+phy_chain_tx_polarity_flip_physical{71.0}=0x0
+phy_chain_tx_polarity_flip_physical{72.0}=0x0
+
+#FC18
+dport_map_port_59=46
+dport_map_port_60=45
+dport_map_port_61=48
+dport_map_port_62=47
+portmap_59=73:10
+portmap_60=74:10
+portmap_61=75:10
+portmap_62=76:10
+#port_phy_addr_59=0x124
+#port_phy_addr_60=0x125
+#port_phy_addr_61=0x126
+#port_phy_addr_62=0x127
+phy_chain_rx_lane_map_physical{73.0}=0x3210
+phy_chain_rx_lane_map_physical{74.0}=0x3210
+phy_chain_rx_lane_map_physical{75.0}=0x3210
+phy_chain_rx_lane_map_physical{76.0}=0x3210
+phy_chain_tx_lane_map_physical{73.0}=0x2031
+phy_chain_tx_lane_map_physical{74.0}=0x2031
+phy_chain_tx_lane_map_physical{75.0}=0x2031
+phy_chain_tx_lane_map_physical{76.0}=0x2031
+phy_chain_rx_polarity_flip_physical{73.0}=0x1
+phy_chain_rx_polarity_flip_physical{74.0}=0x1
+phy_chain_rx_polarity_flip_physical{75.0}=0x1
+phy_chain_rx_polarity_flip_physical{76.0}=0x1
+phy_chain_tx_polarity_flip_physical{73.0}=0x0
+phy_chain_tx_polarity_flip_physical{74.0}=0x1
+phy_chain_tx_polarity_flip_physical{75.0}=0x1
+phy_chain_tx_polarity_flip_physical{76.0}=0x0
+
+#FC19
+
+dport_map_port_64=64
+portmap_64=81:10:m
+phy_chain_rx_polarity_flip_physical{81.0}=0x1
+phy_chain_tx_polarity_flip_physical{81.0}=0x1
+
diff --git a/device/accton/x86_64-accton_as5835_54t-r0/default_sku b/device/accton/x86_64-accton_as5835_54t-r0/default_sku
new file mode 100644
index 0000000000..d0bfc0f22e
--- /dev/null
+++ b/device/accton/x86_64-accton_as5835_54t-r0/default_sku
@@ -0,0 +1 @@
+Accton-AS5835-54T t1
diff --git a/device/accton/x86_64-accton_as5835_54t-r0/installer.conf b/device/accton/x86_64-accton_as5835_54t-r0/installer.conf
new file mode 100644
index 0000000000..925a32fc0c
--- /dev/null
+++ b/device/accton/x86_64-accton_as5835_54t-r0/installer.conf
@@ -0,0 +1,3 @@
+CONSOLE_PORT=0x3f8
+CONSOLE_DEV=0
+CONSOLE_SPEED=115200
diff --git a/device/accton/x86_64-accton_as5835_54t-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as5835_54t-r0/plugins/eeprom.py
new file mode 100644
index 0000000000..7681caafee
--- /dev/null
+++ b/device/accton/x86_64-accton_as5835_54t-r0/plugins/eeprom.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+
+try:
+ import exceptions
+ import binascii
+ import time
+ import optparse
+ import warnings
+ import os
+ import sys
+ from sonic_eeprom import eeprom_base
+ from sonic_eeprom import eeprom_tlvinfo
+ import subprocess
+except ImportError, e:
+ raise ImportError (str(e) + "- required module not found")
+
+class board(eeprom_tlvinfo.TlvInfoDecoder):
+ _TLV_INFO_MAX_LEN = 256
+ def __init__(self, name, path, cpld_root, ro):
+ self.eeprom_path = "/sys/bus/i2c/devices/1-0057/eeprom"
+ #Two i2c buses might get flipped order, check them both.
+ if not os.path.exists(self.eeprom_path):
+ self.eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom"
+ super(board, self).__init__(self.eeprom_path, 0, '', True)
diff --git a/device/accton/x86_64-accton_as5835_54t-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as5835_54t-r0/plugins/psuutil.py
new file mode 100644
index 0000000000..c95bc27897
--- /dev/null
+++ b/device/accton/x86_64-accton_as5835_54t-r0/plugins/psuutil.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+
+#############################################################################
+# Accton
+#
+# Module contains an implementation of SONiC PSU Base API and
+# provides the PSUs status which are available in the platform
+#
+#############################################################################
+
+import os.path
+
+try:
+ from sonic_psu.psu_base import PsuBase
+except ImportError as e:
+ raise ImportError (str(e) + "- required module not found")
+
+class PsuUtil(PsuBase):
+ """Platform-specific PSUutil class"""
+
+ def __init__(self):
+ PsuBase.__init__(self)
+
+ self.psu_path = "/sys/bus/i2c/devices/"
+ self.psu_presence = "/psu_present"
+ self.psu_oper_status = "/psu_power_good"
+ self.psu_mapping = {
+ 1: "11-0050",
+ 2: "12-0053",
+ }
+
+ def get_num_psus(self):
+ return len(self.psu_mapping)
+
+ def get_psu_status(self, index):
+ if index is None:
+ return False
+
+ status = 0
+ node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status
+ try:
+ with open(node, 'r') as power_status:
+ status = int(power_status.read())
+ except IOError:
+ return False
+
+ return status == 1
+
+ def get_psu_presence(self, index):
+ if index is None:
+ return False
+
+ status = 0
+ node = self.psu_path + self.psu_mapping[index] + self.psu_presence
+ try:
+ with open(node, 'r') as presence_status:
+ status = int(presence_status.read())
+ except IOError:
+ return False
+
+ return status == 1
diff --git a/device/accton/x86_64-accton_as5835_54t-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as5835_54t-r0/plugins/sfputil.py
new file mode 100644
index 0000000000..58ed8007a4
--- /dev/null
+++ b/device/accton/x86_64-accton_as5835_54t-r0/plugins/sfputil.py
@@ -0,0 +1,225 @@
+# sfputil.py
+#
+# Platform-specific SFP transceiver interface for SONiC
+#
+
+try:
+ import time
+ import string
+ from ctypes import create_string_buffer
+ from sonic_sfp.sfputilbase import SfpUtilBase
+except ImportError as e:
+ raise ImportError("%s - required module not found" % str(e))
+
+
+class SfpUtil(SfpUtilBase):
+ """Platform-specific SfpUtil class"""
+
+ PORT_START = 49
+ PORT_END = 72
+ PORTS_IN_BLOCK = 72
+
+ _port_to_eeprom_mapping = {}
+ _port_to_i2c_mapping = {
+ 49: 28, #QSFP49
+ 50: 28,
+ 51: 28,
+ 52: 28,
+ 53: 29, #QSFP50
+ 54: 29,
+ 55: 29,
+ 56: 29,
+ 57: 26, #QSFP51
+ 58: 26,
+ 59: 26,
+ 60: 26,
+ 61: 30, #QSFP52
+ 62: 30,
+ 63: 30,
+ 64: 30,
+ 65: 31, #QSFP53
+ 66: 31,
+ 67: 31,
+ 68: 31,
+ 69: 27, #QSFP54
+ 70: 27,
+ 71: 27,
+ 72: 27,
+ }
+
+ @property
+ def port_start(self):
+ return self.PORT_START
+
+ @property
+ def port_end(self):
+ return self.PORT_END
+
+ @property
+ def qsfp_port_start(self):
+ return self.PORT_START
+
+ @property
+ def qsfp_port_end(self):
+ return self.PORT_END
+
+ @property
+ def qsfp_ports(self):
+ return range(self.PORT_START, self.PORTS_IN_BLOCK + 1)
+
+ @property
+ def port_to_eeprom_mapping(self):
+ return self._port_to_eeprom_mapping
+
+ def __init__(self):
+ eeprom_path = '/sys/bus/i2c/devices/{0}-0050/eeprom'
+ for x in range(self.port_start, self.port_end+1):
+ self.port_to_eeprom_mapping[x] = eeprom_path.format(
+ self._port_to_i2c_mapping[x])
+
+ SfpUtilBase.__init__(self)
+
+
+ # For port 49~54 are QSFP, here presumed they're all split to 4 lanes.
+ def get_cage_num(self, port_num):
+ cage_num = port_num
+ if (port_num >= self.PORT_START):
+ cage_num = (port_num - self.PORT_START)/4
+ cage_num = cage_num + self.PORT_START
+
+ return cage_num
+
+ def get_presence(self, port_num):
+ # Check for invalid port_num
+ if port_num < self.port_start or port_num > self.port_end:
+ return False
+
+ cage_num = self.get_cage_num(port_num)
+ path = "/sys/bus/i2c/devices/3-0062/module_present_{0}"
+ port_ps = path.format(cage_num)
+
+ try:
+ val_file = open(port_ps)
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ content = val_file.readline().rstrip()
+ val_file.close()
+
+ # content is a string, either "0" or "1"
+ if content == "1":
+ return True
+
+ return False
+
+ def get_low_power_mode_cpld(self, port_num):
+ if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
+ return False
+
+ cage_num = self.get_cage_num(port_num)
+ path = "/sys/bus/i2c/devices/3-0062/module_lpmode_{0}"
+ lp_mode_path = path.format(cage_num)
+
+ try:
+ val_file = open(lp_mode_path)
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ content = val_file.readline().rstrip()
+ val_file.close()
+
+ # content is a string, either "0" or "1"
+ if content == "1":
+ return True
+
+ return False
+
+ def get_low_power_mode(self, port_num):
+ if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
+ return False
+
+ if not self.get_presence(port_num):
+ return False
+
+ try:
+ eeprom = None
+
+ eeprom = open(self.port_to_eeprom_mapping[port_num], mode="rb", buffering=0)
+ eeprom.seek(93)
+ lpmode = ord(eeprom.read(1))
+
+ if not (lpmode & 0x1): # 'Power override' bit is 0
+ return self.get_low_power_mode_cpld(port_num)
+ else:
+ if ((lpmode & 0x2) == 0x2):
+ return True # Low Power Mode if "Power set" bit is 1
+ else:
+ return False # High Power Mode if "Power set" bit is 0
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+ finally:
+ if eeprom is not None:
+ eeprom.close()
+ time.sleep(0.01)
+
+ def set_low_power_mode(self, port_num, lpmode):
+ if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
+ return False
+
+ try:
+ eeprom = None
+
+ if not self.get_presence(port_num):
+ return False # Port is not present, unable to set the eeprom
+
+ # Fill in write buffer
+ regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode
+ buffer = create_string_buffer(1)
+ buffer[0] = chr(regval)
+
+ # Write to eeprom
+ eeprom = open(self.port_to_eeprom_mapping[port_num], mode="r+b", buffering=0)
+ eeprom.seek(93)
+ eeprom.write(buffer[0])
+ return True
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+ finally:
+ if eeprom is not None:
+ eeprom.close()
+ time.sleep(0.01)
+
+ def reset(self, port_num):
+ if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
+ return False
+
+ cage_num = self.get_cage_num(port_num)
+ path = "/sys/bus/i2c/devices/3-0062/module_reset_{0}"
+ port_ps = path.format(cage_num)
+ try:
+ reg_file = open(port_ps, mode="w", buffering=0)
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ #toggle reset
+ reg_file.seek(0)
+ reg_file.write('0')
+ time.sleep(1)
+ reg_file.seek(0)
+ reg_file.write('1')
+ reg_file.close()
+
+ return True
+
+ def get_transceiver_change_event(self):
+ """
+ TODO: This function need to be implemented
+ when decide to support monitoring SFP(Xcvrd)
+ on this platform.
+ """
+ raise NotImplementedError
diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk
index 2a36bd3c56..897845ab82 100755
--- a/platform/broadcom/one-image.mk
+++ b/platform/broadcom/one-image.mk
@@ -28,6 +28,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
$(ACCTON_AS5812_54X_PLATFORM_MODULE) \
$(ACCTON_AS5835_54X_PLATFORM_MODULE) \
$(ACCTON_AS9716_32D_PLATFORM_MODULE) \
+ $(ACCTON_AS5835_54T_PLATFORM_MODULE) \
$(INVENTEC_D7032Q28B_PLATFORM_MODULE) \
$(INVENTEC_D7054Q28B_PLATFORM_MODULE) \
$(INVENTEC_D7264Q28B_PLATFORM_MODULE) \
diff --git a/platform/broadcom/platform-modules-accton.mk b/platform/broadcom/platform-modules-accton.mk
index fa786b51d7..af8cb0fb47 100755
--- a/platform/broadcom/platform-modules-accton.mk
+++ b/platform/broadcom/platform-modules-accton.mk
@@ -14,6 +14,7 @@ ACCTON_MINIPACK_PLATFORM_MODULE_VERSION = 1.1
ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION = 1.1
ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION = 1.1
ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION = 1.1
+ACCTON_AS5835_54T_PLATFORM_MODULE_VERSION = 1.1
export ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION
export ACCTON_AS5712_54X_PLATFORM_MODULE_VERSION
@@ -29,6 +30,7 @@ export ACCTON_MINIPACK_PLATFORM_MODULE_VERSION
export ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION
export ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION
export ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION
+export ACCTON_AS5835_54T_PLATFORM_MODULE_VERSION
ACCTON_AS7712_32X_PLATFORM_MODULE = sonic-platform-accton-as7712-32x_$(ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION)_amd64.deb
$(ACCTON_AS7712_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-accton
@@ -89,5 +91,8 @@ ACCTON_AS9716_32D_PLATFORM_MODULE = sonic-platform-accton-as9716-32d_$(ACCTON_AS
$(ACCTON_AS9716_32D_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as9716_32d-r0
$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS9716_32D_PLATFORM_MODULE)))
+ACCTON_AS5835_54T_PLATFORM_MODULE = sonic-platform-accton-as5835-54t_$(ACCTON_AS5835_54T_PLATFORM_MODULE_VERSION)_amd64.deb
+$(ACCTON_AS5835_54T_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5835_54t-r0
+$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5835_54T_PLATFORM_MODULE)))
SONIC_STRETCH_DEBS += $(ACCTON_AS7712_32X_PLATFORM_MODULE)
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/fanutil.py
new file mode 100644
index 0000000000..c741ebfd72
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/fanutil.py
@@ -0,0 +1,237 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 Accton Technology Corporation
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+# ------------------------------------------------------------------
+# HISTORY:
+# mm/dd/yyyy (A.D.)
+# 5/27/2019: Brandon_Chuang create
+# ------------------------------------------------------------------
+
+try:
+ import time
+ import logging
+ from collections import namedtuple
+except ImportError as e:
+ raise ImportError('%s - required module not found' % str(e))
+
+
+class FanUtil(object):
+ """Platform-specific FanUtil class"""
+
+ FAN_NUM_ON_MAIN_BROAD = 5
+ FAN_NUM_1_IDX = 1
+ FAN_NUM_2_IDX = 2
+ FAN_NUM_3_IDX = 3
+ FAN_NUM_4_IDX = 4
+ FAN_NUM_5_IDX = 5
+
+ FAN_NODE_NUM_OF_MAP = 2
+ FAN_NODE_FAULT_IDX_OF_MAP = 1
+ FAN_NODE_DIR_IDX_OF_MAP = 2
+
+ BASE_VAL_PATH = '/sys/bus/i2c/devices/3-0063/{0}'
+ FAN_DUTY_PATH = '/sys/bus/i2c/devices/3-0063/fan_duty_cycle_percentage'
+
+ #logfile = ''
+ #loglevel = logging.INFO
+
+ """ Dictionary where
+ key1 = fan id index (integer) starting from 1
+ key2 = fan node index (interger) starting from 1
+ value = path to fan device file (string) """
+ _fan_to_device_path_mapping = {}
+
+#fan1_direction
+#fan1_fault
+#fan1_present
+
+ #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage',
+ _fan_to_device_node_mapping = {
+ (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault',
+ (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction',
+
+ (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault',
+ (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction',
+
+ (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault',
+ (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction',
+
+ (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault',
+ (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction',
+
+ (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault',
+ (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction',
+ }
+
+ def _get_fan_to_device_node(self, fan_num, node_num):
+ return self._fan_to_device_node_mapping[(fan_num, node_num)]
+
+ def _get_fan_node_val(self, fan_num, node_num):
+ if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD:
+ logging.debug('GET. Parameter error. fan_num:%d', fan_num)
+ return None
+
+ if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP:
+ logging.debug('GET. Parameter error. node_num:%d', node_num)
+ return None
+
+ device_path = self.get_fan_to_device_path(fan_num, node_num)
+
+ try:
+ val_file = open(device_path, 'r')
+ except IOError as e:
+ logging.error('GET. unable to open file: %s', str(e))
+ return None
+
+ content = val_file.readline().rstrip()
+
+ if content == '':
+ logging.debug('GET. content is NULL. device_path:%s', device_path)
+ return None
+
+ try:
+ val_file.close()
+ except:
+ logging.debug('GET. unable to close file. device_path:%s', device_path)
+ return None
+
+ return int(content)
+
+ def _set_fan_node_val(self, fan_num, node_num, val):
+ if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD:
+ logging.debug('GET. Parameter error. fan_num:%d', fan_num)
+ return None
+
+ if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP:
+ logging.debug('GET. Parameter error. node_num:%d', node_num)
+ return None
+
+ content = str(val)
+ if content == '':
+ logging.debug('GET. content is NULL. device_path:%s', device_path)
+ return None
+
+ device_path = self.get_fan_to_device_path(fan_num, node_num)
+ try:
+ val_file = open(device_path, 'w')
+ except IOError as e:
+ logging.error('GET. unable to open file: %s', str(e))
+ return None
+
+ val_file.write(content)
+
+ try:
+ val_file.close()
+ except:
+ logging.debug('GET. unable to close file. device_path:%s', device_path)
+ return None
+
+ return True
+
+ def __init__(self):
+ fan_path = self.BASE_VAL_PATH
+
+ for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1):
+ for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1):
+ self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format(
+ self._fan_to_device_node_mapping[(fan_num, node_num)])
+
+ def get_num_fans(self):
+ return self.FAN_NUM_ON_MAIN_BROAD
+
+ def get_idx_fan_start(self):
+ return self.FAN_NUM_1_IDX
+
+ def get_num_nodes(self):
+ return self.FAN_NODE_NUM_OF_MAP
+
+ def get_idx_node_start(self):
+ return self.FAN_NODE_FAULT_IDX_OF_MAP
+
+ def get_size_node_map(self):
+ return len(self._fan_to_device_node_mapping)
+
+ def get_size_path_map(self):
+ return len(self._fan_to_device_path_mapping)
+
+ def get_fan_to_device_path(self, fan_num, node_num):
+ return self._fan_to_device_path_mapping[(fan_num, node_num)]
+
+ def get_fan_fault(self, fan_num):
+ return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP)
+
+ #def get_fan_speed(self, fan_num):
+ # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP)
+
+ def get_fan_dir(self, fan_num):
+ return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP)
+
+ def get_fan_duty_cycle(self):
+ #duty_path = self.FAN_DUTY_PATH
+ try:
+ val_file = open(self.FAN_DUTY_PATH)
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+
+ content = val_file.readline().rstrip()
+ val_file.close()
+
+ return int(content)
+
+ def set_fan_duty_cycle(self, val):
+ try:
+ fan_file = open(self.FAN_DUTY_PATH, 'r+')
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+ fan_file.write(str(val))
+ fan_file.close()
+ return True
+
+ #def get_fanr_fault(self, fan_num):
+ # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP)
+
+ def get_fanr_speed(self, fan_num):
+ return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP)
+
+ def get_fan_status(self, fan_num):
+ if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD:
+ logging.debug('GET. Parameter error. fan_num, %d', fan_num)
+ return None
+
+ if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0:
+ logging.debug('GET. FAN fault. fan_num, %d', fan_num)
+ return False
+
+ #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0:
+ # logging.debug('GET. FANR fault. fan_num, %d', fan_num)
+ # return False
+
+ return True
+
+#def main():
+# fan = FanUtil()
+#
+# print 'get_size_node_map : %d' % fan.get_size_node_map()
+# print 'get_size_path_map : %d' % fan.get_size_path_map()
+# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1):
+# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1):
+# print fan.get_fan_to_device_path(x, y)
+#
+#if __name__ == '__main__':
+# main()
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/thermalutil.py
new file mode 100644
index 0000000000..1dc97cfe27
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/classes/thermalutil.py
@@ -0,0 +1,129 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 Accton Technology Corporation
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+# ------------------------------------------------------------------
+# HISTORY:
+# mm/dd/yyyy (A.D.)
+# 6/11/2019: Brandon_Chuang create
+# ------------------------------------------------------------------
+
+try:
+ import os
+ import time
+ import logging
+ import glob
+ import commands
+ from collections import namedtuple
+except ImportError as e:
+ raise ImportError('%s - required module not found' % str(e))
+
+class ThermalUtil(object):
+ """Platform-specific ThermalUtil class"""
+ THERMAL_NUM_MAX = 4
+ THERMAL_NUM_1_IDX = 1 # 1_ON_CPU_BROAD. LM75
+ THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD. LM75
+ THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD. LM75
+ THERMAL_NUM_4_IDX = 4 # 4_ON_MAIN_BROAD. LM75
+
+ """ Dictionary where
+ key1 = thermal id index (integer) starting from 1
+ value = path to fan device file (string) """
+ #_thermal_to_device_path_mapping = {}
+
+ _thermal_to_device_node_mapping = {
+ THERMAL_NUM_1_IDX: ['18', '4b'],
+ THERMAL_NUM_2_IDX: ['19', '4c'],
+ THERMAL_NUM_3_IDX: ['20', '49'],
+ THERMAL_NUM_4_IDX: ['21', '4a'],
+ }
+ thermal_sysfspath ={
+ THERMAL_NUM_1_IDX: ["/sys/bus/i2c/devices/18-004b/hwmon/hwmon3/temp1_input"],
+ THERMAL_NUM_2_IDX: ["/sys/bus/i2c/devices/19-004c/hwmon/hwmon4/temp1_input"],
+ THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/20-0049/hwmon/hwmon5/temp1_input"],
+ THERMAL_NUM_4_IDX: ["/sys/bus/i2c/devices/21-004a/hwmon/hwmon6/temp1_input"],
+ }
+
+ #def __init__(self):
+ def _get_thermal_val(self, thermal_num):
+ if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_MAX:
+ logging.debug('GET. Parameter error. thermal_num, %d', thermal_num)
+ return None
+
+ device_path = self.get_thermal_to_device_path(thermal_num)
+ if(os.path.isfile(device_path)):
+ for filename in glob.glob(device_path):
+ try:
+ val_file = open(filename, 'r')
+ except IOError as e:
+ logging.error('GET. unable to open file: %s', str(e))
+ return None
+ content = val_file.readline().rstrip()
+ if content == '':
+ logging.debug('GET. content is NULL. device_path:%s', device_path)
+ return None
+ try:
+ val_file.close()
+ except:
+ logging.debug('GET. unable to close file. device_path:%s', device_path)
+ return None
+ return int(content)
+
+ else:
+ print "No such device_path=%s"%device_path
+ return 0
+
+ def get_num_thermals(self):
+ return self.THERMAL_NUM_MAX
+
+ def get_idx_thermal_start(self):
+ return self.THERMAL_NUM_1_IDX
+
+ def get_size_node_map(self):
+ return len(self._thermal_to_device_node_mapping)
+
+ def get_size_path_map(self):
+ return len(self.thermal_sysfspath)
+
+ def get_thermal_to_device_path(self, thermal_num):
+ return self.thermal_sysfspath[thermal_num][0]
+
+ def get_thermal_1_val(self):
+ return self._get_thermal_val(self.THERMAL_NUM_1_IDX)
+
+ def get_thermal_2_val(self):
+ return self._get_thermal_val(self.THERMAL_NUM_2_IDX)
+
+ def get_thermal_3_val(self):
+ return self._get_thermal_val(self.THERMAL_NUM_3_IDX)
+
+ def get_thermal_temp(self):
+ return (self._get_thermal_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_val(self.THERMAL_NUM_3_IDX))
+
+def main():
+ thermal = ThermalUtil()
+ print "termal1=%d" %thermal._get_thermal_val(1)
+ print "termal2=%d" %thermal._get_thermal_val(2)
+ print "termal3=%d" %thermal._get_thermal_val(3)
+ print "termal4=%d" %thermal._get_thermal_val(4)
+#
+# print 'get_size_node_map : %d' % thermal.get_size_node_map()
+# print 'get_size_path_map : %d' % thermal.get_size_path_map()
+# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1):
+# print thermal.get_thermal_to_device_path(x)
+#
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/Makefile
new file mode 100644
index 0000000000..887ac3189c
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/Makefile
@@ -0,0 +1,17 @@
+ifneq ($(KERNELRELEASE),)
+obj-m:= accton_as5835_54t_cpld.o accton_as5835_54t_psu.o \
+ accton_as5835_54t_fan.o accton_as5835_54t_leds.o \
+ ym2651y.o
+
+else
+ifeq (,$(KERNEL_SRC))
+$(error KERNEL_SRC is not defined)
+else
+KERNELDIR:=$(KERNEL_SRC)
+endif
+PWD:=$(shell pwd)
+default:
+ $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+clean:
+ rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order
+endif
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_cpld.c
new file mode 100644
index 0000000000..ae773b4d82
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_cpld.c
@@ -0,0 +1,603 @@
+/*
+ * Copyright (C) Brandon Chuang
+ *
+ * This module supports the accton cpld that hold the channel select
+ * mechanism for other i2c slave devices, such as SFP.
+ * This includes the:
+ * Accton as5835_54t CPLD1/CPLD2/CPLD3
+ *
+ * Based on:
+ * pca954t.c from Kumar Gala
+ * Copyright (C) 2006
+ *
+ * Based on:
+ * pca954t.c from Ken Harrenstien
+ * Copyright (C) 2004 Google, Inc. (Ken Harrenstien)
+ *
+ * Based on:
+ * i2c-virtual_cb.c from Brian Kuschak
+ * and
+ * pca9540.c from Jean Delvare .
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define I2C_RW_RETRY_COUNT 10
+#define I2C_RW_RETRY_INTERVAL 60 /* ms */
+
+static LIST_HEAD(cpld_client_list);
+static struct mutex list_lock;
+
+struct cpld_client_node {
+ struct i2c_client *client;
+ struct list_head list;
+};
+
+enum cpld_type {
+ as5835_54t_cpld1,
+ as5835_54t_cpld2,
+ as5835_54t_cpld3
+};
+
+struct as5835_54t_cpld_data {
+ enum cpld_type type;
+ struct device *hwmon_dev;
+ struct mutex update_lock;
+};
+
+static const struct i2c_device_id as5835_54t_cpld_id[] = {
+ { "as5835_54t_cpld1", as5835_54t_cpld1 },
+ { "as5835_54t_cpld2", as5835_54t_cpld2 },
+ { "as5835_54t_cpld3", as5835_54t_cpld3 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, as5835_54t_cpld_id);
+
+#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index
+#define TRANSCEIVER_LPMODE_ATTR_ID(index) MODULE_LPMODE_##index
+#define TRANSCEIVER_RESET_ATTR_ID(index) MODULE_RESET_##index
+
+enum as5835_54t_cpld1_sysfs_attributes {
+ CPLD_VERSION,
+ ACCESS,
+ MODULE_PRESENT_ALL,
+ MODULE_RXLOS_ALL,
+ /* transceiver attributes */
+ TRANSCEIVER_PRESENT_ATTR_ID(49),
+ TRANSCEIVER_PRESENT_ATTR_ID(50),
+ TRANSCEIVER_PRESENT_ATTR_ID(51),
+ TRANSCEIVER_PRESENT_ATTR_ID(52),
+ TRANSCEIVER_PRESENT_ATTR_ID(53),
+ TRANSCEIVER_PRESENT_ATTR_ID(54),
+ TRANSCEIVER_LPMODE_ATTR_ID(49),
+ TRANSCEIVER_LPMODE_ATTR_ID(50),
+ TRANSCEIVER_LPMODE_ATTR_ID(51),
+ TRANSCEIVER_LPMODE_ATTR_ID(52),
+ TRANSCEIVER_LPMODE_ATTR_ID(53),
+ TRANSCEIVER_LPMODE_ATTR_ID(54),
+ TRANSCEIVER_RESET_ATTR_ID(49),
+ TRANSCEIVER_RESET_ATTR_ID(50),
+ TRANSCEIVER_RESET_ATTR_ID(51),
+ TRANSCEIVER_RESET_ATTR_ID(52),
+ TRANSCEIVER_RESET_ATTR_ID(53),
+ TRANSCEIVER_RESET_ATTR_ID(54),
+};
+
+/* sysfs attributes for hwmon
+ */
+static ssize_t show_status(struct device *dev, struct device_attribute *da,
+ char *buf);
+static ssize_t show_present_all(struct device *dev, struct device_attribute *da,
+ char *buf);
+static ssize_t set_control(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count);
+static ssize_t access(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count);
+static ssize_t show_version(struct device *dev, struct device_attribute *da,
+ char *buf);
+static int as5835_54t_cpld_read_internal(struct i2c_client *client, u8 reg);
+static int as5835_54t_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value);
+
+/* transceiver attributes */
+#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \
+ static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index)
+#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr
+
+#define DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \
+ static SENSOR_DEVICE_ATTR(module_lpmode_##index, S_IRUGO | S_IWUSR, show_status, set_control, MODULE_LPMODE_##index); \
+ static SENSOR_DEVICE_ATTR(module_reset_##index, S_IRUGO | S_IWUSR, show_status, set_control, MODULE_RESET_##index)
+#define DECLARE_QSFP_TRANSCEIVER_ATTR(index) \
+ &sensor_dev_attr_module_lpmode_##index.dev_attr.attr, \
+ &sensor_dev_attr_module_reset_##index.dev_attr.attr
+
+static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION);
+static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS);
+/* transceiver attributes */
+static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL);
+DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(49);
+DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(50);
+DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(51);
+DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(52);
+DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(53);
+DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(54);
+
+DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(49);
+DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(50);
+DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(51);
+DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(52);
+DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(53);
+DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(54);
+
+static struct attribute *as5835_54t_cpld1_attributes[] = {
+ &sensor_dev_attr_version.dev_attr.attr,
+ &sensor_dev_attr_access.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group as5835_54t_cpld1_group = {
+ .attrs = as5835_54t_cpld1_attributes,
+};
+
+static struct attribute *as5835_54t_cpld2_attributes[] = {
+ &sensor_dev_attr_version.dev_attr.attr,
+ &sensor_dev_attr_access.dev_attr.attr,
+ /* transceiver attributes */
+ NULL
+};
+
+static const struct attribute_group as5835_54t_cpld2_group = {
+ .attrs = as5835_54t_cpld2_attributes,
+};
+
+static struct attribute *as5835_54t_cpld3_attributes[] = {
+ &sensor_dev_attr_version.dev_attr.attr,
+ &sensor_dev_attr_access.dev_attr.attr,
+ /* transceiver attributes */
+ &sensor_dev_attr_module_present_all.dev_attr.attr,
+ DECLARE_TRANSCEIVER_PRESENT_ATTR(49),
+ DECLARE_TRANSCEIVER_PRESENT_ATTR(50),
+ DECLARE_TRANSCEIVER_PRESENT_ATTR(51),
+ DECLARE_TRANSCEIVER_PRESENT_ATTR(52),
+ DECLARE_TRANSCEIVER_PRESENT_ATTR(53),
+ DECLARE_TRANSCEIVER_PRESENT_ATTR(54),
+ DECLARE_QSFP_TRANSCEIVER_ATTR(49),
+ DECLARE_QSFP_TRANSCEIVER_ATTR(50),
+ DECLARE_QSFP_TRANSCEIVER_ATTR(51),
+ DECLARE_QSFP_TRANSCEIVER_ATTR(52),
+ DECLARE_QSFP_TRANSCEIVER_ATTR(53),
+ DECLARE_QSFP_TRANSCEIVER_ATTR(54),
+ NULL
+};
+
+static const struct attribute_group as5835_54t_cpld3_group = {
+ .attrs = as5835_54t_cpld3_attributes,
+};
+
+static ssize_t show_present_all(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ int i, status;
+ u8 values[5] = {0};
+ u8 regs_cpld3[] = {0x14};
+ u8 *regs[] = {NULL, NULL, regs_cpld3};
+ u8 size[] = {0, 0, ARRAY_SIZE(regs_cpld3)};
+ struct i2c_client *client = to_i2c_client(dev);
+ struct as5835_54t_cpld_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->update_lock);
+
+ for (i = 0; i < size[data->type]; i++) {
+ status = as5835_54t_cpld_read_internal(client, regs[data->type][i]);
+ if (status < 0) {
+ goto exit;
+ }
+
+ values[i] = ~(u8)status;
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ /* Return values in order */
+ values[0] &= 0x3F;
+ return sprintf(buf, "%.2x\n", values[0]);
+
+exit:
+ mutex_unlock(&data->update_lock);
+ return status;
+}
+
+static ssize_t show_status(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 as5835_54t_cpld_data *data = i2c_get_clientdata(client);
+ int status = 0;
+ u8 reg = 0, mask = 0, revert = 0;
+
+ switch (attr->index) {
+ case MODULE_PRESENT_49 ... MODULE_PRESENT_54:
+ reg = 0x14;
+ mask = 0x1 << (attr->index - MODULE_PRESENT_49);
+ break;
+ case MODULE_LPMODE_49 ... MODULE_LPMODE_54:
+ reg = 0x16;
+ mask = 0x1 << (attr->index - MODULE_LPMODE_49);
+ break;
+ case MODULE_RESET_49 ... MODULE_RESET_54:
+ reg = 0x15;
+ mask = 0x1 << (attr->index - MODULE_RESET_49);
+ break;
+ default:
+ return 0;
+ }
+
+ if (attr->index >= MODULE_PRESENT_49 && attr->index <= MODULE_PRESENT_54) {
+ revert = 1;
+ }
+
+ mutex_lock(&data->update_lock);
+ status = as5835_54t_cpld_read_internal(client, reg);
+ if (unlikely(status < 0)) {
+ goto exit;
+ }
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask));
+
+exit:
+ mutex_unlock(&data->update_lock);
+ return status;
+}
+
+static ssize_t set_control(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct as5835_54t_cpld_data *data = i2c_get_clientdata(client);
+ long value;
+ int status;
+ u8 reg = 0, mask = 0;
+
+ status = kstrtol(buf, 10, &value);
+ if (status) {
+ return status;
+ }
+
+ switch (attr->index) {
+ case MODULE_LPMODE_49 ... MODULE_LPMODE_54:
+ reg = 0x16;
+ mask = 0x1 << (attr->index - MODULE_LPMODE_49);
+ break;
+ case MODULE_RESET_49 ... MODULE_RESET_54:
+ reg = 0x15;
+ mask = 0x1 << (attr->index - MODULE_RESET_49);
+ break;
+ default:
+ return 0;
+ }
+
+ /* Read current status */
+ mutex_lock(&data->update_lock);
+ status = as5835_54t_cpld_read_internal(client, reg);
+ if (unlikely(status < 0)) {
+ goto exit;
+ }
+
+ /* Update tx_disable/lpmode/reset status */
+ if (value) {
+ status |= mask;
+ }
+ else {
+ status &= ~mask;
+ }
+
+ status = as5835_54t_cpld_write_internal(client, reg, status);
+ if (unlikely(status < 0)) {
+ goto exit;
+ }
+
+ mutex_unlock(&data->update_lock);
+ return count;
+
+exit:
+ mutex_unlock(&data->update_lock);
+ return status;
+}
+
+static ssize_t access(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count)
+{
+ int status;
+ u32 addr, val;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct as5835_54t_cpld_data *data = i2c_get_clientdata(client);
+
+ if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) {
+ return -EINVAL;
+ }
+
+ if (addr > 0xFF || val > 0xFF) {
+ return -EINVAL;
+ }
+
+ mutex_lock(&data->update_lock);
+ status = as5835_54t_cpld_write_internal(client, addr, val);
+ if (unlikely(status < 0)) {
+ goto exit;
+ }
+ mutex_unlock(&data->update_lock);
+ return count;
+
+exit:
+ mutex_unlock(&data->update_lock);
+ return status;
+}
+
+static void as5835_54t_cpld_add_client(struct i2c_client *client)
+{
+ struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL);
+
+ if (!node) {
+ dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr);
+ return;
+ }
+
+ node->client = client;
+
+ mutex_lock(&list_lock);
+ list_add(&node->list, &cpld_client_list);
+ mutex_unlock(&list_lock);
+}
+
+static void as5835_54t_cpld_remove_client(struct i2c_client *client)
+{
+ struct list_head *list_node = NULL;
+ struct cpld_client_node *cpld_node = NULL;
+ int found = 0;
+
+ mutex_lock(&list_lock);
+
+ list_for_each(list_node, &cpld_client_list)
+ {
+ cpld_node = list_entry(list_node, struct cpld_client_node, list);
+
+ if (cpld_node->client == client) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found) {
+ list_del(list_node);
+ kfree(cpld_node);
+ }
+
+ mutex_unlock(&list_lock);
+}
+
+static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int val = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+
+ val = i2c_smbus_read_byte_data(client, 0x1);
+
+ if (val < 0) {
+ dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val);
+ }
+
+ return sprintf(buf, "%d\n", val);
+}
+
+/*
+ * I2C init/probing/exit functions
+ */
+static int as5835_54t_cpld_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
+ struct as5835_54t_cpld_data *data;
+ int ret = -ENODEV;
+ const struct attribute_group *group = NULL;
+
+ if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
+ goto exit;
+
+ data = kzalloc(sizeof(struct as5835_54t_cpld_data), GFP_KERNEL);
+ if (!data) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+ data->type = id->driver_data;
+
+ /* Register sysfs hooks */
+ switch (data->type) {
+ case as5835_54t_cpld1:
+ group = &as5835_54t_cpld1_group;
+ break;
+ case as5835_54t_cpld2:
+ group = &as5835_54t_cpld2_group;
+ break;
+ case as5835_54t_cpld3:
+ group = &as5835_54t_cpld3_group;
+ break;
+ default:
+ break;
+ }
+
+ if (group) {
+ ret = sysfs_create_group(&client->dev.kobj, group);
+ if (ret) {
+ goto exit_free;
+ }
+ }
+
+ as5835_54t_cpld_add_client(client);
+ return 0;
+
+exit_free:
+ kfree(data);
+exit:
+ return ret;
+}
+
+static int as5835_54t_cpld_remove(struct i2c_client *client)
+{
+ struct as5835_54t_cpld_data *data = i2c_get_clientdata(client);
+ const struct attribute_group *group = NULL;
+
+ as5835_54t_cpld_remove_client(client);
+
+ /* Remove sysfs hooks */
+ switch (data->type) {
+ case as5835_54t_cpld1:
+ group = &as5835_54t_cpld1_group;
+ break;
+ case as5835_54t_cpld2:
+ group = &as5835_54t_cpld2_group;
+ break;
+ case as5835_54t_cpld3:
+ group = &as5835_54t_cpld3_group;
+ break;
+ default:
+ break;
+ }
+
+ if (group) {
+ sysfs_remove_group(&client->dev.kobj, group);
+ }
+
+ kfree(data);
+
+ return 0;
+}
+
+static int as5835_54t_cpld_read_internal(struct i2c_client *client, u8 reg)
+{
+ int status = 0, retry = I2C_RW_RETRY_COUNT;
+
+ while (retry) {
+ status = i2c_smbus_read_byte_data(client, reg);
+ if (unlikely(status < 0)) {
+ msleep(I2C_RW_RETRY_INTERVAL);
+ retry--;
+ continue;
+ }
+
+ break;
+ }
+
+ return status;
+}
+
+static int as5835_54t_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value)
+{
+ int status = 0, retry = I2C_RW_RETRY_COUNT;
+
+ while (retry) {
+ status = i2c_smbus_write_byte_data(client, reg, value);
+ if (unlikely(status < 0)) {
+ msleep(I2C_RW_RETRY_INTERVAL);
+ retry--;
+ continue;
+ }
+
+ break;
+ }
+
+ return status;
+}
+
+int as5835_54t_cpld_read(unsigned short cpld_addr, u8 reg)
+{
+ struct list_head *list_node = NULL;
+ struct cpld_client_node *cpld_node = NULL;
+ int ret = -EPERM;
+
+ mutex_lock(&list_lock);
+
+ list_for_each(list_node, &cpld_client_list)
+ {
+ cpld_node = list_entry(list_node, struct cpld_client_node, list);
+
+ if (cpld_node->client->addr == cpld_addr) {
+ ret = as5835_54t_cpld_read_internal(cpld_node->client, reg);
+ break;
+ }
+ }
+
+ mutex_unlock(&list_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(as5835_54t_cpld_read);
+
+int as5835_54t_cpld_write(unsigned short cpld_addr, u8 reg, u8 value)
+{
+ struct list_head *list_node = NULL;
+ struct cpld_client_node *cpld_node = NULL;
+ int ret = -EIO;
+
+ mutex_lock(&list_lock);
+
+ list_for_each(list_node, &cpld_client_list)
+ {
+ cpld_node = list_entry(list_node, struct cpld_client_node, list);
+
+ if (cpld_node->client->addr == cpld_addr) {
+ ret = as5835_54t_cpld_write_internal(cpld_node->client, reg, value);
+ break;
+ }
+ }
+
+ mutex_unlock(&list_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(as5835_54t_cpld_write);
+
+static struct i2c_driver as5835_54t_cpld_driver = {
+ .driver = {
+ .name = "as5835_54t_cpld",
+ .owner = THIS_MODULE,
+ },
+ .probe = as5835_54t_cpld_probe,
+ .remove = as5835_54t_cpld_remove,
+ .id_table = as5835_54t_cpld_id,
+};
+
+static int __init as5835_54t_cpld_init(void)
+{
+ mutex_init(&list_lock);
+ return i2c_add_driver(&as5835_54t_cpld_driver);
+}
+
+static void __exit as5835_54t_cpld_exit(void)
+{
+ i2c_del_driver(&as5835_54t_cpld_driver);
+}
+
+MODULE_AUTHOR("Brandon Chuang ");
+MODULE_DESCRIPTION("Accton I2C CPLD driver");
+MODULE_LICENSE("GPL");
+
+module_init(as5835_54t_cpld_init);
+module_exit(as5835_54t_cpld_exit);
+
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_fan.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_fan.c
new file mode 100644
index 0000000000..ea6fdb8296
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_fan.c
@@ -0,0 +1,484 @@
+/*
+ * A hwmon driver for the Accton as5835 54t fan
+ *
+ * Copyright (C) 2016 Accton Technology Corporation.
+ * Brandon Chuang
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DRVNAME "as5835_54t_fan"
+#define MAX_FAN_SPEED_RPM 21500
+
+static struct as5835_54t_fan_data *as5835_54t_fan_update_device(struct device *dev);
+static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf);
+static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count);
+static ssize_t show_version(struct device *dev, struct device_attribute *da,
+ char *buf);
+extern int as5835_54t_cpld_read(unsigned short cpld_addr, u8 reg);
+extern int as5835_54t_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
+
+/* fan related data, the index should match sysfs_fan_attributes
+ */
+static const u8 fan_reg[] = {
+ 0x02, /* fan 1-5 present status */
+ 0x03, /* fan 1-5 direction(0:F2B 1:B2F) */
+ 0x04, /* front fan 1-5 fault status */
+ 0x05, /* rear fan 1-5 fault status */
+ 0x06, /* fan PWM(for all fan) */
+ 0x07, /* front fan 1 speed(rpm) */
+ 0x08, /* front fan 2 speed(rpm) */
+ 0x09, /* front fan 3 speed(rpm) */
+ 0x0A, /* front fan 4 speed(rpm) */
+ 0x0B, /* front fan 5 speed(rpm) */
+ 0x0C, /* rear fan 1 speed(rpm) */
+ 0x0D, /* rear fan 2 speed(rpm) */
+ 0x0E, /* rear fan 3 speed(rpm) */
+ 0x0F, /* rear fan 4 speed(rpm) */
+ 0x10, /* rear fan 5 speed(rpm) */
+};
+
+/* fan data */
+struct as5835_54t_fan_data {
+ struct platform_device *pdev;
+ struct device *hwmon_dev;
+ struct mutex update_lock;
+ char valid; /* != 0 if registers are valid */
+ unsigned long last_updated; /* In jiffies */
+ u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */
+};
+
+enum fan_id {
+ FAN1_ID,
+ FAN2_ID,
+ FAN3_ID,
+ FAN4_ID,
+ FAN5_ID
+};
+
+enum sysfs_fan_attributes {
+ FAN_PRESENT_REG,
+ FAN_DIRECTION_REG,
+ FAN_FRONT_FAULT_REG,
+ FAN_REAR_FAULT_REG,
+ FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */
+ FAN1_FRONT_SPEED_RPM,
+ FAN2_FRONT_SPEED_RPM,
+ FAN3_FRONT_SPEED_RPM,
+ FAN4_FRONT_SPEED_RPM,
+ FAN5_FRONT_SPEED_RPM,
+ FAN1_REAR_SPEED_RPM,
+ FAN2_REAR_SPEED_RPM,
+ FAN3_REAR_SPEED_RPM,
+ FAN4_REAR_SPEED_RPM,
+ FAN5_REAR_SPEED_RPM,
+ FAN1_DIRECTION,
+ FAN2_DIRECTION,
+ FAN3_DIRECTION,
+ FAN4_DIRECTION,
+ FAN5_DIRECTION,
+ FAN1_PRESENT,
+ FAN2_PRESENT,
+ FAN3_PRESENT,
+ FAN4_PRESENT,
+ FAN5_PRESENT,
+ FAN1_FAULT,
+ FAN2_FAULT,
+ FAN3_FAULT,
+ FAN4_FAULT,
+ FAN5_FAULT,
+ FAN_MAX_RPM,
+ CPLD_VERSION
+};
+
+/* Define attributes
+ */
+#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \
+ static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\
+ static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT)
+#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \
+ &sensor_dev_attr_fan##index2##_fault.dev_attr.attr
+#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \
+ static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION)
+#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr
+
+#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \
+ static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE)
+#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr
+
+#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \
+ static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT)
+#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr
+
+#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \
+ static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\
+ static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\
+ static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\
+ static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM)
+#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \
+ &sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \
+ &sensor_dev_attr_fan##index##_input.dev_attr.attr, \
+ &sensor_dev_attr_fan##index2##_input.dev_attr.attr
+
+static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION);
+static SENSOR_DEVICE_ATTR(fan_max_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN_MAX_RPM);
+#define DECLARE_FAN_MAX_RPM_ATTR(index) &sensor_dev_attr_fan_max_speed_rpm.dev_attr.attr
+
+
+/* 5 fan fault attributes in this platform */
+DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1, 11);
+DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2, 12);
+DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3, 13);
+DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4, 14);
+DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5, 15);
+/* 5 fan speed(rpm) attributes in this platform */
+DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1, 11);
+DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2, 12);
+DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3, 13);
+DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4, 14);
+DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5, 15);
+/* 5 fan present attributes in this platform */
+DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1);
+DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2);
+DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3);
+DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4);
+DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5);
+/* 5 fan direction attribute in this platform */
+DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1);
+DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2);
+DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3);
+DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4);
+DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5);
+/* 1 fan duty cycle attribute in this platform */
+DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR();
+
+static struct attribute *as5835_54t_fan_attributes[] = {
+ &sensor_dev_attr_version.dev_attr.attr,
+ /* fan related attributes */
+ DECLARE_FAN_FAULT_ATTR(1, 11),
+ DECLARE_FAN_FAULT_ATTR(2, 12),
+ DECLARE_FAN_FAULT_ATTR(3, 13),
+ DECLARE_FAN_FAULT_ATTR(4, 14),
+ DECLARE_FAN_FAULT_ATTR(5, 15),
+ DECLARE_FAN_SPEED_RPM_ATTR(1, 11),
+ DECLARE_FAN_SPEED_RPM_ATTR(2, 12),
+ DECLARE_FAN_SPEED_RPM_ATTR(3, 13),
+ DECLARE_FAN_SPEED_RPM_ATTR(4, 14),
+ DECLARE_FAN_SPEED_RPM_ATTR(5, 15),
+ DECLARE_FAN_PRESENT_ATTR(1),
+ DECLARE_FAN_PRESENT_ATTR(2),
+ DECLARE_FAN_PRESENT_ATTR(3),
+ DECLARE_FAN_PRESENT_ATTR(4),
+ DECLARE_FAN_PRESENT_ATTR(5),
+ DECLARE_FAN_DIRECTION_ATTR(1),
+ DECLARE_FAN_DIRECTION_ATTR(2),
+ DECLARE_FAN_DIRECTION_ATTR(3),
+ DECLARE_FAN_DIRECTION_ATTR(4),
+ DECLARE_FAN_DIRECTION_ATTR(5),
+ DECLARE_FAN_DUTY_CYCLE_ATTR(),
+ DECLARE_FAN_MAX_RPM_ATTR(),
+ NULL
+};
+
+#define FAN_DUTY_CYCLE_REG_MASK 0x1F
+#define FAN_MAX_DUTY_CYCLE 100
+#define FAN_REG_VAL_TO_SPEED_RPM_STEP 150
+
+static int as5835_54t_fan_read_value(struct i2c_client *client, u8 reg)
+{
+ return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int as5835_54t_fan_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+ return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/* fan utility functions
+ */
+static u32 reg_val_to_duty_cycle(u8 reg_val)
+{
+ return (reg_val & FAN_DUTY_CYCLE_REG_MASK) * 5;
+}
+
+static u8 duty_cycle_to_reg_val(u8 duty_cycle)
+{
+ if (duty_cycle > FAN_MAX_DUTY_CYCLE) {
+ duty_cycle = FAN_MAX_DUTY_CYCLE;
+ }
+
+ return (duty_cycle / 5);
+}
+
+static u32 reg_val_to_speed_rpm(u8 reg_val)
+{
+ return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP;
+}
+
+static u8 reg_val_to_direction(u8 reg_val, enum fan_id id)
+{
+ return !!(reg_val & BIT(id)); /* 0: Front to Back, 1: Back to Front*/
+}
+
+static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id)
+{
+ return !(reg_val & BIT(id));
+}
+
+static u8 is_fan_fault(struct as5835_54t_fan_data *data, enum fan_id id)
+{
+ if ((data->reg_val[FAN_FRONT_FAULT_REG] & BIT(id)) ||
+ (data->reg_val[FAN_REAR_FAULT_REG] & BIT(id))) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count)
+{
+ int error, value;
+ struct i2c_client *client = to_i2c_client(dev);
+
+ error = kstrtoint(buf, 10, &value);
+ if (error) {
+ return error;
+ }
+
+ if (value < 0 || value > FAN_MAX_DUTY_CYCLE) {
+ return -EINVAL;
+ }
+
+ as5835_54t_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value));
+ return count;
+}
+
+static ssize_t fan_show_value(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct as5835_54t_fan_data *data = as5835_54t_fan_update_device(dev);
+ ssize_t ret = 0;
+
+ if (data->valid) {
+ switch (attr->index) {
+ case FAN_DUTY_CYCLE_PERCENTAGE:
+ {
+ u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]);
+ ret = sprintf(buf, "%u\n", duty_cycle);
+ break;
+ }
+ case FAN1_FRONT_SPEED_RPM:
+ case FAN2_FRONT_SPEED_RPM:
+ case FAN3_FRONT_SPEED_RPM:
+ case FAN4_FRONT_SPEED_RPM:
+ case FAN5_FRONT_SPEED_RPM:
+ case FAN1_REAR_SPEED_RPM:
+ case FAN2_REAR_SPEED_RPM:
+ case FAN3_REAR_SPEED_RPM:
+ case FAN4_REAR_SPEED_RPM:
+ case FAN5_REAR_SPEED_RPM:
+ ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index]));
+ break;
+ case FAN1_PRESENT:
+ case FAN2_PRESENT:
+ case FAN3_PRESENT:
+ case FAN4_PRESENT:
+ case FAN5_PRESENT:
+ ret = sprintf(buf, "%d\n",
+ reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG],
+ attr->index - FAN1_PRESENT));
+ break;
+ case FAN1_FAULT:
+ case FAN2_FAULT:
+ case FAN3_FAULT:
+ case FAN4_FAULT:
+ case FAN5_FAULT:
+ ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT));
+ break;
+ case FAN1_DIRECTION:
+ case FAN2_DIRECTION:
+ case FAN3_DIRECTION:
+ case FAN4_DIRECTION:
+ case FAN5_DIRECTION:
+ ret = sprintf(buf, "%d\n",
+ reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG],
+ attr->index - FAN1_DIRECTION));
+ break;
+ case FAN_MAX_RPM:
+ ret = sprintf(buf, "%d\n", MAX_FAN_SPEED_RPM);
+ default:
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static const struct attribute_group as5835_54t_fan_group = {
+ .attrs = as5835_54t_fan_attributes,
+};
+
+static struct as5835_54t_fan_data *as5835_54t_fan_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct as5835_54t_fan_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2) ||
+ !data->valid) {
+ int i;
+
+ dev_dbg(&client->dev, "Starting as5835_54t_fan update\n");
+ data->valid = 0;
+
+ /* Update fan data
+ */
+ for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) {
+ int status = as5835_54t_fan_read_value(client, fan_reg[i]);
+
+ if (status < 0) {
+ data->valid = 0;
+ mutex_unlock(&data->update_lock);
+ dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status);
+ return data;
+ }
+ else {
+ data->reg_val[i] = status;
+ }
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
+
+static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int val = 0;
+ struct i2c_client *client = to_i2c_client(dev);
+
+ val = i2c_smbus_read_byte_data(client, 0x1);
+
+ if (val < 0) {
+ dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val);
+ }
+
+ return sprintf(buf, "%d\n", val);
+}
+
+static int as5835_54t_fan_probe(struct i2c_client *client,
+ const struct i2c_device_id *dev_id)
+{
+ struct as5835_54t_fan_data *data;
+ int status;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+ status = -EIO;
+ goto exit;
+ }
+
+ data = kzalloc(sizeof(struct as5835_54t_fan_data), GFP_KERNEL);
+ if (!data) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(client, data);
+ data->valid = 0;
+ mutex_init(&data->update_lock);
+
+ dev_info(&client->dev, "chip found\n");
+
+ /* Register sysfs hooks */
+ status = sysfs_create_group(&client->dev.kobj, &as5835_54t_fan_group);
+ if (status) {
+ goto exit_free;
+ }
+
+ data->hwmon_dev = hwmon_device_register_with_info(&client->dev, "as5835_54t_fan",
+ NULL, NULL, NULL);
+ if (IS_ERR(data->hwmon_dev)) {
+ status = PTR_ERR(data->hwmon_dev);
+ goto exit_remove;
+ }
+
+ dev_info(&client->dev, "%s: fan '%s'\n",
+ dev_name(data->hwmon_dev), client->name);
+ return 0;
+
+exit_remove:
+ sysfs_remove_group(&client->dev.kobj, &as5835_54t_fan_group);
+exit_free:
+ kfree(data);
+exit:
+
+ return status;
+}
+
+static int as5835_54t_fan_remove(struct i2c_client *client)
+{
+ struct as5835_54t_fan_data *data = i2c_get_clientdata(client);
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &as5835_54t_fan_group);
+
+ return 0;
+}
+
+/* Addresses to scan */
+static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static const struct i2c_device_id as5835_54t_fan_id[] = {
+ { "as5835_54t_fan", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, as5835_54t_fan_id);
+
+static struct i2c_driver as5835_54t_fan_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = DRVNAME,
+ },
+ .probe = as5835_54t_fan_probe,
+ .remove = as5835_54t_fan_remove,
+ .id_table = as5835_54t_fan_id,
+ .address_list = normal_i2c,
+};
+
+module_i2c_driver(as5835_54t_fan_driver);
+
+MODULE_AUTHOR("Brandon Chuang ");
+MODULE_DESCRIPTION("as5835_54t_fan driver");
+MODULE_LICENSE("GPL");
+
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_leds.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_leds.c
new file mode 100644
index 0000000000..e02930a2f6
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_leds.c
@@ -0,0 +1,380 @@
+/*
+ * A LED driver for the accton_as5822_54t_led
+ *
+ * Copyright (C) 2016 Accton Technology Corporation.
+ * Brandon Chuang
+ *
+ * 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
+
+#define DRVNAME "as5835_54t_led"
+
+#define DEBUG_MODE 0
+
+#if (DEBUG_MODE == 1)
+ #define DEBUG_PRINT(fmt, args...) \
+ printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args)
+#else
+ #define DEBUG_PRINT(fmt, args...)
+#endif
+
+extern int as5835_54t_cpld_read(unsigned short cpld_addr, u8 reg);
+extern int as5835_54t_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
+
+struct accton_as5835_54t_led_data {
+ struct platform_device *pdev;
+ struct mutex update_lock;
+ char valid; /* != 0 if registers are valid */
+ unsigned long last_updated; /* In jiffies */
+ u8 reg_val[2]; /* Register value, 0 = RELEASE/DIAG LED,
+ 1 = FAN/PSU LED,
+ 2 ~ 4 = SYSTEM LED */
+};
+
+static struct accton_as5835_54t_led_data *ledctl = NULL;
+
+#define LED_CNTRLER_I2C_ADDRESS (0x60)
+
+#define LED_TYPE_DIAG_REG_MASK (0x0C)
+#define LED_MODE_DIAG_GREEN_VALUE (0x08)
+#define LED_MODE_DIAG_AMBER_VALUE (0x04)
+#define LED_MODE_DIAG_OFF_VALUE (0x0C)
+#define LED_MODE_DIAG_AMBER_VALUE1 (0x00)
+
+#define LED_TYPE_LOC_REG_MASK (0x30)
+#define LED_MODE_LOC_AMBER_BLINK_VALUE (0x20)
+#define LED_MODE_LOC_OFF_VALUE (0x10)
+#define LED_MODE_LOC_AMBER_VALUE (0x00)
+
+static const u8 led_reg[] = {
+ 0xA, /* LOC/DIAG/FAN LED */
+ 0xB, /* PSU LED */
+};
+
+enum led_type {
+ LED_TYPE_DIAG,
+ LED_TYPE_LOC,
+ LED_TYPE_FAN,
+ LED_TYPE_PSU1,
+ LED_TYPE_PSU2
+};
+
+/* FAN/PSU/DIAG/RELEASE led mode */
+enum led_light_mode {
+ LED_MODE_OFF = 0,
+ LED_MODE_GREEN,
+ LED_MODE_GREEN_BLINK,
+ LED_MODE_AMBER,
+ LED_MODE_AMBER_BLINK,
+ LED_MODE_RED,
+ LED_MODE_RED_BLINK,
+ LED_MODE_BLUE,
+ LED_MODE_BLUE_BLINK,
+ LED_MODE_AUTO,
+ LED_MODE_UNKNOWN
+};
+
+struct led_type_mode {
+ enum led_type type;
+ enum led_light_mode mode;
+ int type_mask;
+ int mode_value;
+};
+
+static struct led_type_mode led_type_mode_data[] = {
+{LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE},
+{LED_TYPE_LOC, LED_MODE_AMBER_BLINK, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_BLINK_VALUE},
+{LED_TYPE_LOC, LED_MODE_AMBER, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_VALUE},
+{LED_TYPE_DIAG, LED_MODE_OFF, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_OFF_VALUE},
+{LED_TYPE_DIAG, LED_MODE_GREEN, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_GREEN_VALUE},
+{LED_TYPE_DIAG, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_AMBER_VALUE},
+{LED_TYPE_DIAG, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_AMBER_VALUE1},
+};
+
+static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) {
+ if (type != led_type_mode_data[i].type) {
+ continue;
+ }
+
+ if ((led_type_mode_data[i].type_mask & reg_val) ==
+ led_type_mode_data[i].mode_value) {
+ return led_type_mode_data[i].mode;
+ }
+ }
+
+ return LED_MODE_UNKNOWN;
+}
+
+static u8 led_light_mode_to_reg_val(enum led_type type,
+ enum led_light_mode mode, u8 reg_val) {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) {
+ int type_mask, mode_value;
+
+ if (type != led_type_mode_data[i].type)
+ continue;
+
+ if (mode != led_type_mode_data[i].mode)
+ continue;
+
+ type_mask = led_type_mode_data[i].type_mask;
+ mode_value = led_type_mode_data[i].mode_value;
+ reg_val = (reg_val & ~type_mask) | mode_value;
+ }
+
+ return reg_val;
+}
+
+static int accton_as5835_54t_led_read_value(u8 reg)
+{
+ return as5835_54t_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg);
+}
+
+static int accton_as5835_54t_led_write_value(u8 reg, u8 value)
+{
+ return as5835_54t_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value);
+}
+
+static void accton_as5835_54t_led_update(void)
+{
+ mutex_lock(&ledctl->update_lock);
+
+ if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2)
+ || !ledctl->valid) {
+ int i;
+
+ dev_dbg(&ledctl->pdev->dev, "Starting accton_as5835_54t_led update\n");
+ ledctl->valid = 0;
+
+ /* Update LED data
+ */
+ for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) {
+ int status = accton_as5835_54t_led_read_value(led_reg[i]);
+
+ if (status < 0) {
+ dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status);
+ goto exit;
+ }
+ else
+ ledctl->reg_val[i] = status;
+ }
+
+ ledctl->last_updated = jiffies;
+ ledctl->valid = 1;
+ }
+
+exit:
+ mutex_unlock(&ledctl->update_lock);
+}
+
+static void accton_as5835_54t_led_set(struct led_classdev *led_cdev,
+ enum led_brightness led_light_mode,
+ u8 reg, enum led_type type)
+{
+ int reg_val;
+
+ mutex_lock(&ledctl->update_lock);
+ reg_val = accton_as5835_54t_led_read_value(reg);
+
+ if (reg_val < 0) {
+ dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val);
+ goto exit;
+ }
+
+ reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val);
+ accton_as5835_54t_led_write_value(reg, reg_val);
+ ledctl->valid = 0;
+
+exit:
+ mutex_unlock(&ledctl->update_lock);
+}
+
+static void accton_as7312_54t_led_auto_set(struct led_classdev *led_cdev,
+ enum led_brightness led_light_mode)
+{
+}
+
+static enum led_brightness accton_as7312_54t_led_auto_get(struct led_classdev *cdev)
+{
+ return LED_MODE_AUTO;
+}
+
+static void accton_as5835_54t_led_diag_set(struct led_classdev *led_cdev,
+ enum led_brightness led_light_mode)
+{
+ accton_as5835_54t_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG);
+}
+
+static enum led_brightness accton_as5835_54t_led_diag_get(struct led_classdev *cdev)
+{
+ accton_as5835_54t_led_update();
+ return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]);
+}
+
+static enum led_brightness accton_as5835_54t_led_loc_get(struct led_classdev *cdev)
+{
+ accton_as5835_54t_led_update();
+ return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]);
+}
+
+static void accton_as5835_54t_led_loc_set(struct led_classdev *led_cdev,
+ enum led_brightness led_light_mode)
+{
+ accton_as5835_54t_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC);
+}
+
+static struct led_classdev accton_as5835_54t_leds[] = {
+ [LED_TYPE_LOC] = {
+ .name = "as5835_54t_led::loc",
+ .default_trigger = "unused",
+ .brightness_set = accton_as5835_54t_led_loc_set,
+ .brightness_get = accton_as5835_54t_led_loc_get,
+ .max_brightness = LED_MODE_AMBER_BLINK,
+ },
+ [LED_TYPE_DIAG] = {
+ .name = "as5835_54t_led::diag",
+ .default_trigger = "unused",
+ .brightness_set = accton_as5835_54t_led_diag_set,
+ .brightness_get = accton_as5835_54t_led_diag_get,
+ .max_brightness = LED_MODE_AMBER,
+ },
+ [LED_TYPE_PSU1] = {
+ .name = "as5835_54t_led::psu1",
+ .default_trigger = "unused",
+ .brightness_set = accton_as7312_54t_led_auto_set,
+ .brightness_get = accton_as7312_54t_led_auto_get,
+ .max_brightness = LED_MODE_AUTO,
+ },
+ [LED_TYPE_PSU2] = {
+ .name = "as5835_54t_led::psu2",
+ .default_trigger = "unused",
+ .brightness_set = accton_as7312_54t_led_auto_set,
+ .brightness_get = accton_as7312_54t_led_auto_get,
+ .max_brightness = LED_MODE_AUTO,
+ },
+ [LED_TYPE_FAN] = {
+ .name = "as5835_54t_led::fan",
+ .default_trigger = "unused",
+ .brightness_set = accton_as7312_54t_led_auto_set,
+ .brightness_get = accton_as7312_54t_led_auto_get,
+ .max_brightness = LED_MODE_AUTO,
+ },
+};
+
+static int accton_as5835_54t_led_probe(struct platform_device *pdev)
+{
+ int ret, i;
+
+ for (i = 0; i < ARRAY_SIZE(accton_as5835_54t_leds); i++) {
+ ret = led_classdev_register(&pdev->dev, &accton_as5835_54t_leds[i]);
+
+ if (ret < 0) {
+ break;
+ }
+ }
+
+ /* Check if all LEDs were successfully registered */
+ if (i != ARRAY_SIZE(accton_as5835_54t_leds)){
+ int j;
+
+ /* only unregister the LEDs that were successfully registered */
+ for (j = 0; j < i; j++) {
+ led_classdev_unregister(&accton_as5835_54t_leds[i]);
+ }
+ }
+
+ return ret;
+}
+
+static int accton_as5835_54t_led_remove(struct platform_device *pdev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(accton_as5835_54t_leds); i++) {
+ led_classdev_unregister(&accton_as5835_54t_leds[i]);
+ }
+
+ return 0;
+}
+
+static struct platform_driver accton_as5835_54t_led_driver = {
+ .probe = accton_as5835_54t_led_probe,
+ .remove = accton_as5835_54t_led_remove,
+ .driver = {
+ .name = DRVNAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init accton_as5835_54t_led_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&accton_as5835_54t_led_driver);
+ if (ret < 0) {
+ goto exit;
+ }
+
+ ledctl = kzalloc(sizeof(struct accton_as5835_54t_led_data), GFP_KERNEL);
+ if (!ledctl) {
+ ret = -ENOMEM;
+ goto exit_driver;
+ }
+
+ mutex_init(&ledctl->update_lock);
+
+ ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
+ if (IS_ERR(ledctl->pdev)) {
+ ret = PTR_ERR(ledctl->pdev);
+ goto exit_free;
+ }
+
+ return 0;
+
+exit_free:
+ kfree(ledctl);
+exit_driver:
+ platform_driver_unregister(&accton_as5835_54t_led_driver);
+exit:
+ return ret;
+}
+
+static void __exit accton_as5835_54t_led_exit(void)
+{
+ platform_device_unregister(ledctl->pdev);
+ platform_driver_unregister(&accton_as5835_54t_led_driver);
+ kfree(ledctl);
+}
+
+late_initcall(accton_as5835_54t_led_init);
+module_exit(accton_as5835_54t_led_exit);
+
+MODULE_AUTHOR("Brandon Chuang ");
+MODULE_DESCRIPTION("accton_as5835_54t_led driver");
+MODULE_LICENSE("GPL");
+
+
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_psu.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_psu.c
new file mode 100644
index 0000000000..78f0b4298a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/accton_as5835_54t_psu.c
@@ -0,0 +1,343 @@
+/*
+ * An hwmon driver for accton as5835_54t Power Module
+ *
+ * Copyright (C) 2014 Accton Technology Corporation.
+ * Brandon Chuang
+ *
+ * Based on ad7414.c
+ * Copyright 2006 Stefan Roese , DENX Software Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+#define PSU_STATUS_I2C_ADDR 0x60
+#define PSU_STATUS_I2C_REG_OFFSET 0x2
+
+#define MODEL_NAME_LEN 8
+#define MODEL_NAME_REG_OFFSET 0x20
+
+#define SERIAL_NUM_LEN 18
+#define SERIAL_NUM_REG_OFFSET 0x35
+
+#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4 + 1)))
+#define IS_PRESENT(id, value) (!(value & BIT(id*4)))
+
+static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf);
+static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf);
+extern int as5835_54t_cpld_read(unsigned short cpld_addr, u8 reg);
+
+/* Addresses scanned
+ */
+static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+/* Each client has this additional data
+ */
+struct as5835_54t_psu_data {
+ struct device *hwmon_dev;
+ struct mutex update_lock;
+ char valid; /* !=0 if registers are valid */
+ unsigned long last_updated; /* In jiffies */
+ u8 index; /* PSU index */
+ u8 status; /* Status(present/power_good) register read from CPLD */
+ char model_name[MODEL_NAME_LEN+1]; /* Model name, read from eeprom */
+ char serial[SERIAL_NUM_LEN+1]; /* Serial number, read from eeprom*/
+};
+
+static struct as5835_54t_psu_data *as5835_54t_psu_update_device(struct device *dev);
+
+enum as5835_54t_psu_sysfs_attributes {
+ PSU_PRESENT,
+ PSU_MODEL_NAME,
+ PSU_POWER_GOOD,
+ PSU_SERIAL_NUMBER
+};
+
+/* sysfs attributes for hwmon
+ */
+static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT);
+static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME);
+static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD);
+static SENSOR_DEVICE_ATTR(psu_serial_numer, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER);
+
+static struct attribute *as5835_54t_psu_attributes[] = {
+ &sensor_dev_attr_psu_present.dev_attr.attr,
+ &sensor_dev_attr_psu_model_name.dev_attr.attr,
+ &sensor_dev_attr_psu_power_good.dev_attr.attr,
+ &sensor_dev_attr_psu_serial_numer.dev_attr.attr,
+ NULL
+};
+
+static ssize_t show_status(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct as5835_54t_psu_data *data = as5835_54t_psu_update_device(dev);
+ u8 status = 0;
+
+ if (!data->valid) {
+ return sprintf(buf, "0\n");
+ }
+
+ if (attr->index == PSU_PRESENT) {
+ status = IS_PRESENT(data->index, data->status);
+ }
+ else { /* PSU_POWER_GOOD */
+ status = IS_POWER_GOOD(data->index, data->status);
+ }
+
+ return sprintf(buf, "%d\n", status);
+}
+
+static ssize_t show_string(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct as5835_54t_psu_data *data = as5835_54t_psu_update_device(dev);
+ char *str = NULL;
+
+ if (!data->valid) {
+ return 0;
+ }
+
+ if (attr->index == PSU_MODEL_NAME) {
+ str = data->model_name;
+ }
+ else { /* PSU_SERIAL_NUBMER */
+ str = data->serial;
+ }
+
+ return sprintf(buf, "%s\n", str);
+}
+
+static const struct attribute_group as5835_54t_psu_group = {
+ .attrs = as5835_54t_psu_attributes,
+};
+
+static int as5835_54t_psu_probe(struct i2c_client *client,
+ const struct i2c_device_id *dev_id)
+{
+ struct as5835_54t_psu_data *data;
+ int status;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
+ status = -EIO;
+ goto exit;
+ }
+
+ data = kzalloc(sizeof(struct as5835_54t_psu_data), GFP_KERNEL);
+ if (!data) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(client, data);
+ data->valid = 0;
+ data->index = dev_id->driver_data;
+ mutex_init(&data->update_lock);
+
+ dev_info(&client->dev, "chip found\n");
+
+ /* Register sysfs hooks */
+ status = sysfs_create_group(&client->dev.kobj, &as5835_54t_psu_group);
+ if (status) {
+ goto exit_free;
+ }
+
+ data->hwmon_dev = hwmon_device_register_with_info(&client->dev, "as5835_54t_psu",
+ NULL, NULL, NULL);
+ if (IS_ERR(data->hwmon_dev)) {
+ status = PTR_ERR(data->hwmon_dev);
+ goto exit_remove;
+ }
+
+ dev_info(&client->dev, "%s: psu '%s'\n",
+ dev_name(data->hwmon_dev), client->name);
+
+ return 0;
+
+exit_remove:
+ sysfs_remove_group(&client->dev.kobj, &as5835_54t_psu_group);
+exit_free:
+ kfree(data);
+exit:
+
+ return status;
+}
+
+static int as5835_54t_psu_remove(struct i2c_client *client)
+{
+ struct as5835_54t_psu_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &as5835_54t_psu_group);
+ kfree(data);
+
+ return 0;
+}
+
+enum psu_index
+{
+ as5835_54t_psu1,
+ as5835_54t_psu2
+};
+
+static const struct i2c_device_id as5835_54t_psu_id[] = {
+ { "as5835_54t_psu1", as5835_54t_psu1 },
+ { "as5835_54t_psu2", as5835_54t_psu2 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, as5835_54t_psu_id);
+
+static struct i2c_driver as5835_54t_psu_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "as5835_54t_psu",
+ },
+ .probe = as5835_54t_psu_probe,
+ .remove = as5835_54t_psu_remove,
+ .id_table = as5835_54t_psu_id,
+ .address_list = normal_i2c,
+};
+
+static int as5835_54t_psu_read_byte(struct i2c_client *client, u8 command, u8 *data)
+{
+ int status = 0;
+ int retry_count = 5;
+
+ while (retry_count) {
+ status = i2c_smbus_read_byte_data(client, command);
+ if (unlikely(status < 0)) {
+ msleep(10);
+ retry_count--;
+ continue;
+ }
+
+ break;
+ }
+
+ if (unlikely(status < 0)) {
+ dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status);
+ goto abort;
+ }
+
+ *data = (u8)status;
+
+abort:
+ return status;
+}
+
+static int as5835_54t_psu_read_bytes(struct i2c_client *client, u8 command, u8 *data,
+ int data_len)
+{
+ int ret = 0;
+
+ while (data_len) {
+ ssize_t status;
+
+ status = as5835_54t_psu_read_byte(client, command, data);
+ if (status <= 0) {
+ ret = status;
+ break;
+ }
+
+ data += 1;
+ command += 1;
+ data_len -= 1;
+ }
+
+ return ret;
+}
+
+static struct as5835_54t_psu_data *as5835_54t_psu_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct as5835_54t_psu_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
+ int status;
+
+ dev_dbg(&client->dev, "Starting as5835_54t update\n");
+ data->valid = 0;
+
+ /* Read psu status */
+ status = as5835_54t_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET);
+
+ if (status < 0) {
+ dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status);
+ goto exit;
+ }
+ else {
+ data->status = status;
+ }
+
+
+ memset(data->model_name, 0, sizeof(data->model_name));
+ memset(data->serial, 0, sizeof(data->serial));
+
+ if (IS_PRESENT(data->index, data->status)) {
+ /* Read model name */
+ status = as5835_54t_psu_read_bytes(client, MODEL_NAME_REG_OFFSET, data->model_name,
+ ARRAY_SIZE(data->model_name)-1);
+ if (status < 0) {
+ data->model_name[0] = '\0';
+ dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr);
+ goto exit;
+ }
+
+ /* Read serial number */
+ status = as5835_54t_psu_read_bytes(client, SERIAL_NUM_REG_OFFSET, data->serial,
+ ARRAY_SIZE(data->serial)-1);
+ if (status < 0) {
+ data->serial[0] = '\0';
+ dev_dbg(&client->dev, "unable to read serial number from (0x%x)\n", client->addr);
+ goto exit;
+ }
+ else {
+ data->serial[SERIAL_NUM_LEN] = '\0';
+ }
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+exit:
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
+
+module_i2c_driver(as5835_54t_psu_driver);
+
+MODULE_AUTHOR("Brandon Chuang ");
+MODULE_DESCRIPTION("as5835_54t_psu driver");
+MODULE_LICENSE("GPL");
+
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/ym2651y.c
new file mode 120000
index 0000000000..f4d67640cc
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/modules/ym2651y.c
@@ -0,0 +1 @@
+../../common/modules/ym2651y.c
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-fan.service b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-fan.service
new file mode 100644
index 0000000000..19ad3e5194
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-fan.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=Accton AS5835-54T Platform Monitoring FAN service
+Before=pmon.service
+After=as5835-54t-platform-monitor.service
+DefaultDependencies=no
+
+[Service]
+ExecStart=/usr/local/bin/accton_as5835_54t_monitor_fan.py
+KillSignal=SIGKILL
+SuccessExitStatus=SIGKILL
+
+# Resource Limitations
+LimitCORE=infinity
+
+[Install]
+WantedBy=multi-user.target
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-psu.service b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-psu.service
new file mode 100644
index 0000000000..f30b13b6bc
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor-psu.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=Accton AS5835-54T Platform Monitoring PSU service
+Before=pmon.service
+After=as5835-54t-platform-monitor.service
+DefaultDependencies=no
+
+[Service]
+ExecStart=/usr/local/bin/accton_as5835_54t_monitor_psu.py
+KillSignal=SIGKILL
+SuccessExitStatus=SIGKILL
+
+# Resource Limitations
+LimitCORE=infinity
+
+[Install]
+WantedBy=multi-user.target
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor.service b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor.service
new file mode 100644
index 0000000000..9789201034
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/service/as5835-54t-platform-monitor.service
@@ -0,0 +1,18 @@
+[Unit]
+Description=Accton AS5835-54T Platform Monitoring service
+Before=pmon.service
+After=sysinit.target
+DefaultDependencies=no
+
+[Service]
+ExecStartPre=/usr/local/bin/accton_as5835_54t_util.py install
+ExecStart=/usr/local/bin/accton_as5835_54t_monitor.py
+KillSignal=SIGKILL
+SuccessExitStatus=SIGKILL
+#StandardOutput=tty
+
+# Resource Limitations
+LimitCORE=infinity
+
+[Install]
+WantedBy=multi-user.target
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/setup.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/setup.py
new file mode 100644
index 0000000000..ac880c41e4
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/setup.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+import os
+import sys
+from setuptools import setup
+os.listdir
+
+setup(
+ name='as5835_54t',
+ version='1.0',
+ description='Module to initialize Accton AS5835-54T platforms',
+
+ packages=['as5835_54t'],
+ package_dir={'as5835_54t': 'as5835-54t/classes'},
+)
+
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/README b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/README
new file mode 100644
index 0000000000..dc9b838f9f
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/README
@@ -0,0 +1,74 @@
+Copyright (C) 2016 Accton Networks, Inc.
+
+This program is free software: you can redistribute it and/or modify
+It under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+
+Contents of this package:
+ module - Contains source code of as5835 kernel driver modules.
+ util - operational scripts.
+
+Sonic creates a docker container and run building process under it.
+If user tries to built new drivers, please get into that docker and
+dpkg-buildpackage for them.
+
+All Linux kernel code is licensed under the GPLv1. All other code is
+licensed under the GPLv3. Please see the LICENSE file for copies of
+both licenses.
+
+The code for integacting with Accton AS5835-54T has 2 parts,
+kernel drivers and operational script.
+The kernel drivers of peripherals are under module/ directory.
+1. These drivers can be built to individual ko during dpkg-buildpackage.
+2. A operational script, accton_as5835_54t_util.py, for device initializatian.
+ Run "accton_as5835_54t_util.py install" to install drivers.
+
+To initialize the system, run "accton_as5835_54t_util.py install".
+To clean up the drivers & devices, run "accton_as5835_54t_util.py clean".
+To dump information of sensors, run "accton_as5835_54t_util.py show".
+To dump SFP EEPROM, run "accton_as5835_54t_util.py sff".
+To set fan speed, run "accton_as5835_54t_util.py set fan".
+To enable/disable SFP emission, run "accton_as5835_54t_util.py set sfp".
+To set system LEDs' color, run "accton_as5835_54t_util.py set led"
+For more information, run "accton_as5835_54t_util.py --help".
+
+====================================================================
+Besides applying accton_as5835_54t_util.py to access peripherals, you can
+access peripherals by sysfs nodes directly after the installation is run.
+
+System LED:
+ There are 5 system LEDs at the lower-left corner of front panel.
+ They are loc, diag, fan, ps1, and ps2.
+ The sysfs interface color mappings are as follows:
+ Brightness:
+ 0 => off
+ 1 => green
+ 2 => green blinking
+ 3 => amber
+ 4 => amber blinking
+ But not all colors are available for each LED.
+
+Fan Control:
+ There are 10 fans inside 5 fan modules.
+ All fans share 1 duty setting, ranged from 0~100.
+
+Thermal sensers:
+ 4 temperature sensors are controlled by the lm75 kernel modules.
+
+PSUs:
+ There 2 power supplies slot at the left/right side of the back.
+ Once if a PSU is not plugged, the status of it is shown failed.
+
+There are 48 SFP+ and 6 QSFP modules are equipped.
+Before operating on PSU and QSFP+, please make sure it is well plugged.
+Otherwise, operation is going to fail.
+
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor.py
new file mode 100755
index 0000000000..ce2e0d18d4
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor.py
@@ -0,0 +1,206 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2019 Accton Technology Corporation
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+# ------------------------------------------------------------------
+# HISTORY:
+# mm/dd/yyyy (A.D.)
+# 11/13/2017: Polly Hsu, Create
+# 05/08/2019: Roy Lee, changed for as5812-54x.
+# 05/29/2019: Brandon Chuang, changed for as5835-54x.
+# 06/11/2019: Brandon Chuang, changed for as5835-54t.
+# ------------------------------------------------------------------
+
+try:
+ import os
+ import sys, getopt
+ import subprocess
+ import click
+ import imp
+ import logging
+ import logging.config
+ import types
+ import time # this is only being used as part of the example
+ import traceback
+ import signal
+ from tabulate import tabulate
+ from as5835_54t.fanutil import FanUtil
+ from as5835_54t.thermalutil import ThermalUtil
+except ImportError as e:
+ raise ImportError('%s - required module not found' % str(e))
+
+# Deafults
+VERSION = '1.0'
+FUNCTION_NAME = 'accton_as5835_54t_monitor'
+DUTY_MAX = 100
+
+global log_file
+global log_level
+
+# Make a class we can use to capture stdout and sterr in the log
+class accton_as5835_54t_monitor(object):
+ # static temp var
+ _ori_temp = 0
+ _new_perc = 0
+
+ def __init__(self, log_file, log_level):
+ """Needs a logger and a logger level."""
+ # set up logging to file
+ logging.basicConfig(
+ filename=log_file,
+ filemode='w',
+ level=log_level,
+ format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s',
+ datefmt='%H:%M:%S'
+ )
+
+ # set up logging to console
+ if log_level == logging.DEBUG:
+ console = logging.StreamHandler()
+ console.setLevel(log_level)
+ formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
+ console.setFormatter(formatter)
+ logging.getLogger('').addHandler(console)
+
+ logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level)
+
+ def manage_fans(self):
+ FAN_LEV1_UP_TEMP = 57700 # temperature
+ FAN_LEV1_DOWN_TEMP = 0 # unused
+ FAN_LEV1_SPEED_PERC = DUTY_MAX # percentage*/
+
+ FAN_LEV2_UP_TEMP = 53000
+ FAN_LEV2_DOWN_TEMP = 52700
+ FAN_LEV2_SPEED_PERC = 80
+
+ FAN_LEV3_UP_TEMP = 49500
+ FAN_LEV3_DOWN_TEMP = 47700
+ FAN_LEV3_SPEED_PERC = 65
+
+ FAN_LEV4_UP_TEMP = 0 # unused
+ FAN_LEV4_DOWN_TEMP = 42700
+ FAN_LEV4_SPEED_PERC = 40
+
+
+ thermal = ThermalUtil()
+ fan = FanUtil()
+
+ temp2 = thermal.get_thermal_2_val()
+ if temp2 is None:
+ return False
+
+ temp3 = thermal.get_thermal_3_val()
+ if temp3 is None:
+ return False
+
+ new_temp = (temp2 + temp3) / 2
+
+ for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1):
+ fan_stat = fan.get_fan_status(x)
+ if fan_stat is None:
+ return False
+ if fan_stat is False:
+ self._new_perc = FAN_LEV1_SPEED_PERC
+ logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', self._new_perc, x)
+ break
+ logging.debug('INFO. fan_stat is True (fan_num:%d)', x)
+
+ if fan_stat is not None and fan_stat is not False:
+ diff = new_temp - self._ori_temp
+ if diff == 0:
+ logging.debug('INFO. RETURN. THERMAL temp not changed. %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp)
+ return True
+ else:
+ if diff >= 0:
+ is_up = True
+ logging.debug('INFO. THERMAL temp UP %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp)
+ else:
+ is_up = False
+ logging.debug('INFO. THERMAL temp DOWN %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp)
+
+ if is_up is True:
+ if new_temp >= FAN_LEV1_UP_TEMP:
+ self._new_perc = FAN_LEV1_SPEED_PERC
+ elif new_temp >= FAN_LEV2_UP_TEMP:
+ self._new_perc = FAN_LEV2_SPEED_PERC
+ elif new_temp >= FAN_LEV3_UP_TEMP:
+ self._new_perc = FAN_LEV3_SPEED_PERC
+ else:
+ self._new_perc = FAN_LEV4_SPEED_PERC
+ logging.debug('INFO. SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp)
+ else:
+ if new_temp <= FAN_LEV4_DOWN_TEMP:
+ self._new_perc = FAN_LEV4_SPEED_PERC
+ elif new_temp <= FAN_LEV3_DOWN_TEMP:
+ self._new_perc = FAN_LEV3_SPEED_PERC
+ elif new_temp <= FAN_LEV2_DOWN_TEMP:
+ self._new_perc = FAN_LEV2_SPEED_PERC
+ else:
+ self._new_perc = FAN_LEV1_SPEED_PERC
+ logging.debug('INFO. SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp)
+
+ cur_perc = fan.get_fan_duty_cycle()
+ if cur_perc == self._new_perc:
+ logging.debug('INFO. RETURN. FAN speed not changed. %d / %d (new_perc / ori_perc)', self._new_perc, cur_perc)
+ return True
+
+ set_stat = fan.set_fan_duty_cycle(self._new_perc)
+ if set_stat is True:
+ logging.debug('INFO: PASS. set_fan_duty_cycle (%d)', self._new_perc)
+ else:
+ logging.debug('INFO: FAIL. set_fan_duty_cycle (%d)', self._new_perc)
+
+ logging.debug('INFO: GET. ori_perc is %d. ori_temp is %d', cur_perc, self._ori_temp)
+ self._ori_temp = new_temp
+ logging.debug('INFO: UPDATE. ori_perc to %d. ori_temp to %d', cur_perc, self._ori_temp)
+
+ return True
+
+def handler(signum, frame):
+ fan = FanUtil()
+ logging.debug('INFO:Cause signal %d, set fan speed max.', signum)
+ fan.set_fan_duty_cycle(DUTY_MAX)
+ sys.exit(0)
+
+def main(argv):
+ log_file = '%s.log' % FUNCTION_NAME
+ log_level = logging.INFO
+ if len(sys.argv) != 1:
+ try:
+ opts, args = getopt.getopt(argv,'hdl:',['lfile='])
+ except getopt.GetoptError:
+ print 'Usage: %s [-d] [-l ]' % sys.argv[0]
+ return 0
+ for opt, arg in opts:
+ if opt == '-h':
+ print 'Usage: %s [-d] [-l ]' % sys.argv[0]
+ return 0
+ elif opt in ('-d', '--debug'):
+ log_level = logging.DEBUG
+ elif opt in ('-l', '--lfile'):
+ log_file = arg
+
+ signal.signal(signal.SIGINT, handler)
+ signal.signal(signal.SIGTERM, handler)
+ monitor = accton_as5835_54t_monitor(log_file, log_level)
+
+ # Loop forever, doing something useful hopefully:
+ while True:
+ monitor.manage_fans()
+ time.sleep(10)
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_fan.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_fan.py
new file mode 100755
index 0000000000..d1d93d4f8a
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_fan.py
@@ -0,0 +1,198 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2018 Accton Technology Corporation
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+# ------------------------------------------------------------------
+# HISTORY:
+# mm/dd/yyyy (A.D.)
+# 5/27/2019: Brandon_Chuang create
+# ------------------------------------------------------------------
+
+try:
+ import os
+ import sys, getopt
+ import subprocess
+ import click
+ import imp
+ import logging
+ import logging.config
+ import logging.handlers
+ import types
+ import time # this is only being used as part of the example
+ import traceback
+ from tabulate import tabulate
+
+except ImportError as e:
+ raise ImportError('%s - required module not found' % str(e))
+
+# Deafults
+VERSION = '1.0'
+FUNCTION_NAME = '/usr/local/bin/accton_as5835_54t_monitor_fan'
+
+global log_file
+global log_level
+
+
+class switch(object):
+ def __init__(self, value):
+ self.value = value
+ self.fall = False
+
+ def __iter__(self):
+ """Return the match method once, then stop"""
+ yield self.match
+ raise StopIteration
+
+ def match(self, *args):
+ """Indicate whether or not to enter a case suite"""
+ if self.fall or not args:
+ return True
+ elif self.value in args: # changed for v1.5, see below
+ self.fall = True
+ return True
+ else:
+ return False
+
+
+fan_state=[2, 2, 2, 2, 2, 2] #init state=2, insert=1, remove=0
+fan_status_state=[2, 2, 2, 2, 2, 2] #init state=2, fault=1, normal=0
+# Make a class we can use to capture stdout and sterr in the log
+class device_monitor(object):
+
+ #/sys/bus/i2c/devices/3-0063
+ #fan1_present, fan5_present
+
+ def __init__(self, log_file, log_level):
+
+ self.fan_num = 5
+ self.fan_path = "/sys/bus/i2c/devices/3-0063/"
+ self.present = {
+ 0: "fan1_present",
+ 1: "fan2_present",
+ 2: "fan3_present",
+ 3: "fan4_present",
+ 4: "fan5_present",
+ }
+
+ self.fault = {
+ 0: "fan1_fault",
+ 1: "fan2_fault",
+ 2: "fan3_fault",
+ 3: "fan4_fault",
+ 4: "fan5_fault",
+ }
+
+
+ """Needs a logger and a logger level."""
+ # set up logging to file
+ logging.basicConfig(
+ filename=log_file,
+ filemode='w',
+ level=log_level,
+ format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s',
+ datefmt='%H:%M:%S'
+ )
+
+ # set up logging to console
+ if log_level == logging.DEBUG:
+ console = logging.StreamHandler()
+ console.setLevel(logging.DEBUG)
+ formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
+ console.setFormatter(formatter)
+ logging.getLogger('').addHandler(console)
+
+ sys_handler = logging.handlers.SysLogHandler(address = '/dev/log')
+ #sys_handler.setLevel(logging.WARNING)
+ sys_handler.setLevel(logging.INFO)
+ logging.getLogger('').addHandler(sys_handler)
+
+
+ #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level)
+
+ def manage_fan(self):
+
+ FAN_STATE_REMOVE = 0
+ FAN_STATE_INSERT = 1
+
+ FAN_STATUS_FAULT = 1
+ FAN_STATUS_NORMAL = 0
+
+ global fan_state
+ global fan_status_state
+
+ for idx in range (0, self.fan_num):
+ node = self.fan_path + self.present[idx]
+ try:
+ val_file = open(node)
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+ content = val_file.readline().rstrip()
+ val_file.close()
+ # content is a string, either "0" or "1"
+ if content == "1":
+ if fan_state[idx]!=1:
+ fan_state[idx]=FAN_STATE_INSERT
+ logging.info("FAN-%d present is detected", idx+1);
+ else:
+ if fan_state[idx]!=0:
+ fan_state[idx]=FAN_STATE_REMOVE
+ logging.warning("Alarm for FAN-%d absent is detected", idx+1)
+
+ for idx in range (0, self.fan_num):
+ node = self.fan_path + self.fault[idx]
+ try:
+ val_file = open(node)
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+ content = val_file.readline().rstrip()
+ val_file.close()
+ # content is a string, either "0" or "1"
+ if content == "1":
+ if fan_status_state[idx]!=FAN_STATUS_FAULT:
+ if fan_state[idx] == FAN_STATE_INSERT:
+ logging.warning("Alarm for FAN-%d failed is detected", idx+1);
+ fan_status_state[idx]=FAN_STATUS_FAULT
+ else:
+ fan_status_state[idx]=FAN_STATUS_NORMAL
+
+ return True
+
+def main(argv):
+ log_file = '%s.log' % FUNCTION_NAME
+ log_level = logging.INFO
+ if len(sys.argv) != 1:
+ try:
+ opts, args = getopt.getopt(argv,'hdl:',['lfile='])
+ except getopt.GetoptError:
+ print 'Usage: %s [-d] [-l ]' % sys.argv[0]
+ return 0
+ for opt, arg in opts:
+ if opt == '-h':
+ print 'Usage: %s [-d] [-l ]' % sys.argv[0]
+ return 0
+ elif opt in ('-d', '--debug'):
+ log_level = logging.DEBUG
+ elif opt in ('-l', '--lfile'):
+ log_file = arg
+ monitor = device_monitor(log_file, log_level)
+ while True:
+ monitor.manage_fan()
+ time.sleep(3)
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_psu.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_psu.py
new file mode 100755
index 0000000000..51837c7262
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_monitor_psu.py
@@ -0,0 +1,190 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2018 Accton Technology Corporation
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+# ------------------------------------------------------------------
+# HISTORY:
+# mm/dd/yyyy (A.D.)
+# 7/2/2018: Jostar create for as7326-56x
+# ------------------------------------------------------------------
+
+try:
+ import os
+ import sys, getopt
+ import subprocess
+ import click
+ import imp
+ import logging
+ import logging.config
+ import logging.handlers
+ import types
+ import time # this is only being used as part of the example
+ import traceback
+ from tabulate import tabulate
+except ImportError as e:
+ raise ImportError('%s - required module not found' % str(e))
+
+# Deafults
+VERSION = '1.0'
+FUNCTION_NAME = '/usr/local/bin/accton_as5835_54t_monitor_psu'
+
+global log_file
+global log_level
+
+
+class switch(object):
+ def __init__(self, value):
+ self.value = value
+ self.fall = False
+
+ def __iter__(self):
+ """Return the match method once, then stop"""
+ yield self.match
+ raise StopIteration
+
+ def match(self, *args):
+ """Indicate whether or not to enter a case suite"""
+ if self.fall or not args:
+ return True
+ elif self.value in args: # changed for v1.5, see below
+ self.fall = True
+ return True
+ else:
+ return False
+
+
+psu_state=[2, 2]
+psu_power_status=[2, 2]
+# Make a class we can use to capture stdout and sterr in the log
+class device_monitor(object):
+
+ def __init__(self, log_file, log_level):
+
+ self.psu_num = 2
+ self.psu_path = "/sys/bus/i2c/devices/"
+ self.presence = "/psu_present"
+ self.oper_status = "/psu_power_good"
+ self.mapping = {
+ 0: "11-0050",
+ 1: "12-0053",
+ }
+
+ """Needs a logger and a logger level."""
+ # set up logging to file
+ logging.basicConfig(
+ filename=log_file,
+ filemode='w',
+ level=log_level,
+ format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s',
+ datefmt='%H:%M:%S'
+ )
+ # set up logging to console
+
+ if log_level == logging.DEBUG:
+ console = logging.StreamHandler()
+ console.setLevel(log_level)
+ formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
+ console.setFormatter(formatter)
+ logging.getLogger('').addHandler(console)
+
+ sys_handler = logging.handlers.SysLogHandler(address = '/dev/log')
+ #sys_handler.setLevel(logging.WARNING)
+ sys_handler.setLevel(logging.INFO)
+ logging.getLogger('').addHandler(sys_handler)
+
+ #logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level)
+
+ def manage_psu(self):
+
+ PSU_STATE_REMOVE = 0
+ PSU_STATE_INSERT = 1
+
+ PSU_STATUS_NO_POWER = 0
+ PSU_STATUS_POWER_GOOD = 1
+
+ global psu_state
+ global psu_power_status
+
+ for idx in range (0, self.psu_num):
+ node = self.psu_path + self.mapping[idx] + self.presence
+ try:
+ val_file = open(node)
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+ content = val_file.readline().rstrip()
+ val_file.close()
+ # content is a string, either "0" or "1"
+ if content == "1":
+ if psu_state[idx]!=PSU_STATE_INSERT:
+ psu_state[idx]=PSU_STATE_INSERT
+ logging.info("PSU-%d present is detected", idx+1);
+ #psu_power_status[idx]=PSU_STATUS_POWER_GOOD #when insert, assume power is good. If no_power, next code will find it.
+ else:
+ if psu_state[idx]!=PSU_STATE_REMOVE:
+ psu_state[idx]=PSU_STATE_REMOVE
+ logging.warning("Alarm for PSU-%d absent is detected", idx+1);
+ psu_power_status[idx]=PSU_STATUS_NO_POWER
+
+ for idx in range (0, self.psu_num):
+ node = self.psu_path + self.mapping[idx] + self.oper_status
+ try:
+ val_file = open(node)
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+ content = val_file.readline().rstrip()
+ val_file.close()
+ # content is a string, either "0" or "1"
+ #logging.info("content=%s, psu_power_status[%d]=%d", content, idx, psu_power_status[idx]);
+ if content == "0":
+ if psu_power_status[idx]!=PSU_STATUS_NO_POWER:
+ if psu_state[idx]==PSU_STATE_INSERT:
+ logging.warning("Alarm for PSU-%d fault is detected", idx+1);
+ psu_power_status[idx]=PSU_STATUS_NO_POWER
+ else:
+ if psu_power_status[idx] !=PSU_STATUS_POWER_GOOD:
+ logging.info("PSU-%d power_good is detected", idx+1);
+ psu_power_status[idx]=PSU_STATUS_POWER_GOOD
+
+
+ return True
+
+def main(argv):
+ log_file = '%s.log' % FUNCTION_NAME
+ log_level = logging.INFO
+ if len(sys.argv) != 1:
+ try:
+ opts, args = getopt.getopt(argv,'hdl:',['lfile='])
+ except getopt.GetoptError:
+ print 'Usage: %s [-d] [-l ]' % sys.argv[0]
+ return 0
+ for opt, arg in opts:
+ if opt == '-h':
+ print 'Usage: %s [-d] [-l ]' % sys.argv[0]
+ return 0
+ elif opt in ('-d', '--debug'):
+ log_level = logging.DEBUG
+ elif opt in ('-l', '--lfile'):
+ log_file = arg
+ monitor = device_monitor(log_file, log_level)
+ # Loop forever, doing something useful hopefully:
+ while True:
+ monitor.manage_psu()
+ time.sleep(3)
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_util.py b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_util.py
new file mode 100755
index 0000000000..a07ab1a1bc
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5835-54t/utils/accton_as5835_54t_util.py
@@ -0,0 +1,576 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2019 Accton Networks, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+"""
+Usage: %(scriptName)s [options] command object
+
+options:
+ -h | --help : this help message
+ -d | --debug : run with debug mode
+ -f | --force : ignore error during installation or clean
+command:
+ install : install drivers and generate related sysfs nodes
+ clean : uninstall drivers and remove related sysfs nodes
+ show : show all systen status
+ sff : dump SFP eeprom
+ set : change board setting with fan|led|sfp
+"""
+
+import os
+import commands
+import sys, getopt
+import logging
+import re
+import time
+from collections import namedtuple
+
+
+
+
+PROJECT_NAME = 'as5835_54t'
+version = '0.1.0'
+verbose = False
+DEBUG = False
+args = []
+ALL_DEVICE = {}
+DEVICE_NO = {'led':5, 'fan':5,'thermal':4, 'psu':2, 'sfp':6}
+FORCE = 0
+#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG)
+#logging.basicConfig(level=logging.INFO)
+
+
+if DEBUG == True:
+ print sys.argv[0]
+ print 'ARGV :', sys.argv[1:]
+
+
+def main():
+ global DEBUG
+ global args
+ global FORCE
+
+ if len(sys.argv)<2:
+ show_help()
+
+ options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help',
+ 'debug',
+ 'force',
+ ])
+ if DEBUG == True:
+ print options
+ print args
+ print len(sys.argv)
+
+ for opt, arg in options:
+ if opt in ('-h', '--help'):
+ show_help()
+ elif opt in ('-d', '--debug'):
+ DEBUG = True
+ logging.basicConfig(level=logging.INFO)
+ elif opt in ('-f', '--force'):
+ FORCE = 1
+ else:
+ logging.info('no option')
+ for arg in args:
+ if arg == 'install':
+ do_install()
+ elif arg == 'clean':
+ do_uninstall()
+ elif arg == 'show':
+ device_traversal()
+ elif arg == 'sff':
+ if len(args)!=2:
+ show_eeprom_help()
+ elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']:
+ show_eeprom_help()
+ else:
+ show_eeprom(args[1])
+ return
+ elif arg == 'set':
+ if len(args)<3:
+ show_set_help()
+ else:
+ set_device(args[1:])
+ return
+ else:
+ show_help()
+
+
+ return 0
+
+def show_help():
+ print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]}
+ sys.exit(0)
+
+def show_set_help():
+ cmd = sys.argv[0].split("/")[-1]+ " " + args[0]
+ print cmd +" [led|sfp|fan]"
+ print " use \""+ cmd + " led 0-4 \" to set led color"
+ print " use \""+ cmd + " fan 0-100\" to set fan duty percetage"
+ print " use \""+ cmd + " sfp 49-54 {0|1}\" to set sfp# tx_disable"
+ sys.exit(0)
+
+def show_eeprom_help():
+ cmd = sys.argv[0].split("/")[-1]+ " " + args[0]
+ print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom"
+ sys.exit(0)
+
+def my_log(txt):
+ if DEBUG == True:
+ print "[Debug]"+txt
+ return
+
+def log_os_system(cmd, show):
+ logging.info('Run :'+cmd)
+ status, output = commands.getstatusoutput(cmd)
+ my_log (cmd +"with result:" + str(status))
+ my_log (" output:"+output)
+ if status:
+ logging.info('Failed :'+cmd)
+ if show:
+ print('Failed :'+cmd)
+ return status, output
+
+def driver_check():
+ ret, lsmod = log_os_system("lsmod| grep accton", 0)
+ logging.info('mods:'+lsmod)
+ if len(lsmod) ==0:
+ return False
+ return True
+
+
+
+kos = [
+'modprobe i2c_dev',
+'modprobe i2c_mux_pca954x force_deselect_on_exit=1',
+'modprobe accton_as5835_54t_cpld' ,
+'modprobe ym2651y' ,
+'modprobe accton_as5835_54t_fan' ,
+'modprobe optoe' ,
+'modprobe accton_as5835_54t_leds' ,
+'modprobe accton_as5835_54t_psu' ]
+
+def driver_install():
+ global FORCE
+ status, output = log_os_system("depmod", 1)
+ for i in range(0,len(kos)):
+ status, output = log_os_system(kos[i], 1)
+ if status:
+ if FORCE == 0:
+ return status
+ return 0
+
+def driver_uninstall():
+ global FORCE
+ for i in range(0,len(kos)):
+ rm = kos[-(i+1)].replace("modprobe", "modprobe -rq")
+ rm = rm.replace("insmod", "rmmod")
+ lst = rm.split(" ")
+ if len(lst) > 3:
+ del(lst[3])
+ rm = " ".join(lst)
+ status, output = log_os_system(rm, 1)
+ if status:
+ if FORCE == 0:
+ return status
+ return 0
+
+led_prefix ='/sys/class/leds/accton_'+PROJECT_NAME+'_led::'
+hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']}
+hwmon_nodes = {'led': ['brightness'] }
+hwmon_prefix ={'led': led_prefix}
+
+i2c_prefix = '/sys/bus/i2c/devices/'
+i2c_bus = {'fan': ['3-0063'] ,
+ 'thermal': ['18-004b','19-004c', '20-0049', '21-004a'] ,
+ 'psu': ['11-0050','12-0053'],
+ 'sfp': ['-0050']}
+i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] ,
+ 'thermal': ['hwmon/hwmon*/temp1_input'] ,
+ 'psu': ['psu_present ', 'psu_power_good'] ,
+ 'sfp': ['module_present_', 'module_tx_disable_']}
+
+sfp_map = [28,29,26,30,31,27]
+
+qsfp_start = 48
+
+mknod =[
+'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-1/new_device',
+'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device' ,
+'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device' ,
+'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device' ,
+'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device',
+
+'echo as5835_54t_fan 0x63 > /sys/bus/i2c/devices/i2c-3/new_device',
+'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-18/new_device',
+'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-19/new_device',
+'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-20/new_device',
+'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-21/new_device',
+'echo as5835_54t_psu1 0x50 > /sys/bus/i2c/devices/i2c-11/new_device',
+'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-11/new_device',
+'echo as5835_54t_psu2 0x53 > /sys/bus/i2c/devices/i2c-12/new_device',
+'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-12/new_device',
+'echo as5835_54t_cpld1 0x60 > /sys/bus/i2c/devices/i2c-3/new_device',
+'echo as5835_54t_cpld2 0x61 > /sys/bus/i2c/devices/i2c-3/new_device',
+'echo as5835_54t_cpld3 0x62 > /sys/bus/i2c/devices/i2c-3/new_device']
+
+mknod2 =[
+'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device',
+'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device' ,
+'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device' ,
+'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device' ,
+'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device',
+
+'echo as5835_54t_fan 0x63 > /sys/bus/i2c/devices/i2c-3/new_device',
+'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-18/new_device',
+'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-19/new_device',
+'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-20/new_device',
+'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-21/new_device',
+'echo as5835_54t_psu1 0x50 > /sys/bus/i2c/devices/i2c-11/new_device',
+'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-11/new_device',
+'echo as5835_54t_psu2 0x53 > /sys/bus/i2c/devices/i2c-12/new_device',
+'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-12/new_device',
+'echo as5835_54t_cpld1 0x60 > /sys/bus/i2c/devices/i2c-3/new_device',
+'echo as5835_54t_cpld2 0x61 > /sys/bus/i2c/devices/i2c-3/new_device',
+'echo as5835_54t_cpld3 0x62 > /sys/bus/i2c/devices/i2c-3/new_device']
+
+
+def i2c_order_check():
+ # i2c bus 0 and 1 might be installed in different order.
+ # Here check if 0x77 is exist @ i2c-1
+ tmp = "echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-1/new_device"
+ status, output = log_os_system(tmp, 0)
+ if not device_exist():
+ order = 1
+ else:
+ order = 0
+ tmp = "echo 0x77 > /sys/bus/i2c/devices/i2c-1/delete_device"
+ status, output = log_os_system(tmp, 0)
+ return order
+
+def device_install():
+ global FORCE
+
+ order = i2c_order_check()
+
+ # if 0x77 is not exist @i2c-1, use reversed bus order
+ if order:
+ for i in range(0,len(mknod2)):
+ #for pca954x need times to built new i2c buses
+ if mknod2[i].find('pca954') != -1:
+ time.sleep(1)
+
+ status, output = log_os_system(mknod2[i], 1)
+ time.sleep(0.01)
+ if status:
+ print output
+ if FORCE == 0:
+ return status
+ else:
+ for i in range(0,len(mknod)):
+ #for pca954x need times to built new i2c buses
+ if mknod[i].find('pca954') != -1:
+ time.sleep(1)
+
+ status, output = log_os_system(mknod[i], 1)
+ if status:
+ print output
+ if FORCE == 0:
+ return status
+ for i in range(0,len(sfp_map)):
+ status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1)
+ if status:
+ print output
+ if FORCE == 0:
+ return status
+ path = "/sys/bus/i2c/devices/{0}-0050/port_name"
+ status, output =log_os_system("echo port{0} > ".format(i+49)+path.format(sfp_map[i]), 1)
+ if status:
+ print output
+ if FORCE == 0:
+ return status
+ return
+
+def device_uninstall():
+ global FORCE
+
+ status, output =log_os_system("ls /sys/bus/i2c/devices/0-0077", 0)
+ if status==0:
+ I2C_ORDER=1
+ else:
+ I2C_ORDER=0
+
+ for i in range(0,len(sfp_map)):
+ target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device"
+ status, output =log_os_system("echo 0x50 > "+ target, 1)
+ if status:
+ print output
+ if FORCE == 0:
+ return status
+
+ if I2C_ORDER==0:
+ nodelist = mknod
+ else:
+ nodelist = mknod2
+
+ for i in range(len(nodelist)):
+ target = nodelist[-(i+1)]
+ temp = target.split()
+ del temp[1]
+ temp[-1] = temp[-1].replace('new_device', 'delete_device')
+ status, output = log_os_system(" ".join(temp), 1)
+ if status:
+ print output
+ if FORCE == 0:
+ return status
+
+ return
+
+def system_ready():
+ if driver_check() == False:
+ return False
+ if not device_exist():
+ return False
+ return True
+
+def do_install():
+ print "Checking system...."
+ if driver_check() == False:
+ print "No driver, installing...."
+ status = driver_install()
+ if status:
+ if FORCE == 0:
+ return status
+ else:
+ print PROJECT_NAME.upper()+" drivers detected...."
+ if not device_exist():
+ print "No device, installing...."
+ status = device_install()
+ if status:
+ if FORCE == 0:
+ return status
+ else:
+ print PROJECT_NAME.upper()+" devices detected...."
+ return
+
+def do_uninstall():
+ print "Checking system...."
+ if not device_exist():
+ print PROJECT_NAME.upper() +" has no device installed...."
+ else:
+ print "Removing device...."
+ status = device_uninstall()
+ if status:
+ if FORCE == 0:
+ return status
+
+ if driver_check()== False :
+ print PROJECT_NAME.upper() +" has no driver installed...."
+ else:
+ print "Removing installed driver...."
+ status = driver_uninstall()
+ if status:
+ if FORCE == 0:
+ return status
+
+ return
+
+def devices_info():
+ global DEVICE_NO
+ global ALL_DEVICE
+ global i2c_bus, hwmon_types
+ for key in DEVICE_NO:
+ ALL_DEVICE[key]= {}
+ for i in range(0,DEVICE_NO[key]):
+ ALL_DEVICE[key][key+str(i+1)] = []
+
+ for key in i2c_bus:
+ buses = i2c_bus[key]
+ nodes = i2c_nodes[key]
+ for i in range(0,len(buses)):
+ for j in range(0,len(nodes)):
+ if 'fan' == key:
+ for k in range(0,DEVICE_NO[key]):
+ node = key+str(k+1)
+ path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j]
+ my_log(node+": "+ path)
+ ALL_DEVICE[key][node].append(path)
+ elif 'sfp' == key:
+ for k in range(0,DEVICE_NO[key]):
+ node = key+str(k+1)
+ path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j]
+ my_log(node+": "+ path)
+ ALL_DEVICE[key][node].append(path)
+ else:
+ node = key+str(i+1)
+ path = i2c_prefix+ buses[i]+"/"+ nodes[j]
+ my_log(node+": "+ path)
+ ALL_DEVICE[key][node].append(path)
+
+ for key in hwmon_types:
+ itypes = hwmon_types[key]
+ nodes = hwmon_nodes[key]
+ for i in range(0,len(itypes)):
+ for j in range(0,len(nodes)):
+ node = key+"_"+itypes[i]
+ path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j]
+ my_log(node+": "+ path)
+ ALL_DEVICE[key][ key+str(i+1)].append(path)
+
+ #show dict all in the order
+ if DEBUG == True:
+ for i in sorted(ALL_DEVICE.keys()):
+ print(i+": ")
+ for j in sorted(ALL_DEVICE[i].keys()):
+ print(" "+j)
+ for k in (ALL_DEVICE[i][j]):
+ print(" "+" "+k)
+ return
+
+def show_eeprom(index):
+ if system_ready()==False:
+ print("System's not ready.")
+ print("Please install first!")
+ return
+
+ if len(ALL_DEVICE)==0:
+ devices_info()
+ node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0]
+ node = node.replace(node.split("/")[-1], 'sfp_eeprom')
+ # check if got hexdump command in current environment
+ ret, log = log_os_system("which hexdump", 0)
+ ret, log2 = log_os_system("which busybox hexdump", 0)
+ if len(log):
+ hex_cmd = 'hexdump'
+ elif len(log2):
+ hex_cmd = ' busybox hexdump'
+ else:
+ log = 'Failed : no hexdump cmd!!'
+ logging.info(log)
+ print log
+ return 1
+
+ print node + ":"
+ ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1)
+ if ret==0:
+ print log
+ else:
+ print "**********device no found**********"
+ return
+
+def set_device(args):
+ global DEVICE_NO
+ global ALL_DEVICE
+ if system_ready()==False:
+ print("System's not ready.")
+ print("Please install first!")
+ return
+
+ if len(ALL_DEVICE)==0:
+ devices_info()
+
+ if args[0]=='led':
+ if int(args[1])>4:
+ show_set_help()
+ return
+ #print ALL_DEVICE['led']
+ for i in range(0,len(ALL_DEVICE['led'])):
+ for k in (ALL_DEVICE['led']['led'+str(i+1)]):
+ ret, log = log_os_system("echo "+args[1]+" >"+k, 1)
+ if ret:
+ return ret
+ elif args[0]=='fan':
+ if int(args[1])>100:
+ show_set_help()
+ return
+ #print ALL_DEVICE['fan']
+ #fan1~5 is all fine, all fan share same setting
+ node = ALL_DEVICE['fan'] ['fan1'][0]
+ node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage')
+ ret, log = log_os_system("cat "+ node, 1)
+ if ret==0:
+ print ("Previous fan duty: " + log.strip() +"%")
+ ret, log = log_os_system("echo "+args[1]+" >"+node, 1)
+ if ret==0:
+ print ("Current fan duty: " + args[1] +"%")
+ return ret
+ elif args[0]=='sfp':
+ if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0:
+ show_set_help()
+ return
+ if len(args)<2:
+ show_set_help()
+ return
+
+ if int(args[2])>1:
+ show_set_help()
+ return
+
+ #print ALL_DEVICE[args[0]]
+ for i in range(0,len(ALL_DEVICE[args[0]])):
+ for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]:
+ if j.find('tx_disable')!= -1:
+ ret, log = log_os_system("echo "+args[2]+" >"+ j, 1)
+ if ret:
+ return ret
+
+ return
+
+#get digits inside a string.
+#Ex: 31 for "sfp31"
+def get_value(input):
+ digit = re.findall('\d+', input)
+ return int(digit[0])
+
+def device_traversal():
+ if system_ready()==False:
+ print("System's not ready.")
+ print("Please install first!")
+ return
+
+ if len(ALL_DEVICE)==0:
+ devices_info()
+ for i in sorted(ALL_DEVICE.keys()):
+ print("============================================")
+ print(i.upper()+": ")
+ print("============================================")
+
+ for j in sorted(ALL_DEVICE[i].keys(), key=get_value):
+ print " "+j+":",
+ for k in (ALL_DEVICE[i][j]):
+ ret, log = log_os_system("cat "+k, 0)
+ func = k.split("/")[-1].strip()
+ func = re.sub(j+'_','',func,1)
+ func = re.sub(i.lower()+'_','',func,1)
+ if ret==0:
+ print func+"="+log+" ",
+ else:
+ print func+"="+"X"+" ",
+ print
+ print("----------------------------------------------------------------")
+
+
+ print
+ return
+
+def device_exist():
+ ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0)
+ ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0)
+ return not(ret1 or ret2)
+
+if __name__ == "__main__":
+ main()
diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/control b/platform/broadcom/sonic-platform-modules-accton/debian/control
index b22828af67..8100f6b76e 100755
--- a/platform/broadcom/sonic-platform-modules-accton/debian/control
+++ b/platform/broadcom/sonic-platform-modules-accton/debian/control
@@ -1,7 +1,7 @@
Source: sonic-accton-platform-modules
Section: main
Priority: extra
-Maintainer: Accton network , Accton Network , Accton Network
+Maintainer: Accton network , Accton Network , Accton Network , Accton Network
Build-Depends: debhelper (>= 9), bzip2
Standards-Version: 3.9.3
@@ -61,3 +61,6 @@ Package: sonic-platform-accton-as9716-32d
Architecture: amd64
Description: kernel modules for platform devices such as fan, led, sfp
+Package: sonic-platform-accton-as5835-54t
+Architecture: amd64
+Description: kernel modules for platform devices such as fan, led, sfp
diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/rules b/platform/broadcom/sonic-platform-modules-accton/debian/rules
index e570be68be..ba2f3e394d 100755
--- a/platform/broadcom/sonic-platform-modules-accton/debian/rules
+++ b/platform/broadcom/sonic-platform-modules-accton/debian/rules
@@ -19,7 +19,7 @@ PACKAGE_PRE_NAME := sonic-platform-accton
KVERSION ?= $(shell uname -r)
KERNEL_SRC := /lib/modules/$(KVERSION)
MOD_SRC_DIR:= $(shell pwd)
-MODULE_DIRS:= as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x as7326-56x as6712-32x as7726-32x as4630-54pe minipack as5812-54x as5835-54x as9716-32d
+MODULE_DIRS:= as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x as7326-56x as6712-32x as7726-32x as4630-54pe minipack as5812-54x as5835-54x as9716-32d as5835-54t
MODULE_DIR := modules
UTILS_DIR := utils
SERVICE_DIR := service