diff --git a/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/port_config.ini b/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/port_config.ini
new file mode 100755
index 0000000000..ee60c52622
--- /dev/null
+++ b/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/port_config.ini
@@ -0,0 +1,73 @@
+# name lanes alias index speed
+Ethernet0 13 tenGigE0 1 10000
+Ethernet1 14 tenGigE1 2 10000
+Ethernet2 15 tenGigE2 3 10000
+Ethernet3 16 tenGigE3 4 10000
+Ethernet4 21 tenGigE4 5 10000
+Ethernet5 22 tenGigE5 6 10000
+Ethernet6 23 tenGigE6 7 10000
+Ethernet7 24 tenGigE7 8 10000
+Ethernet8 25 tenGigE8 9 10000
+Ethernet9 26 tenGigE9 10 10000
+Ethernet10 27 tenGigE10 11 10000
+Ethernet11 28 tenGigE11 12 10000
+Ethernet12 29 tenGigE12 13 10000
+Ethernet13 30 tenGigE13 14 10000
+Ethernet14 31 tenGigE14 15 10000
+Ethernet15 32 tenGigE15 16 10000
+Ethernet16 45 tenGigE16 17 10000
+Ethernet17 46 tenGigE17 18 10000
+Ethernet18 47 tenGigE18 19 10000
+Ethernet19 48 tenGigE19 20 10000
+Ethernet20 49 tenGigE20 21 10000
+Ethernet21 50 tenGigE21 22 10000
+Ethernet22 51 tenGigE22 23 10000
+Ethernet23 52 tenGigE23 24 10000
+Ethernet24 53 tenGigE24 25 10000
+Ethernet25 54 tenGigE25 26 10000
+Ethernet26 55 tenGigE26 27 10000
+Ethernet27 56 tenGigE27 28 10000
+Ethernet28 57 tenGigE28 29 10000
+Ethernet29 58 tenGigE29 30 10000
+Ethernet30 59 tenGigE30 31 10000
+Ethernet31 60 tenGigE31 32 10000
+Ethernet32 61 tenGigE32 33 10000
+Ethernet33 62 tenGigE33 34 10000
+Ethernet34 63 tenGigE34 35 10000
+Ethernet35 64 tenGigE35 36 10000
+Ethernet36 65 tenGigE36 37 10000
+Ethernet37 66 tenGigE37 38 10000
+Ethernet38 67 tenGigE38 39 10000
+Ethernet39 68 tenGigE39 40 10000
+Ethernet40 69 tenGigE40 41 10000
+Ethernet41 70 tenGigE41 42 10000
+Ethernet42 71 tenGigE42 43 10000
+Ethernet43 72 tenGigE43 44 10000
+Ethernet44 73 tenGigE44 45 10000
+Ethernet45 74 tenGigE45 46 10000
+Ethernet46 75 tenGigE46 47 10000
+Ethernet47 76 tenGigE47 48 10000
+Ethernet48 97 tenGigE48 49 10000
+Ethernet49 98 tenGigE49 49 10000
+Ethernet50 99 tenGigE50 49 10000
+Ethernet51 100 tenGigE51 49 10000
+Ethernet52 101 tenGigE52 50 10000
+Ethernet53 102 tenGigE53 50 10000
+Ethernet54 103 tenGigE54 50 10000
+Ethernet55 104 tenGigE55 50 10000
+Ethernet56 81 tenGigE56 51 10000
+Ethernet57 82 tenGigE57 51 10000
+Ethernet58 83 tenGigE58 51 10000
+Ethernet59 84 tenGigE59 51 10000
+Ethernet60 105 tenGigE60 52 10000
+Ethernet61 106 tenGigE61 52 10000
+Ethernet62 107 tenGigE62 52 10000
+Ethernet63 108 tenGigE63 52 10000
+Ethernet64 109 tenGigE64 53 10000
+Ethernet65 110 tenGigE65 53 10000
+Ethernet66 111 tenGigE66 53 10000
+Ethernet67 112 tenGigE67 53 10000
+Ethernet68 77 tenGigE68 54 10000
+Ethernet69 78 tenGigE69 54 10000
+Ethernet70 79 tenGigE70 54 10000
+Ethernet71 80 tenGigE71 54 10000
diff --git a/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/sai.profile b/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/sai.profile
new file mode 100755
index 0000000000..063814c1fc
--- /dev/null
+++ b/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/sai.profile
@@ -0,0 +1 @@
+SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td2-as5812-72x10G.config.bcm
diff --git a/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/td2-as5812-72x10G.config.bcm b/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/td2-as5812-72x10G.config.bcm
new file mode 100644
index 0000000000..4844616d03
--- /dev/null
+++ b/device/accton/x86_64-accton_as5812_54t-r0/Accton-AS5812-54T/td2-as5812-72x10G.config.bcm
@@ -0,0 +1,148 @@
+os=unix
+bcm_stat_flags=0
+parity_enable=0
+parity_correction=0
+
+bcm_num_cos=8
+l2_mem_entries=32768
+l3_mem_entries=16384
+l3_alpm_enable=2
+ipv6_lpm_128b_enable=1
+
+mmu_lossless=0
+lls_num_l2uc=12
+module_64ports=0
+
+#SFI
+serdes_if_type=9
+
+port_init_cl72=0
+phy_an_c73=5 # TSCMOD_CL73_CL37
+
+#sdk6.5.5 only supports 156(default) or 125
+#xgxs_lcpll_xtal_refclk=1
+tslam_dma_enable=1
+table_dma_enable=1
+
+#for 72 ports with 48 10G ports and 6 40G ports for breakout mode
+pbmp_oversubscribe=0x1fffffffffffffffffe
+pbmp_xport_xe=0x1fffffffffffffffffe
+
+rate_ext_mdio_divisor=96
+
+#SFP+ 1-4 from WC3
+portmap_1=13:10
+portmap_2=14:10
+portmap_3=15:10
+portmap_4=16:10
+
+#SFP+ 5-8 from WC5
+portmap_5=21:10
+portmap_6=22:10
+portmap_7=23:10
+portmap_8=24:10
+
+#SFP+ 9-12 from WC6
+portmap_9=25:10
+portmap_10=26:10
+portmap_11=27:10
+portmap_12=28:10
+
+#SFP+ 13-16 from WC7
+portmap_13=29:10
+portmap_14=30:10
+portmap_15=31:10
+portmap_16=32:10
+
+#SFP+ 17-20 from WC11
+portmap_17=45:10
+portmap_18=46:10
+portmap_19=47:10
+portmap_20=48:10
+
+#SFP+ 21-24 from WC12
+portmap_21=49:10
+portmap_22=50:10
+portmap_23=51:10
+portmap_24=52:10
+
+#SFP+ 25-28 from WC13
+portmap_25=53:10
+portmap_26=54:10
+portmap_27=55:10
+portmap_28=56:10
+
+#SFP+ 29-32 from WC14
+portmap_29=57:10
+portmap_30=58:10
+portmap_31=59:10
+portmap_32=60:10
+
+#SFP+ 33-36 from WC15
+portmap_33=61:10
+portmap_34=62:10
+portmap_35=63:10
+portmap_36=64:10
+
+#SFP+ 37-40 from WC16
+portmap_37=65:10
+portmap_38=66:10
+portmap_39=67:10
+portmap_40=68:10
+
+#SFP+ 41-44 from WC17
+portmap_41=69:10
+portmap_42=70:10
+portmap_43=71:10
+portmap_44=72:10
+
+#SFP+ 45-48 from WC18
+portmap_45=73:10
+portmap_46=74:10
+portmap_47=75:10
+portmap_48=76:10
+
+# QSFP+ 49/WC24/port 49
+portmap_49=97:10
+portmap_50=98:10
+portmap_51=99:10
+portmap_52=100:10
+
+# QSFP+ 51/WC25/port 50
+portmap_53=101:10
+portmap_54=102:10
+portmap_55=103:10
+portmap_56=104:10
+
+# QSFP+ 53/WC20/port 51
+portmap_57=81:10
+portmap_58=82:10
+portmap_59=83:10
+portmap_60=84:10
+
+# QSFP+ 50/WC26/port 52
+portmap_61=105:10
+portmap_62=106:10
+portmap_63=107:10
+portmap_64=108:10
+
+# QSFP+ 52/WC27/port 53
+portmap_65=109:10
+portmap_66=110:10
+portmap_67=111:10
+portmap_68=112:10
+
+# QSFP+ 54/WC19/port 54
+portmap_69=77:10
+portmap_70=78:10
+portmap_71=79:10
+portmap_72=80:10
+
+# L3 ECMP
+# - In Trident2, VP LAGs share the same table as ECMP group table.
+# The first N entries are reserved for VP LAGs, where N is the value of the
+# config property "max_vp_lags". By default this was set to 256
+l3_max_ecmp_mode=1
+max_vp_lags=0
+
+stable_size=0x2000000
diff --git a/device/accton/x86_64-accton_as5812_54t-r0/default_sku b/device/accton/x86_64-accton_as5812_54t-r0/default_sku
new file mode 100644
index 0000000000..87b99bac77
--- /dev/null
+++ b/device/accton/x86_64-accton_as5812_54t-r0/default_sku
@@ -0,0 +1 @@
+Accton-AS5812-54T t1
diff --git a/device/accton/x86_64-accton_as5812_54t-r0/installer.conf b/device/accton/x86_64-accton_as5812_54t-r0/installer.conf
new file mode 100644
index 0000000000..14404194ef
--- /dev/null
+++ b/device/accton/x86_64-accton_as5812_54t-r0/installer.conf
@@ -0,0 +1,3 @@
+CONSOLE_PORT=0x2f8
+CONSOLE_DEV=1
+CONSOLE_SPEED=115200
diff --git a/device/accton/x86_64-accton_as5812_54t-r0/led_proc_init.soc b/device/accton/x86_64-accton_as5812_54t-r0/led_proc_init.soc
new file mode 100644
index 0000000000..d93e373d05
--- /dev/null
+++ b/device/accton/x86_64-accton_as5812_54t-r0/led_proc_init.soc
@@ -0,0 +1,162 @@
+# LED setting for active
+# -----------------------------------------------------------------------------
+# for as5812_54x (48xg+6qxg)
+#
+# on green - if link up
+# off - if link down
+# blink - if active
+# -----------------------------------------------------------------------------
+m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0
+m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=1
+m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=2
+m CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3
+m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=4
+m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=5
+m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=6
+m CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7
+m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=8
+m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=9
+m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=10
+m CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11
+m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=12
+m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=13
+m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=14
+m CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15
+m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=16
+m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=17
+m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=18
+m CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19
+m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=20
+m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=21
+m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=22
+m CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23
+m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=24
+m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=25
+m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=26
+m CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27
+m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=28
+m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=29
+m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=30
+m CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31
+m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=32
+m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=33
+m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=34
+m CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=35
+m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=36
+m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=37
+m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=38
+m CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=39
+m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=40
+m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=41
+m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=42
+m CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=43
+m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=44
+m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=45
+m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=46
+m CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47
+m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=48
+m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=49
+m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=50
+m CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=51
+m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=52
+m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=53
+m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=54
+m CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=55
+m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=56
+m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=57
+m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=58
+m CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=59
+m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=60
+m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=61
+m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=62
+m CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63
+m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_63=0
+m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_62=1
+m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_61=2
+m CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 REMAP_PORT_60=3
+m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_59=4
+m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_58=5
+m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_57=6
+m CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 REMAP_PORT_56=7
+m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_55=8
+m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_54=9
+m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_53=10
+m CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 REMAP_PORT_52=11
+m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_51=12
+m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_50=13
+m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_49=14
+m CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 REMAP_PORT_48=15
+m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_35=16
+m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_34=17
+m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_33=18
+m CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 REMAP_PORT_32=19
+m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_39=20
+m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_38=21
+m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_37=22
+m CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 REMAP_PORT_36=23
+m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_43=24
+m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_42=25
+m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_41=26
+m CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 REMAP_PORT_40=27
+m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_47=28
+m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_46=29
+m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_45=30
+m CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 REMAP_PORT_44=31
+m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_31=32
+m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_30=33
+m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_29=34
+m CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 REMAP_PORT_28=35
+m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_27=36
+m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_26=37
+m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_25=38
+m CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 REMAP_PORT_24=39
+m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_23=40
+m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_22=41
+m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_21=42
+m CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 REMAP_PORT_20=43
+m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_19=44
+m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_18=45
+m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_17=46
+m CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 REMAP_PORT_16=47
+m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_3=48
+m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_2=49
+m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_1=50
+m CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 REMAP_PORT_0=51
+m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_7=52
+m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_6=53
+m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_5=54
+m CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 REMAP_PORT_4=55
+m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_11=56
+m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_10=57
+m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_9=58
+m CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 REMAP_PORT_8=59
+m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_15=60
+m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_14=61
+m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_13=62
+m CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 REMAP_PORT_12=63
+
+led 0 stop
+led 0 prog \
+ 06 FE 80 D2 19 71 08 E0 60 FE E9 D2 0F 75 10 81 \
+ 61 FD 02 3F 60 FF 28 32 0F 87 67 4A 96 FF 06 FF \
+ D2 2B 74 16 02 1F 60 FF 28 32 0F 87 67 4A 96 FF \
+ 06 FF D2 13 74 28 02 0F 60 FF 28 32 0F 87 67 4A \
+ 96 FF 06 FF D2 0B 74 3A 3A 48 32 07 32 08 C7 32 \
+ 04 C7 97 71 57 77 69 32 00 32 01 B7 97 71 63 32 \
+ 0E 77 6B 26 FD 97 27 77 6B 32 0F 87 57 00 00 00
+led 0 start
+
+led 1 stop
+led 1 prog \
+ 06 FE 80 D2 19 71 08 E0 60 FE E9 D2 0F 75 10 81 \
+ 61 FD 02 20 67 89 02 24 67 89 02 10 67 89 02 28 \
+ 67 89 02 2C 67 89 02 0C 67 89 02 2C 67 79 02 28 \
+ 67 79 02 24 67 79 02 20 67 79 02 10 67 79 02 0C \
+ 67 79 02 0B 60 FF 28 32 0F 87 67 56 96 FF 06 FF \
+ D2 FF 74 46 3A 36 32 07 32 08 C7 32 04 C7 97 71 \
+ 63 77 75 32 00 32 01 B7 97 71 6F 32 0E 77 77 26 \
+ FD 97 27 77 77 32 0F 87 57 12 A0 F8 15 1A 01 75 \
+ 85 28 67 56 57 32 0F 87 57 12 A0 F8 15 1A 01 71 \
+ A1 28 67 56 80 28 67 56 80 28 67 56 80 28 67 56 \
+ 57 32 0F 87 32 0F 87 32 0F 87 32 0F 87 57 00 00
+led 1 start
diff --git a/device/accton/x86_64-accton_as5812_54t-r0/plugins/eeprom.py b/device/accton/x86_64-accton_as5812_54t-r0/plugins/eeprom.py
new file mode 100644
index 0000000000..7681caafee
--- /dev/null
+++ b/device/accton/x86_64-accton_as5812_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_as5812_54t-r0/plugins/psuutil.py b/device/accton/x86_64-accton_as5812_54t-r0/plugins/psuutil.py
new file mode 100755
index 0000000000..cfcd62e582
--- /dev/null
+++ b/device/accton/x86_64-accton_as5812_54t-r0/plugins/psuutil.py
@@ -0,0 +1,65 @@
+#!/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-0038", "11-0050"],
+ 2: ["12-003b", "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
+ lst = self.psu_mapping[index]
+ for i in lst:
+ node = self.psu_path + i + self.psu_oper_status
+ try:
+ with open(node, 'r') as power_status:
+ status += int(power_status.read())
+ except IOError:
+ return False
+
+ return status > 0
+
+ def get_psu_presence(self, index):
+ if index is None:
+ return False
+
+ status = 0
+ lst = self.psu_mapping[index]
+ for i in lst:
+ node = self.psu_path + i + self.psu_presence
+ try:
+ with open(node, 'r') as presence_status:
+ status += int(presence_status.read())
+ except IOError:
+ return False
+
+ return status > 0
diff --git a/device/accton/x86_64-accton_as5812_54t-r0/plugins/sfputil.py b/device/accton/x86_64-accton_as5812_54t-r0/plugins/sfputil.py
new file mode 100755
index 0000000000..c9f3008dcc
--- /dev/null
+++ b/device/accton/x86_64-accton_as5812_54t-r0/plugins/sfputil.py
@@ -0,0 +1,290 @@
+# sfputil.py
+#
+# Platform-specific SFP transceiver interface for SONiC
+#
+try:
+ import time
+ import os
+ import pickle
+ 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))
+
+#from xcvrd
+SFP_STATUS_INSERTED = '1'
+SFP_STATUS_REMOVED = '0'
+
+
+class SfpUtil(SfpUtilBase):
+ """Platform-specific SfpUtil class"""
+
+ PORT_START = 49
+ PORT_END = 54
+ PORTS_IN_BLOCK = 54
+ QSFP_PORT_START = 49
+ QSFP_PORT_END = 54
+
+ BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/"
+ BASE_OOM_PATH = "/sys/bus/i2c/devices/{0}-0050/"
+ BASE_CPLD_PATH = "/sys/bus/i2c/devices/{0}-0060/"
+ I2C_BUS_ORDER = -1
+
+ #The sidebands of QSFP is different.
+ #present is in-order.
+ #But lp_mode and reset are not.
+ qsfp_sb_map = [0, 2, 4, 1, 3, 5]
+
+ _port_to_is_present = {}
+ _port_to_lp_mode = {}
+
+ _port_to_eeprom_mapping = {}
+ _port_to_i2c_mapping = {
+ 49: [1,4],#QSFP_start
+ 50: [2,6],
+ 51: [3,3],
+ 52: [4,5],
+ 53: [5,7],
+ 54: [6,2],
+ }
+
+ @property
+ def port_start(self):
+ return self.PORT_START
+
+ @property
+ def port_end(self):
+ return self.PORT_END
+
+ @property
+ def qsfp_port_start(self):
+ return self.QSFP_PORT_START
+
+ @property
+ def qsfp_port_end(self):
+ return self.QSFP_PORT_END
+
+ @property
+ def qsfp_ports(self):
+ return range(self.QSFP_PORT_START, self.PORTS_IN_BLOCK + 1)
+
+ @property
+ def port_to_eeprom_mapping(self):
+ return self._port_to_eeprom_mapping
+
+ def __init__(self):
+ eeprom_path = self.BASE_OOM_PATH + "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][1]
+ )
+ SfpUtilBase.__init__(self)
+
+ #Two i2c buses might get flipped order, check them both.
+ def update_i2c_order(self):
+ if os.path.exists("/tmp/accton_util.p"):
+ self.I2C_BUS_ORDER = pickle.load(open("/tmp/accton_util.p", "rb"))
+ else:
+ if self.I2C_BUS_ORDER < 0:
+ eeprom_path = "/sys/bus/i2c/devices/1-0057/eeprom"
+ if os.path.exists(eeprom_path):
+ self.I2C_BUS_ORDER = 0
+ eeprom_path = "/sys/bus/i2c/devices/0-0057/eeprom"
+ if os.path.exists(eeprom_path):
+ self.I2C_BUS_ORDER = 1
+ return self.I2C_BUS_ORDER
+
+ 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
+
+ order = self.update_i2c_order()
+ present_path = self.BASE_CPLD_PATH.format(order)
+ present_path = present_path + "module_present_" + str(port_num)
+ self.__port_to_is_present = present_path
+
+ try:
+ val_file = open(self.__port_to_is_present)
+ 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
+
+ order = self.update_i2c_order()
+ lp_mode_path = self.BASE_CPLD_PATH.format(order)
+ lp_mode_path = lp_mode_path + "module_lp_mode_"
+ lp_mode_path = lp_mode_path + str(port_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 self.get_low_power_mode_cpld(port_num)
+
+ try:
+ eeprom = None
+ eeprom = open(self.port_to_eeprom_mapping[port_num], "rb")
+ 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 err:
+ print "Error: unable to open file: %s" % str(err)
+ 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], "r+b")
+ eeprom.seek(93)
+ eeprom.write(buffer[0])
+ return True
+ except IOError as err:
+ print "Error: unable to open file: %s" % str(err)
+ 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
+
+ order = self.update_i2c_order()
+ lp_mode_path = self.BASE_CPLD_PATH.format(order)
+ mod_rst_path = lp_mode_path + "module_reset_"
+ mod_rst_path = mod_rst_path + str(port_num)
+ print(mod_rst_path)
+
+ try:
+ reg_file = open(mod_rst_path, 'r+', 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('1')
+ time.sleep(1)
+ reg_file.seek(0)
+ reg_file.write('0')
+ reg_file.close()
+ return True
+
+ @property
+ def _get_presence_bitmap(self):
+ nodes = []
+ order = self.update_i2c_order()
+
+ present_path = self.BASE_CPLD_PATH.format(order)
+ nodes.append(present_path + "module_present_all")
+
+ bitmap = ""
+ for node in nodes:
+ try:
+ reg_file = open(node)
+
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ return False
+ bitmap += reg_file.readline().rstrip() + " "
+ reg_file.close()
+
+ rev = bitmap.split(" ")
+ rev = "".join(rev[::-1])
+ return int(rev,16)
+
+
+ data = {'present':0}
+ def get_transceiver_change_event(self, timeout=2000):
+ port_dict = {}
+ port = 0
+
+ if timeout == 0:
+ cd_ms = sys.maxint
+ else:
+ cd_ms = timeout
+
+ #poll per second
+ while cd_ms > 0:
+ reg_value = self._get_presence_bitmap
+ changed_ports = self.data['present'] ^ reg_value
+ if changed_ports != 0:
+ break
+ time.sleep(1)
+ cd_ms = cd_ms - 1000
+
+ if changed_ports:
+ for port in range (self.port_start, self.port_end+1):
+ # Mask off the bit corresponding to our port
+ fp_port = self._port_to_i2c_mapping[port][0]
+ mask = (1 << (fp_port - 1))
+ if changed_ports & mask:
+
+ if (reg_value & mask) == 0:
+ port_dict[port] = SFP_STATUS_REMOVED
+ else:
+ port_dict[port] = SFP_STATUS_INSERTED
+
+ # Update cache
+ self.data['present'] = reg_value
+
+ return True, port_dict
+ else:
+ return True, {}
+ return False, {}
+
diff --git a/device/accton/x86_64-accton_as5812_54t-r0/pmon_daemon_control.json b/device/accton/x86_64-accton_as5812_54t-r0/pmon_daemon_control.json
new file mode 100644
index 0000000000..44bad64942
--- /dev/null
+++ b/device/accton/x86_64-accton_as5812_54t-r0/pmon_daemon_control.json
@@ -0,0 +1,4 @@
+{
+ "skip_ledd": true
+}
+
diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk
index 451e22ba37..7d50b133ac 100644
--- a/platform/broadcom/one-image.mk
+++ b/platform/broadcom/one-image.mk
@@ -27,6 +27,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
$(ACCTON_AS4630_54PE_PLATFORM_MODULE) \
$(ACCTON_MINIPACK_PLATFORM_MODULE) \
$(ACCTON_AS5812_54X_PLATFORM_MODULE) \
+ $(ACCTON_AS5812_54T_PLATFORM_MODULE) \
$(ACCTON_AS5835_54X_PLATFORM_MODULE) \
$(ACCTON_AS9716_32D_PLATFORM_MODULE) \
$(ACCTON_AS5835_54T_PLATFORM_MODULE) \
diff --git a/platform/broadcom/platform-modules-accton.mk b/platform/broadcom/platform-modules-accton.mk
index 37ef2669fb..bab9c5ef9f 100755
--- a/platform/broadcom/platform-modules-accton.mk
+++ b/platform/broadcom/platform-modules-accton.mk
@@ -12,6 +12,7 @@ ACCTON_AS7726_32X_PLATFORM_MODULE_VERSION = 1.1
ACCTON_AS4630_54PE_PLATFORM_MODULE_VERSION = 1.1
ACCTON_MINIPACK_PLATFORM_MODULE_VERSION = 1.1
ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION = 1.1
+ACCTON_AS5812_54T_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
@@ -30,6 +31,7 @@ export ACCTON_AS7726_32X_PLATFORM_MODULE_VERSION
export ACCTON_AS4630_54PE_PLATFORM_MODULE_VERSION
export ACCTON_MINIPACK_PLATFORM_MODULE_VERSION
export ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION
+export ACCTON_AS5812_54T_PLATFORM_MODULE_VERSION
export ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION
export ACCTON_AS9716_32D_PLATFORM_MODULE_VERSION
export ACCTON_AS5835_54T_PLATFORM_MODULE_VERSION
@@ -90,6 +92,10 @@ ACCTON_AS5812_54X_PLATFORM_MODULE = sonic-platform-accton-as5812-54x_$(ACCTON_AS
$(ACCTON_AS5812_54X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5812_54x-r0
$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5812_54X_PLATFORM_MODULE)))
+ACCTON_AS5812_54T_PLATFORM_MODULE = sonic-platform-accton-as5812-54t_$(ACCTON_AS5812_54T_PLATFORM_MODULE_VERSION)_amd64.deb
+$(ACCTON_AS5812_54T_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5812_54t-r0
+$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5812_54T_PLATFORM_MODULE)))
+
ACCTON_AS5835_54X_PLATFORM_MODULE = sonic-platform-accton-as5835-54x_$(ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION)_amd64.deb
$(ACCTON_AS5835_54X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5835_54x-r0
$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5835_54X_PLATFORM_MODULE)))
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/classes/__init__.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/classes/__init__.py
new file mode 100755
index 0000000000..e69de29bb2
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/classes/fanutil.py
new file mode 100755
index 0000000000..223408fb96
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/classes/fanutil.py
@@ -0,0 +1,243 @@
+#!/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.)
+# 11/13/2017: Polly Hsu, 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 = 6
+ FAN_NODE_FAULT_IDX_OF_MAP = 1
+ FAN_NODE_SPEED_IDX_OF_MAP = 2
+ FAN_NODE_DIR_IDX_OF_MAP = 3
+ FAN_NODE_DUTY_IDX_OF_MAP = 4
+ FANR_NODE_FAULT_IDX_OF_MAP = 5
+ FANR_NODE_SPEED_IDX_OF_MAP = 6
+
+ BASE_VAL_PATH = '/sys/devices/platform/as5812_54t_fan/{0}'
+
+ #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 = {}
+
+ _fan_to_device_node_mapping = {
+ (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault',
+ (FAN_NUM_1_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan1_speed_rpm',
+ (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction',
+ (FAN_NUM_1_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan1_duty_cycle_percentage',
+ (FAN_NUM_1_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr1_fault',
+ (FAN_NUM_1_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr1_speed_rpm',
+
+ (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault',
+ (FAN_NUM_2_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan2_speed_rpm',
+ (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction',
+ (FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage',
+ (FAN_NUM_2_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr2_fault',
+ (FAN_NUM_2_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr2_speed_rpm',
+
+ (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault',
+ (FAN_NUM_3_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan3_speed_rpm',
+ (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction',
+ (FAN_NUM_3_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan3_duty_cycle_percentage',
+ (FAN_NUM_3_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr3_fault',
+ (FAN_NUM_3_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr3_speed_rpm',
+
+ (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault',
+ (FAN_NUM_4_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan4_speed_rpm',
+ (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction',
+ (FAN_NUM_4_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan4_duty_cycle_percentage',
+ (FAN_NUM_4_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr4_fault',
+ (FAN_NUM_4_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr4_speed_rpm',
+
+ (FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault',
+ (FAN_NUM_5_IDX, FAN_NODE_SPEED_IDX_OF_MAP): 'fan5_speed_rpm',
+ (FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction',
+ (FAN_NUM_5_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan5_duty_cycle_percentage',
+ (FAN_NUM_5_IDX, FANR_NODE_FAULT_IDX_OF_MAP): 'fanr5_fault',
+ (FAN_NUM_5_IDX, FANR_NODE_SPEED_IDX_OF_MAP): 'fanr5_speed_rpm',
+ }
+
+ logger = logging.getLogger(__name__)
+ def __init__(self, log_level=logging.DEBUG):
+ ch = logging.StreamHandler()
+ ch.setLevel(log_level)
+ self.logger.addHandler(ch)
+
+ 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_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:
+ self.logger.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:
+ self.logger.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:
+ self.logger.error('GET. unable to open file: %s', str(e))
+ return None
+
+ content = val_file.readline().rstrip()
+
+ if content == '':
+ self.logger.debug('GET. content is NULL. device_path:%s', device_path)
+ return None
+
+ try:
+ val_file.close()
+ except:
+ self.logger.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:
+ self.logger.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:
+ self.logger.debug('GET. Parameter error. node_num:%d', node_num)
+ return None
+
+ content = str(val)
+ if content == '':
+ self.logger.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:
+ self.logger.error('GET. unable to open file: %s', str(e))
+ return None
+
+ val_file.write(content)
+
+ try:
+ val_file.close()
+ except:
+ self.logger.debug('GET. unable to close file. device_path:%s', device_path)
+ return None
+
+ return True
+
+ 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, fan_num):
+ return self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP)
+
+ def set_fan_duty_cycle(self, fan_num, val):
+ return self._set_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP, val)
+
+ 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:
+ self.logger.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:
+ self.logger.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:
+ self.logger.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/as5812-54t/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/classes/thermalutil.py
new file mode 100755
index 0000000000..0095a78710
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/classes/thermalutil.py
@@ -0,0 +1,125 @@
+#!/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.)
+# 11/13/2017: Polly Hsu, Create
+#
+# ------------------------------------------------------------------
+
+try:
+ import time
+ import logging
+ import glob
+ 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_ON_MAIN_BROAD = 3
+ THERMAL_NUM_1_IDX = 1 # 1_ON_MAIN_BROAD
+ THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD
+ THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD
+
+ BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input'
+
+ """ 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: ['15', '48'],
+ THERMAL_NUM_2_IDX: ['16', '49'],
+ THERMAL_NUM_3_IDX: ['17', '4a'],
+ }
+
+ logger = logging.getLogger(__name__)
+ def __init__(self, log_level=logging.DEBUG):
+ ch = logging.StreamHandler()
+ ch.setLevel(log_level)
+ self.logger.addHandler(ch)
+ thermal_path = self.BASE_VAL_PATH
+
+ for x in range(self.THERMAL_NUM_1_IDX, self.THERMAL_NUM_ON_MAIN_BROAD+1):
+ self._thermal_to_device_path_mapping[x] = thermal_path.format(
+ self._thermal_to_device_node_mapping[x][0],
+ self._thermal_to_device_node_mapping[x][1])
+
+ def _get_thermal_node_val(self, thermal_num):
+ if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD:
+ self.logger.debug('GET. Parameter error. thermal_num, %d', thermal_num)
+ return None
+
+ device_path = self.get_thermal_to_device_path(thermal_num)
+ for filename in glob.glob(device_path):
+ try:
+ val_file = open(filename, 'r')
+ except IOError as e:
+ self.logger.error('GET. unable to open file: %s', str(e))
+ return None
+
+ content = val_file.readline().rstrip()
+
+ if content == '':
+ self.logger.debug('GET. content is NULL. device_path:%s', device_path)
+ return None
+
+ try:
+ val_file.close()
+ except:
+ self.logger.debug('GET. unable to close file. device_path:%s', device_path)
+ return None
+
+ return int(content)
+
+
+ def get_num_thermals(self):
+ return self.THERMAL_NUM_ON_MAIN_BROAD
+
+ 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_to_device_path_mapping)
+
+ def get_thermal_to_device_path(self, thermal_num):
+ return self._thermal_to_device_path_mapping[thermal_num]
+
+ def get_thermal_1_val(self):
+ return self._get_thermal_node_val(self.THERMAL_NUM_1_IDX)
+
+ def get_thermal_2_val(self):
+ return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX)
+
+#def main():
+# thermal = ThermalUtil()
+#
+# 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()
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/Makefile b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/Makefile
old mode 100644
new mode 100755
index 697dcff656..9e338c01f2
--- a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/Makefile
+++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/Makefile
@@ -1,4 +1,4 @@
-obj-m:=accton_i2c_cpld.o x86-64-accton-as5812-54t-fan.o \
- x86-64-accton-as5812-54t-leds.o x86-64-accton-as5812-54t-psu.o \
- x86-64-accton-as5812-54t-sfp.o ym2651y.o
+obj-m:= x86-64-accton-as5812-54t-cpld.o x86-64-accton-as5812-54t-fan.o \
+ x86-64-accton-as5812-54t-leds.o x86-64-accton-as5812-54t-sfp.o \
+ x86-64-accton-as5812-54t-psu.o ym2651y.o cpr_4011_4mxx.o
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/accton_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/accton_i2c_cpld.c
deleted file mode 100644
index c01d6bcca2..0000000000
--- a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/accton_i2c_cpld.c
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * A hwmon driver for the accton_i2c_cpld
- *
- * Copyright (C) 2013 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
-
-static LIST_HEAD(cpld_client_list);
-static struct mutex list_lock;
-
-struct cpld_client_node {
- struct i2c_client *client;
- struct list_head list;
-};
-
-/* Addresses scanned for accton_i2c_cpld
- */
-static const unsigned short normal_i2c[] = { 0x31, 0x35, 0x60, 0x61, 0x62, 0x64, I2C_CLIENT_END };
-
-static ssize_t show_cpld_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", val);
-}
-
-static struct device_attribute ver = __ATTR(version, 0600, show_cpld_version, NULL);
-
-static void accton_i2c_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 accton_i2c_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 int accton_i2c_cpld_probe(struct i2c_client *client,
- const struct i2c_device_id *dev_id)
-{
- int status;
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
- dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr);
- status = -EIO;
- goto exit;
- }
-
- status = sysfs_create_file(&client->dev.kobj, &ver.attr);
- if (status) {
- goto exit;
- }
-
- dev_info(&client->dev, "chip found\n");
- accton_i2c_cpld_add_client(client);
-
- return 0;
-
-exit:
- return status;
-}
-
-static int accton_i2c_cpld_remove(struct i2c_client *client)
-{
- sysfs_remove_file(&client->dev.kobj, &ver.attr);
- accton_i2c_cpld_remove_client(client);
-
- return 0;
-}
-
-static const struct i2c_device_id accton_i2c_cpld_id[] = {
- { "accton_i2c_cpld", 0 },
- {}
-};
-MODULE_DEVICE_TABLE(i2c, accton_i2c_cpld_id);
-
-static struct i2c_driver accton_i2c_cpld_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "accton_i2c_cpld",
- },
- .probe = accton_i2c_cpld_probe,
- .remove = accton_i2c_cpld_remove,
- .id_table = accton_i2c_cpld_id,
- .address_list = normal_i2c,
-};
-
-int accton_i2c_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 = i2c_smbus_read_byte_data(cpld_node->client, reg);
- break;
- }
- }
-
- mutex_unlock(&list_lock);
-
- return ret;
-}
-EXPORT_SYMBOL(accton_i2c_cpld_read);
-
-int accton_i2c_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 = i2c_smbus_write_byte_data(cpld_node->client, reg, value);
- break;
- }
- }
-
- mutex_unlock(&list_lock);
-
- return ret;
-}
-EXPORT_SYMBOL(accton_i2c_cpld_write);
-
-static int __init accton_i2c_cpld_init(void)
-{
- mutex_init(&list_lock);
- return i2c_add_driver(&accton_i2c_cpld_driver);
-}
-
-static void __exit accton_i2c_cpld_exit(void)
-{
- i2c_del_driver(&accton_i2c_cpld_driver);
-}
-
-static struct dmi_system_id as7512_dmi_table[] = {
- {
- .ident = "Accton AS7512",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "Accton"),
- DMI_MATCH(DMI_PRODUCT_NAME, "AS7512"),
- },
- },
- {
- .ident = "Accton AS7512",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Accton"),
- DMI_MATCH(DMI_PRODUCT_NAME, "AS7512"),
- },
- },
-};
-
-int platform_accton_as7512_32x(void)
-{
- return dmi_check_system(as7512_dmi_table);
-}
-EXPORT_SYMBOL(platform_accton_as7512_32x);
-
-static struct dmi_system_id as7712_dmi_table[] = {
- {
- .ident = "Accton AS7712",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "Accton"),
- DMI_MATCH(DMI_PRODUCT_NAME, "AS7712"),
- },
- },
- {
- .ident = "Accton AS7712",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Accton"),
- DMI_MATCH(DMI_PRODUCT_NAME, "AS7712"),
- },
- },
-};
-
-int platform_accton_as7712_32x(void)
-{
- return dmi_check_system(as7712_dmi_table);
-}
-EXPORT_SYMBOL(platform_accton_as7712_32x);
-
-static struct dmi_system_id as5812_54t_dmi_table[] = {
- {
- .ident = "Accton AS5812 54t",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "Accton"),
- DMI_MATCH(DMI_PRODUCT_NAME, "AS5812-54T"),
- },
- },
- {
- .ident = "Accton AS5812 54t",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Accton"),
- DMI_MATCH(DMI_PRODUCT_NAME, "AS5812-54T"),
- },
- },
-};
-
-int platform_accton_as5812_54t(void)
-{
- return dmi_check_system(as5812_54t_dmi_table);
-}
-EXPORT_SYMBOL(platform_accton_as5812_54t);
-
-static struct dmi_system_id as5512_54x_dmi_table[] = {
- {
- .ident = "Accton AS5512",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "Accton"),
- DMI_MATCH(DMI_PRODUCT_NAME, "AS5512"),
- },
- },
- {
- .ident = "Accton AS5512",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Accton"),
- DMI_MATCH(DMI_PRODUCT_NAME, "AS5512"),
- },
- },
-};
-
-int platform_accton_as5512_54x(void)
-{
- return dmi_check_system(as5512_54x_dmi_table);
-}
-EXPORT_SYMBOL(platform_accton_as5512_54x);
-
-static struct dmi_system_id as7716_dmi_table[] = {
- {
- .ident = "Accton AS7716",
- .matches = {
- DMI_MATCH(DMI_BOARD_VENDOR, "Accton"),
- DMI_MATCH(DMI_PRODUCT_NAME, "AS7716"),
- },
- },
- {
- .ident = "Accton AS7716",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Accton"),
- DMI_MATCH(DMI_PRODUCT_NAME, "AS7716"),
- },
- },
-};
-
-int platform_accton_as7716_32x(void)
-{
- return dmi_check_system(as7716_dmi_table);
-}
-EXPORT_SYMBOL(platform_accton_as7716_32x);
-
-MODULE_AUTHOR("Brandon Chuang ");
-MODULE_DESCRIPTION("accton_i2c_cpld driver");
-MODULE_LICENSE("GPL");
-
-module_init(accton_i2c_cpld_init);
-module_exit(accton_i2c_cpld_exit);
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/cpr_4011_4mxx.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/cpr_4011_4mxx.c
new file mode 120000
index 0000000000..fd43cc1f1c
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/cpr_4011_4mxx.c
@@ -0,0 +1 @@
+../../common/modules/cpr_4011_4mxx.c
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-cpld.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-cpld.c
new file mode 100755
index 0000000000..2d44d5355c
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-cpld.c
@@ -0,0 +1,544 @@
+/*
+ * A hwmon driver for the as5812_54t_cpld
+ *
+ * Copyright (C) 2013 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
+
+static LIST_HEAD(cpld_client_list);
+static struct mutex list_lock;
+
+struct cpld_client_node {
+ struct i2c_client *client;
+ struct list_head list;
+};
+
+#define I2C_RW_RETRY_COUNT 10
+#define I2C_RW_RETRY_INTERVAL 60 /* ms */
+
+static ssize_t show_bit(struct device *dev, struct device_attribute *da,
+ char *buf);
+static ssize_t set_1bit(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count);
+static ssize_t show_present_all(struct device *dev, struct device_attribute *da,
+ char *buf);
+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 as5812_54t_cpld_read_internal(struct i2c_client *client, u8 reg);
+static int as5812_54t_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value);
+
+struct as5812_54t_cpld_data {
+ struct device *hwmon_dev;
+ struct mutex update_lock;
+};
+
+/* Addresses scanned for as5812_54t_cpld
+ */
+static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+
+
+#define _ATTR_CONCAT(name,idx) name##idx
+
+#define TRANSCEIVER_ATTR_ID(_attr) \
+ _ATTR_CONCAT(MODULE_##_attr##_, 49), \
+ _ATTR_CONCAT(MODULE_##_attr##_, 50), \
+ _ATTR_CONCAT(MODULE_##_attr##_, 51), \
+ _ATTR_CONCAT(MODULE_##_attr##_, 52), \
+ _ATTR_CONCAT(MODULE_##_attr##_, 53), \
+ _ATTR_CONCAT(MODULE_##_attr##_, 54)
+
+
+enum as5812_54t_cpld_sysfs_attributes {
+ CPLD_VERSION,
+ ACCESS,
+ MODULE_PRESENT_ALL,
+ /* transceiver attributes */
+ TRANSCEIVER_ATTR_ID(PRESENT),
+ TRANSCEIVER_ATTR_ID(LPMODE),
+ TRANSCEIVER_ATTR_ID(RESET),
+};
+
+/* sysfs attributes for hwmon
+ */
+
+/* transceiver attributes */
+#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \
+ static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_bit, NULL, MODULE_PRESENT_##index);\
+ static SENSOR_DEVICE_ATTR(module_lp_mode_##index, S_IRUGO|S_IWUSR, show_bit, set_1bit, MODULE_LPMODE_##index);\
+ static SENSOR_DEVICE_ATTR(module_reset_##index, S_IRUGO|S_IWUSR, show_bit, set_1bit, MODULE_RESET_##index)
+
+#define DECLARE_TRANSCEIVER_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr, \
+ &sensor_dev_attr_module_lp_mode_##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_SENSOR_DEVICE_ATTR(49);
+DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(50);
+DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(51);
+DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(52);
+DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(53);
+DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(54);
+
+static struct attribute *as5812_54t_cpld_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_ATTR(49),
+ DECLARE_TRANSCEIVER_ATTR(50),
+ DECLARE_TRANSCEIVER_ATTR(51),
+ DECLARE_TRANSCEIVER_ATTR(52),
+ DECLARE_TRANSCEIVER_ATTR(53),
+ DECLARE_TRANSCEIVER_ATTR(54),
+ NULL
+};
+
+static const struct attribute_group as5812_54t_cpld_group = {
+ .attrs = as5812_54t_cpld_attributes,
+};
+
+static ssize_t show_present_all(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ int status;
+ u8 value = 0;
+ u8 reg = 0x22;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct as5812_54t_cpld_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->update_lock);
+
+ status = as5812_54t_cpld_read_internal(client, reg);
+ if (status < 0) {
+ goto exit;
+ }
+
+ value = ~(u8)status;
+ value &= 0x3F;
+
+ mutex_unlock(&data->update_lock);
+
+ /* Return values 49 -> 54 in order */
+ return sprintf(buf, "%.2x\n", value);
+
+exit:
+ mutex_unlock(&data->update_lock);
+ return status;
+}
+
+static int get_reg_index(struct sensor_device_attribute *attr, u8 *reg, u8 *index, u8 *revert) {
+ if (attr->index >= MODULE_RESET_49){
+ *reg = 0x23;
+ *index = attr->index - MODULE_RESET_49;
+ *revert = 1;
+ }else if (attr->index >= MODULE_LPMODE_49){
+ *reg = 0x24;
+ *index = attr->index - MODULE_LPMODE_49;
+ *revert = 0;
+ } else {
+ *reg = 0x22;
+ *index = attr->index - MODULE_PRESENT_49;
+ *revert = 1;
+ }
+ return 0;
+}
+
+static ssize_t set_1bit(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count)
+{
+ u8 index, revert;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct as5812_54t_cpld_data *data = i2c_get_clientdata(client);
+ int status, value;
+ u8 reg = 0, mask = 0;
+
+ status = kstrtoint(buf, 10, &value);
+ if (status)
+ return status;
+
+ get_reg_index(attr, ®, &index, &revert);
+ mask = 0x1 << index;
+
+ mutex_lock(&data->update_lock);
+ status = as5812_54t_cpld_read_internal(client, reg);
+ if (unlikely(status < 0)) {
+ goto exit;
+ }
+ status &= ~(mask);
+ value = !value;
+ if (!revert)
+ value = !value;
+ status |= (value << index); /*low-active*/
+ status = as5812_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 show_bit(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u8 index, revert;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct as5812_54t_cpld_data *data = i2c_get_clientdata(client);
+ int status = 0;
+ u8 reg = 0, mask = 0;
+
+ get_reg_index(attr, ®, &index, &revert);
+ mask = 0x1 << index;
+
+ mutex_lock(&data->update_lock);
+ status = as5812_54t_cpld_read_internal(client, reg);
+ if (unlikely(status < 0)) {
+ goto exit;
+ }
+ mutex_unlock(&data->update_lock);
+
+ status = !(status & mask);
+ if (!revert)
+ status = !status;
+
+ return sprintf(buf, "%d\n", status);
+
+exit:
+ mutex_unlock(&data->update_lock);
+ return status;
+}
+
+static ssize_t show_version(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ u8 reg = 0, mask = 0;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct as5812_54t_cpld_data *data = i2c_get_clientdata(client);
+ int status = 0;
+
+ switch (attr->index) {
+ case CPLD_VERSION:
+ reg = 0x1;
+ mask = 0xFF;
+ break;
+ default:
+ break;
+ }
+
+ mutex_lock(&data->update_lock);
+ status = as5812_54t_cpld_read_internal(client, reg);
+ if (unlikely(status < 0)) {
+ goto exit;
+ }
+ mutex_unlock(&data->update_lock);
+ return sprintf(buf, "%d\n", (status & mask));
+
+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 as5812_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 = as5812_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 int as5812_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 as5812_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;
+}
+
+static void as5812_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 as5812_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 int as5812_54t_cpld_probe(struct i2c_client *client,
+ const struct i2c_device_id *dev_id)
+{
+ int status;
+ struct as5812_54t_cpld_data *data = NULL;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+ dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr);
+ status = -EIO;
+ goto exit;
+ }
+
+ data = kzalloc(sizeof(struct as5812_54t_cpld_data), GFP_KERNEL);
+ if (!data) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+ dev_info(&client->dev, "chip found\n");
+
+ /* Register sysfs hooks */
+ status = sysfs_create_group(&client->dev.kobj, &as5812_54t_cpld_group);
+ if (status) {
+ goto exit_free;
+ }
+
+ data->hwmon_dev = hwmon_device_register_with_info(&client->dev, "as5812_54t_cpld",
+ NULL, NULL, NULL);
+ if (IS_ERR(data->hwmon_dev)) {
+ status = PTR_ERR(data->hwmon_dev);
+ goto exit_remove;
+ }
+
+ as5812_54t_cpld_add_client(client);
+
+ /*
+ * Bring QSFPs out of reset,
+ * This is a temporary fix until the QSFP+_MOD_RST register
+ * can be exposed through the driver.
+ */
+ as5812_54t_cpld_write_internal(client, 0x23, 0x3F);
+
+ dev_info(&client->dev, "%s: cpld '%s'\n",
+ dev_name(data->hwmon_dev), client->name);
+
+ return 0;
+
+exit_remove:
+ sysfs_remove_group(&client->dev.kobj, &as5812_54t_cpld_group);
+exit_free:
+ kfree(data);
+exit:
+
+ return status;
+}
+
+static int as5812_54t_cpld_remove(struct i2c_client *client)
+{
+ struct as5812_54t_cpld_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &as5812_54t_cpld_group);
+ kfree(data);
+ as5812_54t_cpld_remove_client(client);
+
+ return 0;
+}
+
+int as5812_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 = i2c_smbus_read_byte_data(cpld_node->client, reg);
+ break;
+ }
+ }
+
+ mutex_unlock(&list_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(as5812_54t_cpld_read);
+
+int as5812_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 = i2c_smbus_write_byte_data(cpld_node->client, reg, value);
+ break;
+ }
+ }
+
+ mutex_unlock(&list_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(as5812_54t_cpld_write);
+
+static const struct i2c_device_id as5812_54t_cpld_id[] = {
+ { "as5812_54t_cpld", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, as5812_54t_cpld_id);
+
+static struct i2c_driver as5812_54t_cpld_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "as5812_54t_cpld",
+ },
+ .probe = as5812_54t_cpld_probe,
+ .remove = as5812_54t_cpld_remove,
+ .id_table = as5812_54t_cpld_id,
+ .address_list = normal_i2c,
+};
+
+static int __init as5812_54t_cpld_init(void)
+{
+ mutex_init(&list_lock);
+ return i2c_add_driver(&as5812_54t_cpld_driver);
+}
+
+static void __exit as5812_54t_cpld_exit(void)
+{
+ i2c_del_driver(&as5812_54t_cpld_driver);
+}
+
+module_init(as5812_54t_cpld_init);
+module_exit(as5812_54t_cpld_exit);
+
+MODULE_AUTHOR("Brandon Chuang ");
+MODULE_DESCRIPTION("as5812_54t_cpld driver");
+MODULE_LICENSE("GPL");
+
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-fan.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-fan.c
index bad9245e93..66370fb37f 100644
--- a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-fan.c
+++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-fan.c
@@ -33,6 +33,8 @@
#include
#include
+#define DRVNAME "as5812_54t_fan"
+
#define FAN_MAX_NUMBER 5
#define FAN_SPEED_CPLD_TO_RPM_STEP 150
#define FAN_SPEED_PRECENT_TO_CPLD_STEP 5
@@ -130,47 +132,62 @@ static ssize_t fan_set_duty_cycle(struct device *dev,
struct device_attribute *da,const char *buf, size_t count);
static ssize_t fan_show_value(struct device *dev,
struct device_attribute *da, char *buf);
+static ssize_t show_name(struct device *dev,
+ struct device_attribute *da, char *buf);
-extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
-extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
+extern int as5812_54t_cpld_read(unsigned short cpld_addr, u8 reg);
+extern int as5812_54t_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
/*******************/
-#define _MAKE_SENSOR_DEVICE_ATTR(prj, id) \
- static SENSOR_DEVICE_ATTR(prj##fan##id##_fault, S_IRUGO, fan_show_value, NULL, FAN##id##_FAULT); \
+#define _MAKE_SENSOR_DEVICE_ATTR(prj, id, id2) \
static SENSOR_DEVICE_ATTR(prj##fan##id##_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##id##_SPEED); \
static SENSOR_DEVICE_ATTR(prj##fan##id##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, \
fan_set_duty_cycle, FAN##id##_DUTY_CYCLE); \
+ static SENSOR_DEVICE_ATTR(prj##pwm##id, S_IWUSR | S_IRUGO, fan_show_value, \
+ fan_set_duty_cycle, FAN##id##_DUTY_CYCLE); \
static SENSOR_DEVICE_ATTR(prj##fan##id##_direction, S_IRUGO, fan_show_value, NULL, FAN##id##_DIRECTION); \
static SENSOR_DEVICE_ATTR(prj##fanr##id##_fault, S_IRUGO, fan_show_value, NULL, FANR##id##_FAULT); \
- static SENSOR_DEVICE_ATTR(prj##fanr##id##_speed_rpm, S_IRUGO, fan_show_value, NULL, FANR##id##_SPEED);
+ static SENSOR_DEVICE_ATTR(prj##fanr##id##_speed_rpm, S_IRUGO, fan_show_value, NULL, FANR##id##_SPEED); \
+ static SENSOR_DEVICE_ATTR(prj##fan##id##_input, S_IRUGO, fan_show_value, NULL, FAN##id##_SPEED); \
+ static SENSOR_DEVICE_ATTR(prj##fan##id2##_input, S_IRUGO, fan_show_value, NULL, FANR##id##_SPEED); \
+ static SENSOR_DEVICE_ATTR(prj##fan##id##_fault, S_IRUGO, fan_show_value, NULL, FAN##id##_FAULT); \
+ static SENSOR_DEVICE_ATTR(prj##fan##id2##_fault, S_IRUGO, fan_show_value, NULL, FAN##id##_FAULT);
-#define MAKE_SENSOR_DEVICE_ATTR(prj,id) _MAKE_SENSOR_DEVICE_ATTR(prj,id)
+#define MAKE_SENSOR_DEVICE_ATTR(prj,id, id2) _MAKE_SENSOR_DEVICE_ATTR(prj,id, id2)
-MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 1)
-MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 2)
-MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 3)
-MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 4)
-MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME, 5)
+MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME,1,11)
+MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME,2,12)
+MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME,3,13)
+MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME,4,14)
+MAKE_SENSOR_DEVICE_ATTR(PROJECT_NAME,5,15)
+
+static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
/*******************/
-#define _MAKE_FAN_ATTR(prj, id) \
- &sensor_dev_attr_##prj##fan##id##_fault.dev_attr.attr, \
+#define _MAKE_FAN_ATTR(prj, id, id2) \
&sensor_dev_attr_##prj##fan##id##_speed_rpm.dev_attr.attr, \
&sensor_dev_attr_##prj##fan##id##_duty_cycle_percentage.dev_attr.attr,\
+ &sensor_dev_attr_##prj##pwm##id.dev_attr.attr,\
&sensor_dev_attr_##prj##fan##id##_direction.dev_attr.attr, \
&sensor_dev_attr_##prj##fanr##id##_fault.dev_attr.attr, \
- &sensor_dev_attr_##prj##fanr##id##_speed_rpm.dev_attr.attr,
+ &sensor_dev_attr_##prj##fanr##id##_speed_rpm.dev_attr.attr, \
+ &sensor_dev_attr_##prj##fan##id##_input.dev_attr.attr, \
+ &sensor_dev_attr_##prj##fan##id2##_input.dev_attr.attr, \
+ &sensor_dev_attr_##prj##fan##id##_fault.dev_attr.attr, \
+ &sensor_dev_attr_##prj##fan##id2##_fault.dev_attr.attr,
-#define MAKE_FAN_ATTR(prj, id) _MAKE_FAN_ATTR(prj, id)
+
+#define MAKE_FAN_ATTR(prj, id, id2) _MAKE_FAN_ATTR(prj, id, id2)
static struct attribute *accton_as5812_54t_fan_attributes[] = {
/* fan related attributes */
- MAKE_FAN_ATTR(PROJECT_NAME,1)
- MAKE_FAN_ATTR(PROJECT_NAME,2)
- MAKE_FAN_ATTR(PROJECT_NAME,3)
- MAKE_FAN_ATTR(PROJECT_NAME,4)
- MAKE_FAN_ATTR(PROJECT_NAME,5)
+ MAKE_FAN_ATTR(PROJECT_NAME,1,11)
+ MAKE_FAN_ATTR(PROJECT_NAME,2,12)
+ MAKE_FAN_ATTR(PROJECT_NAME,3,13)
+ MAKE_FAN_ATTR(PROJECT_NAME,4,14)
+ MAKE_FAN_ATTR(PROJECT_NAME,5,15)
+ &sensor_dev_attr_name.dev_attr.attr,
NULL
};
/*******************/
@@ -232,6 +249,12 @@ static ssize_t fan_show_value(struct device *dev, struct device_attribute *da,
return ret;
}
+
+static ssize_t show_name(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ return sprintf(buf, "%s\n", DRVNAME);
+}
/*******************/
static ssize_t fan_set_duty_cycle(struct device *dev, struct device_attribute *da,
const char *buf, size_t count) {
@@ -258,12 +281,12 @@ static const struct attribute_group accton_as5812_54t_fan_group = {
static int accton_as5812_54t_fan_read_value(u8 reg)
{
- return accton_i2c_cpld_read(0x60, reg);
+ return as5812_54t_cpld_read(0x60, reg);
}
static int accton_as5812_54t_fan_write_value(u8 reg, u8 value)
{
- return accton_i2c_cpld_write(0x60, reg, value);
+ return as5812_54t_cpld_write(0x60, reg, value);
}
static void accton_as5812_54t_fan_update_device(struct device *dev)
@@ -379,7 +402,6 @@ static int accton_as5812_54t_fan_remove(struct platform_device *pdev)
return 0;
}
-#define DRVNAME "as5812_54t_fan"
static struct platform_driver accton_as5812_54t_fan_driver = {
.probe = accton_as5812_54t_fan_probe,
@@ -394,11 +416,6 @@ static int __init accton_as5812_54t_fan_init(void)
{
int ret;
- extern int platform_accton_as5812_54t(void);
- if (!platform_accton_as5812_54t()) {
- return -ENODEV;
- }
-
ret = platform_driver_register(&accton_as5812_54t_fan_driver);
if (ret < 0) {
goto exit;
@@ -439,4 +456,3 @@ MODULE_LICENSE("GPL");
module_init(accton_as5812_54t_fan_init);
module_exit(accton_as5812_54t_fan_exit);
-
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-psu.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-psu.c
index a77014e877..c62998655b 100644
--- a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-psu.c
+++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-psu.c
@@ -43,7 +43,7 @@ static ssize_t show_index(struct device *dev, struct device_attribute *da, char
static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf);
static int as5812_54t_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len);
-extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
+extern int as5812_54t_cpld_read(unsigned short cpld_addr, u8 reg);
static int as5812_54t_psu_model_name_get(struct device *dev);
/* Addresses scanned
@@ -170,7 +170,8 @@ static int as5812_54t_psu_probe(struct i2c_client *client,
goto exit_free;
}
- data->hwmon_dev = hwmon_device_register(&client->dev);
+ data->hwmon_dev = hwmon_device_register_with_info(&client->dev, "as5812_54t_psu",
+ NULL, NULL, NULL);
if (IS_ERR(data->hwmon_dev)) {
status = PTR_ERR(data->hwmon_dev);
goto exit_remove;
@@ -328,7 +329,7 @@ static struct as5812_54t_psu_data *as5812_54t_psu_update_device(struct device *d
data->valid = 0;
/* Read psu status */
- status = accton_i2c_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET);
+ status = as5812_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);
@@ -348,25 +349,9 @@ exit:
return data;
}
-static int __init as5812_54t_psu_init(void)
-{
- extern int platform_accton_as5812_54t(void);
- if (!platform_accton_as5812_54t()) {
- return -ENODEV;
- }
-
- return i2c_add_driver(&as5812_54t_psu_driver);
-}
-
-static void __exit as5812_54t_psu_exit(void)
-{
- i2c_del_driver(&as5812_54t_psu_driver);
-}
+module_i2c_driver(as5812_54t_psu_driver);
MODULE_AUTHOR("Brandon Chuang ");
MODULE_DESCRIPTION("accton as5812_54t_psu driver");
MODULE_LICENSE("GPL");
-module_init(as5812_54t_psu_init);
-module_exit(as5812_54t_psu_exit);
-
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-sfp.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-sfp.c
deleted file mode 100644
index 88bf552de0..0000000000
--- a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/x86-64-accton-as5812-54t-sfp.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * An hwmon driver for accton as5812_54t sfp
- *
- * Copyright (C) 2015 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
-
-#define QSFP_PORT_START_INDEX 49
-#define BIT_INDEX(i) (1ULL << (i))
-
-/* Addresses scanned
- */
-static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END };
-
-/* Each client has this additional data
- */
-struct as5812_54t_sfp_data {
- struct device *hwmon_dev;
- struct mutex update_lock;
- char valid; /* !=0 if registers are valid */
- unsigned long last_updated; /* In jiffies */
- int port; /* Front port index */
- char eeprom[256]; /* eeprom data */
- u8 status; /* bit0:port49, bit1:port50 and so on */
-};
-
-static struct as5812_54t_sfp_data *as5812_54t_sfp_update_device(struct device *dev, int update_eeprom);
-static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf);
-static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf);
-static ssize_t show_eeprom(struct device *dev, struct device_attribute *da, char *buf);
-extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
-extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
-
-enum as5812_54t_sfp_sysfs_attributes {
- SFP_IS_PRESENT,
- SFP_PORT_NUMBER,
- SFP_EEPROM,
- SFP_IS_PRESENT_ALL,
-};
-
-/* sysfs attributes for hwmon
- */
-static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_status, NULL, SFP_IS_PRESENT);
-static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, SFP_PORT_NUMBER);
-static SENSOR_DEVICE_ATTR(sfp_eeprom, S_IRUGO, show_eeprom, NULL, SFP_EEPROM);
-static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_status,NULL, SFP_IS_PRESENT_ALL);
-
-static struct attribute *as5812_54t_sfp_attributes[] = {
- &sensor_dev_attr_sfp_is_present.dev_attr.attr,
- &sensor_dev_attr_sfp_eeprom.dev_attr.attr,
- &sensor_dev_attr_sfp_port_number.dev_attr.attr,
- &sensor_dev_attr_sfp_is_present_all.dev_attr.attr,
- NULL
-};
-
-static ssize_t show_port_number(struct device *dev, struct device_attribute *da,
- char *buf)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct as5812_54t_sfp_data *data = i2c_get_clientdata(client);
-
- return sprintf(buf, "%d\n",data->port);
-}
-
-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 as5812_54t_sfp_data *data = as5812_54t_sfp_update_device(dev, 0);
-
- if (attr->index == SFP_IS_PRESENT) {
- u8 val;
-
- val = (data->status & BIT_INDEX(data->port - QSFP_PORT_START_INDEX)) ? 0 : 1;
- return sprintf(buf, "%d", val);
- }
- else { /* SFP_IS_PRESENT_ALL */
- return sprintf(buf, "%.2x\n", ~data->status);
- }
-}
-
-static ssize_t show_eeprom(struct device *dev, struct device_attribute *da,
- char *buf)
-{
- struct as5812_54t_sfp_data *data = as5812_54t_sfp_update_device(dev, 1);
-
- if (!data->valid) {
- return 0;
- }
-
- if ((data->status & BIT_INDEX(data->port - QSFP_PORT_START_INDEX)) != 0) {
- return 0;
- }
-
- memcpy(buf, data->eeprom, sizeof(data->eeprom));
-
- return sizeof(data->eeprom);
-}
-
-static const struct attribute_group as5812_54t_sfp_group = {
- .attrs = as5812_54t_sfp_attributes,
-};
-
-static int as5812_54t_sfp_probe(struct i2c_client *client,
- const struct i2c_device_id *dev_id)
-{
- struct as5812_54t_sfp_data *data;
- int status;
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
- status = -EIO;
- goto exit;
- }
-
- data = kzalloc(sizeof(struct as5812_54t_sfp_data), GFP_KERNEL);
- if (!data) {
- status = -ENOMEM;
- goto exit;
- }
-
- mutex_init(&data->update_lock);
- data->port = dev_id->driver_data;
- i2c_set_clientdata(client, data);
-
- dev_info(&client->dev, "chip found\n");
-
- /* Register sysfs hooks */
- status = sysfs_create_group(&client->dev.kobj, &as5812_54t_sfp_group);
- if (status) {
- goto exit_free;
- }
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- status = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- dev_info(&client->dev, "%s: sfp '%s'\n",
- dev_name(data->hwmon_dev), client->name);
-
- return 0;
-
-exit_remove:
- sysfs_remove_group(&client->dev.kobj, &as5812_54t_sfp_group);
-exit_free:
- kfree(data);
-exit:
-
- return status;
-}
-
-static int as5812_54t_sfp_remove(struct i2c_client *client)
-{
- struct as5812_54t_sfp_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &as5812_54t_sfp_group);
- kfree(data);
-
- return 0;
-}
-
-enum port_numbers {
-as5812_54t_qsfp49 = 49,
-as5812_54t_qsfp50,
-as5812_54t_qsfp51,
-as5812_54t_qsfp52,
-as5812_54t_qsfp53,
-as5812_54t_qsfp54
-};
-
-static const struct i2c_device_id as5812_54t_sfp_id[] = {
-{ "as5812_54t_qsfp49", as5812_54t_qsfp49 }, { "as5812_54t_qsfp50", as5812_54t_qsfp50 },
-{ "as5812_54t_qsfp51", as5812_54t_qsfp51 }, { "as5812_54t_qsfp52", as5812_54t_qsfp52 },
-{ "as5812_54t_qsfp53", as5812_54t_qsfp53 }, { "as5812_54t_qsfp54", as5812_54t_qsfp54 },
-{}
-};
-MODULE_DEVICE_TABLE(i2c, as5812_54t_sfp_id);
-
-static struct i2c_driver as5812_54t_sfp_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "as5812_54t_sfp",
- },
- .probe = as5812_54t_sfp_probe,
- .remove = as5812_54t_sfp_remove,
- .id_table = as5812_54t_sfp_id,
- .address_list = normal_i2c,
-};
-
-static int as5812_54t_sfp_read_byte(struct i2c_client *client, u8 command, u8 *data)
-{
- int result = i2c_smbus_read_byte_data(client, command);
-
- if (unlikely(result < 0)) {
- dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, result);
- goto abort;
- }
-
- *data = (u8)result;
- result = 0;
-
-abort:
- return result;
-}
-
-static struct as5812_54t_sfp_data *as5812_54t_sfp_update_device(struct device *dev, int update_eeprom)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct as5812_54t_sfp_data *data = i2c_get_clientdata(client);
-
- mutex_lock(&data->update_lock);
-
- if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
- || !data->valid || update_eeprom) {
- int status = -1;
- int i = 0;
-
- data->valid = 0;
- //dev_dbg(&client->dev, "Starting as5812_54t sfp status update\n");
- data->status = 0xFF;
-
- /*
- * Bring QSFPs out of reset,
- * This is a temporary fix until the QSFP+_MOD_RST register
- * can be exposed through the driver.
- */
- accton_i2c_cpld_write(0x60, 0x23, 0x3F);
-
- /* Read present status of port 49-54(QSFP port) */
- status = accton_i2c_cpld_read(0x60, 0x22);
-
- if (status < 0) {
- dev_dbg(&client->dev, "cpld(0x60) reg(0x22) err %d\n", status);
- }
- else {
- data->status = status & 0x3F; /* (u32)status */
- }
-
- if (update_eeprom) {
- /* Read eeprom data based on port number */
- memset(data->eeprom, 0, sizeof(data->eeprom));
-
- /* Check if the port is present */
- if ((data->status & BIT_INDEX(data->port - QSFP_PORT_START_INDEX)) == 0) {
- /* read eeprom */
- for (i = 0; i < sizeof(data->eeprom); i++) {
- status = as5812_54t_sfp_read_byte(client, i, data->eeprom + i);
-
- if (status < 0) {
- dev_dbg(&client->dev, "unable to read eeprom from port(%d)\n",
- data->port);
- goto exit;
- }
- }
- }
- }
-
- data->valid = 1;
- data->last_updated = jiffies;
- }
-
-exit:
- mutex_unlock(&data->update_lock);
-
- return data;
-}
-
-static int __init as5812_54t_sfp_init(void)
-{
- extern int platform_accton_as5812_54t(void);
- if (!platform_accton_as5812_54t()) {
- return -ENODEV;
- }
-
- return i2c_add_driver(&as5812_54t_sfp_driver);
-}
-
-static void __exit as5812_54t_sfp_exit(void)
-{
- i2c_del_driver(&as5812_54t_sfp_driver);
-}
-
-MODULE_AUTHOR("Brandon Chuang ");
-MODULE_DESCRIPTION("accton as5812_54t_sfp driver");
-MODULE_LICENSE("GPL");
-
-module_init(as5812_54t_sfp_init);
-module_exit(as5812_54t_sfp_exit);
-
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/ym2651y.c
deleted file mode 100644
index 7101aa411f..0000000000
--- a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/ym2651y.c
+++ /dev/null
@@ -1,680 +0,0 @@
-/*
- * An hwmon driver for the 3Y Power YM-2651Y 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
-
-#define MAX_FAN_DUTY_CYCLE 100
-
-/* Addresses scanned
- */
-static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
-
-enum chips {
- YM2651,
- YM2401,
-};
-
-/* Each client has this additional data
- */
-struct ym2651y_data {
- struct device *hwmon_dev;
- struct mutex update_lock;
- char valid; /* !=0 if registers are valid */
- unsigned long last_updated; /* In jiffies */
- u8 chip; /* chip id */
- u8 capability; /* Register value */
- u16 status_word; /* Register value */
- u8 fan_fault; /* Register value */
- u8 over_temp; /* Register value */
- u16 v_out; /* Register value */
- u16 i_out; /* Register value */
- u16 p_out; /* Register value */
- u8 vout_mode; /* Register value */
- u16 temp; /* Register value */
- u16 fan_speed; /* Register value */
- u16 fan_duty_cycle[2]; /* Register value */
- u8 fan_dir[5]; /* Register value */
- u8 pmbus_revision; /* Register value */
- u8 mfr_id[10]; /* Register value */
- u8 mfr_model[16]; /* Register value */
- u8 mfr_revsion[3]; /* Register value */
- u16 mfr_vin_min; /* Register value */
- u16 mfr_vin_max; /* Register value */
- u16 mfr_iin_max; /* Register value */
- u16 mfr_iout_max; /* Register value */
- u16 mfr_pin_max; /* Register value */
- u16 mfr_pout_max; /* Register value */
- u16 mfr_vout_min; /* Register value */
- u16 mfr_vout_max; /* Register value */
-};
-
-static ssize_t show_byte(struct device *dev, struct device_attribute *da,
- char *buf);
-static ssize_t show_word(struct device *dev, struct device_attribute *da,
- char *buf);
-static ssize_t show_linear(struct device *dev, struct device_attribute *da,
- char *buf);
-static ssize_t show_vout(struct device *dev, struct device_attribute *da, char *buf);
-static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da,
- char *buf);
-static ssize_t show_over_temp(struct device *dev, struct device_attribute *da,
- char *buf);
-static ssize_t show_ascii(struct device *dev, struct device_attribute *da,
- char *buf);
-static struct ym2651y_data *ym2651y_update_device(struct device *dev);
-static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da,
- const char *buf, size_t count);
-static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value);
-
-enum ym2651y_sysfs_attributes {
- PSU_POWER_ON = 0,
- PSU_TEMP_FAULT,
- PSU_POWER_GOOD,
- PSU_FAN1_FAULT,
- PSU_FAN_DIRECTION,
- PSU_OVER_TEMP,
- PSU_V_OUT,
- PSU_I_OUT,
- PSU_P_OUT,
- PSU_TEMP1_INPUT,
- PSU_FAN1_SPEED,
- PSU_FAN1_DUTY_CYCLE,
- PSU_PMBUS_REVISION,
- PSU_MFR_ID,
- PSU_MFR_MODEL,
- PSU_MFR_REVISION,
- PSU_MFR_VIN_MIN,
- PSU_MFR_VIN_MAX,
- PSU_MFR_VOUT_MIN,
- PSU_MFR_VOUT_MAX,
- PSU_MFR_IIN_MAX,
- PSU_MFR_IOUT_MAX,
- PSU_MFR_PIN_MAX,
- PSU_MFR_POUT_MAX
-};
-
-/* sysfs attributes for hwmon
- */
-static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON);
-static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT);
-static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD);
-static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT);
-static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP);
-static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_vout, NULL, PSU_V_OUT);
-static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT);
-static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT);
-static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT);
-static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED);
-static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE);
-static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION);
-static SENSOR_DEVICE_ATTR(psu_pmbus_revision,S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION);
-static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID);
-static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL);
-static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION);
-static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN);
-static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX);
-static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN);
-static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX);
-static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX);
-static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX);
-static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX);
-static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX);
-
-static struct attribute *ym2651y_attributes[] = {
- &sensor_dev_attr_psu_power_on.dev_attr.attr,
- &sensor_dev_attr_psu_temp_fault.dev_attr.attr,
- &sensor_dev_attr_psu_power_good.dev_attr.attr,
- &sensor_dev_attr_psu_fan1_fault.dev_attr.attr,
- &sensor_dev_attr_psu_over_temp.dev_attr.attr,
- &sensor_dev_attr_psu_v_out.dev_attr.attr,
- &sensor_dev_attr_psu_i_out.dev_attr.attr,
- &sensor_dev_attr_psu_p_out.dev_attr.attr,
- &sensor_dev_attr_psu_temp1_input.dev_attr.attr,
- &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr,
- &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr,
- &sensor_dev_attr_psu_fan_dir.dev_attr.attr,
- &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_id.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_model.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_revision.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr,
- NULL
-};
-
-static ssize_t show_byte(struct device *dev, struct device_attribute *da,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct ym2651y_data *data = ym2651y_update_device(dev);
-
- if (!data->valid) {
- return 0;
- }
-
- return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) :
- sprintf(buf, "0\n");
-}
-
-static ssize_t show_word(struct device *dev, struct device_attribute *da,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct ym2651y_data *data = ym2651y_update_device(dev);
- u16 status = 0;
-
- if (!data->valid) {
- return 0;
- }
-
- switch (attr->index) {
- case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */
- status = (data->status_word & 0x40) ? 0 : 1;
- break;
- case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */
- status = (data->status_word & 0x4) >> 2;
- break;
- case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */
- status = (data->status_word & 0x800) ? 0 : 1;
- break;
- }
-
- return sprintf(buf, "%d\n", status);
-}
-
-static int two_complement_to_int(u16 data, u8 valid_bit, int mask)
-{
- u16 valid_data = data & mask;
- bool is_negative = valid_data >> (valid_bit - 1);
-
- return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data;
-}
-
-static ssize_t set_fan_duty_cycle(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 ym2651y_data *data = i2c_get_clientdata(client);
- int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1;
- long speed;
- int error;
-
- error = kstrtol(buf, 10, &speed);
- if (error)
- return error;
-
- if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE)
- return -EINVAL;
-
- mutex_lock(&data->update_lock);
- data->fan_duty_cycle[nr] = speed;
- ym2651y_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]);
- mutex_unlock(&data->update_lock);
-
- return count;
-}
-
-static ssize_t show_linear(struct device *dev, struct device_attribute *da,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct ym2651y_data *data = ym2651y_update_device(dev);
-
- u16 value = 0;
- int exponent, mantissa;
- int multiplier = 1000;
-
- if (!data->valid) {
- return 0;
- }
-
- switch (attr->index) {
- case PSU_V_OUT:
- value = data->v_out;
- break;
- case PSU_I_OUT:
- value = data->i_out;
- break;
- case PSU_P_OUT:
- value = data->p_out;
- break;
- case PSU_TEMP1_INPUT:
- value = data->temp;
- break;
- case PSU_FAN1_SPEED:
- value = data->fan_speed;
- multiplier = 1;
- break;
- case PSU_FAN1_DUTY_CYCLE:
- value = data->fan_duty_cycle[0];
- multiplier = 1;
- break;
- case PSU_MFR_VIN_MIN:
- value = data->mfr_vin_min;
- break;
- case PSU_MFR_VIN_MAX:
- value = data->mfr_vin_max;
- break;
- case PSU_MFR_VOUT_MIN:
- value = data->mfr_vout_min;
- break;
- case PSU_MFR_VOUT_MAX:
- value = data->mfr_vout_max;
- break;
- case PSU_MFR_PIN_MAX:
- value = data->mfr_pin_max;
- break;
- case PSU_MFR_POUT_MAX:
- value = data->mfr_pout_max;
- break;
- case PSU_MFR_IOUT_MAX:
- value = data->mfr_iout_max;
- break;
- case PSU_MFR_IIN_MAX:
- value = data->mfr_iin_max;
- break;
- }
-
- exponent = two_complement_to_int(value >> 11, 5, 0x1f);
- mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff);
-
- return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) :
- sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent));
-}
-
-static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct ym2651y_data *data = ym2651y_update_device(dev);
- u8 shift;
-
- if (!data->valid) {
- return 0;
- }
-
- shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6;
-
- return sprintf(buf, "%d\n", data->fan_fault >> shift);
-}
-
-static ssize_t show_over_temp(struct device *dev, struct device_attribute *da,
- char *buf)
-{
- struct ym2651y_data *data = ym2651y_update_device(dev);
-
- if (!data->valid) {
- return 0;
- }
-
- return sprintf(buf, "%d\n", data->over_temp >> 7);
-}
-
-static ssize_t show_ascii(struct device *dev, struct device_attribute *da,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct ym2651y_data *data = ym2651y_update_device(dev);
- u8 *ptr = NULL;
-
- if (!data->valid) {
- return 0;
- }
-
- switch (attr->index) {
- case PSU_FAN_DIRECTION: /* psu_fan_dir */
- ptr = data->fan_dir + 1; /* Skip the first byte since it is the length of string. */
- break;
- case PSU_MFR_ID: /* psu_mfr_id */
- ptr = data->mfr_id + 1; /* The first byte is the count byte of string. */;
- break;
- case PSU_MFR_MODEL: /* psu_mfr_model */
- ptr = data->mfr_model + 1; /* The first byte is the count byte of string. */
- break;
- case PSU_MFR_REVISION: /* psu_mfr_revision */
- ptr = data->mfr_revsion + 1; /* The first byte is the count byte of string. */
- break;
- default:
- return 0;
- }
-
- return sprintf(buf, "%s\n", ptr);
-}
-
-static ssize_t show_vout_by_mode(struct device *dev, struct device_attribute *da,
- char *buf)
-{
- struct ym2651y_data *data = ym2651y_update_device(dev);
- int exponent, mantissa;
- int multiplier = 1000;
-
- if (!data->valid) {
- return 0;
- }
-
- exponent = two_complement_to_int(data->vout_mode, 5, 0x1f);
- mantissa = data->v_out;
-
- return (exponent > 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) :
- sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent));
-}
-
-static ssize_t show_vout(struct device *dev, struct device_attribute *da,
- char *buf)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct ym2651y_data *data = i2c_get_clientdata(client);
-
- if (data->chip == YM2401) {
- return show_vout_by_mode(dev, da, buf);
- }
-
- return show_linear(dev, da, buf);
-}
-
-static const struct attribute_group ym2651y_group = {
- .attrs = ym2651y_attributes,
-};
-
-static int ym2651y_probe(struct i2c_client *client,
- const struct i2c_device_id *dev_id)
-{
- struct ym2651y_data *data;
- int status;
-
- if (!i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_BYTE_DATA |
- I2C_FUNC_SMBUS_WORD_DATA |
- I2C_FUNC_SMBUS_I2C_BLOCK)) {
- status = -EIO;
- goto exit;
- }
-
- data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL);
- if (!data) {
- status = -ENOMEM;
- goto exit;
- }
-
- i2c_set_clientdata(client, data);
- mutex_init(&data->update_lock);
- data->chip = dev_id->driver_data;
- dev_info(&client->dev, "chip found\n");
-
- /* Register sysfs hooks */
- status = sysfs_create_group(&client->dev.kobj, &ym2651y_group);
- if (status) {
- goto exit_free;
- }
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- status = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- dev_info(&client->dev, "%s: psu '%s'\n",
- dev_name(data->hwmon_dev), client->name);
-
- return 0;
-
-exit_remove:
- sysfs_remove_group(&client->dev.kobj, &ym2651y_group);
-exit_free:
- kfree(data);
-exit:
-
- return status;
-}
-
-static int ym2651y_remove(struct i2c_client *client)
-{
- struct ym2651y_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &ym2651y_group);
- kfree(data);
-
- return 0;
-}
-
-static const struct i2c_device_id ym2651y_id[] = {
- { "ym2651", YM2651 },
- { "ym2401", YM2401 },
- {}
-};
-MODULE_DEVICE_TABLE(i2c, ym2651y_id);
-
-static struct i2c_driver ym2651y_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "ym2651",
- },
- .probe = ym2651y_probe,
- .remove = ym2651y_remove,
- .id_table = ym2651y_id,
- .address_list = normal_i2c,
-};
-
-static int ym2651y_read_byte(struct i2c_client *client, u8 reg)
-{
- return i2c_smbus_read_byte_data(client, reg);
-}
-
-static int ym2651y_read_word(struct i2c_client *client, u8 reg)
-{
- return i2c_smbus_read_word_data(client, reg);
-}
-
-static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value)
-{
- return i2c_smbus_write_word_data(client, reg, value);
-}
-
-static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data,
- int data_len)
-{
- int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data);
-
- if (unlikely(result < 0))
- goto abort;
- if (unlikely(result != data_len)) {
- result = -EIO;
- goto abort;
- }
-
- result = 0;
-
-abort:
- return result;
-}
-
-struct reg_data_byte {
- u8 reg;
- u8 *value;
-};
-
-struct reg_data_word {
- u8 reg;
- u16 *value;
-};
-
-static struct ym2651y_data *ym2651y_update_device(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct ym2651y_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, status, length;
- u8 command, buf;
- struct reg_data_byte regs_byte[] = { {0x19, &data->capability},
- {0x20, &data->vout_mode},
- {0x7d, &data->over_temp},
- {0x81, &data->fan_fault},
- {0x98, &data->pmbus_revision}};
- struct reg_data_word regs_word[] = { {0x79, &data->status_word},
- {0x8b, &data->v_out},
- {0x8c, &data->i_out},
- {0x96, &data->p_out},
- {0x8d, &data->temp},
- {0x3b, &(data->fan_duty_cycle[0])},
- {0x3c, &(data->fan_duty_cycle[1])},
- {0x90, &data->fan_speed},
- {0xa0, &data->mfr_vin_min},
- {0xa1, &data->mfr_vin_max},
- {0xa2, &data->mfr_iin_max},
- {0xa3, &data->mfr_pin_max},
- {0xa4, &data->mfr_vout_min},
- {0xa5, &data->mfr_vout_max},
- {0xa6, &data->mfr_iout_max},
- {0xa7, &data->mfr_pout_max}};
-
- dev_dbg(&client->dev, "Starting ym2651 update\n");
- data->valid = 0;
-
- /* Read byte data */
- for (i = 0; i < ARRAY_SIZE(regs_byte); i++) {
- status = ym2651y_read_byte(client, regs_byte[i].reg);
-
- if (status < 0) {
- dev_dbg(&client->dev, "reg %d, err %d\n",
- regs_byte[i].reg, status);
- goto exit;
- }
- else {
- *(regs_byte[i].value) = status;
- }
- }
-
- /* Read word data */
- for (i = 0; i < ARRAY_SIZE(regs_word); i++) {
- status = ym2651y_read_word(client, regs_word[i].reg);
-
- if (status < 0) {
- dev_dbg(&client->dev, "reg %d, err %d\n",
- regs_word[i].reg, status);
- goto exit;
- }
- else {
- *(regs_word[i].value) = status;
- }
- }
-
- /* Read fan_direction */
- command = 0xC3;
- status = ym2651y_read_block(client, command, data->fan_dir,
- ARRAY_SIZE(data->fan_dir)-1);
- data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0';
-
- if (status < 0) {
- dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
- goto exit;
- }
-
- /* Read mfr_id */
- command = 0x99;
- status = ym2651y_read_block(client, command, data->mfr_id,
- ARRAY_SIZE(data->mfr_id)-1);
- data->mfr_id[ARRAY_SIZE(data->mfr_id)-1] = '\0';
-
- if (status < 0) {
- dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
- goto exit;
- }
-
- /* Read mfr_model */
- command = 0x9a;
- length = 1;
-
- /* Read first byte to determine the length of data */
- status = ym2651y_read_block(client, command, &buf, length);
- if (status < 0) {
- dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
- goto exit;
- }
-
- status = ym2651y_read_block(client, command, data->mfr_model, buf+1);
- data->mfr_model[buf+1] = '\0';
-
- if (status < 0) {
- dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
- goto exit;
- }
-
- /* Read mfr_revsion */
- command = 0x9b;
- status = ym2651y_read_block(client, command, data->mfr_revsion,
- ARRAY_SIZE(data->mfr_revsion)-1);
- data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0';
-
- if (status < 0) {
- dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
- goto exit;
- }
-
- data->last_updated = jiffies;
- data->valid = 1;
- }
-
-exit:
- mutex_unlock(&data->update_lock);
-
- return data;
-}
-
-static int __init ym2651y_init(void)
-{
- return i2c_add_driver(&ym2651y_driver);
-}
-
-static void __exit ym2651y_exit(void)
-{
- i2c_del_driver(&ym2651y_driver);
-}
-
-MODULE_AUTHOR("Brandon Chuang ");
-MODULE_DESCRIPTION("3Y Power YM-2651Y driver");
-MODULE_LICENSE("GPL");
-
-module_init(ym2651y_init);
-module_exit(ym2651y_exit);
-
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/modules/ym2651y.c
new file mode 120000
index 0000000000..f4d67640cc
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5812-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/as5812-54t/service/as5812-platform-init.service b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/service/as5812-platform-init.service
index 30c1703dc4..91c9adb01c 100755
--- a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/service/as5812-platform-init.service
+++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/service/as5812-platform-init.service
@@ -1,13 +1,17 @@
[Unit]
-Description=Accton AS5712-54T Platform initialization service
+Description=Accton AS5812-54X Platform Monitoring service
Before=pmon.service
+After=sysinit.target
DefaultDependencies=no
[Service]
-Type=oneshot
-ExecStart=/usr/local/bin/accton_as5812_54t_util.py install
-ExecStop=/usr/local/bin/accton_as5812_54t_util.py clean
-RemainAfterExit=yes
+Type=simple
+ExecStartPre=/usr/local/bin/accton_as5812_util.py install
+ExecStart=/usr/local/bin/accton_as5812_monitor.py
+#RemainAfterExit=yes
+
+# Resource Limitations
+LimitCORE=infinity
[Install]
WantedBy=multi-user.target
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/setup.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/setup.py
new file mode 100755
index 0000000000..0af58ba919
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/setup.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+
+import os
+import sys
+from setuptools import setup
+os.listdir
+
+setup(
+ name='as5812_54t',
+ version='1.0',
+ description='Module to initialize Accton AS5812-54X platforms',
+
+ packages=['as5812_54t'],
+ package_dir={'as5812_54t': 'as5812-54t/classes'},
+)
+
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_monitor.py
new file mode 100755
index 0000000000..c8574557b3
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_monitor.py
@@ -0,0 +1,213 @@
+#!/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-54t.
+# ------------------------------------------------------------------
+
+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
+ import signal
+ from tabulate import tabulate
+ from as5812_54t.fanutil import FanUtil
+ from as5812_54t.thermalutil import ThermalUtil
+except ImportError as e:
+ raise ImportError('%s - required module not found' % str(e))
+
+# Deafults
+VERSION = '1.0'
+FUNCTION_NAME = 'accton_as5812_monitor'
+DUTY_MAX = 100
+
+global log_file
+global log_console
+
+# Make a class we can use to capture stdout and sterr in the log
+class accton_as5812_monitor(object):
+ # static temp var
+ _ori_temp = 0
+ _new_perc = 0
+
+ llog = logging.getLogger("["+FUNCTION_NAME+"]")
+ def __init__(self, log_console, log_file):
+ """Needs a logger and a logger level."""
+
+ formatter = logging.Formatter('%(name)s %(message)s')
+ sys_handler = logging.handlers.SysLogHandler(address = '/dev/log')
+ sys_handler.setFormatter(formatter)
+ sys_handler.ident = 'common'
+ sys_handler.setLevel(logging.WARNING) #only fatal for syslog
+ self.llog.addHandler(sys_handler)
+ self.llog.setLevel(logging.DEBUG)
+
+ if log_file:
+ fh = logging.FileHandler(log_file)
+ fh.setLevel(logging.INFO)
+ formatter = logging.Formatter('%(asctime)-15s %(name)s %(message)s')
+ fh.setFormatter(formatter)
+ self.llog.addHandler(fh)
+
+ # set up logging to console
+ if log_console:
+ console = logging.StreamHandler()
+ console.setLevel(logging.DEBUG) #For debugging
+ formatter = logging.Formatter('%(asctime)-15s %(name)s %(message)s')
+ console.setFormatter(formatter)
+ self.llog.addHandler(console)
+
+ 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()
+
+ temp1 = thermal.get_thermal_1_val()
+ if temp1 is None:
+ return False
+
+ temp2 = thermal.get_thermal_2_val()
+ if temp2 is None:
+ return False
+
+ new_temp = (temp1 + temp2) / 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 or fan_stat is False:
+ self._new_perc = FAN_LEV1_SPEED_PERC
+ self.llog.error('SET new_perc to %d (FAN fault. fan_num:%d)', self._new_perc, x)
+ break
+ else:
+ self.llog.debug('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:
+ self.llog.debug('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
+ self.llog.debug('THERMAL temp UP %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp)
+ else:
+ is_up = False
+ self.llog.debug('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
+ self.llog.debug('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
+ self.llog.debug('SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp)
+
+ cur_perc = fan.get_fan_duty_cycle(fan.get_idx_fan_start())
+ if cur_perc == self._new_perc:
+ self.llog.debug('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(fan.get_idx_fan_start(), self._new_perc)
+ if set_stat is True:
+ self.llog.debug('PASS. set_fan_duty_cycle (%d)', self._new_perc)
+ else:
+ self.llog.error('FAIL. set_fan_duty_cycle (%d)', self._new_perc)
+
+ self.llog.debug('GET. ori_perc is %d. ori_temp is %d', cur_perc, self._ori_temp)
+ self._ori_temp = new_temp
+ self.llog.info('UPDATE. ori_perc to %d. ori_temp to %d', cur_perc, self._ori_temp)
+
+ return True
+
+def sig_handler(signum, frame):
+ fan = FanUtil()
+ logging.critical('Cause signal %d, set fan speed max.', signum)
+ fan.set_fan_duty_cycle(fan.get_idx_fan_start(), DUTY_MAX)
+ sys.exit(0)
+
+def main(argv):
+ log_file = '%s.log' % FUNCTION_NAME
+ log_console = 0
+ log_file = ""
+ if len(sys.argv) != 1:
+ try:
+ opts, args = getopt.getopt(argv,'hdl')
+ 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'):
+ log_console = 1
+ elif opt in ('-l'):
+ log_file = '%s.log' % sys.argv[0]
+
+ signal.signal(signal.SIGINT, sig_handler)
+ signal.signal(signal.SIGTERM, sig_handler)
+ monitor = accton_as5812_monitor(log_console, log_file)
+
+ #time.sleep(100)
+ # Loop forever, doing something useful hopefully:
+ while True:
+ monitor.manage_fans()
+ time.sleep(10)
+
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
diff --git a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_54t_util.py b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_util.py
similarity index 97%
rename from platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_54t_util.py
rename to platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_util.py
index 4e9b079508..7a2bec3a01 100755
--- a/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_54t_util.py
+++ b/platform/broadcom/sonic-platform-modules-accton/as5812-54t/utils/accton_as5812_util.py
@@ -151,18 +151,12 @@ def driver_check():
if len(lsmod) ==0:
return False
return True
-
-
- self.insmod("accton_i2c_cpld")
- self.insmod("cpr_4011_4mxx")
- self.insmod("ym2651y")
- for m in [ "sfp", "psu", "fan", "leds" ]:
- self.insmod("x86-64-accton-as5812-54t-%s" % m)
kos = [
'modprobe i2c_dev',
'modprobe i2c_mux_pca954x force_deselect_on_exit=1',
-'modprobe accton_i2c_cpld' ,
+'modprobe optoe',
+'modprobe x86-64-accton-as5812-54t-cpld' ,
'modprobe cpr_4011_4mxx' ,
'modprobe ym2651y' ,
'modprobe x86-64-accton-as5812-54t-sfp' ,
@@ -172,6 +166,7 @@ kos = [
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:
@@ -184,6 +179,10 @@ def driver_uninstall():
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:
@@ -212,7 +211,7 @@ sfp_1st_index = 48
mknod =[
'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-0/new_device',
'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-1/new_device' ,
-'echo accton_i2c_cpld 0x60 > /sys/bus/i2c/devices/i2c-0/new_device',
+'echo as5812_54t_cpld 0x60 > /sys/bus/i2c/devices/i2c-0/new_device',
'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-15/new_device',
'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-16/new_device',
'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-17/new_device',
@@ -229,7 +228,7 @@ mknod =[
mknod2 =[
'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-1/new_device',
'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-0/new_device' ,
-'echo accton_i2c_cpld 0x60 > /sys/bus/i2c/devices/i2c-1/new_device',
+'echo as5812_54t_cpld 0x60 > /sys/bus/i2c/devices/i2c-1/new_device',
'echo lm75 0x48 > /sys/bus/i2c/devices/i2c-15/new_device',
'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-16/new_device',
'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-17/new_device',
@@ -286,8 +285,8 @@ def device_install():
print output
if FORCE == 0:
return status
- for i in range(sfp_1st_index,len(sfp_map)):
- status, output =log_os_system("echo sfp"+str(i+1)+" 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1)
+ 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:
diff --git a/platform/broadcom/sonic-platform-modules-accton/debian/control b/platform/broadcom/sonic-platform-modules-accton/debian/control
index e8bedd9081..2b3c1af3d8 100755
--- a/platform/broadcom/sonic-platform-modules-accton/debian/control
+++ b/platform/broadcom/sonic-platform-modules-accton/debian/control
@@ -53,6 +53,10 @@ Package: sonic-platform-accton-as5812-54x
Architecture: amd64
Description: kernel modules for platform devices such as fan, led, sfp
+Package: sonic-platform-accton-as5812-54t
+Architecture: amd64
+Description: kernel modules for platform devices such as fan, led, sfp
+
Package: sonic-platform-accton-as5835-54x
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 11e5b10ae4..f1d730b577 100755
--- a/platform/broadcom/sonic-platform-modules-accton/debian/rules
+++ b/platform/broadcom/sonic-platform-modules-accton/debian/rules
@@ -21,7 +21,7 @@ KERNEL_SRC := /lib/modules/$(KVERSION)
MOD_SRC_DIR:= $(shell pwd)
MODULE_DIRS := as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x
MODULE_DIRS += as7326-56x as6712-32x as7726-32x as4630-54pe minipack as5812-54x
-MODULE_DIRS += as5835-54x as9716-32d as5835-54t as7312-54xs as7315-27xb
+MODULE_DIRS += as5835-54x as9716-32d as5835-54t as7312-54xs as7315-27xb as5812-54x
MODULE_DIR := modules
UTILS_DIR := utils
SERVICE_DIR := service