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