[device][platform] add platform as5835-54x, accton. (#2977)
Signed-off-by: brandon_chuang <brandon_chuang@edge-core.com>
This commit is contained in:
parent
f7774bec6b
commit
4073e8fa64
@ -0,0 +1,55 @@
|
|||||||
|
# name lanes alias index
|
||||||
|
Ethernet0 1 twentyfiveGigE1 1
|
||||||
|
Ethernet1 2 twentyfiveGigE2 2
|
||||||
|
Ethernet2 3 twentyfiveGigE3 3
|
||||||
|
Ethernet3 4 twentyfiveGigE4 4
|
||||||
|
Ethernet4 5 twentyfiveGigE5 5
|
||||||
|
Ethernet5 6 twentyfiveGigE6 6
|
||||||
|
Ethernet6 7 twentyfiveGigE7 7
|
||||||
|
Ethernet7 8 twentyfiveGigE8 8
|
||||||
|
Ethernet8 9 twentyfiveGigE9 9
|
||||||
|
Ethernet9 10 twentyfiveGigE10 10
|
||||||
|
Ethernet10 11 twentyfiveGigE11 11
|
||||||
|
Ethernet11 12 twentyfiveGigE12 12
|
||||||
|
Ethernet12 13 twentyfiveGigE13 13
|
||||||
|
Ethernet13 14 twentyfiveGigE14 14
|
||||||
|
Ethernet14 15 twentyfiveGigE15 15
|
||||||
|
Ethernet15 16 twentyfiveGigE16 16
|
||||||
|
Ethernet16 17 twentyfiveGigE17 17
|
||||||
|
Ethernet17 18 twentyfiveGigE18 18
|
||||||
|
Ethernet18 19 twentyfiveGigE19 19
|
||||||
|
Ethernet19 20 twentyfiveGigE20 20
|
||||||
|
Ethernet20 21 twentyfiveGigE21 21
|
||||||
|
Ethernet21 22 twentyfiveGigE22 22
|
||||||
|
Ethernet22 23 twentyfiveGigE23 23
|
||||||
|
Ethernet23 24 twentyfiveGigE24 24
|
||||||
|
Ethernet24 53 twentyfiveGigE25 25
|
||||||
|
Ethernet25 54 twentyfiveGigE26 26
|
||||||
|
Ethernet26 55 twentyfiveGigE27 27
|
||||||
|
Ethernet27 56 twentyfiveGigE28 28
|
||||||
|
Ethernet28 57 twentyfiveGigE29 29
|
||||||
|
Ethernet29 58 twentyfiveGigE30 30
|
||||||
|
Ethernet30 59 twentyfiveGigE31 31
|
||||||
|
Ethernet31 60 twentyfiveGigE32 32
|
||||||
|
Ethernet32 61 twentyfiveGigE33 33
|
||||||
|
Ethernet33 62 twentyfiveGigE34 34
|
||||||
|
Ethernet34 63 twentyfiveGigE35 35
|
||||||
|
Ethernet35 64 twentyfiveGigE36 36
|
||||||
|
Ethernet36 65 twentyfiveGigE37 37
|
||||||
|
Ethernet37 66 twentyfiveGigE38 38
|
||||||
|
Ethernet38 67 twentyfiveGigE39 39
|
||||||
|
Ethernet39 68 twentyfiveGigE40 40
|
||||||
|
Ethernet40 69 twentyfiveGigE41 41
|
||||||
|
Ethernet41 70 twentyfiveGigE42 42
|
||||||
|
Ethernet42 71 twentyfiveGigE43 43
|
||||||
|
Ethernet43 72 twentyfiveGigE44 44
|
||||||
|
Ethernet44 73 twentyfiveGigE45 45
|
||||||
|
Ethernet45 74 twentyfiveGigE46 46
|
||||||
|
Ethernet46 75 twentyfiveGigE47 47
|
||||||
|
Ethernet47 76 twentyfiveGigE48 48
|
||||||
|
Ethernet48 29,30,31,32 hundredGigE49 49
|
||||||
|
Ethernet52 33,34,35,36 hundredGigE50 53
|
||||||
|
Ethernet56 37,38,39,40 hundredGigE51 57
|
||||||
|
Ethernet60 41,42,43,44 hundredGigE52 61
|
||||||
|
Ethernet64 45,46,47,48 hundredGigE53 65
|
||||||
|
Ethernet68 49,50,51,52 hundredGigE54 69
|
@ -0,0 +1 @@
|
|||||||
|
SAI_INIT_CONFIG_FILE=/etc/bcm/td3-as5835-48x10G+6x100G.config.bcm
|
@ -0,0 +1,467 @@
|
|||||||
|
#polarity/lanemap is using TH2 style.
|
||||||
|
core_clock_frequency=1525
|
||||||
|
dpp_clock_ratio=2:3
|
||||||
|
|
||||||
|
ptp_ts_pll_fref=50000000
|
||||||
|
ptp_bs_fref_0=50000000
|
||||||
|
ptp_bs_fref_1=50000000
|
||||||
|
|
||||||
|
oversubscribe_mode=1
|
||||||
|
|
||||||
|
pbmp_xport_xe=0x1FFFFFFFFFFFFFFFE
|
||||||
|
|
||||||
|
parity_enable=0
|
||||||
|
mem_cache_enable=0
|
||||||
|
|
||||||
|
l2_mem_entries=32768
|
||||||
|
#l3_mem_entries=49152
|
||||||
|
#fpem_mem_entries=16384
|
||||||
|
l2xmsg_mode=1
|
||||||
|
|
||||||
|
#FC0
|
||||||
|
dport_map_port_1=1
|
||||||
|
dport_map_port_2=2
|
||||||
|
dport_map_port_3=3
|
||||||
|
dport_map_port_4=4
|
||||||
|
portmap_1=1:10
|
||||||
|
portmap_2=2:10
|
||||||
|
portmap_3=3:10
|
||||||
|
portmap_4=4:10
|
||||||
|
phy_chain_rx_lane_map_physical{1.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{2.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{3.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{4.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{1.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{2.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{3.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{4.0}=0x0123
|
||||||
|
phy_chain_rx_polarity_flip_physical{1.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{2.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{3.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{4.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{1.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{2.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{3.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{4.0}=0x1
|
||||||
|
|
||||||
|
#FC1
|
||||||
|
dport_map_port_5=5
|
||||||
|
dport_map_port_6=6
|
||||||
|
dport_map_port_7=7
|
||||||
|
dport_map_port_8=8
|
||||||
|
portmap_5=5:10
|
||||||
|
portmap_6=6:10
|
||||||
|
portmap_7=7:10
|
||||||
|
portmap_8=8:10
|
||||||
|
phy_chain_rx_lane_map_physical{5.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{6.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{7.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{8.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{5.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{6.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{7.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{8.0}=0x0123
|
||||||
|
phy_chain_rx_polarity_flip_physical{5.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{6.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{7.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{8.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{5.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{6.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{7.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{8.0}=0x1
|
||||||
|
|
||||||
|
#FC2
|
||||||
|
dport_map_port_9=9
|
||||||
|
dport_map_port_10=10
|
||||||
|
dport_map_port_11=11
|
||||||
|
dport_map_port_12=12
|
||||||
|
portmap_9=9:10
|
||||||
|
portmap_10=10:10
|
||||||
|
portmap_11=11:10
|
||||||
|
portmap_12=12:10
|
||||||
|
phy_chain_rx_lane_map_physical{9.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{10.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{11.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{12.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{9.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{10.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{11.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{12.0}=0x0123
|
||||||
|
phy_chain_rx_polarity_flip_physical{9.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{10.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{11.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{12.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{9.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{10.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{11.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{12.0}=0x1
|
||||||
|
|
||||||
|
#FC3
|
||||||
|
dport_map_port_13=13
|
||||||
|
dport_map_port_14=14
|
||||||
|
dport_map_port_15=15
|
||||||
|
dport_map_port_16=16
|
||||||
|
portmap_13=13:10
|
||||||
|
portmap_14=14:10
|
||||||
|
portmap_15=15:10
|
||||||
|
portmap_16=16:10
|
||||||
|
phy_chain_rx_lane_map_physical{13.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{14.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{15.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{16.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{13.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{14.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{15.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{16.0}=0x0123
|
||||||
|
phy_chain_rx_polarity_flip_physical{13.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{14.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{15.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{16.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{13.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{14.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{15.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{16.0}=0x1
|
||||||
|
|
||||||
|
#FC4
|
||||||
|
dport_map_port_17=17
|
||||||
|
dport_map_port_18=18
|
||||||
|
dport_map_port_19=19
|
||||||
|
dport_map_port_20=20
|
||||||
|
portmap_17=17:10
|
||||||
|
portmap_18=18:10
|
||||||
|
portmap_19=19:10
|
||||||
|
portmap_20=20:10
|
||||||
|
phy_chain_rx_lane_map_physical{17.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{18.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{19.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{20.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{17.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{18.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{19.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{20.0}=0x0123
|
||||||
|
phy_chain_rx_polarity_flip_physical{17.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{18.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{19.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{20.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{17.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{18.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{19.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{20.0}=0x1
|
||||||
|
|
||||||
|
#FC5
|
||||||
|
dport_map_port_21=21
|
||||||
|
dport_map_port_22=22
|
||||||
|
dport_map_port_23=23
|
||||||
|
dport_map_port_24=24
|
||||||
|
portmap_21=21:10
|
||||||
|
portmap_22=22:10
|
||||||
|
portmap_23=23:10
|
||||||
|
portmap_24=24:10
|
||||||
|
phy_chain_rx_lane_map_physical{21.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{22.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{23.0}=0x0123
|
||||||
|
phy_chain_rx_lane_map_physical{24.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{21.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{22.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{23.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{24.0}=0x0123
|
||||||
|
phy_chain_rx_polarity_flip_physical{21.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{22.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{23.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{24.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{21.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{22.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{23.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{24.0}=0x1
|
||||||
|
|
||||||
|
#FC6
|
||||||
|
|
||||||
|
#FC7
|
||||||
|
dport_map_port_25=50
|
||||||
|
portmap_25=29:100:4
|
||||||
|
phy_chain_rx_lane_map_physical{29.0}=0x1302
|
||||||
|
phy_chain_rx_lane_map_physical{30.0}=0x1302
|
||||||
|
phy_chain_rx_lane_map_physical{31.0}=0x1302
|
||||||
|
phy_chain_rx_lane_map_physical{32.0}=0x1302
|
||||||
|
phy_chain_tx_lane_map_physical{29.0}=0x2031
|
||||||
|
phy_chain_tx_lane_map_physical{30.0}=0x2031
|
||||||
|
phy_chain_tx_lane_map_physical{31.0}=0x2031
|
||||||
|
phy_chain_tx_lane_map_physical{32.0}=0x2031
|
||||||
|
phy_chain_rx_polarity_flip_physical{29.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{30.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{31.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{32.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{29.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{30.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{31.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{32.0}=0x1
|
||||||
|
|
||||||
|
#FC8
|
||||||
|
dport_map_port_26=51
|
||||||
|
portmap_26=33:100:4
|
||||||
|
phy_chain_rx_lane_map_physical{33.0}=0x1203
|
||||||
|
phy_chain_rx_lane_map_physical{34.0}=0x1203
|
||||||
|
phy_chain_rx_lane_map_physical{35.0}=0x1203
|
||||||
|
phy_chain_rx_lane_map_physical{36.0}=0x1203
|
||||||
|
phy_chain_tx_lane_map_physical{33.0}=0x3120
|
||||||
|
phy_chain_tx_lane_map_physical{34.0}=0x3120
|
||||||
|
phy_chain_tx_lane_map_physical{35.0}=0x3120
|
||||||
|
phy_chain_tx_lane_map_physical{36.0}=0x3120
|
||||||
|
phy_chain_rx_polarity_flip_physical{33.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{34.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{35.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{36.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{33.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{34.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{35.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{36.0}=0x0
|
||||||
|
|
||||||
|
#FC9
|
||||||
|
dport_map_port_27=49
|
||||||
|
dport_map_port_28=52
|
||||||
|
dport_map_port_29=53
|
||||||
|
dport_map_port_30=54
|
||||||
|
portmap_27=37:100:4
|
||||||
|
phy_chain_rx_lane_map_physical{37.0}=0x2130
|
||||||
|
phy_chain_rx_lane_map_physical{38.0}=0x2130
|
||||||
|
phy_chain_rx_lane_map_physical{39.0}=0x2130
|
||||||
|
phy_chain_rx_lane_map_physical{40.0}=0x2130
|
||||||
|
phy_chain_tx_lane_map_physical{37.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{38.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{39.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{40.0}=0x3210
|
||||||
|
phy_chain_rx_polarity_flip_physical{37.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{38.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{39.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{40.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{37.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{38.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{39.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{40.0}=0x0
|
||||||
|
|
||||||
|
#FC10
|
||||||
|
dport_map_port_33=57
|
||||||
|
portmap_33=41:100:4
|
||||||
|
phy_chain_rx_lane_map_physical{41.0}=0x1320
|
||||||
|
phy_chain_rx_lane_map_physical{42.0}=0x1320
|
||||||
|
phy_chain_rx_lane_map_physical{43.0}=0x1320
|
||||||
|
phy_chain_rx_lane_map_physical{44.0}=0x1320
|
||||||
|
phy_chain_tx_lane_map_physical{41.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{42.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{43.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{44.0}=0x3210
|
||||||
|
phy_chain_rx_polarity_flip_physical{41.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{42.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{43.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{44.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{41.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{42.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{43.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{44.0}=0x0
|
||||||
|
|
||||||
|
#FC11
|
||||||
|
dport_map_port_34=56
|
||||||
|
portmap_34=45:100:4
|
||||||
|
phy_chain_rx_lane_map_physical{45.0}=0x3201
|
||||||
|
phy_chain_rx_lane_map_physical{46.0}=0x3201
|
||||||
|
phy_chain_rx_lane_map_physical{47.0}=0x3201
|
||||||
|
phy_chain_rx_lane_map_physical{48.0}=0x3201
|
||||||
|
phy_chain_tx_lane_map_physical{45.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{46.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{47.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{48.0}=0x3210
|
||||||
|
phy_chain_rx_polarity_flip_physical{45.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{46.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{47.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{48.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{45.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{46.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{47.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{48.0}=0x0
|
||||||
|
|
||||||
|
#FC12
|
||||||
|
dport_map_port_35=55
|
||||||
|
dport_map_port_36=58
|
||||||
|
dport_map_port_37=59
|
||||||
|
dport_map_port_38=60
|
||||||
|
portmap_35=49:100:4
|
||||||
|
phy_chain_rx_lane_map_physical{49.0}=0x0312
|
||||||
|
phy_chain_rx_lane_map_physical{50.0}=0x0312
|
||||||
|
phy_chain_rx_lane_map_physical{51.0}=0x0312
|
||||||
|
phy_chain_rx_lane_map_physical{52.0}=0x0312
|
||||||
|
phy_chain_tx_lane_map_physical{49.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{50.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{51.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{52.0}=0x3210
|
||||||
|
phy_chain_rx_polarity_flip_physical{49.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{50.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{51.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{52.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{49.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{50.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{51.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{52.0}=0x0
|
||||||
|
|
||||||
|
#FC13
|
||||||
|
dport_map_port_39=25
|
||||||
|
dport_map_port_40=26
|
||||||
|
dport_map_port_41=27
|
||||||
|
dport_map_port_42=28
|
||||||
|
portmap_39=53:10
|
||||||
|
portmap_40=54:10
|
||||||
|
portmap_41=55:10
|
||||||
|
portmap_42=56:10
|
||||||
|
phy_chain_rx_lane_map_physical{53.0}=0x3120
|
||||||
|
phy_chain_rx_lane_map_physical{54.0}=0x3120
|
||||||
|
phy_chain_rx_lane_map_physical{55.0}=0x3120
|
||||||
|
phy_chain_rx_lane_map_physical{56.0}=0x3120
|
||||||
|
phy_chain_tx_lane_map_physical{53.0}=0x3102
|
||||||
|
phy_chain_tx_lane_map_physical{54.0}=0x3102
|
||||||
|
phy_chain_tx_lane_map_physical{55.0}=0x3102
|
||||||
|
phy_chain_tx_lane_map_physical{56.0}=0x3102
|
||||||
|
phy_chain_rx_polarity_flip_physical{53.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{54.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{55.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{56.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{53.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{54.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{55.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{56.0}=0x1
|
||||||
|
|
||||||
|
#FC14
|
||||||
|
dport_map_port_43=29
|
||||||
|
dport_map_port_44=30
|
||||||
|
dport_map_port_45=31
|
||||||
|
dport_map_port_46=32
|
||||||
|
portmap_43=57:10
|
||||||
|
portmap_44=58:10
|
||||||
|
portmap_45=59:10
|
||||||
|
portmap_46=60:10
|
||||||
|
phy_chain_rx_lane_map_physical{57.0}=0x3210
|
||||||
|
phy_chain_rx_lane_map_physical{58.0}=0x3210
|
||||||
|
phy_chain_rx_lane_map_physical{59.0}=0x3210
|
||||||
|
phy_chain_rx_lane_map_physical{60.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{57.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{58.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{59.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{60.0}=0x3210
|
||||||
|
phy_chain_rx_polarity_flip_physical{57.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{58.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{59.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{60.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{57.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{58.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{59.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{60.0}=0x1
|
||||||
|
|
||||||
|
#FC15
|
||||||
|
dport_map_port_47=33
|
||||||
|
dport_map_port_48=34
|
||||||
|
dport_map_port_49=35
|
||||||
|
dport_map_port_50=36
|
||||||
|
portmap_47=61:10
|
||||||
|
portmap_48=62:10
|
||||||
|
portmap_49=63:10
|
||||||
|
portmap_50=64:10
|
||||||
|
phy_chain_rx_lane_map_physical{61.0}=0x3210
|
||||||
|
phy_chain_rx_lane_map_physical{62.0}=0x3210
|
||||||
|
phy_chain_rx_lane_map_physical{63.0}=0x3210
|
||||||
|
phy_chain_rx_lane_map_physical{64.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{61.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{62.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{63.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{64.0}=0x3210
|
||||||
|
phy_chain_rx_polarity_flip_physical{61.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{62.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{63.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{64.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{61.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{62.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{63.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{64.0}=0x1
|
||||||
|
|
||||||
|
#FC16
|
||||||
|
dport_map_port_51=37
|
||||||
|
dport_map_port_52=38
|
||||||
|
dport_map_port_53=39
|
||||||
|
dport_map_port_54=40
|
||||||
|
portmap_51=65:10
|
||||||
|
portmap_52=66:10
|
||||||
|
portmap_53=67:10
|
||||||
|
portmap_54=68:10
|
||||||
|
phy_chain_rx_lane_map_physical{65.0}=0x3210
|
||||||
|
phy_chain_rx_lane_map_physical{66.0}=0x3210
|
||||||
|
phy_chain_rx_lane_map_physical{67.0}=0x3210
|
||||||
|
phy_chain_rx_lane_map_physical{68.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{65.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{66.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{67.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{68.0}=0x3210
|
||||||
|
phy_chain_rx_polarity_flip_physical{65.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{66.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{67.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{68.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{65.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{66.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{67.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{68.0}=0x1
|
||||||
|
|
||||||
|
#FC17
|
||||||
|
dport_map_port_55=41
|
||||||
|
dport_map_port_56=42
|
||||||
|
dport_map_port_57=43
|
||||||
|
dport_map_port_58=44
|
||||||
|
portmap_55=69:10
|
||||||
|
portmap_56=70:10
|
||||||
|
portmap_57=71:10
|
||||||
|
portmap_58=72:10
|
||||||
|
phy_chain_rx_lane_map_physical{69.0}=0x3210
|
||||||
|
phy_chain_rx_lane_map_physical{70.0}=0x3210
|
||||||
|
phy_chain_rx_lane_map_physical{71.0}=0x3210
|
||||||
|
phy_chain_rx_lane_map_physical{72.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{69.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{70.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{71.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{72.0}=0x3210
|
||||||
|
phy_chain_rx_polarity_flip_physical{69.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{70.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{71.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{72.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{69.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{70.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{71.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{72.0}=0x1
|
||||||
|
|
||||||
|
#FC18
|
||||||
|
dport_map_port_59=45
|
||||||
|
dport_map_port_60=46
|
||||||
|
dport_map_port_61=47
|
||||||
|
dport_map_port_62=48
|
||||||
|
portmap_59=73:10
|
||||||
|
portmap_60=74:10
|
||||||
|
portmap_61=75:10
|
||||||
|
portmap_62=76:10
|
||||||
|
phy_chain_rx_lane_map_physical{73.0}=0x3210
|
||||||
|
phy_chain_rx_lane_map_physical{74.0}=0x3210
|
||||||
|
phy_chain_rx_lane_map_physical{75.0}=0x3210
|
||||||
|
phy_chain_rx_lane_map_physical{76.0}=0x3210
|
||||||
|
phy_chain_tx_lane_map_physical{73.0}=0x0231
|
||||||
|
phy_chain_tx_lane_map_physical{74.0}=0x0231
|
||||||
|
phy_chain_tx_lane_map_physical{75.0}=0x0231
|
||||||
|
phy_chain_tx_lane_map_physical{76.0}=0x0231
|
||||||
|
phy_chain_rx_polarity_flip_physical{73.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{74.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{75.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{76.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{73.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{74.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{75.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{76.0}=0x0
|
||||||
|
|
||||||
|
#FC19
|
||||||
|
|
||||||
|
dport_map_port_64=64
|
||||||
|
portmap_64=81:10:m
|
||||||
|
phy_chain_rx_polarity_flip_physical{81.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{81.0}=0x1
|
||||||
|
|
1
device/accton/x86_64-accton_as5835_54x-r0/default_sku
Normal file
1
device/accton/x86_64-accton_as5835_54x-r0/default_sku
Normal file
@ -0,0 +1 @@
|
|||||||
|
Accton-AS5835-54X t1
|
3
device/accton/x86_64-accton_as5835_54x-r0/installer.conf
Normal file
3
device/accton/x86_64-accton_as5835_54x-r0/installer.conf
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
CONSOLE_PORT=0x3f8
|
||||||
|
CONSOLE_DEV=0
|
||||||
|
CONSOLE_SPEED=115200
|
24
device/accton/x86_64-accton_as5835_54x-r0/plugins/eeprom.py
Normal file
24
device/accton/x86_64-accton_as5835_54x-r0/plugins/eeprom.py
Normal file
@ -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)
|
61
device/accton/x86_64-accton_as5835_54x-r0/plugins/psuutil.py
Normal file
61
device/accton/x86_64-accton_as5835_54x-r0/plugins/psuutil.py
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# Accton
|
||||||
|
#
|
||||||
|
# Module contains an implementation of SONiC PSU Base API and
|
||||||
|
# provides the PSUs status which are available in the platform
|
||||||
|
#
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
try:
|
||||||
|
from sonic_psu.psu_base import PsuBase
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError (str(e) + "- required module not found")
|
||||||
|
|
||||||
|
class PsuUtil(PsuBase):
|
||||||
|
"""Platform-specific PSUutil class"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
PsuBase.__init__(self)
|
||||||
|
|
||||||
|
self.psu_path = "/sys/bus/i2c/devices/"
|
||||||
|
self.psu_presence = "/psu_present"
|
||||||
|
self.psu_oper_status = "/psu_power_good"
|
||||||
|
self.psu_mapping = {
|
||||||
|
1: "11-0050",
|
||||||
|
2: "12-0053",
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_num_psus(self):
|
||||||
|
return len(self.psu_mapping)
|
||||||
|
|
||||||
|
def get_psu_status(self, index):
|
||||||
|
if index is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
status = 0
|
||||||
|
node = self.psu_path + self.psu_mapping[index]+self.psu_oper_status
|
||||||
|
try:
|
||||||
|
with open(node, 'r') as power_status:
|
||||||
|
status = int(power_status.read())
|
||||||
|
except IOError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return status == 1
|
||||||
|
|
||||||
|
def get_psu_presence(self, index):
|
||||||
|
if index is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
status = 0
|
||||||
|
node = self.psu_path + self.psu_mapping[index] + self.psu_presence
|
||||||
|
try:
|
||||||
|
with open(node, 'r') as presence_status:
|
||||||
|
status = int(presence_status.read())
|
||||||
|
except IOError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return status == 1
|
297
device/accton/x86_64-accton_as5835_54x-r0/plugins/sfputil.py
Normal file
297
device/accton/x86_64-accton_as5835_54x-r0/plugins/sfputil.py
Normal file
@ -0,0 +1,297 @@
|
|||||||
|
# sfputil.py
|
||||||
|
#
|
||||||
|
# Platform-specific SFP transceiver interface for SONiC
|
||||||
|
#
|
||||||
|
|
||||||
|
try:
|
||||||
|
import time
|
||||||
|
import string
|
||||||
|
from ctypes import create_string_buffer
|
||||||
|
from sonic_sfp.sfputilbase import SfpUtilBase
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError("%s - required module not found" % str(e))
|
||||||
|
|
||||||
|
|
||||||
|
class SfpUtil(SfpUtilBase):
|
||||||
|
"""Platform-specific SfpUtil class"""
|
||||||
|
|
||||||
|
PORT_START = 1
|
||||||
|
PORT_END = 72
|
||||||
|
PORTS_IN_BLOCK = 72
|
||||||
|
QSFP_PORT_START = 49
|
||||||
|
QSFP_PORT_END = 72
|
||||||
|
|
||||||
|
BASE_VAL_PATH = "/sys/class/i2c-adapter/i2c-{0}/{1}-0050/"
|
||||||
|
|
||||||
|
_port_to_is_present = {}
|
||||||
|
_port_to_lp_mode = {}
|
||||||
|
|
||||||
|
_port_to_eeprom_mapping = {}
|
||||||
|
_cpld_mapping = {
|
||||||
|
0: "3-0060",
|
||||||
|
1: "3-0061",
|
||||||
|
2: "3-0062",
|
||||||
|
}
|
||||||
|
_port_to_i2c_mapping = {
|
||||||
|
1: 42,
|
||||||
|
2: 43,
|
||||||
|
3: 44,
|
||||||
|
4: 45,
|
||||||
|
5: 46,
|
||||||
|
6: 47,
|
||||||
|
7: 48,
|
||||||
|
8: 49,
|
||||||
|
9: 50,
|
||||||
|
10: 51,
|
||||||
|
11: 52,
|
||||||
|
12: 53,
|
||||||
|
13: 54,
|
||||||
|
14: 55,
|
||||||
|
15: 56,
|
||||||
|
16: 57,
|
||||||
|
17: 58,
|
||||||
|
18: 59,
|
||||||
|
19: 60,
|
||||||
|
20: 61,
|
||||||
|
21: 62,
|
||||||
|
22: 63,
|
||||||
|
23: 64,
|
||||||
|
24: 65,
|
||||||
|
25: 66,
|
||||||
|
26: 67,
|
||||||
|
27: 68,
|
||||||
|
28: 69,
|
||||||
|
29: 70,
|
||||||
|
30: 71,
|
||||||
|
31: 72,
|
||||||
|
32: 73,
|
||||||
|
33: 74,
|
||||||
|
34: 75,
|
||||||
|
35: 76,
|
||||||
|
36: 77,
|
||||||
|
37: 78,
|
||||||
|
38: 79,
|
||||||
|
39: 80,
|
||||||
|
40: 81,
|
||||||
|
41: 82,
|
||||||
|
42: 83,
|
||||||
|
43: 84,
|
||||||
|
44: 85,
|
||||||
|
45: 86,
|
||||||
|
46: 87,
|
||||||
|
47: 88,
|
||||||
|
48: 89,
|
||||||
|
49: 28, #QSFP49
|
||||||
|
50: 28,
|
||||||
|
51: 28,
|
||||||
|
52: 28,
|
||||||
|
53: 29, #QSFP50
|
||||||
|
54: 29,
|
||||||
|
55: 29,
|
||||||
|
56: 29,
|
||||||
|
57: 26, #QSFP51
|
||||||
|
58: 26,
|
||||||
|
59: 26,
|
||||||
|
60: 26,
|
||||||
|
61: 30, #QSFP52
|
||||||
|
62: 30,
|
||||||
|
63: 30,
|
||||||
|
64: 30,
|
||||||
|
65: 31, #QSFP53
|
||||||
|
66: 31,
|
||||||
|
67: 31,
|
||||||
|
68: 31,
|
||||||
|
69: 27, #QSFP54
|
||||||
|
70: 27,
|
||||||
|
71: 27,
|
||||||
|
72: 27,
|
||||||
|
}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def port_start(self):
|
||||||
|
return self.PORT_START
|
||||||
|
|
||||||
|
@property
|
||||||
|
def port_end(self):
|
||||||
|
return self.PORT_END
|
||||||
|
|
||||||
|
@property
|
||||||
|
def qsfp_port_start(self):
|
||||||
|
return self.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 = '/sys/bus/i2c/devices/{0}-0050/eeprom'
|
||||||
|
for x in range(self.port_start, self.port_end+1):
|
||||||
|
self.port_to_eeprom_mapping[x] = eeprom_path.format(
|
||||||
|
self._port_to_i2c_mapping[x])
|
||||||
|
|
||||||
|
SfpUtilBase.__init__(self)
|
||||||
|
|
||||||
|
|
||||||
|
# For port 49~54 are QSFP, here presumed they're all split to 4 lanes.
|
||||||
|
def get_cage_num(self, port_num):
|
||||||
|
cage_num = port_num
|
||||||
|
if (port_num >= self.QSFP_PORT_START):
|
||||||
|
cage_num = (port_num - self.QSFP_PORT_START)/4
|
||||||
|
cage_num = cage_num + self.QSFP_PORT_START
|
||||||
|
|
||||||
|
return cage_num
|
||||||
|
|
||||||
|
# For cage 1~38 are at cpld2, others are at cpld3.
|
||||||
|
def get_cpld_num(self, port_num):
|
||||||
|
return 1 if (port_num < 39) else 2
|
||||||
|
|
||||||
|
def get_presence(self, port_num):
|
||||||
|
# Check for invalid port_num
|
||||||
|
if port_num < self.port_start or port_num > self.port_end:
|
||||||
|
return False
|
||||||
|
|
||||||
|
cage_num = self.get_cage_num(port_num)
|
||||||
|
cpld_i = self.get_cpld_num(port_num)
|
||||||
|
|
||||||
|
cpld_ps = self._cpld_mapping[cpld_i]
|
||||||
|
path = "/sys/bus/i2c/devices/{0}/module_present_{1}"
|
||||||
|
port_ps = path.format(cpld_ps, cage_num)
|
||||||
|
|
||||||
|
try:
|
||||||
|
val_file = open(port_ps)
|
||||||
|
except IOError as e:
|
||||||
|
print "Error: unable to open file: %s" % str(e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
content = val_file.readline().rstrip()
|
||||||
|
val_file.close()
|
||||||
|
|
||||||
|
# content is a string, either "0" or "1"
|
||||||
|
if content == "1":
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_low_power_mode_cpld(self, port_num):
|
||||||
|
if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
|
||||||
|
return False
|
||||||
|
|
||||||
|
cage_num = self.get_cage_num(port_num)
|
||||||
|
cpld_i = self.get_cpld_num(port_num)
|
||||||
|
|
||||||
|
cpld_ps = self._cpld_mapping[cpld_i]
|
||||||
|
path = "/sys/bus/i2c/devices/{0}/module_lpmode_{1}"
|
||||||
|
lp_mode_path = path.format(cpld_ps, cage_num)
|
||||||
|
|
||||||
|
try:
|
||||||
|
val_file = open(lp_mode_path)
|
||||||
|
except IOError as e:
|
||||||
|
print "Error: unable to open file: %s" % str(e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
content = val_file.readline().rstrip()
|
||||||
|
val_file.close()
|
||||||
|
|
||||||
|
# content is a string, either "0" or "1"
|
||||||
|
if content == "1":
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_low_power_mode(self, port_num):
|
||||||
|
if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not self.get_presence(port_num):
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
eeprom = None
|
||||||
|
|
||||||
|
eeprom = open(self.port_to_eeprom_mapping[port_num], "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 e:
|
||||||
|
print "Error: unable to open file: %s" % str(e)
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
if eeprom is not None:
|
||||||
|
eeprom.close()
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
def set_low_power_mode(self, port_num, lpmode):
|
||||||
|
if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
eeprom = None
|
||||||
|
|
||||||
|
if not self.get_presence(port_num):
|
||||||
|
return False # Port is not present, unable to set the eeprom
|
||||||
|
|
||||||
|
# Fill in write buffer
|
||||||
|
regval = 0x3 if lpmode else 0x1 # 0x3:Low Power Mode, 0x1:High Power Mode
|
||||||
|
buffer = create_string_buffer(1)
|
||||||
|
buffer[0] = chr(regval)
|
||||||
|
|
||||||
|
# Write to eeprom
|
||||||
|
eeprom = open(self.port_to_eeprom_mapping[port_num], "r+b")
|
||||||
|
eeprom.seek(93)
|
||||||
|
eeprom.write(buffer[0])
|
||||||
|
return True
|
||||||
|
except IOError as e:
|
||||||
|
print "Error: unable to open file: %s" % str(e)
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
if eeprom is not None:
|
||||||
|
eeprom.close()
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
def reset(self, port_num):
|
||||||
|
if port_num < self.qsfp_port_start or port_num > self.qsfp_port_end:
|
||||||
|
return False
|
||||||
|
|
||||||
|
cage_num = self.get_cage_num(port_num)
|
||||||
|
cpld_i = self.get_cpld_num(port_num)
|
||||||
|
cpld_ps = self._cpld_mapping[cpld_i]
|
||||||
|
path = "/sys/bus/i2c/devices/{0}/module_reset_{1}"
|
||||||
|
port_ps = path.format(cpld_ps, cage_num)
|
||||||
|
try:
|
||||||
|
reg_file = open(port_ps, 'w')
|
||||||
|
except IOError as e:
|
||||||
|
print "Error: unable to open file: %s" % str(e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
#toggle reset
|
||||||
|
reg_file.seek(0)
|
||||||
|
reg_file.write('0')
|
||||||
|
time.sleep(1)
|
||||||
|
reg_file.seek(0)
|
||||||
|
reg_file.write('1')
|
||||||
|
reg_file.close()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_transceiver_change_event(self):
|
||||||
|
"""
|
||||||
|
TODO: This function need to be implemented
|
||||||
|
when decide to support monitoring SFP(Xcvrd)
|
||||||
|
on this platform.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
@ -25,6 +25,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
|
|||||||
$(ACCTON_AS4630_54PE_PLATFORM_MODULE) \
|
$(ACCTON_AS4630_54PE_PLATFORM_MODULE) \
|
||||||
$(ACCTON_MINIPACK_PLATFORM_MODULE) \
|
$(ACCTON_MINIPACK_PLATFORM_MODULE) \
|
||||||
$(ACCTON_AS5812_54X_PLATFORM_MODULE) \
|
$(ACCTON_AS5812_54X_PLATFORM_MODULE) \
|
||||||
|
$(ACCTON_AS5835_54X_PLATFORM_MODULE) \
|
||||||
$(INVENTEC_D7032Q28B_PLATFORM_MODULE) \
|
$(INVENTEC_D7032Q28B_PLATFORM_MODULE) \
|
||||||
$(INVENTEC_D7054Q28B_PLATFORM_MODULE) \
|
$(INVENTEC_D7054Q28B_PLATFORM_MODULE) \
|
||||||
$(INVENTEC_D7264Q28B_PLATFORM_MODULE) \
|
$(INVENTEC_D7264Q28B_PLATFORM_MODULE) \
|
||||||
|
@ -12,6 +12,7 @@ ACCTON_AS7726_32X_PLATFORM_MODULE_VERSION = 1.1
|
|||||||
ACCTON_AS4630_54PE_PLATFORM_MODULE_VERSION = 1.1
|
ACCTON_AS4630_54PE_PLATFORM_MODULE_VERSION = 1.1
|
||||||
ACCTON_MINIPACK_PLATFORM_MODULE_VERSION = 1.1
|
ACCTON_MINIPACK_PLATFORM_MODULE_VERSION = 1.1
|
||||||
ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION = 1.1
|
ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION = 1.1
|
||||||
|
ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION = 1.1
|
||||||
|
|
||||||
export ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION
|
export ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION
|
||||||
export ACCTON_AS5712_54X_PLATFORM_MODULE_VERSION
|
export ACCTON_AS5712_54X_PLATFORM_MODULE_VERSION
|
||||||
@ -25,6 +26,7 @@ export ACCTON_AS7726_32X_PLATFORM_MODULE_VERSION
|
|||||||
export ACCTON_AS4630_54PE_PLATFORM_MODULE_VERSION
|
export ACCTON_AS4630_54PE_PLATFORM_MODULE_VERSION
|
||||||
export ACCTON_MINIPACK_PLATFORM_MODULE_VERSION
|
export ACCTON_MINIPACK_PLATFORM_MODULE_VERSION
|
||||||
export ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION
|
export ACCTON_AS5812_54X_PLATFORM_MODULE_VERSION
|
||||||
|
export ACCTON_AS5835_54X_PLATFORM_MODULE_VERSION
|
||||||
|
|
||||||
ACCTON_AS7712_32X_PLATFORM_MODULE = sonic-platform-accton-as7712-32x_$(ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION)_amd64.deb
|
ACCTON_AS7712_32X_PLATFORM_MODULE = sonic-platform-accton-as7712-32x_$(ACCTON_AS7712_32X_PLATFORM_MODULE_VERSION)_amd64.deb
|
||||||
$(ACCTON_AS7712_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-accton
|
$(ACCTON_AS7712_32X_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-accton
|
||||||
@ -77,4 +79,8 @@ ACCTON_AS5812_54X_PLATFORM_MODULE = sonic-platform-accton-as5812-54x_$(ACCTON_AS
|
|||||||
$(ACCTON_AS5812_54X_PLATFORM_MODULE)_PLATFORM = x86_64-accton_as5812_54x-r0
|
$(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)))
|
$(eval $(call add_extra_package,$(ACCTON_AS7712_32X_PLATFORM_MODULE),$(ACCTON_AS5812_54X_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)))
|
||||||
|
|
||||||
SONIC_STRETCH_DEBS += $(ACCTON_AS7712_32X_PLATFORM_MODULE)
|
SONIC_STRETCH_DEBS += $(ACCTON_AS7712_32X_PLATFORM_MODULE)
|
||||||
|
@ -0,0 +1,237 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright (C) 2017 Accton Technology Corporation
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# HISTORY:
|
||||||
|
# mm/dd/yyyy (A.D.)
|
||||||
|
# 5/27/2019: Brandon_Chuang create
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
|
try:
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
|
from collections import namedtuple
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError('%s - required module not found' % str(e))
|
||||||
|
|
||||||
|
|
||||||
|
class FanUtil(object):
|
||||||
|
"""Platform-specific FanUtil class"""
|
||||||
|
|
||||||
|
FAN_NUM_ON_MAIN_BROAD = 5
|
||||||
|
FAN_NUM_1_IDX = 1
|
||||||
|
FAN_NUM_2_IDX = 2
|
||||||
|
FAN_NUM_3_IDX = 3
|
||||||
|
FAN_NUM_4_IDX = 4
|
||||||
|
FAN_NUM_5_IDX = 5
|
||||||
|
|
||||||
|
FAN_NODE_NUM_OF_MAP = 2
|
||||||
|
FAN_NODE_FAULT_IDX_OF_MAP = 1
|
||||||
|
FAN_NODE_DIR_IDX_OF_MAP = 2
|
||||||
|
|
||||||
|
BASE_VAL_PATH = '/sys/bus/i2c/devices/3-0063/{0}'
|
||||||
|
FAN_DUTY_PATH = '/sys/bus/i2c/devices/3-0063/fan_duty_cycle_percentage'
|
||||||
|
|
||||||
|
#logfile = ''
|
||||||
|
#loglevel = logging.INFO
|
||||||
|
|
||||||
|
""" Dictionary where
|
||||||
|
key1 = fan id index (integer) starting from 1
|
||||||
|
key2 = fan node index (interger) starting from 1
|
||||||
|
value = path to fan device file (string) """
|
||||||
|
_fan_to_device_path_mapping = {}
|
||||||
|
|
||||||
|
#fan1_direction
|
||||||
|
#fan1_fault
|
||||||
|
#fan1_present
|
||||||
|
|
||||||
|
#(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage',
|
||||||
|
_fan_to_device_node_mapping = {
|
||||||
|
(FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault',
|
||||||
|
(FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction',
|
||||||
|
|
||||||
|
(FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault',
|
||||||
|
(FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction',
|
||||||
|
|
||||||
|
(FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault',
|
||||||
|
(FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction',
|
||||||
|
|
||||||
|
(FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault',
|
||||||
|
(FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction',
|
||||||
|
|
||||||
|
(FAN_NUM_5_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan5_fault',
|
||||||
|
(FAN_NUM_5_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan5_direction',
|
||||||
|
}
|
||||||
|
|
||||||
|
def _get_fan_to_device_node(self, fan_num, node_num):
|
||||||
|
return self._fan_to_device_node_mapping[(fan_num, node_num)]
|
||||||
|
|
||||||
|
def _get_fan_node_val(self, fan_num, node_num):
|
||||||
|
if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD:
|
||||||
|
logging.debug('GET. Parameter error. fan_num:%d', fan_num)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP:
|
||||||
|
logging.debug('GET. Parameter error. node_num:%d', node_num)
|
||||||
|
return None
|
||||||
|
|
||||||
|
device_path = self.get_fan_to_device_path(fan_num, node_num)
|
||||||
|
|
||||||
|
try:
|
||||||
|
val_file = open(device_path, 'r')
|
||||||
|
except IOError as e:
|
||||||
|
logging.error('GET. unable to open file: %s', str(e))
|
||||||
|
return None
|
||||||
|
|
||||||
|
content = val_file.readline().rstrip()
|
||||||
|
|
||||||
|
if content == '':
|
||||||
|
logging.debug('GET. content is NULL. device_path:%s', device_path)
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
val_file.close()
|
||||||
|
except:
|
||||||
|
logging.debug('GET. unable to close file. device_path:%s', device_path)
|
||||||
|
return None
|
||||||
|
|
||||||
|
return int(content)
|
||||||
|
|
||||||
|
def _set_fan_node_val(self, fan_num, node_num, val):
|
||||||
|
if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD:
|
||||||
|
logging.debug('GET. Parameter error. fan_num:%d', fan_num)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP:
|
||||||
|
logging.debug('GET. Parameter error. node_num:%d', node_num)
|
||||||
|
return None
|
||||||
|
|
||||||
|
content = str(val)
|
||||||
|
if content == '':
|
||||||
|
logging.debug('GET. content is NULL. device_path:%s', device_path)
|
||||||
|
return None
|
||||||
|
|
||||||
|
device_path = self.get_fan_to_device_path(fan_num, node_num)
|
||||||
|
try:
|
||||||
|
val_file = open(device_path, 'w')
|
||||||
|
except IOError as e:
|
||||||
|
logging.error('GET. unable to open file: %s', str(e))
|
||||||
|
return None
|
||||||
|
|
||||||
|
val_file.write(content)
|
||||||
|
|
||||||
|
try:
|
||||||
|
val_file.close()
|
||||||
|
except:
|
||||||
|
logging.debug('GET. unable to close file. device_path:%s', device_path)
|
||||||
|
return None
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
fan_path = self.BASE_VAL_PATH
|
||||||
|
|
||||||
|
for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1):
|
||||||
|
for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1):
|
||||||
|
self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format(
|
||||||
|
self._fan_to_device_node_mapping[(fan_num, node_num)])
|
||||||
|
|
||||||
|
def get_num_fans(self):
|
||||||
|
return self.FAN_NUM_ON_MAIN_BROAD
|
||||||
|
|
||||||
|
def get_idx_fan_start(self):
|
||||||
|
return self.FAN_NUM_1_IDX
|
||||||
|
|
||||||
|
def get_num_nodes(self):
|
||||||
|
return self.FAN_NODE_NUM_OF_MAP
|
||||||
|
|
||||||
|
def get_idx_node_start(self):
|
||||||
|
return self.FAN_NODE_FAULT_IDX_OF_MAP
|
||||||
|
|
||||||
|
def get_size_node_map(self):
|
||||||
|
return len(self._fan_to_device_node_mapping)
|
||||||
|
|
||||||
|
def get_size_path_map(self):
|
||||||
|
return len(self._fan_to_device_path_mapping)
|
||||||
|
|
||||||
|
def get_fan_to_device_path(self, fan_num, node_num):
|
||||||
|
return self._fan_to_device_path_mapping[(fan_num, node_num)]
|
||||||
|
|
||||||
|
def get_fan_fault(self, fan_num):
|
||||||
|
return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP)
|
||||||
|
|
||||||
|
#def get_fan_speed(self, fan_num):
|
||||||
|
# return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP)
|
||||||
|
|
||||||
|
def get_fan_dir(self, fan_num):
|
||||||
|
return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP)
|
||||||
|
|
||||||
|
def get_fan_duty_cycle(self):
|
||||||
|
#duty_path = self.FAN_DUTY_PATH
|
||||||
|
try:
|
||||||
|
val_file = open(self.FAN_DUTY_PATH)
|
||||||
|
except IOError as e:
|
||||||
|
print "Error: unable to open file: %s" % str(e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
content = val_file.readline().rstrip()
|
||||||
|
val_file.close()
|
||||||
|
|
||||||
|
return int(content)
|
||||||
|
|
||||||
|
def set_fan_duty_cycle(self, val):
|
||||||
|
try:
|
||||||
|
fan_file = open(self.FAN_DUTY_PATH, 'r+')
|
||||||
|
except IOError as e:
|
||||||
|
print "Error: unable to open file: %s" % str(e)
|
||||||
|
return False
|
||||||
|
fan_file.write(str(val))
|
||||||
|
fan_file.close()
|
||||||
|
return True
|
||||||
|
|
||||||
|
#def get_fanr_fault(self, fan_num):
|
||||||
|
# return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP)
|
||||||
|
|
||||||
|
def get_fanr_speed(self, fan_num):
|
||||||
|
return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP)
|
||||||
|
|
||||||
|
def get_fan_status(self, fan_num):
|
||||||
|
if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD:
|
||||||
|
logging.debug('GET. Parameter error. fan_num, %d', fan_num)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0:
|
||||||
|
logging.debug('GET. FAN fault. fan_num, %d', fan_num)
|
||||||
|
return False
|
||||||
|
|
||||||
|
#if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0:
|
||||||
|
# logging.debug('GET. FANR fault. fan_num, %d', fan_num)
|
||||||
|
# return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
#def main():
|
||||||
|
# fan = FanUtil()
|
||||||
|
#
|
||||||
|
# print 'get_size_node_map : %d' % fan.get_size_node_map()
|
||||||
|
# print 'get_size_path_map : %d' % fan.get_size_path_map()
|
||||||
|
# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1):
|
||||||
|
# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1):
|
||||||
|
# print fan.get_fan_to_device_path(x, y)
|
||||||
|
#
|
||||||
|
#if __name__ == '__main__':
|
||||||
|
# main()
|
@ -0,0 +1,129 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright (C) 2017 Accton Technology Corporation
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# HISTORY:
|
||||||
|
# mm/dd/yyyy (A.D.)
|
||||||
|
# 5/27/2019: Brandon_Chuang create
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
|
try:
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
|
import glob
|
||||||
|
import commands
|
||||||
|
from collections import namedtuple
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError('%s - required module not found' % str(e))
|
||||||
|
|
||||||
|
class ThermalUtil(object):
|
||||||
|
"""Platform-specific ThermalUtil class"""
|
||||||
|
THERMAL_NUM_MAX = 4
|
||||||
|
THERMAL_NUM_1_IDX = 1 # 1_ON_CPU_BROAD. LM75
|
||||||
|
THERMAL_NUM_2_IDX = 2 # 2_ON_MAIN_BROAD. LM75
|
||||||
|
THERMAL_NUM_3_IDX = 3 # 3_ON_MAIN_BROAD. LM75
|
||||||
|
THERMAL_NUM_4_IDX = 4 # 4_ON_MAIN_BROAD. LM75
|
||||||
|
|
||||||
|
""" Dictionary where
|
||||||
|
key1 = thermal id index (integer) starting from 1
|
||||||
|
value = path to fan device file (string) """
|
||||||
|
#_thermal_to_device_path_mapping = {}
|
||||||
|
|
||||||
|
_thermal_to_device_node_mapping = {
|
||||||
|
THERMAL_NUM_1_IDX: ['18', '4b'],
|
||||||
|
THERMAL_NUM_2_IDX: ['19', '4c'],
|
||||||
|
THERMAL_NUM_3_IDX: ['20', '49'],
|
||||||
|
THERMAL_NUM_4_IDX: ['21', '4a'],
|
||||||
|
}
|
||||||
|
thermal_sysfspath ={
|
||||||
|
THERMAL_NUM_1_IDX: ["/sys/bus/i2c/devices/18-004b/hwmon/hwmon3/temp1_input"],
|
||||||
|
THERMAL_NUM_2_IDX: ["/sys/bus/i2c/devices/19-004c/hwmon/hwmon4/temp1_input"],
|
||||||
|
THERMAL_NUM_3_IDX: ["/sys/bus/i2c/devices/20-0049/hwmon/hwmon5/temp1_input"],
|
||||||
|
THERMAL_NUM_4_IDX: ["/sys/bus/i2c/devices/21-004a/hwmon/hwmon6/temp1_input"],
|
||||||
|
}
|
||||||
|
|
||||||
|
#def __init__(self):
|
||||||
|
def _get_thermal_val(self, thermal_num):
|
||||||
|
if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_MAX:
|
||||||
|
logging.debug('GET. Parameter error. thermal_num, %d', thermal_num)
|
||||||
|
return None
|
||||||
|
|
||||||
|
device_path = self.get_thermal_to_device_path(thermal_num)
|
||||||
|
if(os.path.isfile(device_path)):
|
||||||
|
for filename in glob.glob(device_path):
|
||||||
|
try:
|
||||||
|
val_file = open(filename, 'r')
|
||||||
|
except IOError as e:
|
||||||
|
logging.error('GET. unable to open file: %s', str(e))
|
||||||
|
return None
|
||||||
|
content = val_file.readline().rstrip()
|
||||||
|
if content == '':
|
||||||
|
logging.debug('GET. content is NULL. device_path:%s', device_path)
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
val_file.close()
|
||||||
|
except:
|
||||||
|
logging.debug('GET. unable to close file. device_path:%s', device_path)
|
||||||
|
return None
|
||||||
|
return int(content)
|
||||||
|
|
||||||
|
else:
|
||||||
|
print "No such device_path=%s"%device_path
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def get_num_thermals(self):
|
||||||
|
return self.THERMAL_NUM_MAX
|
||||||
|
|
||||||
|
def get_idx_thermal_start(self):
|
||||||
|
return self.THERMAL_NUM_1_IDX
|
||||||
|
|
||||||
|
def get_size_node_map(self):
|
||||||
|
return len(self._thermal_to_device_node_mapping)
|
||||||
|
|
||||||
|
def get_size_path_map(self):
|
||||||
|
return len(self.thermal_sysfspath)
|
||||||
|
|
||||||
|
def get_thermal_to_device_path(self, thermal_num):
|
||||||
|
return self.thermal_sysfspath[thermal_num][0]
|
||||||
|
|
||||||
|
def get_thermal_1_val(self):
|
||||||
|
return self._get_thermal_val(self.THERMAL_NUM_1_IDX)
|
||||||
|
|
||||||
|
def get_thermal_2_val(self):
|
||||||
|
return self._get_thermal_val(self.THERMAL_NUM_2_IDX)
|
||||||
|
|
||||||
|
def get_thermal_3_val(self):
|
||||||
|
return self._get_thermal_val(self.THERMAL_NUM_3_IDX)
|
||||||
|
|
||||||
|
def get_thermal_temp(self):
|
||||||
|
return (self._get_thermal_val(self.THERMAL_NUM_1_IDX) + self._get_thermal_val(self.THERMAL_NUM_2_IDX) +self._get_thermal_val(self.THERMAL_NUM_3_IDX))
|
||||||
|
|
||||||
|
def main():
|
||||||
|
thermal = ThermalUtil()
|
||||||
|
print "termal1=%d" %thermal._get_thermal_val(1)
|
||||||
|
print "termal2=%d" %thermal._get_thermal_val(2)
|
||||||
|
print "termal3=%d" %thermal._get_thermal_val(3)
|
||||||
|
print "termal4=%d" %thermal._get_thermal_val(4)
|
||||||
|
#
|
||||||
|
# print 'get_size_node_map : %d' % thermal.get_size_node_map()
|
||||||
|
# print 'get_size_path_map : %d' % thermal.get_size_path_map()
|
||||||
|
# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1):
|
||||||
|
# print thermal.get_thermal_to_device_path(x)
|
||||||
|
#
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
@ -0,0 +1,17 @@
|
|||||||
|
ifneq ($(KERNELRELEASE),)
|
||||||
|
obj-m:= accton_as5835_54x_cpld.o accton_as5835_54x_psu.o \
|
||||||
|
accton_as5835_54x_fan.o accton_as5835_54x_leds.o \
|
||||||
|
ym2651y.o
|
||||||
|
|
||||||
|
else
|
||||||
|
ifeq (,$(KERNEL_SRC))
|
||||||
|
$(error KERNEL_SRC is not defined)
|
||||||
|
else
|
||||||
|
KERNELDIR:=$(KERNEL_SRC)
|
||||||
|
endif
|
||||||
|
PWD:=$(shell pwd)
|
||||||
|
default:
|
||||||
|
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
|
||||||
|
clean:
|
||||||
|
rm -rf *.o *.mod.o *.mod.o *.ko .*cmd .tmp_versions Module.markers Module.symvers modules.order
|
||||||
|
endif
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,484 @@
|
|||||||
|
/*
|
||||||
|
* A hwmon driver for the Accton as5835 54x fan
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Accton Technology Corporation.
|
||||||
|
* Brandon Chuang <brandon_chuang@accton.com.tw>
|
||||||
|
*
|
||||||
|
* 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 <linux/module.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/hwmon.h>
|
||||||
|
#include <linux/hwmon-sysfs.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/sysfs.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/dmi.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
|
||||||
|
#define DRVNAME "as5835_54x_fan"
|
||||||
|
#define MAX_FAN_SPEED_RPM 21500
|
||||||
|
|
||||||
|
static struct as5835_54x_fan_data *as5835_54x_fan_update_device(struct device *dev);
|
||||||
|
static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf);
|
||||||
|
static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da,
|
||||||
|
const char *buf, size_t count);
|
||||||
|
static ssize_t show_version(struct device *dev, struct device_attribute *da,
|
||||||
|
char *buf);
|
||||||
|
extern int as5835_54x_cpld_read(unsigned short cpld_addr, u8 reg);
|
||||||
|
extern int as5835_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
|
||||||
|
|
||||||
|
/* fan related data, the index should match sysfs_fan_attributes
|
||||||
|
*/
|
||||||
|
static const u8 fan_reg[] = {
|
||||||
|
0x02, /* fan 1-5 present status */
|
||||||
|
0x03, /* fan 1-5 direction(0:F2B 1:B2F) */
|
||||||
|
0x04, /* front fan 1-5 fault status */
|
||||||
|
0x05, /* rear fan 1-5 fault status */
|
||||||
|
0x06, /* fan PWM(for all fan) */
|
||||||
|
0x07, /* front fan 1 speed(rpm) */
|
||||||
|
0x08, /* front fan 2 speed(rpm) */
|
||||||
|
0x09, /* front fan 3 speed(rpm) */
|
||||||
|
0x0A, /* front fan 4 speed(rpm) */
|
||||||
|
0x0B, /* front fan 5 speed(rpm) */
|
||||||
|
0x0C, /* rear fan 1 speed(rpm) */
|
||||||
|
0x0D, /* rear fan 2 speed(rpm) */
|
||||||
|
0x0E, /* rear fan 3 speed(rpm) */
|
||||||
|
0x0F, /* rear fan 4 speed(rpm) */
|
||||||
|
0x10, /* rear fan 5 speed(rpm) */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* fan data */
|
||||||
|
struct as5835_54x_fan_data {
|
||||||
|
struct platform_device *pdev;
|
||||||
|
struct device *hwmon_dev;
|
||||||
|
struct mutex update_lock;
|
||||||
|
char valid; /* != 0 if registers are valid */
|
||||||
|
unsigned long last_updated; /* In jiffies */
|
||||||
|
u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum fan_id {
|
||||||
|
FAN1_ID,
|
||||||
|
FAN2_ID,
|
||||||
|
FAN3_ID,
|
||||||
|
FAN4_ID,
|
||||||
|
FAN5_ID
|
||||||
|
};
|
||||||
|
|
||||||
|
enum sysfs_fan_attributes {
|
||||||
|
FAN_PRESENT_REG,
|
||||||
|
FAN_DIRECTION_REG,
|
||||||
|
FAN_FRONT_FAULT_REG,
|
||||||
|
FAN_REAR_FAULT_REG,
|
||||||
|
FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */
|
||||||
|
FAN1_FRONT_SPEED_RPM,
|
||||||
|
FAN2_FRONT_SPEED_RPM,
|
||||||
|
FAN3_FRONT_SPEED_RPM,
|
||||||
|
FAN4_FRONT_SPEED_RPM,
|
||||||
|
FAN5_FRONT_SPEED_RPM,
|
||||||
|
FAN1_REAR_SPEED_RPM,
|
||||||
|
FAN2_REAR_SPEED_RPM,
|
||||||
|
FAN3_REAR_SPEED_RPM,
|
||||||
|
FAN4_REAR_SPEED_RPM,
|
||||||
|
FAN5_REAR_SPEED_RPM,
|
||||||
|
FAN1_DIRECTION,
|
||||||
|
FAN2_DIRECTION,
|
||||||
|
FAN3_DIRECTION,
|
||||||
|
FAN4_DIRECTION,
|
||||||
|
FAN5_DIRECTION,
|
||||||
|
FAN1_PRESENT,
|
||||||
|
FAN2_PRESENT,
|
||||||
|
FAN3_PRESENT,
|
||||||
|
FAN4_PRESENT,
|
||||||
|
FAN5_PRESENT,
|
||||||
|
FAN1_FAULT,
|
||||||
|
FAN2_FAULT,
|
||||||
|
FAN3_FAULT,
|
||||||
|
FAN4_FAULT,
|
||||||
|
FAN5_FAULT,
|
||||||
|
FAN_MAX_RPM,
|
||||||
|
CPLD_VERSION
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Define attributes
|
||||||
|
*/
|
||||||
|
#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index, index2) \
|
||||||
|
static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT);\
|
||||||
|
static SENSOR_DEVICE_ATTR(fan##index2##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT)
|
||||||
|
#define DECLARE_FAN_FAULT_ATTR(index, index2) &sensor_dev_attr_fan##index##_fault.dev_attr.attr, \
|
||||||
|
&sensor_dev_attr_fan##index2##_fault.dev_attr.attr
|
||||||
|
#define DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(index) \
|
||||||
|
static SENSOR_DEVICE_ATTR(fan##index##_direction, S_IRUGO, fan_show_value, NULL, FAN##index##_DIRECTION)
|
||||||
|
#define DECLARE_FAN_DIRECTION_ATTR(index) &sensor_dev_attr_fan##index##_direction.dev_attr.attr
|
||||||
|
|
||||||
|
#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \
|
||||||
|
static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE)
|
||||||
|
#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr
|
||||||
|
|
||||||
|
#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \
|
||||||
|
static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT)
|
||||||
|
#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr
|
||||||
|
|
||||||
|
#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index, index2) \
|
||||||
|
static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\
|
||||||
|
static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM);\
|
||||||
|
static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\
|
||||||
|
static SENSOR_DEVICE_ATTR(fan##index2##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM)
|
||||||
|
#define DECLARE_FAN_SPEED_RPM_ATTR(index, index2) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \
|
||||||
|
&sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr, \
|
||||||
|
&sensor_dev_attr_fan##index##_input.dev_attr.attr, \
|
||||||
|
&sensor_dev_attr_fan##index2##_input.dev_attr.attr
|
||||||
|
|
||||||
|
static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION);
|
||||||
|
static SENSOR_DEVICE_ATTR(fan_max_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN_MAX_RPM);
|
||||||
|
#define DECLARE_FAN_MAX_RPM_ATTR(index) &sensor_dev_attr_fan_max_speed_rpm.dev_attr.attr
|
||||||
|
|
||||||
|
|
||||||
|
/* 5 fan fault attributes in this platform */
|
||||||
|
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1, 11);
|
||||||
|
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2, 12);
|
||||||
|
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3, 13);
|
||||||
|
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4, 14);
|
||||||
|
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5, 15);
|
||||||
|
/* 5 fan speed(rpm) attributes in this platform */
|
||||||
|
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1, 11);
|
||||||
|
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2, 12);
|
||||||
|
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3, 13);
|
||||||
|
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4, 14);
|
||||||
|
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5, 15);
|
||||||
|
/* 5 fan present attributes in this platform */
|
||||||
|
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1);
|
||||||
|
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2);
|
||||||
|
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3);
|
||||||
|
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4);
|
||||||
|
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5);
|
||||||
|
/* 5 fan direction attribute in this platform */
|
||||||
|
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(1);
|
||||||
|
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(2);
|
||||||
|
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(3);
|
||||||
|
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(4);
|
||||||
|
DECLARE_FAN_DIRECTION_SENSOR_DEV_ATTR(5);
|
||||||
|
/* 1 fan duty cycle attribute in this platform */
|
||||||
|
DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR();
|
||||||
|
|
||||||
|
static struct attribute *as5835_54x_fan_attributes[] = {
|
||||||
|
&sensor_dev_attr_version.dev_attr.attr,
|
||||||
|
/* fan related attributes */
|
||||||
|
DECLARE_FAN_FAULT_ATTR(1, 11),
|
||||||
|
DECLARE_FAN_FAULT_ATTR(2, 12),
|
||||||
|
DECLARE_FAN_FAULT_ATTR(3, 13),
|
||||||
|
DECLARE_FAN_FAULT_ATTR(4, 14),
|
||||||
|
DECLARE_FAN_FAULT_ATTR(5, 15),
|
||||||
|
DECLARE_FAN_SPEED_RPM_ATTR(1, 11),
|
||||||
|
DECLARE_FAN_SPEED_RPM_ATTR(2, 12),
|
||||||
|
DECLARE_FAN_SPEED_RPM_ATTR(3, 13),
|
||||||
|
DECLARE_FAN_SPEED_RPM_ATTR(4, 14),
|
||||||
|
DECLARE_FAN_SPEED_RPM_ATTR(5, 15),
|
||||||
|
DECLARE_FAN_PRESENT_ATTR(1),
|
||||||
|
DECLARE_FAN_PRESENT_ATTR(2),
|
||||||
|
DECLARE_FAN_PRESENT_ATTR(3),
|
||||||
|
DECLARE_FAN_PRESENT_ATTR(4),
|
||||||
|
DECLARE_FAN_PRESENT_ATTR(5),
|
||||||
|
DECLARE_FAN_DIRECTION_ATTR(1),
|
||||||
|
DECLARE_FAN_DIRECTION_ATTR(2),
|
||||||
|
DECLARE_FAN_DIRECTION_ATTR(3),
|
||||||
|
DECLARE_FAN_DIRECTION_ATTR(4),
|
||||||
|
DECLARE_FAN_DIRECTION_ATTR(5),
|
||||||
|
DECLARE_FAN_DUTY_CYCLE_ATTR(),
|
||||||
|
DECLARE_FAN_MAX_RPM_ATTR(),
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FAN_DUTY_CYCLE_REG_MASK 0x1F
|
||||||
|
#define FAN_MAX_DUTY_CYCLE 100
|
||||||
|
#define FAN_REG_VAL_TO_SPEED_RPM_STEP 150
|
||||||
|
|
||||||
|
static int as5835_54x_fan_read_value(struct i2c_client *client, u8 reg)
|
||||||
|
{
|
||||||
|
return i2c_smbus_read_byte_data(client, reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int as5835_54x_fan_write_value(struct i2c_client *client, u8 reg, u8 value)
|
||||||
|
{
|
||||||
|
return i2c_smbus_write_byte_data(client, reg, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fan utility functions
|
||||||
|
*/
|
||||||
|
static u32 reg_val_to_duty_cycle(u8 reg_val)
|
||||||
|
{
|
||||||
|
return (reg_val & FAN_DUTY_CYCLE_REG_MASK) * 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 duty_cycle_to_reg_val(u8 duty_cycle)
|
||||||
|
{
|
||||||
|
if (duty_cycle > FAN_MAX_DUTY_CYCLE) {
|
||||||
|
duty_cycle = FAN_MAX_DUTY_CYCLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (duty_cycle / 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 reg_val_to_speed_rpm(u8 reg_val)
|
||||||
|
{
|
||||||
|
return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 reg_val_to_direction(u8 reg_val, enum fan_id id)
|
||||||
|
{
|
||||||
|
return !!(reg_val & BIT(id)); /* 0: Front to Back, 1: Back to Front*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id)
|
||||||
|
{
|
||||||
|
return !(reg_val & BIT(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 is_fan_fault(struct as5835_54x_fan_data *data, enum fan_id id)
|
||||||
|
{
|
||||||
|
if ((data->reg_val[FAN_FRONT_FAULT_REG] & BIT(id)) ||
|
||||||
|
(data->reg_val[FAN_REAR_FAULT_REG] & BIT(id))) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
int error, value;
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
|
||||||
|
error = kstrtoint(buf, 10, &value);
|
||||||
|
if (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < 0 || value > FAN_MAX_DUTY_CYCLE) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
as5835_54x_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value));
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t fan_show_value(struct device *dev, struct device_attribute *da,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||||
|
struct as5835_54x_fan_data *data = as5835_54x_fan_update_device(dev);
|
||||||
|
ssize_t ret = 0;
|
||||||
|
|
||||||
|
if (data->valid) {
|
||||||
|
switch (attr->index) {
|
||||||
|
case FAN_DUTY_CYCLE_PERCENTAGE:
|
||||||
|
{
|
||||||
|
u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]);
|
||||||
|
ret = sprintf(buf, "%u\n", duty_cycle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FAN1_FRONT_SPEED_RPM:
|
||||||
|
case FAN2_FRONT_SPEED_RPM:
|
||||||
|
case FAN3_FRONT_SPEED_RPM:
|
||||||
|
case FAN4_FRONT_SPEED_RPM:
|
||||||
|
case FAN5_FRONT_SPEED_RPM:
|
||||||
|
case FAN1_REAR_SPEED_RPM:
|
||||||
|
case FAN2_REAR_SPEED_RPM:
|
||||||
|
case FAN3_REAR_SPEED_RPM:
|
||||||
|
case FAN4_REAR_SPEED_RPM:
|
||||||
|
case FAN5_REAR_SPEED_RPM:
|
||||||
|
ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index]));
|
||||||
|
break;
|
||||||
|
case FAN1_PRESENT:
|
||||||
|
case FAN2_PRESENT:
|
||||||
|
case FAN3_PRESENT:
|
||||||
|
case FAN4_PRESENT:
|
||||||
|
case FAN5_PRESENT:
|
||||||
|
ret = sprintf(buf, "%d\n",
|
||||||
|
reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG],
|
||||||
|
attr->index - FAN1_PRESENT));
|
||||||
|
break;
|
||||||
|
case FAN1_FAULT:
|
||||||
|
case FAN2_FAULT:
|
||||||
|
case FAN3_FAULT:
|
||||||
|
case FAN4_FAULT:
|
||||||
|
case FAN5_FAULT:
|
||||||
|
ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT));
|
||||||
|
break;
|
||||||
|
case FAN1_DIRECTION:
|
||||||
|
case FAN2_DIRECTION:
|
||||||
|
case FAN3_DIRECTION:
|
||||||
|
case FAN4_DIRECTION:
|
||||||
|
case FAN5_DIRECTION:
|
||||||
|
ret = sprintf(buf, "%d\n",
|
||||||
|
reg_val_to_direction(data->reg_val[FAN_DIRECTION_REG],
|
||||||
|
attr->index - FAN1_DIRECTION));
|
||||||
|
break;
|
||||||
|
case FAN_MAX_RPM:
|
||||||
|
ret = sprintf(buf, "%d\n", MAX_FAN_SPEED_RPM);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct attribute_group as5835_54x_fan_group = {
|
||||||
|
.attrs = as5835_54x_fan_attributes,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct as5835_54x_fan_data *as5835_54x_fan_update_device(struct device *dev)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
struct as5835_54x_fan_data *data = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
mutex_lock(&data->update_lock);
|
||||||
|
|
||||||
|
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) ||
|
||||||
|
!data->valid) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dev_dbg(&client->dev, "Starting as5835_54x_fan update\n");
|
||||||
|
data->valid = 0;
|
||||||
|
|
||||||
|
/* Update fan data
|
||||||
|
*/
|
||||||
|
for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) {
|
||||||
|
int status = as5835_54x_fan_read_value(client, fan_reg[i]);
|
||||||
|
|
||||||
|
if (status < 0) {
|
||||||
|
data->valid = 0;
|
||||||
|
mutex_unlock(&data->update_lock);
|
||||||
|
dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data->reg_val[i] = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data->last_updated = jiffies;
|
||||||
|
data->valid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&data->update_lock);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
int val = 0;
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
|
||||||
|
val = i2c_smbus_read_byte_data(client, 0x1);
|
||||||
|
|
||||||
|
if (val < 0) {
|
||||||
|
dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf(buf, "%d\n", val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int as5835_54x_fan_probe(struct i2c_client *client,
|
||||||
|
const struct i2c_device_id *dev_id)
|
||||||
|
{
|
||||||
|
struct as5835_54x_fan_data *data;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
|
||||||
|
status = -EIO;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = kzalloc(sizeof(struct as5835_54x_fan_data), GFP_KERNEL);
|
||||||
|
if (!data) {
|
||||||
|
status = -ENOMEM;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_set_clientdata(client, data);
|
||||||
|
data->valid = 0;
|
||||||
|
mutex_init(&data->update_lock);
|
||||||
|
|
||||||
|
dev_info(&client->dev, "chip found\n");
|
||||||
|
|
||||||
|
/* Register sysfs hooks */
|
||||||
|
status = sysfs_create_group(&client->dev.kobj, &as5835_54x_fan_group);
|
||||||
|
if (status) {
|
||||||
|
goto exit_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->hwmon_dev = hwmon_device_register_with_info(&client->dev, "as5835_54x_fan",
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
if (IS_ERR(data->hwmon_dev)) {
|
||||||
|
status = PTR_ERR(data->hwmon_dev);
|
||||||
|
goto exit_remove;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_info(&client->dev, "%s: fan '%s'\n",
|
||||||
|
dev_name(data->hwmon_dev), client->name);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
exit_remove:
|
||||||
|
sysfs_remove_group(&client->dev.kobj, &as5835_54x_fan_group);
|
||||||
|
exit_free:
|
||||||
|
kfree(data);
|
||||||
|
exit:
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int as5835_54x_fan_remove(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct as5835_54x_fan_data *data = i2c_get_clientdata(client);
|
||||||
|
hwmon_device_unregister(data->hwmon_dev);
|
||||||
|
sysfs_remove_group(&client->dev.kobj, &as5835_54x_fan_group);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Addresses to scan */
|
||||||
|
static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
|
||||||
|
|
||||||
|
static const struct i2c_device_id as5835_54x_fan_id[] = {
|
||||||
|
{ "as5835_54x_fan", 0 },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(i2c, as5835_54x_fan_id);
|
||||||
|
|
||||||
|
static struct i2c_driver as5835_54x_fan_driver = {
|
||||||
|
.class = I2C_CLASS_HWMON,
|
||||||
|
.driver = {
|
||||||
|
.name = DRVNAME,
|
||||||
|
},
|
||||||
|
.probe = as5835_54x_fan_probe,
|
||||||
|
.remove = as5835_54x_fan_remove,
|
||||||
|
.id_table = as5835_54x_fan_id,
|
||||||
|
.address_list = normal_i2c,
|
||||||
|
};
|
||||||
|
|
||||||
|
module_i2c_driver(as5835_54x_fan_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
|
||||||
|
MODULE_DESCRIPTION("as5835_54x_fan driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
@ -0,0 +1,380 @@
|
|||||||
|
/*
|
||||||
|
* A LED driver for the accton_as5822_54x_led
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Accton Technology Corporation.
|
||||||
|
* Brandon Chuang <brandon_chuang@accton.com.tw>
|
||||||
|
*
|
||||||
|
* 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 <linux/module.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/leds.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#define DRVNAME "as5835_54x_led"
|
||||||
|
|
||||||
|
#define DEBUG_MODE 0
|
||||||
|
|
||||||
|
#if (DEBUG_MODE == 1)
|
||||||
|
#define DEBUG_PRINT(fmt, args...) \
|
||||||
|
printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args)
|
||||||
|
#else
|
||||||
|
#define DEBUG_PRINT(fmt, args...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int as5835_54x_cpld_read(unsigned short cpld_addr, u8 reg);
|
||||||
|
extern int as5835_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
|
||||||
|
|
||||||
|
struct accton_as5835_54x_led_data {
|
||||||
|
struct platform_device *pdev;
|
||||||
|
struct mutex update_lock;
|
||||||
|
char valid; /* != 0 if registers are valid */
|
||||||
|
unsigned long last_updated; /* In jiffies */
|
||||||
|
u8 reg_val[2]; /* Register value, 0 = RELEASE/DIAG LED,
|
||||||
|
1 = FAN/PSU LED,
|
||||||
|
2 ~ 4 = SYSTEM LED */
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct accton_as5835_54x_led_data *ledctl = NULL;
|
||||||
|
|
||||||
|
#define LED_CNTRLER_I2C_ADDRESS (0x60)
|
||||||
|
|
||||||
|
#define LED_TYPE_DIAG_REG_MASK (0x0C)
|
||||||
|
#define LED_MODE_DIAG_GREEN_VALUE (0x08)
|
||||||
|
#define LED_MODE_DIAG_AMBER_VALUE (0x04)
|
||||||
|
#define LED_MODE_DIAG_OFF_VALUE (0x0C)
|
||||||
|
#define LED_MODE_DIAG_AMBER_VALUE1 (0x00)
|
||||||
|
|
||||||
|
#define LED_TYPE_LOC_REG_MASK (0x30)
|
||||||
|
#define LED_MODE_LOC_AMBER_BLINK_VALUE (0x20)
|
||||||
|
#define LED_MODE_LOC_OFF_VALUE (0x10)
|
||||||
|
#define LED_MODE_LOC_AMBER_VALUE (0x00)
|
||||||
|
|
||||||
|
static const u8 led_reg[] = {
|
||||||
|
0xA, /* LOC/DIAG/FAN LED */
|
||||||
|
0xB, /* PSU LED */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum led_type {
|
||||||
|
LED_TYPE_DIAG,
|
||||||
|
LED_TYPE_LOC,
|
||||||
|
LED_TYPE_FAN,
|
||||||
|
LED_TYPE_PSU1,
|
||||||
|
LED_TYPE_PSU2
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FAN/PSU/DIAG/RELEASE led mode */
|
||||||
|
enum led_light_mode {
|
||||||
|
LED_MODE_OFF = 0,
|
||||||
|
LED_MODE_GREEN,
|
||||||
|
LED_MODE_GREEN_BLINK,
|
||||||
|
LED_MODE_AMBER,
|
||||||
|
LED_MODE_AMBER_BLINK,
|
||||||
|
LED_MODE_RED,
|
||||||
|
LED_MODE_RED_BLINK,
|
||||||
|
LED_MODE_BLUE,
|
||||||
|
LED_MODE_BLUE_BLINK,
|
||||||
|
LED_MODE_AUTO,
|
||||||
|
LED_MODE_UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
struct led_type_mode {
|
||||||
|
enum led_type type;
|
||||||
|
enum led_light_mode mode;
|
||||||
|
int type_mask;
|
||||||
|
int mode_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct led_type_mode led_type_mode_data[] = {
|
||||||
|
{LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE},
|
||||||
|
{LED_TYPE_LOC, LED_MODE_AMBER_BLINK, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_BLINK_VALUE},
|
||||||
|
{LED_TYPE_LOC, LED_MODE_AMBER, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_VALUE},
|
||||||
|
{LED_TYPE_DIAG, LED_MODE_OFF, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_OFF_VALUE},
|
||||||
|
{LED_TYPE_DIAG, LED_MODE_GREEN, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_GREEN_VALUE},
|
||||||
|
{LED_TYPE_DIAG, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_AMBER_VALUE},
|
||||||
|
{LED_TYPE_DIAG, LED_MODE_AMBER, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_AMBER_VALUE1},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) {
|
||||||
|
if (type != led_type_mode_data[i].type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((led_type_mode_data[i].type_mask & reg_val) ==
|
||||||
|
led_type_mode_data[i].mode_value) {
|
||||||
|
return led_type_mode_data[i].mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return LED_MODE_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 led_light_mode_to_reg_val(enum led_type type,
|
||||||
|
enum led_light_mode mode, u8 reg_val) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) {
|
||||||
|
int type_mask, mode_value;
|
||||||
|
|
||||||
|
if (type != led_type_mode_data[i].type)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (mode != led_type_mode_data[i].mode)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
type_mask = led_type_mode_data[i].type_mask;
|
||||||
|
mode_value = led_type_mode_data[i].mode_value;
|
||||||
|
reg_val = (reg_val & ~type_mask) | mode_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reg_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int accton_as5835_54x_led_read_value(u8 reg)
|
||||||
|
{
|
||||||
|
return as5835_54x_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int accton_as5835_54x_led_write_value(u8 reg, u8 value)
|
||||||
|
{
|
||||||
|
return as5835_54x_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void accton_as5835_54x_led_update(void)
|
||||||
|
{
|
||||||
|
mutex_lock(&ledctl->update_lock);
|
||||||
|
|
||||||
|
if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2)
|
||||||
|
|| !ledctl->valid) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dev_dbg(&ledctl->pdev->dev, "Starting accton_as5835_54x_led update\n");
|
||||||
|
ledctl->valid = 0;
|
||||||
|
|
||||||
|
/* Update LED data
|
||||||
|
*/
|
||||||
|
for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) {
|
||||||
|
int status = accton_as5835_54x_led_read_value(led_reg[i]);
|
||||||
|
|
||||||
|
if (status < 0) {
|
||||||
|
dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ledctl->reg_val[i] = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
ledctl->last_updated = jiffies;
|
||||||
|
ledctl->valid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
mutex_unlock(&ledctl->update_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void accton_as5835_54x_led_set(struct led_classdev *led_cdev,
|
||||||
|
enum led_brightness led_light_mode,
|
||||||
|
u8 reg, enum led_type type)
|
||||||
|
{
|
||||||
|
int reg_val;
|
||||||
|
|
||||||
|
mutex_lock(&ledctl->update_lock);
|
||||||
|
reg_val = accton_as5835_54x_led_read_value(reg);
|
||||||
|
|
||||||
|
if (reg_val < 0) {
|
||||||
|
dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val);
|
||||||
|
accton_as5835_54x_led_write_value(reg, reg_val);
|
||||||
|
ledctl->valid = 0;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
mutex_unlock(&ledctl->update_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void accton_as7312_54x_led_auto_set(struct led_classdev *led_cdev,
|
||||||
|
enum led_brightness led_light_mode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum led_brightness accton_as7312_54x_led_auto_get(struct led_classdev *cdev)
|
||||||
|
{
|
||||||
|
return LED_MODE_AUTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void accton_as5835_54x_led_diag_set(struct led_classdev *led_cdev,
|
||||||
|
enum led_brightness led_light_mode)
|
||||||
|
{
|
||||||
|
accton_as5835_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_DIAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum led_brightness accton_as5835_54x_led_diag_get(struct led_classdev *cdev)
|
||||||
|
{
|
||||||
|
accton_as5835_54x_led_update();
|
||||||
|
return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum led_brightness accton_as5835_54x_led_loc_get(struct led_classdev *cdev)
|
||||||
|
{
|
||||||
|
accton_as5835_54x_led_update();
|
||||||
|
return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void accton_as5835_54x_led_loc_set(struct led_classdev *led_cdev,
|
||||||
|
enum led_brightness led_light_mode)
|
||||||
|
{
|
||||||
|
accton_as5835_54x_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct led_classdev accton_as5835_54x_leds[] = {
|
||||||
|
[LED_TYPE_LOC] = {
|
||||||
|
.name = "as5835_54x_led::loc",
|
||||||
|
.default_trigger = "unused",
|
||||||
|
.brightness_set = accton_as5835_54x_led_loc_set,
|
||||||
|
.brightness_get = accton_as5835_54x_led_loc_get,
|
||||||
|
.max_brightness = LED_MODE_AMBER_BLINK,
|
||||||
|
},
|
||||||
|
[LED_TYPE_DIAG] = {
|
||||||
|
.name = "as5835_54x_led::diag",
|
||||||
|
.default_trigger = "unused",
|
||||||
|
.brightness_set = accton_as5835_54x_led_diag_set,
|
||||||
|
.brightness_get = accton_as5835_54x_led_diag_get,
|
||||||
|
.max_brightness = LED_MODE_AMBER,
|
||||||
|
},
|
||||||
|
[LED_TYPE_PSU1] = {
|
||||||
|
.name = "as5835_54x_led::psu1",
|
||||||
|
.default_trigger = "unused",
|
||||||
|
.brightness_set = accton_as7312_54x_led_auto_set,
|
||||||
|
.brightness_get = accton_as7312_54x_led_auto_get,
|
||||||
|
.max_brightness = LED_MODE_AUTO,
|
||||||
|
},
|
||||||
|
[LED_TYPE_PSU2] = {
|
||||||
|
.name = "as5835_54x_led::psu2",
|
||||||
|
.default_trigger = "unused",
|
||||||
|
.brightness_set = accton_as7312_54x_led_auto_set,
|
||||||
|
.brightness_get = accton_as7312_54x_led_auto_get,
|
||||||
|
.max_brightness = LED_MODE_AUTO,
|
||||||
|
},
|
||||||
|
[LED_TYPE_FAN] = {
|
||||||
|
.name = "as5835_54x_led::fan",
|
||||||
|
.default_trigger = "unused",
|
||||||
|
.brightness_set = accton_as7312_54x_led_auto_set,
|
||||||
|
.brightness_get = accton_as7312_54x_led_auto_get,
|
||||||
|
.max_brightness = LED_MODE_AUTO,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int accton_as5835_54x_led_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
int ret, i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(accton_as5835_54x_leds); i++) {
|
||||||
|
ret = led_classdev_register(&pdev->dev, &accton_as5835_54x_leds[i]);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if all LEDs were successfully registered */
|
||||||
|
if (i != ARRAY_SIZE(accton_as5835_54x_leds)){
|
||||||
|
int j;
|
||||||
|
|
||||||
|
/* only unregister the LEDs that were successfully registered */
|
||||||
|
for (j = 0; j < i; j++) {
|
||||||
|
led_classdev_unregister(&accton_as5835_54x_leds[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int accton_as5835_54x_led_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(accton_as5835_54x_leds); i++) {
|
||||||
|
led_classdev_unregister(&accton_as5835_54x_leds[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver accton_as5835_54x_led_driver = {
|
||||||
|
.probe = accton_as5835_54x_led_probe,
|
||||||
|
.remove = accton_as5835_54x_led_remove,
|
||||||
|
.driver = {
|
||||||
|
.name = DRVNAME,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init accton_as5835_54x_led_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = platform_driver_register(&accton_as5835_54x_led_driver);
|
||||||
|
if (ret < 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ledctl = kzalloc(sizeof(struct accton_as5835_54x_led_data), GFP_KERNEL);
|
||||||
|
if (!ledctl) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto exit_driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_init(&ledctl->update_lock);
|
||||||
|
|
||||||
|
ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
|
||||||
|
if (IS_ERR(ledctl->pdev)) {
|
||||||
|
ret = PTR_ERR(ledctl->pdev);
|
||||||
|
goto exit_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
exit_free:
|
||||||
|
kfree(ledctl);
|
||||||
|
exit_driver:
|
||||||
|
platform_driver_unregister(&accton_as5835_54x_led_driver);
|
||||||
|
exit:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit accton_as5835_54x_led_exit(void)
|
||||||
|
{
|
||||||
|
platform_device_unregister(ledctl->pdev);
|
||||||
|
platform_driver_unregister(&accton_as5835_54x_led_driver);
|
||||||
|
kfree(ledctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
late_initcall(accton_as5835_54x_led_init);
|
||||||
|
module_exit(accton_as5835_54x_led_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
|
||||||
|
MODULE_DESCRIPTION("accton_as5835_54x_led driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
|
@ -0,0 +1,343 @@
|
|||||||
|
/*
|
||||||
|
* An hwmon driver for accton as5835_54x Power Module
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Accton Technology Corporation.
|
||||||
|
* Brandon Chuang <brandon_chuang@accton.com.tw>
|
||||||
|
*
|
||||||
|
* Based on ad7414.c
|
||||||
|
* Copyright 2006 Stefan Roese <sr at denx.de>, 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 <linux/module.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/hwmon.h>
|
||||||
|
#include <linux/hwmon-sysfs.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/sysfs.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/dmi.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define PSU_STATUS_I2C_ADDR 0x60
|
||||||
|
#define PSU_STATUS_I2C_REG_OFFSET 0x2
|
||||||
|
|
||||||
|
#define MODEL_NAME_LEN 8
|
||||||
|
#define MODEL_NAME_REG_OFFSET 0x20
|
||||||
|
|
||||||
|
#define SERIAL_NUM_LEN 18
|
||||||
|
#define SERIAL_NUM_REG_OFFSET 0x35
|
||||||
|
|
||||||
|
#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4 + 1)))
|
||||||
|
#define IS_PRESENT(id, value) (!(value & BIT(id*4)))
|
||||||
|
|
||||||
|
static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf);
|
||||||
|
static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf);
|
||||||
|
extern int as5835_54x_cpld_read(unsigned short cpld_addr, u8 reg);
|
||||||
|
|
||||||
|
/* Addresses scanned
|
||||||
|
*/
|
||||||
|
static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
|
||||||
|
|
||||||
|
/* Each client has this additional data
|
||||||
|
*/
|
||||||
|
struct as5835_54x_psu_data {
|
||||||
|
struct device *hwmon_dev;
|
||||||
|
struct mutex update_lock;
|
||||||
|
char valid; /* !=0 if registers are valid */
|
||||||
|
unsigned long last_updated; /* In jiffies */
|
||||||
|
u8 index; /* PSU index */
|
||||||
|
u8 status; /* Status(present/power_good) register read from CPLD */
|
||||||
|
char model_name[MODEL_NAME_LEN+1]; /* Model name, read from eeprom */
|
||||||
|
char serial[SERIAL_NUM_LEN+1]; /* Serial number, read from eeprom*/
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct as5835_54x_psu_data *as5835_54x_psu_update_device(struct device *dev);
|
||||||
|
|
||||||
|
enum as5835_54x_psu_sysfs_attributes {
|
||||||
|
PSU_PRESENT,
|
||||||
|
PSU_MODEL_NAME,
|
||||||
|
PSU_POWER_GOOD,
|
||||||
|
PSU_SERIAL_NUMBER
|
||||||
|
};
|
||||||
|
|
||||||
|
/* sysfs attributes for hwmon
|
||||||
|
*/
|
||||||
|
static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT);
|
||||||
|
static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, PSU_MODEL_NAME);
|
||||||
|
static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD);
|
||||||
|
static SENSOR_DEVICE_ATTR(psu_serial_numer, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER);
|
||||||
|
|
||||||
|
static struct attribute *as5835_54x_psu_attributes[] = {
|
||||||
|
&sensor_dev_attr_psu_present.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_psu_model_name.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_psu_power_good.dev_attr.attr,
|
||||||
|
&sensor_dev_attr_psu_serial_numer.dev_attr.attr,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static ssize_t show_status(struct device *dev, struct device_attribute *da,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||||
|
struct as5835_54x_psu_data *data = as5835_54x_psu_update_device(dev);
|
||||||
|
u8 status = 0;
|
||||||
|
|
||||||
|
if (!data->valid) {
|
||||||
|
return sprintf(buf, "0\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attr->index == PSU_PRESENT) {
|
||||||
|
status = IS_PRESENT(data->index, data->status);
|
||||||
|
}
|
||||||
|
else { /* PSU_POWER_GOOD */
|
||||||
|
status = IS_POWER_GOOD(data->index, data->status);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf(buf, "%d\n", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t show_string(struct device *dev, struct device_attribute *da,
|
||||||
|
char *buf)
|
||||||
|
{
|
||||||
|
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||||
|
struct as5835_54x_psu_data *data = as5835_54x_psu_update_device(dev);
|
||||||
|
char *str = NULL;
|
||||||
|
|
||||||
|
if (!data->valid) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attr->index == PSU_MODEL_NAME) {
|
||||||
|
str = data->model_name;
|
||||||
|
}
|
||||||
|
else { /* PSU_SERIAL_NUBMER */
|
||||||
|
str = data->serial;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf(buf, "%s\n", str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct attribute_group as5835_54x_psu_group = {
|
||||||
|
.attrs = as5835_54x_psu_attributes,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int as5835_54x_psu_probe(struct i2c_client *client,
|
||||||
|
const struct i2c_device_id *dev_id)
|
||||||
|
{
|
||||||
|
struct as5835_54x_psu_data *data;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
|
||||||
|
status = -EIO;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = kzalloc(sizeof(struct as5835_54x_psu_data), GFP_KERNEL);
|
||||||
|
if (!data) {
|
||||||
|
status = -ENOMEM;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_set_clientdata(client, data);
|
||||||
|
data->valid = 0;
|
||||||
|
data->index = dev_id->driver_data;
|
||||||
|
mutex_init(&data->update_lock);
|
||||||
|
|
||||||
|
dev_info(&client->dev, "chip found\n");
|
||||||
|
|
||||||
|
/* Register sysfs hooks */
|
||||||
|
status = sysfs_create_group(&client->dev.kobj, &as5835_54x_psu_group);
|
||||||
|
if (status) {
|
||||||
|
goto exit_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->hwmon_dev = hwmon_device_register_with_info(&client->dev, "as5835_54x_psu",
|
||||||
|
NULL, NULL, NULL);
|
||||||
|
if (IS_ERR(data->hwmon_dev)) {
|
||||||
|
status = PTR_ERR(data->hwmon_dev);
|
||||||
|
goto exit_remove;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_info(&client->dev, "%s: psu '%s'\n",
|
||||||
|
dev_name(data->hwmon_dev), client->name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
exit_remove:
|
||||||
|
sysfs_remove_group(&client->dev.kobj, &as5835_54x_psu_group);
|
||||||
|
exit_free:
|
||||||
|
kfree(data);
|
||||||
|
exit:
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int as5835_54x_psu_remove(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct as5835_54x_psu_data *data = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
hwmon_device_unregister(data->hwmon_dev);
|
||||||
|
sysfs_remove_group(&client->dev.kobj, &as5835_54x_psu_group);
|
||||||
|
kfree(data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum psu_index
|
||||||
|
{
|
||||||
|
as5835_54x_psu1,
|
||||||
|
as5835_54x_psu2
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct i2c_device_id as5835_54x_psu_id[] = {
|
||||||
|
{ "as5835_54x_psu1", as5835_54x_psu1 },
|
||||||
|
{ "as5835_54x_psu2", as5835_54x_psu2 },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(i2c, as5835_54x_psu_id);
|
||||||
|
|
||||||
|
static struct i2c_driver as5835_54x_psu_driver = {
|
||||||
|
.class = I2C_CLASS_HWMON,
|
||||||
|
.driver = {
|
||||||
|
.name = "as5835_54x_psu",
|
||||||
|
},
|
||||||
|
.probe = as5835_54x_psu_probe,
|
||||||
|
.remove = as5835_54x_psu_remove,
|
||||||
|
.id_table = as5835_54x_psu_id,
|
||||||
|
.address_list = normal_i2c,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int as5835_54x_psu_read_byte(struct i2c_client *client, u8 command, u8 *data)
|
||||||
|
{
|
||||||
|
int status = 0;
|
||||||
|
int retry_count = 5;
|
||||||
|
|
||||||
|
while (retry_count) {
|
||||||
|
status = i2c_smbus_read_byte_data(client, command);
|
||||||
|
if (unlikely(status < 0)) {
|
||||||
|
msleep(10);
|
||||||
|
retry_count--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(status < 0)) {
|
||||||
|
dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status);
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
|
||||||
|
*data = (u8)status;
|
||||||
|
|
||||||
|
abort:
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int as5835_54x_psu_read_bytes(struct i2c_client *client, u8 command, u8 *data,
|
||||||
|
int data_len)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
while (data_len) {
|
||||||
|
ssize_t status;
|
||||||
|
|
||||||
|
status = as5835_54x_psu_read_byte(client, command, data);
|
||||||
|
if (status <= 0) {
|
||||||
|
ret = status;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
data += 1;
|
||||||
|
command += 1;
|
||||||
|
data_len -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct as5835_54x_psu_data *as5835_54x_psu_update_device(struct device *dev)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = to_i2c_client(dev);
|
||||||
|
struct as5835_54x_psu_data *data = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
mutex_lock(&data->update_lock);
|
||||||
|
|
||||||
|
if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|
||||||
|
|| !data->valid) {
|
||||||
|
int status;
|
||||||
|
|
||||||
|
dev_dbg(&client->dev, "Starting as5835_54x update\n");
|
||||||
|
data->valid = 0;
|
||||||
|
|
||||||
|
/* Read psu status */
|
||||||
|
status = as5835_54x_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET);
|
||||||
|
|
||||||
|
if (status < 0) {
|
||||||
|
dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data->status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
memset(data->model_name, 0, sizeof(data->model_name));
|
||||||
|
memset(data->serial, 0, sizeof(data->serial));
|
||||||
|
|
||||||
|
if (IS_PRESENT(data->index, data->status)) {
|
||||||
|
/* Read model name */
|
||||||
|
status = as5835_54x_psu_read_bytes(client, MODEL_NAME_REG_OFFSET, data->model_name,
|
||||||
|
ARRAY_SIZE(data->model_name)-1);
|
||||||
|
if (status < 0) {
|
||||||
|
data->model_name[0] = '\0';
|
||||||
|
dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read serial number */
|
||||||
|
status = as5835_54x_psu_read_bytes(client, SERIAL_NUM_REG_OFFSET, data->serial,
|
||||||
|
ARRAY_SIZE(data->serial)-1);
|
||||||
|
if (status < 0) {
|
||||||
|
data->serial[0] = '\0';
|
||||||
|
dev_dbg(&client->dev, "unable to read serial number from (0x%x)\n", client->addr);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
data->serial[SERIAL_NUM_LEN] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data->last_updated = jiffies;
|
||||||
|
data->valid = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
mutex_unlock(&data->update_lock);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
module_i2c_driver(as5835_54x_psu_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
|
||||||
|
MODULE_DESCRIPTION("as5835_54x_psu driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
../../common/modules/ym2651y.c
|
@ -0,0 +1,16 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Accton AS5835-54X Platform Monitoring FAN service
|
||||||
|
Before=pmon.service
|
||||||
|
After=as5835-54x-platform-monitor.service
|
||||||
|
DefaultDependencies=no
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/local/bin/accton_as5835_54x_monitor_fan.py
|
||||||
|
KillSignal=SIGKILL
|
||||||
|
SuccessExitStatus=SIGKILL
|
||||||
|
|
||||||
|
# Resource Limitations
|
||||||
|
LimitCORE=infinity
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
@ -0,0 +1,16 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Accton AS5835-54X Platform Monitoring PSU service
|
||||||
|
Before=pmon.service
|
||||||
|
After=as5835-54x-platform-monitor.service
|
||||||
|
DefaultDependencies=no
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/local/bin/accton_as5835_54x_monitor_psu.py
|
||||||
|
KillSignal=SIGKILL
|
||||||
|
SuccessExitStatus=SIGKILL
|
||||||
|
|
||||||
|
# Resource Limitations
|
||||||
|
LimitCORE=infinity
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
@ -0,0 +1,18 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Accton AS5835-54X Platform Monitoring service
|
||||||
|
Before=pmon.service
|
||||||
|
After=sysinit.target
|
||||||
|
DefaultDependencies=no
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStartPre=/usr/local/bin/accton_as5835_54x_util.py install
|
||||||
|
ExecStart=/usr/local/bin/accton_as5835_54x_monitor.py
|
||||||
|
KillSignal=SIGKILL
|
||||||
|
SuccessExitStatus=SIGKILL
|
||||||
|
#StandardOutput=tty
|
||||||
|
|
||||||
|
# Resource Limitations
|
||||||
|
LimitCORE=infinity
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from setuptools import setup
|
||||||
|
os.listdir
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='as5835_54x',
|
||||||
|
version='1.0',
|
||||||
|
description='Module to initialize Accton AS5835-54X platforms',
|
||||||
|
|
||||||
|
packages=['as5835_54x'],
|
||||||
|
package_dir={'as5835_54x': 'as5835-54x/classes'},
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,74 @@
|
|||||||
|
Copyright (C) 2016 Accton Networks, Inc.
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
It under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Contents of this package:
|
||||||
|
module - Contains source code of as7326 kernel driver modules.
|
||||||
|
util - operational scripts.
|
||||||
|
|
||||||
|
Sonic creates a docker container and run building process under it.
|
||||||
|
If user tries to built new drivers, please get into that docker and
|
||||||
|
dpkg-buildpackage for them.
|
||||||
|
|
||||||
|
All Linux kernel code is licensed under the GPLv1. All other code is
|
||||||
|
licensed under the GPLv3. Please see the LICENSE file for copies of
|
||||||
|
both licenses.
|
||||||
|
|
||||||
|
The code for integacting with Accton AS5835-54X has 2 parts,
|
||||||
|
kernel drivers and operational script.
|
||||||
|
The kernel drivers of peripherals are under module/ directory.
|
||||||
|
1. These drivers can be built to individual ko during dpkg-buildpackage.
|
||||||
|
2. A operational script, accton_as7326_util.py, for device initializatian.
|
||||||
|
Run "accton_as5835_54x_util.py install" to install drivers.
|
||||||
|
|
||||||
|
To initialize the system, run "accton_as5835_54x_util.py install".
|
||||||
|
To clean up the drivers & devices, run "accton_as5835_54x_util.py clean".
|
||||||
|
To dump information of sensors, run "accton_as5835_54x_util.py show".
|
||||||
|
To dump SFP EEPROM, run "accton_as5835_54x_util.py sff".
|
||||||
|
To set fan speed, run "accton_as5835_54x_util.py set fan".
|
||||||
|
To enable/disable SFP emission, run "accton_as5835_54x_util.py set sfp".
|
||||||
|
To set system LEDs' color, run "accton_as5835_54x_util.py set led"
|
||||||
|
For more information, run "accton_as5835_54x_util.py --help".
|
||||||
|
|
||||||
|
====================================================================
|
||||||
|
Besides applying accton_as7326_util.py to access peripherals, you can
|
||||||
|
access peripherals by sysfs nodes directly after the installation is run.
|
||||||
|
|
||||||
|
System LED:
|
||||||
|
There are 5 system LEDs at the lower-left corner of front panel.
|
||||||
|
They are loc, diag, fan, ps1, and ps2.
|
||||||
|
The sysfs interface color mappings are as follows:
|
||||||
|
Brightness:
|
||||||
|
0 => off
|
||||||
|
1 => green
|
||||||
|
2 => green blinking
|
||||||
|
3 => amber
|
||||||
|
4 => amber blinking
|
||||||
|
But not all colors are available for each LED.
|
||||||
|
|
||||||
|
Fan Control:
|
||||||
|
There are 10 fans inside 5 fan modules.
|
||||||
|
All fans share 1 duty setting, ranged from 0~100.
|
||||||
|
|
||||||
|
Thermal sensers:
|
||||||
|
4 temperature sensors are controlled by the lm75 kernel modules.
|
||||||
|
|
||||||
|
PSUs:
|
||||||
|
There 2 power supplies slot at the left/right side of the back.
|
||||||
|
Once if a PSU is not plugged, the status of it is shown failed.
|
||||||
|
|
||||||
|
There are 48 SFP+ and 6 QSFP modules are equipped.
|
||||||
|
Before operating on PSU and QSFP+, please make sure it is well plugged.
|
||||||
|
Otherwise, operation is going to fail.
|
||||||
|
|
@ -0,0 +1,205 @@
|
|||||||
|
#!/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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# HISTORY:
|
||||||
|
# mm/dd/yyyy (A.D.)
|
||||||
|
# 11/13/2017: Polly Hsu, Create
|
||||||
|
# 05/08/2019: Roy Lee, changed for as5812-54x.
|
||||||
|
# 05/29/2019: Brandon Chuang, changed for as5835-54x.
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
|
try:
|
||||||
|
import os
|
||||||
|
import sys, getopt
|
||||||
|
import subprocess
|
||||||
|
import click
|
||||||
|
import imp
|
||||||
|
import logging
|
||||||
|
import logging.config
|
||||||
|
import types
|
||||||
|
import time # this is only being used as part of the example
|
||||||
|
import traceback
|
||||||
|
import signal
|
||||||
|
from tabulate import tabulate
|
||||||
|
from as5835_54x.fanutil import FanUtil
|
||||||
|
from as5835_54x.thermalutil import ThermalUtil
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError('%s - required module not found' % str(e))
|
||||||
|
|
||||||
|
# Deafults
|
||||||
|
VERSION = '1.0'
|
||||||
|
FUNCTION_NAME = 'accton_as5835_54x_monitor'
|
||||||
|
DUTY_MAX = 100
|
||||||
|
|
||||||
|
global log_file
|
||||||
|
global log_level
|
||||||
|
|
||||||
|
# Make a class we can use to capture stdout and sterr in the log
|
||||||
|
class accton_as5835_54x_monitor(object):
|
||||||
|
# static temp var
|
||||||
|
_ori_temp = 0
|
||||||
|
_new_perc = 0
|
||||||
|
|
||||||
|
def __init__(self, log_file, log_level):
|
||||||
|
"""Needs a logger and a logger level."""
|
||||||
|
# set up logging to file
|
||||||
|
logging.basicConfig(
|
||||||
|
filename=log_file,
|
||||||
|
filemode='w',
|
||||||
|
level=log_level,
|
||||||
|
format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s',
|
||||||
|
datefmt='%H:%M:%S'
|
||||||
|
)
|
||||||
|
|
||||||
|
# set up logging to console
|
||||||
|
if log_level == logging.DEBUG:
|
||||||
|
console = logging.StreamHandler()
|
||||||
|
console.setLevel(log_level)
|
||||||
|
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
|
||||||
|
console.setFormatter(formatter)
|
||||||
|
logging.getLogger('').addHandler(console)
|
||||||
|
|
||||||
|
logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level)
|
||||||
|
|
||||||
|
def manage_fans(self):
|
||||||
|
FAN_LEV1_UP_TEMP = 57700 # temperature
|
||||||
|
FAN_LEV1_DOWN_TEMP = 0 # unused
|
||||||
|
FAN_LEV1_SPEED_PERC = DUTY_MAX # percentage*/
|
||||||
|
|
||||||
|
FAN_LEV2_UP_TEMP = 53000
|
||||||
|
FAN_LEV2_DOWN_TEMP = 52700
|
||||||
|
FAN_LEV2_SPEED_PERC = 80
|
||||||
|
|
||||||
|
FAN_LEV3_UP_TEMP = 49500
|
||||||
|
FAN_LEV3_DOWN_TEMP = 47700
|
||||||
|
FAN_LEV3_SPEED_PERC = 65
|
||||||
|
|
||||||
|
FAN_LEV4_UP_TEMP = 0 # unused
|
||||||
|
FAN_LEV4_DOWN_TEMP = 42700
|
||||||
|
FAN_LEV4_SPEED_PERC = 40
|
||||||
|
|
||||||
|
|
||||||
|
thermal = ThermalUtil()
|
||||||
|
fan = FanUtil()
|
||||||
|
|
||||||
|
temp2 = thermal.get_thermal_2_val()
|
||||||
|
if temp2 is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
temp3 = thermal.get_thermal_3_val()
|
||||||
|
if temp3 is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
new_temp = (temp2 + temp3) / 2
|
||||||
|
|
||||||
|
for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1):
|
||||||
|
fan_stat = fan.get_fan_status(x)
|
||||||
|
if fan_stat is None:
|
||||||
|
return False
|
||||||
|
if fan_stat is False:
|
||||||
|
self._new_perc = FAN_LEV1_SPEED_PERC
|
||||||
|
logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', self._new_perc, x)
|
||||||
|
break
|
||||||
|
logging.debug('INFO. fan_stat is True (fan_num:%d)', x)
|
||||||
|
|
||||||
|
if fan_stat is not None and fan_stat is not False:
|
||||||
|
diff = new_temp - self._ori_temp
|
||||||
|
if diff == 0:
|
||||||
|
logging.debug('INFO. RETURN. THERMAL temp not changed. %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
if diff >= 0:
|
||||||
|
is_up = True
|
||||||
|
logging.debug('INFO. THERMAL temp UP %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp)
|
||||||
|
else:
|
||||||
|
is_up = False
|
||||||
|
logging.debug('INFO. THERMAL temp DOWN %d / %d (new_temp / ori_temp)', new_temp, self._ori_temp)
|
||||||
|
|
||||||
|
if is_up is True:
|
||||||
|
if new_temp >= FAN_LEV1_UP_TEMP:
|
||||||
|
self._new_perc = FAN_LEV1_SPEED_PERC
|
||||||
|
elif new_temp >= FAN_LEV2_UP_TEMP:
|
||||||
|
self._new_perc = FAN_LEV2_SPEED_PERC
|
||||||
|
elif new_temp >= FAN_LEV3_UP_TEMP:
|
||||||
|
self._new_perc = FAN_LEV3_SPEED_PERC
|
||||||
|
else:
|
||||||
|
self._new_perc = FAN_LEV4_SPEED_PERC
|
||||||
|
logging.debug('INFO. SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp)
|
||||||
|
else:
|
||||||
|
if new_temp <= FAN_LEV4_DOWN_TEMP:
|
||||||
|
self._new_perc = FAN_LEV4_SPEED_PERC
|
||||||
|
elif new_temp <= FAN_LEV3_DOWN_TEMP:
|
||||||
|
self._new_perc = FAN_LEV3_SPEED_PERC
|
||||||
|
elif new_temp <= FAN_LEV2_DOWN_TEMP:
|
||||||
|
self._new_perc = FAN_LEV2_SPEED_PERC
|
||||||
|
else:
|
||||||
|
self._new_perc = FAN_LEV1_SPEED_PERC
|
||||||
|
logging.debug('INFO. SET. FAN_SPEED as %d (new THERMAL temp:%d)', self._new_perc, new_temp)
|
||||||
|
|
||||||
|
cur_perc = fan.get_fan_duty_cycle()
|
||||||
|
if cur_perc == self._new_perc:
|
||||||
|
logging.debug('INFO. RETURN. FAN speed not changed. %d / %d (new_perc / ori_perc)', self._new_perc, cur_perc)
|
||||||
|
return True
|
||||||
|
|
||||||
|
set_stat = fan.set_fan_duty_cycle(self._new_perc)
|
||||||
|
if set_stat is True:
|
||||||
|
logging.debug('INFO: PASS. set_fan_duty_cycle (%d)', self._new_perc)
|
||||||
|
else:
|
||||||
|
logging.debug('INFO: FAIL. set_fan_duty_cycle (%d)', self._new_perc)
|
||||||
|
|
||||||
|
logging.debug('INFO: GET. ori_perc is %d. ori_temp is %d', cur_perc, self._ori_temp)
|
||||||
|
self._ori_temp = new_temp
|
||||||
|
logging.debug('INFO: UPDATE. ori_perc to %d. ori_temp to %d', cur_perc, self._ori_temp)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def handler(signum, frame):
|
||||||
|
fan = FanUtil()
|
||||||
|
logging.debug('INFO:Cause signal %d, set fan speed max.', signum)
|
||||||
|
fan.set_fan_duty_cycle(DUTY_MAX)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
def main(argv):
|
||||||
|
log_file = '%s.log' % FUNCTION_NAME
|
||||||
|
log_level = logging.INFO
|
||||||
|
if len(sys.argv) != 1:
|
||||||
|
try:
|
||||||
|
opts, args = getopt.getopt(argv,'hdl:',['lfile='])
|
||||||
|
except getopt.GetoptError:
|
||||||
|
print 'Usage: %s [-d] [-l <log_file>]' % sys.argv[0]
|
||||||
|
return 0
|
||||||
|
for opt, arg in opts:
|
||||||
|
if opt == '-h':
|
||||||
|
print 'Usage: %s [-d] [-l <log_file>]' % sys.argv[0]
|
||||||
|
return 0
|
||||||
|
elif opt in ('-d', '--debug'):
|
||||||
|
log_level = logging.DEBUG
|
||||||
|
elif opt in ('-l', '--lfile'):
|
||||||
|
log_file = arg
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, handler)
|
||||||
|
signal.signal(signal.SIGTERM, handler)
|
||||||
|
monitor = accton_as5835_54x_monitor(log_file, log_level)
|
||||||
|
|
||||||
|
# Loop forever, doing something useful hopefully:
|
||||||
|
while True:
|
||||||
|
monitor.manage_fans()
|
||||||
|
time.sleep(10)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main(sys.argv[1:])
|
@ -0,0 +1,198 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright (C) 2018 Accton Technology Corporation
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# HISTORY:
|
||||||
|
# mm/dd/yyyy (A.D.)
|
||||||
|
# 5/27/2019: Brandon_Chuang create
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
|
try:
|
||||||
|
import os
|
||||||
|
import sys, getopt
|
||||||
|
import subprocess
|
||||||
|
import click
|
||||||
|
import imp
|
||||||
|
import logging
|
||||||
|
import logging.config
|
||||||
|
import logging.handlers
|
||||||
|
import types
|
||||||
|
import time # this is only being used as part of the example
|
||||||
|
import traceback
|
||||||
|
from tabulate import tabulate
|
||||||
|
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError('%s - required module not found' % str(e))
|
||||||
|
|
||||||
|
# Deafults
|
||||||
|
VERSION = '1.0'
|
||||||
|
FUNCTION_NAME = '/usr/local/bin/accton_as5835_54x_monitor_fan'
|
||||||
|
|
||||||
|
global log_file
|
||||||
|
global log_level
|
||||||
|
|
||||||
|
|
||||||
|
class switch(object):
|
||||||
|
def __init__(self, value):
|
||||||
|
self.value = value
|
||||||
|
self.fall = False
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
"""Return the match method once, then stop"""
|
||||||
|
yield self.match
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
def match(self, *args):
|
||||||
|
"""Indicate whether or not to enter a case suite"""
|
||||||
|
if self.fall or not args:
|
||||||
|
return True
|
||||||
|
elif self.value in args: # changed for v1.5, see below
|
||||||
|
self.fall = True
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
fan_state=[2, 2, 2, 2, 2, 2] #init state=2, insert=1, remove=0
|
||||||
|
fan_status_state=[2, 2, 2, 2, 2, 2] #init state=2, fault=1, normal=0
|
||||||
|
# Make a class we can use to capture stdout and sterr in the log
|
||||||
|
class device_monitor(object):
|
||||||
|
|
||||||
|
#/sys/bus/i2c/devices/3-0063
|
||||||
|
#fan1_present, fan5_present
|
||||||
|
|
||||||
|
def __init__(self, log_file, log_level):
|
||||||
|
|
||||||
|
self.fan_num = 5
|
||||||
|
self.fan_path = "/sys/bus/i2c/devices/3-0063/"
|
||||||
|
self.present = {
|
||||||
|
0: "fan1_present",
|
||||||
|
1: "fan2_present",
|
||||||
|
2: "fan3_present",
|
||||||
|
3: "fan4_present",
|
||||||
|
4: "fan5_present",
|
||||||
|
}
|
||||||
|
|
||||||
|
self.fault = {
|
||||||
|
0: "fan1_fault",
|
||||||
|
1: "fan2_fault",
|
||||||
|
2: "fan3_fault",
|
||||||
|
3: "fan4_fault",
|
||||||
|
4: "fan5_fault",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
"""Needs a logger and a logger level."""
|
||||||
|
# set up logging to file
|
||||||
|
logging.basicConfig(
|
||||||
|
filename=log_file,
|
||||||
|
filemode='w',
|
||||||
|
level=log_level,
|
||||||
|
format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s',
|
||||||
|
datefmt='%H:%M:%S'
|
||||||
|
)
|
||||||
|
|
||||||
|
# set up logging to console
|
||||||
|
if log_level == logging.DEBUG:
|
||||||
|
console = logging.StreamHandler()
|
||||||
|
console.setLevel(logging.DEBUG)
|
||||||
|
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
|
||||||
|
console.setFormatter(formatter)
|
||||||
|
logging.getLogger('').addHandler(console)
|
||||||
|
|
||||||
|
sys_handler = logging.handlers.SysLogHandler(address = '/dev/log')
|
||||||
|
#sys_handler.setLevel(logging.WARNING)
|
||||||
|
sys_handler.setLevel(logging.INFO)
|
||||||
|
logging.getLogger('').addHandler(sys_handler)
|
||||||
|
|
||||||
|
|
||||||
|
#logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level)
|
||||||
|
|
||||||
|
def manage_fan(self):
|
||||||
|
|
||||||
|
FAN_STATE_REMOVE = 0
|
||||||
|
FAN_STATE_INSERT = 1
|
||||||
|
|
||||||
|
FAN_STATUS_FAULT = 1
|
||||||
|
FAN_STATUS_NORMAL = 0
|
||||||
|
|
||||||
|
global fan_state
|
||||||
|
global fan_status_state
|
||||||
|
|
||||||
|
for idx in range (0, self.fan_num):
|
||||||
|
node = self.fan_path + self.present[idx]
|
||||||
|
try:
|
||||||
|
val_file = open(node)
|
||||||
|
except IOError as e:
|
||||||
|
print "Error: unable to open file: %s" % str(e)
|
||||||
|
return False
|
||||||
|
content = val_file.readline().rstrip()
|
||||||
|
val_file.close()
|
||||||
|
# content is a string, either "0" or "1"
|
||||||
|
if content == "1":
|
||||||
|
if fan_state[idx]!=1:
|
||||||
|
fan_state[idx]=FAN_STATE_INSERT
|
||||||
|
logging.info("FAN-%d present is detected", idx+1);
|
||||||
|
else:
|
||||||
|
if fan_state[idx]!=0:
|
||||||
|
fan_state[idx]=FAN_STATE_REMOVE
|
||||||
|
logging.warning("Alarm for FAN-%d absent is detected", idx+1)
|
||||||
|
|
||||||
|
for idx in range (0, self.fan_num):
|
||||||
|
node = self.fan_path + self.fault[idx]
|
||||||
|
try:
|
||||||
|
val_file = open(node)
|
||||||
|
except IOError as e:
|
||||||
|
print "Error: unable to open file: %s" % str(e)
|
||||||
|
return False
|
||||||
|
content = val_file.readline().rstrip()
|
||||||
|
val_file.close()
|
||||||
|
# content is a string, either "0" or "1"
|
||||||
|
if content == "1":
|
||||||
|
if fan_status_state[idx]!=FAN_STATUS_FAULT:
|
||||||
|
if fan_state[idx] == FAN_STATE_INSERT:
|
||||||
|
logging.warning("Alarm for FAN-%d failed is detected", idx+1);
|
||||||
|
fan_status_state[idx]=FAN_STATUS_FAULT
|
||||||
|
else:
|
||||||
|
fan_status_state[idx]=FAN_STATUS_NORMAL
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def main(argv):
|
||||||
|
log_file = '%s.log' % FUNCTION_NAME
|
||||||
|
log_level = logging.INFO
|
||||||
|
if len(sys.argv) != 1:
|
||||||
|
try:
|
||||||
|
opts, args = getopt.getopt(argv,'hdl:',['lfile='])
|
||||||
|
except getopt.GetoptError:
|
||||||
|
print 'Usage: %s [-d] [-l <log_file>]' % sys.argv[0]
|
||||||
|
return 0
|
||||||
|
for opt, arg in opts:
|
||||||
|
if opt == '-h':
|
||||||
|
print 'Usage: %s [-d] [-l <log_file>]' % sys.argv[0]
|
||||||
|
return 0
|
||||||
|
elif opt in ('-d', '--debug'):
|
||||||
|
log_level = logging.DEBUG
|
||||||
|
elif opt in ('-l', '--lfile'):
|
||||||
|
log_file = arg
|
||||||
|
monitor = device_monitor(log_file, log_level)
|
||||||
|
while True:
|
||||||
|
monitor.manage_fan()
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main(sys.argv[1:])
|
@ -0,0 +1,190 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright (C) 2018 Accton Technology Corporation
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
# HISTORY:
|
||||||
|
# mm/dd/yyyy (A.D.)
|
||||||
|
# 7/2/2018: Jostar create for as7326-56x
|
||||||
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
|
try:
|
||||||
|
import os
|
||||||
|
import sys, getopt
|
||||||
|
import subprocess
|
||||||
|
import click
|
||||||
|
import imp
|
||||||
|
import logging
|
||||||
|
import logging.config
|
||||||
|
import logging.handlers
|
||||||
|
import types
|
||||||
|
import time # this is only being used as part of the example
|
||||||
|
import traceback
|
||||||
|
from tabulate import tabulate
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError('%s - required module not found' % str(e))
|
||||||
|
|
||||||
|
# Deafults
|
||||||
|
VERSION = '1.0'
|
||||||
|
FUNCTION_NAME = '/usr/local/bin/accton_as5835_54x_monitor_fan'
|
||||||
|
|
||||||
|
global log_file
|
||||||
|
global log_level
|
||||||
|
|
||||||
|
|
||||||
|
class switch(object):
|
||||||
|
def __init__(self, value):
|
||||||
|
self.value = value
|
||||||
|
self.fall = False
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
"""Return the match method once, then stop"""
|
||||||
|
yield self.match
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
def match(self, *args):
|
||||||
|
"""Indicate whether or not to enter a case suite"""
|
||||||
|
if self.fall or not args:
|
||||||
|
return True
|
||||||
|
elif self.value in args: # changed for v1.5, see below
|
||||||
|
self.fall = True
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
psu_state=[2, 2]
|
||||||
|
psu_power_status=[2, 2]
|
||||||
|
# Make a class we can use to capture stdout and sterr in the log
|
||||||
|
class device_monitor(object):
|
||||||
|
|
||||||
|
def __init__(self, log_file, log_level):
|
||||||
|
|
||||||
|
self.psu_num = 2
|
||||||
|
self.psu_path = "/sys/bus/i2c/devices/"
|
||||||
|
self.presence = "/psu_present"
|
||||||
|
self.oper_status = "/psu_power_good"
|
||||||
|
self.mapping = {
|
||||||
|
0: "11-0050",
|
||||||
|
1: "12-0053",
|
||||||
|
}
|
||||||
|
|
||||||
|
"""Needs a logger and a logger level."""
|
||||||
|
# set up logging to file
|
||||||
|
logging.basicConfig(
|
||||||
|
filename=log_file,
|
||||||
|
filemode='w',
|
||||||
|
level=log_level,
|
||||||
|
format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s',
|
||||||
|
datefmt='%H:%M:%S'
|
||||||
|
)
|
||||||
|
# set up logging to console
|
||||||
|
|
||||||
|
if log_level == logging.DEBUG:
|
||||||
|
console = logging.StreamHandler()
|
||||||
|
console.setLevel(log_level)
|
||||||
|
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
|
||||||
|
console.setFormatter(formatter)
|
||||||
|
logging.getLogger('').addHandler(console)
|
||||||
|
|
||||||
|
sys_handler = logging.handlers.SysLogHandler(address = '/dev/log')
|
||||||
|
#sys_handler.setLevel(logging.WARNING)
|
||||||
|
sys_handler.setLevel(logging.INFO)
|
||||||
|
logging.getLogger('').addHandler(sys_handler)
|
||||||
|
|
||||||
|
#logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level)
|
||||||
|
|
||||||
|
def manage_psu(self):
|
||||||
|
|
||||||
|
PSU_STATE_REMOVE = 0
|
||||||
|
PSU_STATE_INSERT = 1
|
||||||
|
|
||||||
|
PSU_STATUS_NO_POWER = 0
|
||||||
|
PSU_STATUS_POWER_GOOD = 1
|
||||||
|
|
||||||
|
global psu_state
|
||||||
|
global psu_power_status
|
||||||
|
|
||||||
|
for idx in range (0, self.psu_num):
|
||||||
|
node = self.psu_path + self.mapping[idx] + self.presence
|
||||||
|
try:
|
||||||
|
val_file = open(node)
|
||||||
|
except IOError as e:
|
||||||
|
print "Error: unable to open file: %s" % str(e)
|
||||||
|
return False
|
||||||
|
content = val_file.readline().rstrip()
|
||||||
|
val_file.close()
|
||||||
|
# content is a string, either "0" or "1"
|
||||||
|
if content == "1":
|
||||||
|
if psu_state[idx]!=PSU_STATE_INSERT:
|
||||||
|
psu_state[idx]=PSU_STATE_INSERT
|
||||||
|
logging.info("PSU-%d present is detected", idx+1);
|
||||||
|
#psu_power_status[idx]=PSU_STATUS_POWER_GOOD #when insert, assume power is good. If no_power, next code will find it.
|
||||||
|
else:
|
||||||
|
if psu_state[idx]!=PSU_STATE_REMOVE:
|
||||||
|
psu_state[idx]=PSU_STATE_REMOVE
|
||||||
|
logging.warning("Alarm for PSU-%d absent is detected", idx+1);
|
||||||
|
psu_power_status[idx]=PSU_STATUS_NO_POWER
|
||||||
|
|
||||||
|
for idx in range (0, self.psu_num):
|
||||||
|
node = self.psu_path + self.mapping[idx] + self.oper_status
|
||||||
|
try:
|
||||||
|
val_file = open(node)
|
||||||
|
except IOError as e:
|
||||||
|
print "Error: unable to open file: %s" % str(e)
|
||||||
|
return False
|
||||||
|
content = val_file.readline().rstrip()
|
||||||
|
val_file.close()
|
||||||
|
# content is a string, either "0" or "1"
|
||||||
|
#logging.info("content=%s, psu_power_status[%d]=%d", content, idx, psu_power_status[idx]);
|
||||||
|
if content == "0":
|
||||||
|
if psu_power_status[idx]!=PSU_STATUS_NO_POWER:
|
||||||
|
if psu_state[idx]==PSU_STATE_INSERT:
|
||||||
|
logging.warning("Alarm for PSU-%d fault is detected", idx+1);
|
||||||
|
psu_power_status[idx]=PSU_STATUS_NO_POWER
|
||||||
|
else:
|
||||||
|
if psu_power_status[idx] !=PSU_STATUS_POWER_GOOD:
|
||||||
|
logging.info("PSU-%d power_good is detected", idx+1);
|
||||||
|
psu_power_status[idx]=PSU_STATUS_POWER_GOOD
|
||||||
|
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def main(argv):
|
||||||
|
log_file = '%s.log' % FUNCTION_NAME
|
||||||
|
log_level = logging.INFO
|
||||||
|
if len(sys.argv) != 1:
|
||||||
|
try:
|
||||||
|
opts, args = getopt.getopt(argv,'hdl:',['lfile='])
|
||||||
|
except getopt.GetoptError:
|
||||||
|
print 'Usage: %s [-d] [-l <log_file>]' % sys.argv[0]
|
||||||
|
return 0
|
||||||
|
for opt, arg in opts:
|
||||||
|
if opt == '-h':
|
||||||
|
print 'Usage: %s [-d] [-l <log_file>]' % sys.argv[0]
|
||||||
|
return 0
|
||||||
|
elif opt in ('-d', '--debug'):
|
||||||
|
log_level = logging.DEBUG
|
||||||
|
elif opt in ('-l', '--lfile'):
|
||||||
|
log_file = arg
|
||||||
|
monitor = device_monitor(log_file, log_level)
|
||||||
|
# Loop forever, doing something useful hopefully:
|
||||||
|
while True:
|
||||||
|
monitor.manage_psu()
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main(sys.argv[1:])
|
@ -0,0 +1,592 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright (C) 2019 Accton Networks, Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Usage: %(scriptName)s [options] command object
|
||||||
|
|
||||||
|
options:
|
||||||
|
-h | --help : this help message
|
||||||
|
-d | --debug : run with debug mode
|
||||||
|
-f | --force : ignore error during installation or clean
|
||||||
|
command:
|
||||||
|
install : install drivers and generate related sysfs nodes
|
||||||
|
clean : uninstall drivers and remove related sysfs nodes
|
||||||
|
show : show all systen status
|
||||||
|
sff : dump SFP eeprom
|
||||||
|
set : change board setting with fan|led|sfp
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import commands
|
||||||
|
import sys, getopt
|
||||||
|
import logging
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PROJECT_NAME = 'as5835_54x'
|
||||||
|
version = '0.1.0'
|
||||||
|
verbose = False
|
||||||
|
DEBUG = False
|
||||||
|
args = []
|
||||||
|
ALL_DEVICE = {}
|
||||||
|
DEVICE_NO = {'led':5, 'fan':5,'thermal':4, 'psu':2, 'sfp':54}
|
||||||
|
FORCE = 0
|
||||||
|
#logging.basicConfig(filename= PROJECT_NAME+'.log', filemode='w',level=logging.DEBUG)
|
||||||
|
#logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
|
if DEBUG == True:
|
||||||
|
print sys.argv[0]
|
||||||
|
print 'ARGV :', sys.argv[1:]
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
global DEBUG
|
||||||
|
global args
|
||||||
|
global FORCE
|
||||||
|
|
||||||
|
if len(sys.argv)<2:
|
||||||
|
show_help()
|
||||||
|
|
||||||
|
options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help',
|
||||||
|
'debug',
|
||||||
|
'force',
|
||||||
|
])
|
||||||
|
if DEBUG == True:
|
||||||
|
print options
|
||||||
|
print args
|
||||||
|
print len(sys.argv)
|
||||||
|
|
||||||
|
for opt, arg in options:
|
||||||
|
if opt in ('-h', '--help'):
|
||||||
|
show_help()
|
||||||
|
elif opt in ('-d', '--debug'):
|
||||||
|
DEBUG = True
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
elif opt in ('-f', '--force'):
|
||||||
|
FORCE = 1
|
||||||
|
else:
|
||||||
|
logging.info('no option')
|
||||||
|
for arg in args:
|
||||||
|
if arg == 'install':
|
||||||
|
do_install()
|
||||||
|
elif arg == 'clean':
|
||||||
|
do_uninstall()
|
||||||
|
elif arg == 'show':
|
||||||
|
device_traversal()
|
||||||
|
elif arg == 'sff':
|
||||||
|
if len(args)!=2:
|
||||||
|
show_eeprom_help()
|
||||||
|
elif int(args[1]) ==0 or int(args[1]) > DEVICE_NO['sfp']:
|
||||||
|
show_eeprom_help()
|
||||||
|
else:
|
||||||
|
show_eeprom(args[1])
|
||||||
|
return
|
||||||
|
elif arg == 'set':
|
||||||
|
if len(args)<3:
|
||||||
|
show_set_help()
|
||||||
|
else:
|
||||||
|
set_device(args[1:])
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
show_help()
|
||||||
|
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def show_help():
|
||||||
|
print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]}
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
def show_set_help():
|
||||||
|
cmd = sys.argv[0].split("/")[-1]+ " " + args[0]
|
||||||
|
print cmd +" [led|sfp|fan]"
|
||||||
|
print " use \""+ cmd + " led 0-4 \" to set led color"
|
||||||
|
print " use \""+ cmd + " fan 0-100\" to set fan duty percetage"
|
||||||
|
print " use \""+ cmd + " sfp 1-54 {0|1}\" to set sfp# tx_disable"
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
def show_eeprom_help():
|
||||||
|
cmd = sys.argv[0].split("/")[-1]+ " " + args[0]
|
||||||
|
print " use \""+ cmd + " 1-54 \" to dump sfp# eeprom"
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
def my_log(txt):
|
||||||
|
if DEBUG == True:
|
||||||
|
print "[Debug]"+txt
|
||||||
|
return
|
||||||
|
|
||||||
|
def log_os_system(cmd, show):
|
||||||
|
logging.info('Run :'+cmd)
|
||||||
|
status, output = commands.getstatusoutput(cmd)
|
||||||
|
my_log (cmd +"with result:" + str(status))
|
||||||
|
my_log (" output:"+output)
|
||||||
|
if status:
|
||||||
|
logging.info('Failed :'+cmd)
|
||||||
|
if show:
|
||||||
|
print('Failed :'+cmd)
|
||||||
|
return status, output
|
||||||
|
|
||||||
|
def driver_check():
|
||||||
|
ret, lsmod = log_os_system("lsmod| grep accton", 0)
|
||||||
|
logging.info('mods:'+lsmod)
|
||||||
|
if len(lsmod) ==0:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
kos = [
|
||||||
|
'modprobe i2c_dev',
|
||||||
|
'modprobe i2c_mux_pca954x force_deselect_on_exit=1',
|
||||||
|
'modprobe accton_as5835_54x_cpld' ,
|
||||||
|
'modprobe ym2651y' ,
|
||||||
|
'modprobe accton_as5835_54x_fan' ,
|
||||||
|
'modprobe optoe' ,
|
||||||
|
'modprobe accton_as5835_54x_leds' ,
|
||||||
|
'modprobe accton_as5835_54x_psu' ]
|
||||||
|
|
||||||
|
def driver_install():
|
||||||
|
global FORCE
|
||||||
|
status, output = log_os_system("depmod", 1)
|
||||||
|
for i in range(0,len(kos)):
|
||||||
|
status, output = log_os_system(kos[i], 1)
|
||||||
|
if status:
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def driver_uninstall():
|
||||||
|
global FORCE
|
||||||
|
for i in range(0,len(kos)):
|
||||||
|
rm = kos[-(i+1)].replace("modprobe", "modprobe -rq")
|
||||||
|
rm = rm.replace("insmod", "rmmod")
|
||||||
|
lst = rm.split(" ")
|
||||||
|
if len(lst) > 3:
|
||||||
|
del(lst[3])
|
||||||
|
rm = " ".join(lst)
|
||||||
|
status, output = log_os_system(rm, 1)
|
||||||
|
if status:
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
return 0
|
||||||
|
|
||||||
|
led_prefix ='/sys/class/leds/accton_'+PROJECT_NAME+'_led::'
|
||||||
|
hwmon_types = {'led': ['diag','fan','loc','psu1','psu2']}
|
||||||
|
hwmon_nodes = {'led': ['brightness'] }
|
||||||
|
hwmon_prefix ={'led': led_prefix}
|
||||||
|
|
||||||
|
i2c_prefix = '/sys/bus/i2c/devices/'
|
||||||
|
i2c_bus = {'fan': ['3-0063'] ,
|
||||||
|
'thermal': ['18-004b','19-004c', '20-0049', '21-004a'] ,
|
||||||
|
'psu': ['11-0050','12-0053'],
|
||||||
|
'sfp': ['-0050']}
|
||||||
|
i2c_nodes = {'fan': ['present', 'front_speed_rpm', 'rear_speed_rpm'] ,
|
||||||
|
'thermal': ['hwmon/hwmon*/temp1_input'] ,
|
||||||
|
'psu': ['psu_present ', 'psu_power_good'] ,
|
||||||
|
'sfp': ['module_present_', 'module_tx_disable_']}
|
||||||
|
|
||||||
|
sfp_map = [42,43,44,45,46,47,48,49,50,51,
|
||||||
|
52,53,54,55,56,57,58,59,60,61,
|
||||||
|
62,63,64,65,66,67,68,69,70,71,
|
||||||
|
72,73,74,75,76,77,78,79,80,81,
|
||||||
|
82,83,84,85,86,87,88,89,28,29,
|
||||||
|
26,30,31,27]
|
||||||
|
|
||||||
|
qsfp_start = 48
|
||||||
|
|
||||||
|
mknod =[
|
||||||
|
'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-1/new_device',
|
||||||
|
'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device' ,
|
||||||
|
'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device' ,
|
||||||
|
'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device' ,
|
||||||
|
'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-3/new_device',
|
||||||
|
'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-34/new_device',
|
||||||
|
'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-35/new_device',
|
||||||
|
'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-36/new_device',
|
||||||
|
'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-37/new_device',
|
||||||
|
'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-38/new_device',
|
||||||
|
'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-39/new_device',
|
||||||
|
'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-1/new_device',
|
||||||
|
|
||||||
|
'echo as5835_54x_fan 0x63 > /sys/bus/i2c/devices/i2c-3/new_device',
|
||||||
|
'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-18/new_device',
|
||||||
|
'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-19/new_device',
|
||||||
|
'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-20/new_device',
|
||||||
|
'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-21/new_device',
|
||||||
|
'echo as5835_54x_psu1 0x50 > /sys/bus/i2c/devices/i2c-11/new_device',
|
||||||
|
'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-11/new_device',
|
||||||
|
'echo as5835_54x_psu2 0x53 > /sys/bus/i2c/devices/i2c-12/new_device',
|
||||||
|
'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-12/new_device',
|
||||||
|
'echo as5835_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-3/new_device',
|
||||||
|
'echo as5835_54x_cpld2 0x61 > /sys/bus/i2c/devices/i2c-3/new_device',
|
||||||
|
'echo as5835_54x_cpld3 0x62 > /sys/bus/i2c/devices/i2c-3/new_device']
|
||||||
|
|
||||||
|
mknod2 =[
|
||||||
|
'echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-0/new_device',
|
||||||
|
'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-2/new_device' ,
|
||||||
|
'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-2/new_device' ,
|
||||||
|
'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-2/new_device' ,
|
||||||
|
'echo pca9548 0x70 > /sys/bus/i2c/devices/i2c-3/new_device',
|
||||||
|
'echo pca9548 0x71 > /sys/bus/i2c/devices/i2c-34/new_device',
|
||||||
|
'echo pca9548 0x72 > /sys/bus/i2c/devices/i2c-35/new_device',
|
||||||
|
'echo pca9548 0x73 > /sys/bus/i2c/devices/i2c-36/new_device',
|
||||||
|
'echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-37/new_device',
|
||||||
|
'echo pca9548 0x75 > /sys/bus/i2c/devices/i2c-38/new_device',
|
||||||
|
'echo pca9548 0x76 > /sys/bus/i2c/devices/i2c-39/new_device',
|
||||||
|
'echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device',
|
||||||
|
|
||||||
|
'echo as5835_54x_fan 0x63 > /sys/bus/i2c/devices/i2c-3/new_device',
|
||||||
|
'echo lm75 0x4b > /sys/bus/i2c/devices/i2c-18/new_device',
|
||||||
|
'echo lm75 0x4c > /sys/bus/i2c/devices/i2c-19/new_device',
|
||||||
|
'echo lm75 0x49 > /sys/bus/i2c/devices/i2c-20/new_device',
|
||||||
|
'echo lm75 0x4a > /sys/bus/i2c/devices/i2c-21/new_device',
|
||||||
|
'echo as5835_54x_psu1 0x50 > /sys/bus/i2c/devices/i2c-11/new_device',
|
||||||
|
'echo ym2401 0x58 > /sys/bus/i2c/devices/i2c-11/new_device',
|
||||||
|
'echo as5835_54x_psu2 0x53 > /sys/bus/i2c/devices/i2c-12/new_device',
|
||||||
|
'echo ym2401 0x5b > /sys/bus/i2c/devices/i2c-12/new_device',
|
||||||
|
'echo as5835_54x_cpld1 0x60 > /sys/bus/i2c/devices/i2c-3/new_device',
|
||||||
|
'echo as5835_54x_cpld2 0x61 > /sys/bus/i2c/devices/i2c-3/new_device',
|
||||||
|
'echo as5835_54x_cpld3 0x62 > /sys/bus/i2c/devices/i2c-3/new_device']
|
||||||
|
|
||||||
|
|
||||||
|
def i2c_order_check():
|
||||||
|
# i2c bus 0 and 1 might be installed in different order.
|
||||||
|
# Here check if 0x77 is exist @ i2c-1
|
||||||
|
tmp = "echo pca9548 0x77 > /sys/bus/i2c/devices/i2c-1/new_device"
|
||||||
|
status, output = log_os_system(tmp, 0)
|
||||||
|
if not device_exist():
|
||||||
|
order = 1
|
||||||
|
else:
|
||||||
|
order = 0
|
||||||
|
tmp = "echo 0x77 > /sys/bus/i2c/devices/i2c-1/delete_device"
|
||||||
|
status, output = log_os_system(tmp, 0)
|
||||||
|
return order
|
||||||
|
|
||||||
|
def device_install():
|
||||||
|
global FORCE
|
||||||
|
|
||||||
|
order = i2c_order_check()
|
||||||
|
|
||||||
|
# if 0x77 is not exist @i2c-1, use reversed bus order
|
||||||
|
if order:
|
||||||
|
for i in range(0,len(mknod2)):
|
||||||
|
#for pca954x need times to built new i2c buses
|
||||||
|
if mknod2[i].find('pca954') != -1:
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
status, output = log_os_system(mknod2[i], 1)
|
||||||
|
time.sleep(0.01)
|
||||||
|
if status:
|
||||||
|
print output
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
else:
|
||||||
|
for i in range(0,len(mknod)):
|
||||||
|
#for pca954x need times to built new i2c buses
|
||||||
|
if mknod[i].find('pca954') != -1:
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
status, output = log_os_system(mknod[i], 1)
|
||||||
|
if status:
|
||||||
|
print output
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
for i in range(0,len(sfp_map)):
|
||||||
|
if i < qsfp_start:
|
||||||
|
status, output =log_os_system("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1)
|
||||||
|
else:
|
||||||
|
status, output =log_os_system("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/new_device", 1)
|
||||||
|
if status:
|
||||||
|
print output
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
return
|
||||||
|
|
||||||
|
def device_uninstall():
|
||||||
|
global FORCE
|
||||||
|
|
||||||
|
status, output =log_os_system("ls /sys/bus/i2c/devices/0-0077", 0)
|
||||||
|
if status==0:
|
||||||
|
I2C_ORDER=1
|
||||||
|
else:
|
||||||
|
I2C_ORDER=0
|
||||||
|
|
||||||
|
for i in range(0,len(sfp_map)):
|
||||||
|
target = "/sys/bus/i2c/devices/i2c-"+str(sfp_map[i])+"/delete_device"
|
||||||
|
status, output =log_os_system("echo 0x50 > "+ target, 1)
|
||||||
|
if status:
|
||||||
|
print output
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
|
||||||
|
if I2C_ORDER==0:
|
||||||
|
nodelist = mknod
|
||||||
|
else:
|
||||||
|
nodelist = mknod2
|
||||||
|
|
||||||
|
for i in range(len(nodelist)):
|
||||||
|
target = nodelist[-(i+1)]
|
||||||
|
temp = target.split()
|
||||||
|
del temp[1]
|
||||||
|
temp[-1] = temp[-1].replace('new_device', 'delete_device')
|
||||||
|
status, output = log_os_system(" ".join(temp), 1)
|
||||||
|
if status:
|
||||||
|
print output
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def system_ready():
|
||||||
|
if driver_check() == False:
|
||||||
|
return False
|
||||||
|
if not device_exist():
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def do_install():
|
||||||
|
print "Checking system...."
|
||||||
|
if driver_check() == False:
|
||||||
|
print "No driver, installing...."
|
||||||
|
status = driver_install()
|
||||||
|
if status:
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
else:
|
||||||
|
print PROJECT_NAME.upper()+" drivers detected...."
|
||||||
|
if not device_exist():
|
||||||
|
print "No device, installing...."
|
||||||
|
status = device_install()
|
||||||
|
if status:
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
else:
|
||||||
|
print PROJECT_NAME.upper()+" devices detected...."
|
||||||
|
return
|
||||||
|
|
||||||
|
def do_uninstall():
|
||||||
|
print "Checking system...."
|
||||||
|
if not device_exist():
|
||||||
|
print PROJECT_NAME.upper() +" has no device installed...."
|
||||||
|
else:
|
||||||
|
print "Removing device...."
|
||||||
|
status = device_uninstall()
|
||||||
|
if status:
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
|
||||||
|
if driver_check()== False :
|
||||||
|
print PROJECT_NAME.upper() +" has no driver installed...."
|
||||||
|
else:
|
||||||
|
print "Removing installed driver...."
|
||||||
|
status = driver_uninstall()
|
||||||
|
if status:
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def devices_info():
|
||||||
|
global DEVICE_NO
|
||||||
|
global ALL_DEVICE
|
||||||
|
global i2c_bus, hwmon_types
|
||||||
|
for key in DEVICE_NO:
|
||||||
|
ALL_DEVICE[key]= {}
|
||||||
|
for i in range(0,DEVICE_NO[key]):
|
||||||
|
ALL_DEVICE[key][key+str(i+1)] = []
|
||||||
|
|
||||||
|
for key in i2c_bus:
|
||||||
|
buses = i2c_bus[key]
|
||||||
|
nodes = i2c_nodes[key]
|
||||||
|
for i in range(0,len(buses)):
|
||||||
|
for j in range(0,len(nodes)):
|
||||||
|
if 'fan' == key:
|
||||||
|
for k in range(0,DEVICE_NO[key]):
|
||||||
|
node = key+str(k+1)
|
||||||
|
path = i2c_prefix+ buses[i]+"/fan"+str(k+1)+"_"+ nodes[j]
|
||||||
|
my_log(node+": "+ path)
|
||||||
|
ALL_DEVICE[key][node].append(path)
|
||||||
|
elif 'sfp' == key:
|
||||||
|
for k in range(0,DEVICE_NO[key]):
|
||||||
|
node = key+str(k+1)
|
||||||
|
path = i2c_prefix+ str(sfp_map[k])+ buses[i]+"/"+ nodes[j]
|
||||||
|
my_log(node+": "+ path)
|
||||||
|
ALL_DEVICE[key][node].append(path)
|
||||||
|
else:
|
||||||
|
node = key+str(i+1)
|
||||||
|
path = i2c_prefix+ buses[i]+"/"+ nodes[j]
|
||||||
|
my_log(node+": "+ path)
|
||||||
|
ALL_DEVICE[key][node].append(path)
|
||||||
|
|
||||||
|
for key in hwmon_types:
|
||||||
|
itypes = hwmon_types[key]
|
||||||
|
nodes = hwmon_nodes[key]
|
||||||
|
for i in range(0,len(itypes)):
|
||||||
|
for j in range(0,len(nodes)):
|
||||||
|
node = key+"_"+itypes[i]
|
||||||
|
path = hwmon_prefix[key]+ itypes[i]+"/"+ nodes[j]
|
||||||
|
my_log(node+": "+ path)
|
||||||
|
ALL_DEVICE[key][ key+str(i+1)].append(path)
|
||||||
|
|
||||||
|
#show dict all in the order
|
||||||
|
if DEBUG == True:
|
||||||
|
for i in sorted(ALL_DEVICE.keys()):
|
||||||
|
print(i+": ")
|
||||||
|
for j in sorted(ALL_DEVICE[i].keys()):
|
||||||
|
print(" "+j)
|
||||||
|
for k in (ALL_DEVICE[i][j]):
|
||||||
|
print(" "+" "+k)
|
||||||
|
return
|
||||||
|
|
||||||
|
def show_eeprom(index):
|
||||||
|
if system_ready()==False:
|
||||||
|
print("System's not ready.")
|
||||||
|
print("Please install first!")
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(ALL_DEVICE)==0:
|
||||||
|
devices_info()
|
||||||
|
node = ALL_DEVICE['sfp'] ['sfp'+str(index)][0]
|
||||||
|
node = node.replace(node.split("/")[-1], 'sfp_eeprom')
|
||||||
|
# check if got hexdump command in current environment
|
||||||
|
ret, log = log_os_system("which hexdump", 0)
|
||||||
|
ret, log2 = log_os_system("which busybox hexdump", 0)
|
||||||
|
if len(log):
|
||||||
|
hex_cmd = 'hexdump'
|
||||||
|
elif len(log2):
|
||||||
|
hex_cmd = ' busybox hexdump'
|
||||||
|
else:
|
||||||
|
log = 'Failed : no hexdump cmd!!'
|
||||||
|
logging.info(log)
|
||||||
|
print log
|
||||||
|
return 1
|
||||||
|
|
||||||
|
print node + ":"
|
||||||
|
ret, log = log_os_system("cat "+node+"| "+hex_cmd+" -C", 1)
|
||||||
|
if ret==0:
|
||||||
|
print log
|
||||||
|
else:
|
||||||
|
print "**********device no found**********"
|
||||||
|
return
|
||||||
|
|
||||||
|
def set_device(args):
|
||||||
|
global DEVICE_NO
|
||||||
|
global ALL_DEVICE
|
||||||
|
if system_ready()==False:
|
||||||
|
print("System's not ready.")
|
||||||
|
print("Please install first!")
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(ALL_DEVICE)==0:
|
||||||
|
devices_info()
|
||||||
|
|
||||||
|
if args[0]=='led':
|
||||||
|
if int(args[1])>4:
|
||||||
|
show_set_help()
|
||||||
|
return
|
||||||
|
#print ALL_DEVICE['led']
|
||||||
|
for i in range(0,len(ALL_DEVICE['led'])):
|
||||||
|
for k in (ALL_DEVICE['led']['led'+str(i+1)]):
|
||||||
|
ret, log = log_os_system("echo "+args[1]+" >"+k, 1)
|
||||||
|
if ret:
|
||||||
|
return ret
|
||||||
|
elif args[0]=='fan':
|
||||||
|
if int(args[1])>100:
|
||||||
|
show_set_help()
|
||||||
|
return
|
||||||
|
#print ALL_DEVICE['fan']
|
||||||
|
#fan1~5 is all fine, all fan share same setting
|
||||||
|
node = ALL_DEVICE['fan'] ['fan1'][0]
|
||||||
|
node = node.replace(node.split("/")[-1], 'fan_duty_cycle_percentage')
|
||||||
|
ret, log = log_os_system("cat "+ node, 1)
|
||||||
|
if ret==0:
|
||||||
|
print ("Previous fan duty: " + log.strip() +"%")
|
||||||
|
ret, log = log_os_system("echo "+args[1]+" >"+node, 1)
|
||||||
|
if ret==0:
|
||||||
|
print ("Current fan duty: " + args[1] +"%")
|
||||||
|
return ret
|
||||||
|
elif args[0]=='sfp':
|
||||||
|
if int(args[1])> DEVICE_NO[args[0]] or int(args[1])==0:
|
||||||
|
show_set_help()
|
||||||
|
return
|
||||||
|
if len(args)<2:
|
||||||
|
show_set_help()
|
||||||
|
return
|
||||||
|
|
||||||
|
if int(args[2])>1:
|
||||||
|
show_set_help()
|
||||||
|
return
|
||||||
|
|
||||||
|
#print ALL_DEVICE[args[0]]
|
||||||
|
for i in range(0,len(ALL_DEVICE[args[0]])):
|
||||||
|
for j in ALL_DEVICE[args[0]][args[0]+str(args[1])]:
|
||||||
|
if j.find('tx_disable')!= -1:
|
||||||
|
ret, log = log_os_system("echo "+args[2]+" >"+ j, 1)
|
||||||
|
if ret:
|
||||||
|
return ret
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
#get digits inside a string.
|
||||||
|
#Ex: 31 for "sfp31"
|
||||||
|
def get_value(input):
|
||||||
|
digit = re.findall('\d+', input)
|
||||||
|
return int(digit[0])
|
||||||
|
|
||||||
|
def device_traversal():
|
||||||
|
if system_ready()==False:
|
||||||
|
print("System's not ready.")
|
||||||
|
print("Please install first!")
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(ALL_DEVICE)==0:
|
||||||
|
devices_info()
|
||||||
|
for i in sorted(ALL_DEVICE.keys()):
|
||||||
|
print("============================================")
|
||||||
|
print(i.upper()+": ")
|
||||||
|
print("============================================")
|
||||||
|
|
||||||
|
for j in sorted(ALL_DEVICE[i].keys(), key=get_value):
|
||||||
|
print " "+j+":",
|
||||||
|
for k in (ALL_DEVICE[i][j]):
|
||||||
|
ret, log = log_os_system("cat "+k, 0)
|
||||||
|
func = k.split("/")[-1].strip()
|
||||||
|
func = re.sub(j+'_','',func,1)
|
||||||
|
func = re.sub(i.lower()+'_','',func,1)
|
||||||
|
if ret==0:
|
||||||
|
print func+"="+log+" ",
|
||||||
|
else:
|
||||||
|
print func+"="+"X"+" ",
|
||||||
|
print
|
||||||
|
print("----------------------------------------------------------------")
|
||||||
|
|
||||||
|
|
||||||
|
print
|
||||||
|
return
|
||||||
|
|
||||||
|
def device_exist():
|
||||||
|
ret1, log = log_os_system("ls "+i2c_prefix+"*0077", 0)
|
||||||
|
ret2, log = log_os_system("ls "+i2c_prefix+"i2c-2", 0)
|
||||||
|
return not(ret1 or ret2)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@ -52,6 +52,7 @@ struct ym2651y_data {
|
|||||||
struct mutex update_lock;
|
struct mutex update_lock;
|
||||||
char valid; /* !=0 if registers are valid */
|
char valid; /* !=0 if registers are valid */
|
||||||
unsigned long last_updated; /* In jiffies */
|
unsigned long last_updated; /* In jiffies */
|
||||||
|
u8 chip; /* chip id */
|
||||||
u8 capability; /* Register value */
|
u8 capability; /* Register value */
|
||||||
u16 status_word; /* Register value */
|
u16 status_word; /* Register value */
|
||||||
u8 fan_fault; /* Register value */
|
u8 fan_fault; /* Register value */
|
||||||
@ -59,6 +60,7 @@ struct ym2651y_data {
|
|||||||
u16 v_out; /* Register value */
|
u16 v_out; /* Register value */
|
||||||
u16 i_out; /* Register value */
|
u16 i_out; /* Register value */
|
||||||
u16 p_out; /* Register value */
|
u16 p_out; /* Register value */
|
||||||
|
u8 vout_mode; /* Register value */
|
||||||
u16 temp; /* Register value */
|
u16 temp; /* Register value */
|
||||||
u16 fan_speed; /* Register value */
|
u16 fan_speed; /* Register value */
|
||||||
u16 fan_duty_cycle[2]; /* Register value */
|
u16 fan_duty_cycle[2]; /* Register value */
|
||||||
@ -77,6 +79,8 @@ struct ym2651y_data {
|
|||||||
u16 mfr_vout_max; /* Register value */
|
u16 mfr_vout_max; /* Register value */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static ssize_t show_vout(struct device *dev, struct device_attribute *da,
|
||||||
|
char *buf);
|
||||||
static ssize_t show_byte(struct device *dev, struct device_attribute *da,
|
static ssize_t show_byte(struct device *dev, struct device_attribute *da,
|
||||||
char *buf);
|
char *buf);
|
||||||
static ssize_t show_word(struct device *dev, struct device_attribute *da,
|
static ssize_t show_word(struct device *dev, struct device_attribute *da,
|
||||||
@ -129,7 +133,7 @@ static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TE
|
|||||||
static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD);
|
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_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_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP);
|
||||||
static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_linear, NULL, PSU_V_OUT);
|
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_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_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_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT);
|
||||||
@ -150,7 +154,7 @@ static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR
|
|||||||
static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX);
|
static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX);
|
||||||
|
|
||||||
/*Duplicate nodes for lm-sensors.*/
|
/*Duplicate nodes for lm-sensors.*/
|
||||||
static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_linear, NULL, PSU_V_OUT);
|
static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_vout, NULL, PSU_V_OUT);
|
||||||
static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_linear, NULL, PSU_I_OUT);
|
static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_linear, NULL, PSU_I_OUT);
|
||||||
static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV);
|
static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV);
|
||||||
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT);
|
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT);
|
||||||
@ -369,6 +373,51 @@ static ssize_t show_ascii(struct device *dev, struct device_attribute *da,
|
|||||||
return sprintf(buf, "%s\n", ptr);
|
return sprintf(buf, "%s\n", ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t show_vout_by_mode(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);
|
||||||
|
int exponent, mantissa;
|
||||||
|
int multiplier = 1000;
|
||||||
|
|
||||||
|
if (!data->valid) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
exponent = two_complement_to_int(data->vout_mode, 5, 0x1f);
|
||||||
|
switch (attr->index) {
|
||||||
|
case PSU_MFR_VOUT_MIN:
|
||||||
|
mantissa = data->mfr_vout_min;
|
||||||
|
break;
|
||||||
|
case PSU_MFR_VOUT_MAX:
|
||||||
|
mantissa = data->mfr_vout_max;
|
||||||
|
break;
|
||||||
|
case PSU_V_OUT:
|
||||||
|
mantissa = data->v_out;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return show_linear(dev, da, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const struct attribute_group ym2651y_group = {
|
static const struct attribute_group ym2651y_group = {
|
||||||
.attrs = ym2651y_attributes,
|
.attrs = ym2651y_attributes,
|
||||||
};
|
};
|
||||||
@ -395,7 +444,7 @@ static int ym2651y_probe(struct i2c_client *client,
|
|||||||
|
|
||||||
i2c_set_clientdata(client, data);
|
i2c_set_clientdata(client, data);
|
||||||
mutex_init(&data->update_lock);
|
mutex_init(&data->update_lock);
|
||||||
|
data->chip = dev_id->driver_data;
|
||||||
dev_info(&client->dev, "chip found\n");
|
dev_info(&client->dev, "chip found\n");
|
||||||
|
|
||||||
/* Register sysfs hooks */
|
/* Register sysfs hooks */
|
||||||
@ -511,6 +560,7 @@ static struct ym2651y_data *ym2651y_update_device(struct device *dev)
|
|||||||
u8 command;
|
u8 command;
|
||||||
u8 fan_dir[5] = {0};
|
u8 fan_dir[5] = {0};
|
||||||
struct reg_data_byte regs_byte[] = { {0x19, &data->capability},
|
struct reg_data_byte regs_byte[] = { {0x19, &data->capability},
|
||||||
|
{0x20, &data->vout_mode},
|
||||||
{0x7d, &data->over_temp},
|
{0x7d, &data->over_temp},
|
||||||
{0x81, &data->fan_fault},
|
{0x81, &data->fan_fault},
|
||||||
{0x98, &data->pmbus_revision}
|
{0x98, &data->pmbus_revision}
|
||||||
|
@ -52,3 +52,7 @@ Description: kernel modules for platform devices such as fan, led, sfp
|
|||||||
Package: sonic-platform-accton-as5812-54x
|
Package: sonic-platform-accton-as5812-54x
|
||||||
Architecture: amd64
|
Architecture: amd64
|
||||||
Description: kernel modules for platform devices such as fan, led, sfp
|
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
|
||||||
|
@ -19,7 +19,7 @@ PACKAGE_PRE_NAME := sonic-platform-accton
|
|||||||
KVERSION ?= $(shell uname -r)
|
KVERSION ?= $(shell uname -r)
|
||||||
KERNEL_SRC := /lib/modules/$(KVERSION)
|
KERNEL_SRC := /lib/modules/$(KVERSION)
|
||||||
MOD_SRC_DIR:= $(shell pwd)
|
MOD_SRC_DIR:= $(shell pwd)
|
||||||
MODULE_DIRS:= as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x as7326-56x as6712-32x as7726-32x as4630-54pe minipack as5812-54x
|
MODULE_DIRS:= as7712-32x as5712-54x as7816-64x as7716-32x as7716-32xb as7312-54x as7326-56x as6712-32x as7726-32x as4630-54pe minipack as5812-54x as5835-54x
|
||||||
MODULE_DIR := modules
|
MODULE_DIR := modules
|
||||||
UTILS_DIR := utils
|
UTILS_DIR := utils
|
||||||
SERVICE_DIR := service
|
SERVICE_DIR := service
|
||||||
|
Loading…
Reference in New Issue
Block a user