[platform]: Adding platform support for Juniper QFX5200 (#4376)

This is a 1RU switch with 32 QSFP28 (40G/100G) ports on
Broadcom Tomahawk I chipset. CPU used in QFX5200-32C-S
is Intel Ivy Bridge. The machine has Redundant and
hot-swappable Power Supply (1+1) and also has Redundant
and hot swappable fans (5).

Signed-off-by: Ciju Rajan K <crajank@juniper.net>
Signed-off-by: Ashish Bhensdadia <bashish@juniper.net>
This commit is contained in:
ciju-juniper 2020-04-16 15:39:32 +05:30 committed by GitHub
parent 2ed716478b
commit 695652c9d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 8045 additions and 2 deletions

View File

@ -0,0 +1,33 @@
# name lanes alias index speed
Ethernet0 49,50,51,52 hundredGigE1/1 0 100000
Ethernet4 53,54,55,56 hundredGigE1/2 1 100000
Ethernet8 57,58,59,60 hundredGigE1/3 2 100000
Ethernet12 61,62,63,64 hundredGigE1/4 3 100000
Ethernet16 65,66,67,68 hundredGigE1/5 4 100000
Ethernet20 69,70,71,72 hundredGigE1/6 5 100000
Ethernet24 73,74,75,76 hundredGigE1/7 6 100000
Ethernet28 77,78,79,80 hundredGigE1/8 7 100000
Ethernet32 81,82,83,84 hundredGigE1/9 8 100000
Ethernet36 85,86,87,88 hundredGigE1/10 9 100000
Ethernet40 37,38,39,40 hundredGigE1/11 10 100000
Ethernet44 33,34,35,36 hundredGigE1/12 11 100000
Ethernet48 41,42,43,44 hundredGigE1/13 12 100000
Ethernet52 45,46,47,48 hundredGigE1/14 13 100000
Ethernet56 89,90,91,92 hundredGigE1/15 14 100000
Ethernet60 93,94,95,96 hundredGigE1/16 15 100000
Ethernet64 97,98,99,100 hundredGigE1/17 16 100000
Ethernet68 101,102,103,104 hundredGigE1/18 17 100000
Ethernet72 17,18,19,20 hundredGigE1/19 18 100000
Ethernet76 21,22,23,24 hundredGigE1/20 19 100000
Ethernet80 29,30,31,32 hundredGigE1/21 20 100000
Ethernet84 25,26,27,28 hundredGigE1/22 21 100000
Ethernet88 105,106,107,108 hundredGigE1/23 22 100000
Ethernet92 109,110,111,112 hundredGigE1/24 23 100000
Ethernet96 113,114,115,116 hundredGigE1/25 24 100000
Ethernet100 117,118,119,120 hundredGigE1/26 25 100000
Ethernet104 121,122,123,124 hundredGigE1/27 26 100000
Ethernet108 125,126,127,128 hundredGigE1/28 27 100000
Ethernet112 1,2,3,4 hundredGigE1/29 28 100000
Ethernet116 5,6,7,8 hundredGigE1/30 29 100000
Ethernet120 9,10,11,12 hundredGigE1/31 30 100000
Ethernet124 13,14,15,16 hundredGigE1/32 31 100000

View File

@ -0,0 +1 @@
SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th-qfx5200-32x100g.config.bcm

View File

@ -0,0 +1,586 @@
phy_xaui_tx_polarity_flip_99=0x01
portmap_120=115:25:50:i
portmap_112=107:25:50:i
portmap_104=99:25:50:i
portmap_8=8:25:i
xgxs_rx_lane_map_20=0x3120
xgxs_rx_lane_map_12=0x2301
l2mod_dma_intr_enable=1
xgxs_tx_lane_map_40=0x0123
xgxs_tx_lane_map_32=0x0213
xgxs_tx_lane_map_24=0x2310
xgxs_tx_lane_map_16=0x1023
port_phy_addr_99=0xff
rate_ext_mdio_divisor=0x80
portmap_121=116:25:i
portmap_113=108:25:i
portmap_105=100:25:i
portmap_9=9:100
xgxs_rx_lane_map_21=0x3120
xgxs_rx_lane_map_13=0x0213
tslam_timeout_usec=10000000
xgxs_tx_lane_map_41=0x0123
xgxs_tx_lane_map_25=0x0213
xgxs_tx_lane_map_17=0x0213
portmap_130=125:100
portmap_122=117:100
portmap_114=109:100
xgxs_rx_lane_map_30=0x2301
portmap_106=101:100
xgxs_rx_lane_map_22=0x3120
xgxs_rx_lane_map_14=0x0213
xgxs_tx_lane_map_50=0x0213
xgxs_tx_lane_map_42=0x2310
xgxs_tx_lane_map_34=0x0123
phy_xaui_rx_polarity_flip_20=0x01
xgxs_tx_lane_map_26=0x0213
xgxs_tx_lane_map_18=0x0213
portmap_10=10:25:i
xgxs_tx_lane_map_1=0x3120
portmap_131=126:25:i
portmap_123=118:25:i
portmap_115=110:25:i
xgxs_rx_lane_map_31=0x2301
portmap_107=102:25:i
xgxs_rx_lane_map_23=0x3120
xgxs_rx_lane_map_15=0x0213
xgxs_tx_lane_map_51=0x0213
xgxs_tx_lane_map_43=0x2310
xgxs_tx_lane_map_35=0x0123
phy_xaui_rx_polarity_flip_21=0x03
xgxs_tx_lane_map_27=0x0213
phy_xaui_rx_polarity_flip_13=0x0c
xgxs_tx_lane_map_19=0x0213
portmap_11=11:25:50:i
xgxs_tx_lane_map_2=0x3120
xgxs_tx_lane_map_110=0x1203
xgxs_tx_lane_map_102=0x1203
parity_correction=1
portmap_132=127:25:50:i
portmap_124=119:25:50:i
portmap_116=111:25:50:i
xgxs_rx_lane_map_40=0x2310
xgxs_rx_lane_map_32=0x2301
portmap_108=103:25:50:i
xgxs_rx_lane_map_24=0x3120
xgxs_rx_lane_map_16=0x0213
xgxs_tx_lane_map_60=0x0213
xgxs_tx_lane_map_52=0x0213
xgxs_tx_lane_map_44=0x2310
xgxs_tx_lane_map_36=0x0123
phy_xaui_rx_polarity_flip_22=0x01
xgxs_tx_lane_map_28=0x0213
portmap_20=20:25:i
portmap_12=12:25:i
xgxs_tx_lane_map_3=0x3120
xgxs_tx_lane_map_111=0x1203
xgxs_tx_lane_map_103=0x1203
portmap_133=128:25:i
portmap_125=120:25:i
portmap_117=112:25:i
xgxs_rx_lane_map_41=0x2310
portmap_109=104:25:i
xgxs_rx_lane_map_25=0x3210
xgxs_rx_lane_map_17=0x3120
xgxs_tx_lane_map_61=0x0213
xgxs_tx_lane_map_53=0x0213
xgxs_tx_lane_map_45=0x2310
xgxs_tx_lane_map_37=0x0123
xgxs_tx_lane_map_29=0x0213
phy_xaui_rx_polarity_flip_15=0x03
portmap_21=21:100
portmap_13=13:100
xgxs_rx_lane_map_110=0x2301
xgxs_rx_lane_map_102=0x2301
xgxs_tx_lane_map_4=0x3120
xgxs_tx_lane_map_120=0x1203
xgxs_tx_lane_map_112=0x1203
xgxs_tx_lane_map_104=0x1203
bcm_stat_interval=500000
l2xmsg_hostbuf_size=16384
portmap_126=121:100
xgxs_rx_lane_map_50=0x0231
portmap_118=113:100
xgxs_rx_lane_map_42=0x3201
xgxs_rx_lane_map_34=0x3102
xgxs_rx_lane_map_26=0x3210
xgxs_rx_lane_map_18=0x3120
xgxs_tx_lane_map_70=0x3120
xgxs_tx_lane_map_62=0x2310
xgxs_tx_lane_map_54=0x2310
phy_xaui_rx_polarity_flip_40=0x01
xgxs_tx_lane_map_46=0x2013
xgxs_tx_lane_map_38=0x0123
portmap_30=30:25:i
phy_xaui_rx_polarity_flip_16=0x01
portmap_22=22:25:i
portmap_14=14:25:i
xgxs_rx_lane_map_111=0x2301
xgxs_rx_lane_map_103=0x2301
xgxs_tx_lane_map_5=0x1023
xgxs_tx_lane_map_121=0x1203
xgxs_tx_lane_map_113=0x1203
xgxs_tx_lane_map_105=0x1203
port_phy_addr_10=0xff
mem_check_nocache_override=1
bcm_stat_flags=1
portmap_127=122:25:i
xgxs_rx_lane_map_51=0x0231
portmap_119=114:25:i
xgxs_rx_lane_map_43=0x3201
xgxs_rx_lane_map_35=0x3102
xgxs_rx_lane_map_27=0x3210
xgxs_rx_lane_map_19=0x3120
xgxs_tx_lane_map_71=0x3120
xgxs_tx_lane_map_63=0x2310
phy_xaui_tx_polarity_flip_11=0x02
xgxs_tx_lane_map_55=0x2310
xgxs_tx_lane_map_47=0x2013
xgxs_tx_lane_map_39=0x0123
phy_xaui_rx_polarity_flip_25=0x0c
portmap_31=31:25:50:i
phy_xaui_rx_polarity_flip_17=0x08
portmap_23=23:25:50:i
portmap_15=15:25:50:i
xgxs_rx_lane_map_120=0x3120
xgxs_rx_lane_map_112=0x2301
xgxs_rx_lane_map_104=0x2301
xgxs_tx_lane_map_6=0x1023
xgxs_tx_lane_map_130=0x3201
xgxs_tx_lane_map_122=0x1023
xgxs_tx_lane_map_114=0x0132
xgxs_tx_lane_map_106=0x0132
port_phy_addr_11=0xff
xgxs_rx_lane_map_60=0x0231
portmap_128=123:25:50:i
xgxs_rx_lane_map_52=0x0231
xgxs_rx_lane_map_44=0x3201
xgxs_rx_lane_map_36=0x3102
xgxs_rx_lane_map_28=0x3210
xgxs_tx_lane_map_80=0x3102
xgxs_tx_lane_map_72=0x2310
xgxs_tx_lane_map_64=0x2310
phy_xaui_tx_polarity_flip_12=0x01
xgxs_tx_lane_map_56=0x2310
phy_xaui_rx_polarity_flip_42=0x04
xgxs_tx_lane_map_48=0x2013
phy_xaui_rx_polarity_flip_34=0x08
portmap_40=39:25:50:i
xgxs_rx_lane_map_1=0x3201
portmap_32=32:25:i
portmap_24=24:25:i
portmap_16=16:25:i
xgxs_rx_lane_map_121=0x3120
xgxs_rx_lane_map_113=0x2301
xgxs_rx_lane_map_105=0x2301
xgxs_tx_lane_map_7=0x1023
xgxs_tx_lane_map_131=0x3201
xgxs_tx_lane_map_123=0x1023
xgxs_tx_lane_map_115=0x0132
xgxs_tx_lane_map_107=0x0132
port_phy_addr_20=0xff
port_phy_addr_12=0xff
xgxs_rx_lane_map_61=0x0231
portmap_129=124:25:i
xgxs_rx_lane_map_53=0x0231
xgxs_rx_lane_map_45=0x3201
xgxs_rx_lane_map_37=0x3102
xgxs_rx_lane_map_29=0x2301
xgxs_tx_lane_map_81=0x3102
xgxs_tx_lane_map_73=0x2310
phy_xaui_tx_polarity_flip_21=0x04
xgxs_tx_lane_map_65=0x2310
xgxs_tx_lane_map_57=0x2310
xgxs_tx_lane_map_49=0x2013
portmap_41=40:25:i
phy_xaui_rx_polarity_flip_27=0x03
xgxs_rx_lane_map_2=0x3201
phy_xaui_rx_polarity_flip_19=0x02
portmap_25=25:100
portmap_17=17:100
xgxs_rx_lane_map_130=0x3210
xgxs_rx_lane_map_122=0x1023
xgxs_rx_lane_map_114=0x2301
xgxs_rx_lane_map_106=0x2301
xgxs_tx_lane_map_8=0x1023
xgxs_tx_lane_map_132=0x3201
xgxs_tx_lane_map_124=0x1023
xgxs_tx_lane_map_116=0x0132
xgxs_tx_lane_map_108=0x0132
phy_xaui_rx_polarity_flip_114=0x07
xgxs_rx_lane_map_70=0x0213
xgxs_rx_lane_map_62=0x2310
xgxs_rx_lane_map_54=0x2301
xgxs_rx_lane_map_46=0x3012
xgxs_rx_lane_map_38=0x2310
xgxs_tx_lane_map_90=0x0123
xgxs_tx_lane_map_82=0x3102
xgxs_tx_lane_map_74=0x2310
xgxs_tx_lane_map_58=0x0213
phy_xaui_rx_polarity_flip_44=0x01
portmap_50=49:100
phy_xaui_rx_polarity_flip_36=0x02
portmap_42=41:100
phy_xaui_rx_polarity_flip_28=0x01
xgxs_rx_lane_map_3=0x3201
portmap_34=33:100
portmap_26=26:25:i
portmap_18=18:25:i
xgxs_rx_lane_map_131=0x3210
xgxs_rx_lane_map_123=0x1023
xgxs_rx_lane_map_115=0x2301
xgxs_rx_lane_map_107=0x2301
xgxs_tx_lane_map_9=0x3120
xgxs_tx_lane_map_133=0x3201
xgxs_tx_lane_map_125=0x1023
bcm_linkscan_interval=4000000
xgxs_tx_lane_map_117=0x0132
xgxs_tx_lane_map_109=0x0132
phy_xaui_rx_polarity_flip_115=0x01
port_phy_addr_30=0xff
port_phy_addr_22=0xff
port_phy_addr_14=0xff
xgxs_rx_lane_map_71=0x0213
xgxs_rx_lane_map_63=0x2310
xgxs_rx_lane_map_55=0x2301
xgxs_rx_lane_map_47=0x3012
xgxs_rx_lane_map_39=0x2310
xgxs_tx_lane_map_91=0x0123
xgxs_tx_lane_map_83=0x3102
phy_xaui_tx_polarity_flip_31=0x02
xgxs_tx_lane_map_75=0x2310
phy_xaui_tx_polarity_flip_23=0x01
xgxs_tx_lane_map_59=0x0213
portmap_51=50:25:i
phy_xaui_rx_polarity_flip_37=0x01
portmap_43=42:25:i
xgxs_rx_lane_map_4=0x3201
portmap_35=34:25:i
portmap_27=27:25:50:i
portmap_19=19:25:50:i
xgxs_rx_lane_map_132=0x3210
xgxs_rx_lane_map_124=0x1023
xgxs_rx_lane_map_116=0x2301
cdma_timeout_usec=4000000
xgxs_rx_lane_map_108=0x2301
xgxs_tx_lane_map_126=0x3120
xgxs_tx_lane_map_118=0x1203
phy_xaui_rx_polarity_flip_116=0x01
port_phy_addr_31=0xff
port_phy_addr_23=0xff
port_phy_addr_15=0xff
xgxs_rx_lane_map_80=0x3210
xgxs_rx_lane_map_72=0x2310
xgxs_rx_lane_map_64=0x2310
xgxs_rx_lane_map_56=0x2301
xgxs_rx_lane_map_48=0x3012
xgxs_tx_lane_map_92=0x0213
phy_xaui_tx_polarity_flip_40=0x01
xgxs_tx_lane_map_84=0x0213
phy_xaui_tx_polarity_flip_32=0x01
xgxs_tx_lane_map_76=0x0213
xgxs_tx_lane_map_68=0x3120
portmap_60=59:25:50:i
phy_xaui_rx_polarity_flip_46=0x08
portmap_52=51:25:50:i
phy_xaui_rx_polarity_flip_38=0x04
portmap_44=43:25:50:i
xgxs_rx_lane_map_5=0x1023
portmap_36=35:25:50:i
portmap_28=28:25:i
mdio_output_delay=12
xgxs_rx_lane_map_133=0x3210
xgxs_rx_lane_map_125=0x1023
xgxs_rx_lane_map_117=0x2301
xgxs_rx_lane_map_109=0x2301
xgxs_tx_lane_map_127=0x3120
xgxs_tx_lane_map_119=0x1203
port_phy_addr_40=0xff
port_phy_addr_32=0xff
port_phy_addr_24=0xff
port_phy_addr_16=0xff
xgxs_rx_lane_map_81=0x3210
xgxs_rx_lane_map_73=0x2310
tdma_timeout_usec=10000000
xgxs_rx_lane_map_65=0x2310
xgxs_rx_lane_map_57=0x2301
xgxs_rx_lane_map_49=0x3012
xgxs_tx_lane_map_93=0x0213
xgxs_tx_lane_map_85=0x0213
xgxs_tx_lane_map_77=0x0213
phy_xaui_tx_polarity_flip_25=0x0d
xgxs_tx_lane_map_69=0x3120
portmap_61=60:25:i
portmap_53=52:25:i
portmap_45=44:25:i
xgxs_rx_lane_map_6=0x1023
portmap_37=36:25:i
portmap_29=29:100
xgxs_rx_lane_map_126=0x2301
xgxs_rx_lane_map_118=0x3120
xgxs_tx_lane_map_128=0x3120
port_phy_addr_41=0xff
ipv6_lpm_128b_enable=1
xgxs_rx_lane_map_90=0x3210
xgxs_rx_lane_map_82=0x3210
xgxs_rx_lane_map_74=0x2310
xgxs_rx_lane_map_58=0x0231
fpem_mem_entries=0
xgxs_tx_lane_map_94=0x0213
phy_xaui_tx_polarity_flip_42=0x04
xgxs_tx_lane_map_86=0x0213
phy_xaui_tx_polarity_flip_34=0x08
xgxs_tx_lane_map_78=0x0213
portmap_70=67:25:50:i
portmap_62=61:100
phy_xaui_rx_polarity_flip_48=0x02
pbmp_xport_xe=0xfffffffffffffffffffffffffffffffffe
portmap_54=53:100
portmap_46=45:100
xgxs_rx_lane_map_7=0x1023
portmap_38=37:100
xgxs_rx_lane_map_127=0x2301
xgxs_rx_lane_map_119=0x3120
xgxs_tx_lane_map_129=0x3120
l2_mem_entries=106496
os=unix
port_phy_addr_26=0xff
port_phy_addr_18=0xff
xgxs_rx_lane_map_91=0x3210
xgxs_rx_lane_map_83=0x3210
xgxs_rx_lane_map_75=0x2310
xgxs_rx_lane_map_59=0x0231
xgxs_tx_lane_map_95=0x0213
port_phy_addr_111=0xff
xgxs_tx_lane_map_87=0x0213
port_phy_addr_103=0xff
xgxs_tx_lane_map_79=0x0213
phy_xaui_tx_polarity_flip_27=0x03
portmap_71=68:25:i
portmap_63=62:25:i
phy_xaui_rx_polarity_flip_49=0x01
portmap_55=54:25:i
portmap_47=46:25:i
xgxs_rx_lane_map_8=0x1023
portmap_39=38:25:i
xgxs_rx_lane_map_128=0x2301
port_phy_addr_51=0xff
port_phy_addr_43=0xff
port_phy_addr_35=0xff
port_phy_addr_27=0xff
port_phy_addr_19=0xff
xgxs_rx_lane_map_92=0x2310
xgxs_rx_lane_map_84=0x3210
xgxs_rx_lane_map_76=0x0231
xgxs_rx_lane_map_68=0x0213
port_phy_addr_120=0xff
xgxs_tx_lane_map_96=0x0123
phy_xaui_tx_polarity_flip_44=0x01
port_phy_addr_112=0xff
xgxs_tx_lane_map_88=0x0123
phy_xaui_tx_polarity_flip_36=0x02
port_phy_addr_104=0xff
portmap_80=77:100
phy_xaui_tx_polarity_flip_28=0x01
portmap_72=69:100
portmap_64=63:25:50:i
portmap_56=55:25:50:i
portmap_48=47:25:50:i
xgxs_rx_lane_map_9=0x2301
phy_xaui_rx_polarity_flip_5=4
xgxs_rx_lane_map_129=0x2301
port_phy_addr_60=0xff
port_phy_addr_52=0xff
port_phy_addr_44=0xff
port_phy_addr_36=0xff
port_phy_addr_28=0xff
xgxs_rx_lane_map_93=0x2310
xgxs_rx_lane_map_85=0x3210
table_dma_enable=1
xgxs_rx_lane_map_77=0x0231
xgxs_rx_lane_map_69=0x0213
port_phy_addr_121=0xff
xgxs_tx_lane_map_97=0x0123
port_phy_addr_113=0xff
xgxs_tx_lane_map_89=0x0123
phy_xaui_tx_polarity_flip_37=0x01
port_phy_addr_105=0xff
portmap_81=78:25:i
phy_xaui_tx_polarity_flip_29=0x08
portmap_73=70:25:i
portmap_65=64:25:i
portmap_57=56:25:i
portmap_49=48:25:i
port_phy_addr_61=0xff
port_phy_addr_53=0xff
port_phy_addr_45=0xff
port_phy_addr_37=0xff
xgxs_rx_lane_map_94=0x2310
port_phy_addr_2=0xff
xgxs_rx_lane_map_86=0x3210
xgxs_rx_lane_map_78=0x0231
phy_xaui_rx_polarity_flip_92=0x0c
xgxs_tx_lane_map_98=0x0123
phy_xaui_tx_polarity_flip_46=0x01
portmap_90=87:25:50:i
phy_xaui_tx_polarity_flip_38=0x05
portmap_82=79:25:50:i
portmap_74=71:25:50:i
portmap_66=129:1
portmap_58=57:100
phy_xaui_rx_polarity_flip_7=1
port_phy_addr_70=0xff
xgxs_rx_lane_map_95=0x2310
port_phy_addr_3=0xff
xgxs_rx_lane_map_87=0x3210
xgxs_rx_lane_map_79=0x0231
port_phy_addr_131=0xff
port_phy_addr_123=0xff
xgxs_tx_lane_map_99=0x0123
phy_an_c37=3
port_phy_addr_115=0xff
portmap_91=88:25:i
port_phy_addr_107=0xff
portmap_83=80:25:i
portmap_75=72:25:i
portmap_59=58:25:i
serdes_firmware_mode=0x1
schan_intr_enable=0x00
port_phy_addr_71=0xff
port_phy_addr_63=0xff
port_phy_addr_55=0xff
port_phy_addr_47=0xff
port_phy_addr_39=0xff
l2delete_chunks=128
xgxs_rx_lane_map_96=0x2130
port_phy_addr_4=0xff
xgxs_rx_lane_map_88=0x3210
tslam_intr_enable=0
port_phy_addr_132=0xff
phy_xaui_rx_polarity_flip_94=0x03
port_phy_addr_124=0xff
port_phy_addr_116=0xff
portmap_92=89:100
port_phy_addr_108=0xff
portmap_84=81:100
portmap_76=73:100
portmap_68=65:100
port_phy_addr_64=0xff
mem_cache_enable=1
port_phy_addr_56=0xff
port_phy_addr_48=0xff
parity_enable=1
xgxs_rx_lane_map_97=0x2130
xgxs_rx_lane_map_89=0x3210
port_phy_addr_133=0xff
phy_xaui_rx_polarity_flip_95=0x01
port_phy_addr_125=0xff
port_phy_addr_117=0xff
portmap_93=90:25:i
port_phy_addr_109=0xff
portmap_85=82:25:i
portmap_77=74:25:i
portmap_69=66:25:i
port_phy_addr_81=0xff
port_phy_addr_73=0xff
port_phy_addr_65=0xff
port_phy_addr_57=0xff
port_phy_addr_49=0xff
xgxs_rx_lane_map_98=0x2130
port_phy_addr_6=0xff
phy_xaui_tx_polarity_flip_90=0x03
phy_xaui_rx_polarity_flip_96=0x0c
portmap_94=91:25:50:i
portmap_86=83:25:50:i
portmap_78=75:25:50:i
port_phy_addr_90=0xff
port_phy_addr_82=0xff
port_phy_addr_74=0xff
load_firmware=0x102
l2xmsg_mode=1
xgxs_rx_lane_map_99=0x2130
port_phy_addr_7=0xff
phy_xaui_tx_polarity_flip_91=0x01
phy_an_c73=0
port_phy_addr_127=0xff
port_phy_addr_119=0xff
portmap_95=92:25:i
portmap_87=84:25:i
portmap_79=76:25:i
port_phy_addr_91=0xff
port_phy_addr_83=0xff
port_phy_addr_75=0xff
port_phy_addr_59=0xff
mmu_lossless=0x01
port_phy_addr_8=0xff
phy_xaui_tx_polarity_flip_92=0x04
phy_xaui_tx_polarity_flip_84=0x04
phy_xaui_rx_polarity_flip_98=0x03
port_phy_addr_128=0xff
portmap_96=93:100
portmap_1=1:100
portmap_88=85:100
phy_xaui_tx_polarity_flip_9=0x08
phy_xaui_rx_polarity_flip_99=0x01
port_phy_addr_129=0xff
portmap_97=94:25:i
portmap_2=2:25:i
portmap_89=86:25:i
xgxs_tx_lane_map_10=0x3120
phy_an_c37_100=1
port_phy_addr_93=0xff
port_phy_addr_85=0xff
port_phy_addr_77=0xff
port_phy_addr_69=0xff
phy_xaui_tx_polarity_flip_94=0x01
phy_xaui_tx_polarity_flip_86=0x01
max_vp_lags=0
l3_max_ecmp_mode=1
portmap_98=95:25:50:i
portmap_3=3:25:50:i
miim_intr_enable=0x0
xgxs_tx_lane_map_11=0x3120
port_phy_addr_94=0xff
port_phy_addr_86=0xff
port_phy_addr_78=0xff
module_64ports=0
tdma_intr_enable=0
portmap_100=131:1
portmap_99=96:25:i
pbmp_oversubscribe=0xC4444451111111144444444422222222
portmap_4=4:25:i
l3_mem_entries=40960
xgxs_tx_lane_map_20=0x0213
xgxs_tx_lane_map_12=0x3120
num_ipv6_lpm_128b_entries=1024
port_phy_addr_95=0xff
port_phy_addr_87=0xff
port_phy_addr_79=0xff
ptp_ts_pll_fref=0
phy_xaui_tx_polarity_flip_96=0x08
phy_xaui_tx_polarity_flip_88=0x0c
portmap_5=5:100
xgxs_tx_lane_map_21=0x2310
xgxs_tx_lane_map_13=0x1023
tslam_dma_enable=1
dport_map_direct=0x01
portmap_110=105:100
portmap_102=97:100
portmap_6=6:25:i
xgxs_rx_lane_map_10=0x2301
xgxs_tx_lane_map_30=0x0213
xgxs_tx_lane_map_22=0x2310
xgxs_tx_lane_map_14=0x1023
phy_an_c73_100=0
port_phy_addr_97=0xff
port_phy_addr_89=0xff
phy_xaui_tx_polarity_flip_98=0x02
portmap_111=106:25:i
portmap_103=98:25:i
portmap_7=7:25:50:i
xgxs_rx_lane_map_11=0x2301
xgxs_tx_lane_map_31=0x0213
xgxs_tx_lane_map_23=0x2310
xgxs_tx_lane_map_15=0x1023
port_phy_addr_98=0xff

View File

@ -0,0 +1 @@
Juniper-QFX5200-32C-S t1

View File

@ -0,0 +1,4 @@
CONSOLE_PORT=0x3f8
CONSOLE_DEV=0
CONSOLE_SPEED=9600
VAR_LOG_SIZE=1024

View File

@ -0,0 +1,49 @@
# LED microprocessor initialization for Tomahawk
setreg CMIC_LEDUP0_CLK_DIV 0x54
setreg CMIC_LEDUP1_CLK_DIV 0x54
setreg CMIC_LEDUP2_CLK_DIV 0x54
led 0 stop
led 0 prog 02 fd 42 80 02 ff 42 00 02 fe 42 00 02 fb 42 40 67 14 3a 40 06 fe 88 88 88 4a 00 27 4a 01 27 b7 80 4a 00 27 c7 d7 87 80 4a 00 27 4a 01 27 b7 80 4a 00 27 c7 d7 87 80 4a 00 27 4a 01 27 b7 80 4a 00 27 c7 d7 87 80 4a 00 27 4a 01 27 b7 80 4a 00 27 c7 d7 87 86 fe 06 fe d2 10 74 14 57
setreg CMIC_LEDUP0_PORT_ORDER_REMAP_0_3 0x411493
setreg CMIC_LEDUP0_PORT_ORDER_REMAP_4_7 0x515597
setreg CMIC_LEDUP0_PORT_ORDER_REMAP_8_11 0x30d38f
setreg CMIC_LEDUP0_PORT_ORDER_REMAP_12_15 0x20928b
setreg CMIC_LEDUP0_PORT_ORDER_REMAP_16_19 0xf3dfbf
setreg CMIC_LEDUP0_PORT_ORDER_REMAP_20_23 0xe39ebb
setreg CMIC_LEDUP0_PORT_ORDER_REMAP_24_27 0xd35db7
setreg CMIC_LEDUP0_PORT_ORDER_REMAP_28_31 0xc31cb3
setreg CMIC_LEDUP0_PORT_ORDER_REMAP_32_35 0xb2dbaf
setreg CMIC_LEDUP0_PORT_ORDER_REMAP_36_39 0xa29aab
setreg CMIC_LEDUP0_PORT_ORDER_REMAP_40_43 0x9259a7
setreg CMIC_LEDUP0_PORT_ORDER_REMAP_44_47 0x8218a3
setreg CMIC_LEDUP0_PORT_ORDER_REMAP_48_51 0x71d79f
setreg CMIC_LEDUP0_PORT_ORDER_REMAP_52_55 0x61969b
setreg CMIC_LEDUP0_PORT_ORDER_REMAP_56_59 0x105187
setreg CMIC_LEDUP0_PORT_ORDER_REMAP_60_63 0x1083
led 0 auto on
led 0 start
led 1 stop
led 1 prog 02 fd 42 80 02 ff 42 00 02 fe 42 00 02 fb 42 40 67 14 3a 40 06 fe 88 88 88 4a 00 27 4a 01 27 b7 80 4a 00 27 c7 d7 87 80 4a 00 27 4a 01 27 b7 80 4a 00 27 c7 d7 87 80 4a 00 27 4a 01 27 b7 80 4a 00 27 c7 d7 87 80 4a 00 27 4a 01 27 b7 80 4a 00 27 c7 d7 87 86 fe 06 fe d2 10 74 14 57
setreg CMIC_LEDUP1_PORT_ORDER_REMAP_0_3 0xb2dbaf
setreg CMIC_LEDUP1_PORT_ORDER_REMAP_4_7 0xa29aab
setreg CMIC_LEDUP1_PORT_ORDER_REMAP_8_11 0xc31cb3
setreg CMIC_LEDUP1_PORT_ORDER_REMAP_12_15 0xd35db7
setreg CMIC_LEDUP1_PORT_ORDER_REMAP_16_19 0x1083
setreg CMIC_LEDUP1_PORT_ORDER_REMAP_20_23 0x105187
setreg CMIC_LEDUP1_PORT_ORDER_REMAP_24_27 0x20928b
setreg CMIC_LEDUP1_PORT_ORDER_REMAP_28_31 0x30d38f
setreg CMIC_LEDUP1_PORT_ORDER_REMAP_32_35 0x411493
setreg CMIC_LEDUP1_PORT_ORDER_REMAP_36_39 0x515597
setreg CMIC_LEDUP1_PORT_ORDER_REMAP_40_43 0x61969b
setreg CMIC_LEDUP1_PORT_ORDER_REMAP_44_47 0x71d79f
setreg CMIC_LEDUP1_PORT_ORDER_REMAP_48_51 0x8218a3
setreg CMIC_LEDUP1_PORT_ORDER_REMAP_52_55 0x9259a7
setreg CMIC_LEDUP1_PORT_ORDER_REMAP_56_59 0xe39ebb
setreg CMIC_LEDUP1_PORT_ORDER_REMAP_60_63 0xf3dfbf
led 1 auto on
led 1 start

View File

@ -0,0 +1,36 @@
{
"GLOBAL_MEDIA_SETTINGS": {
"0-31": {
"JUNIPER-AVAGO-AFBR-89CDDZ-JU1": {
"preemphasis": {
"lane0":"0x0c6400",
"lane1":"0x0c6400",
"lane2":"0x0c6400",
"lane3":"0x0c6400"
},
"idriver": {
"lane0":"0xa",
"lane1":"0xa",
"lane2":"0xa",
"lane3":"0xa"
}
},
"FINISAR CORP.-FTL4C1QE1C-J1": {
"preemphasis": {
"lane0":"0x115f00",
"lane1":"0x115f00",
"lane2":"0x115f00",
"lane3":"0x115f00"
},
"idriver": {
"lane0":"0x0",
"lane1":"0x0",
"lane2":"0x0",
"lane3":"0x0"
}
}
}
},
"PORT_MEDIA_SETTINGS": {
}
}

View File

@ -0,0 +1,63 @@
#!/usr/bin/env python
#
# Name: eeprom.py version: 1.0
#
# Description: Platform-specific EEPROM interface for Juniper QFX5200
#
# Copyright (c) 2020, Juniper Networks, Inc.
# All rights reserved.
#
# Notice and Disclaimer: This code is licensed to you under the GNU General
# Public License as published by the Free Software Foundation, version 3 or
# any later version. This code is not an official Juniper product. You can
# obtain a copy of the License at <https://www.gnu.org/licenses/>
#
# OSS License:
#
# 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 <https://www.gnu.org/licenses/>.
#
# Third-Party Code: This code may depend on other components under separate
# copyright notice and license terms. Your use of the source code for those
# components is subject to the terms and conditions of the respective license
# as noted in the Third-Party source code file.
try:
import os
from sonic_eeprom import eeprom_tlvinfo
import syslog
from array import *
except ImportError, e:
raise ImportError (str(e) + "- required module not found")
SYSLOG_IDENTIFIER = "eeprom.py"
EEPROM_PATH = "/sys/bus/i2c/devices/0-0051/eeprom"
def log_error(msg):
syslog.openlog(SYSLOG_IDENTIFIER)
syslog.syslog(syslog.LOG_ERR, msg)
syslog.closelog()
class board(eeprom_tlvinfo.TlvInfoDecoder):
_TLV_INFO_MAX_LEN = 256
def __init__(self, name, path, cpld_root, ro):
if not os.path.exists(EEPROM_PATH):
log_error("Cannot find system eeprom")
raise RuntimeError("No syseeprom found")
self.eeprom_path = EEPROM_PATH
super(board, self).__init__(self.eeprom_path, 0, '', True)

View File

@ -0,0 +1,189 @@
#!/usr/bin/env python
#
# Name: led_control.py version: 1.0
#
# Description: Platform-specific LED control functionality for Juniper QFX5200
#
# Copyright (c) 2020, Juniper Networks, Inc.
# All rights reserved.
#
# Notice and Disclaimer: This code is licensed to you under the GNU General
# Public License as published by the Free Software Foundation, version 3 or
# any later version. This code is not an official Juniper product. You can
# obtain a copy of the License at <https://www.gnu.org/licenses/>
#
# OSS License:
#
# 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 <https://www.gnu.org/licenses/>.
#
# Third-Party Code: This code may depend on other components under separate
# copyright notice and license terms. Your use of the source code for those
# components is subject to the terms and conditions of the respective license
# as noted in the Third-Party source code file.
try:
from sonic_led.led_control_base import LedControlBase
import os
import syslog
import glob
from socket import *
from select import *
except ImportError, e:
raise ImportError(str(e) + " - required module not found")
def DBG_PRINT(str):
syslog.openlog("ledi_control")
syslog.syslog(syslog.LOG_INFO, str)
syslog.closelog()
class LedControl(LedControlBase):
"""Platform specific LED control class"""
SONIC_PORT_NAME_PREFIX = "Ethernet"
LED_MODE_OFF = 0
LED_MODE_GREEN = 1
PORT_START = 0
PORT_END = 127
port_to_gpio_pin_mapping = {}
GPIO_SLAVE0_PORT_START = 0
GPIO_SLAVE0_PORT_END = 63
GPIO_SLAVE1_PORT_START = 64
GPIO_SLAVE1_PORT_END = 127
GPIO_LANE0_PORT_LED_OFFSET = 64
GPIO_LANE1_PORT_LED_OFFSET = 80
GPIO_LANE2_PORT_LED_OFFSET = 96
GPIO_LANE3_PORT_LED_OFFSET = 112
# Turn OFF all port leds during init
def gpio_create_file(self,gpio_pin):
gpio_export_path = "/sys/class/gpio/export"
gpio_pin_path = "/sys/class/gpio/gpio" + str(gpio_pin)
if not os.path.exists(gpio_pin_path):
try:
gpio_export_file = open(gpio_export_path, 'w')
gpio_export_file.write(str(gpio_pin))
gpio_export_file.close()
except IOError as e:
print "Error: unable to open export file: %s" % str(e)
return False
return True
def gpio_port_led_init(self,gpio_base, port):
port_led_pin = gpio_base + self.GPIO_LANE0_PORT_LED_OFFSET + 16*(port%4) + ((port % 64)/4)
if self.gpio_create_file(port_led_pin):
self.port_to_gpio_pin_mapping[port] = port_led_pin
def gpio_port_led_slave_init(self,gpio_base_path, gpio_port_start, gpio_port_end):
flist = glob.glob(gpio_base_path)
if len(flist) == 1:
try:
fp = open(flist[0] + "/base")
gpio_base = int(fp.readline().rstrip())
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return
for port in range(gpio_port_start, gpio_port_end + 1):
self.gpio_port_led_init(gpio_base, port)
def gpio_port_led_base_init(self):
self.gpio_port_led_slave_init("/sys/bus/platform/drivers/gpioslave-tmc/gpioslave-tmc.22/gpio/gpio*",
self.GPIO_SLAVE0_PORT_START, self.GPIO_SLAVE0_PORT_END)
self.gpio_port_led_slave_init("/sys/bus/platform/drivers/gpioslave-tmc/gpioslave-tmc.21/gpio/gpio*",
self.GPIO_SLAVE1_PORT_START, self.GPIO_SLAVE1_PORT_END)
# Write driver for port led
def gpio_led_write(self,gpio_pin, value):
success = False
gpio_pin_path = "/sys/class/gpio/gpio" + str(gpio_pin)
try:
gpio_file = open(gpio_pin_path +"/value", 'w')
gpio_file.write(str(value))
success = True
except IOError as e:
print "error: unable to open file: %s" % str(e)
return success
# Read driver for port led
def gpio_led_read(self,gpio_pin):
gpio_pin_path = "/sys/class/gpio/gpio" + str(gpio_pin)
value = 0
try:
reg_file = open(gpio_pin_path +"/value")
value = int(reg_file.readline().rstrip())
except IOError as e:
print "error: unable to open file: %s" % str(e)
return value
def _initDefaultConfig(self):
DBG_PRINT("start init led")
for port in range(self.PORT_START, self.PORT_END):
self._port_led_mode_update(self.port_to_gpio_pin_mapping[port], self.LED_MODE_OFF)
DBG_PRINT("init led done")
# Helper method to map SONiC port name to index
def _port_name_to_index(self, port_name):
# Strip "Ethernet" off port name
if not port_name.startswith(self.SONIC_PORT_NAME_PREFIX):
return -1
port_idx = int(port_name[len(self.SONIC_PORT_NAME_PREFIX):])
return port_idx
# Convert state up/down to Green/OFF which is 1/0
def _port_state_to_mode(self, state):
if state == "up":
return self.LED_MODE_GREEN
else:
return self.LED_MODE_OFF
# Set the port led mode to Green/OFF
def _port_led_mode_update(self, gpio_pin, ledMode):
if ledMode == self.LED_MODE_GREEN:
self.gpio_led_write(gpio_pin, 1)
else:
self.gpio_led_write(gpio_pin, 0)
# Concrete implementation of port_link_state_change() method
def port_link_state_change(self, portname, state):
port_idx = self._port_name_to_index(portname)
gpio_pin = self.port_to_gpio_pin_mapping[port_idx]
ledMode = self._port_state_to_mode(state)
saveMode = self.gpio_led_read(gpio_pin)
if ledMode == saveMode:
return
self._port_led_mode_update(gpio_pin, ledMode)
DBG_PRINT("update {} led mode from {} to {}".format(portname, saveMode, ledMode))
# Constructor
def __init__(self):
self.gpio_port_led_base_init()
self._initDefaultConfig()

View File

@ -0,0 +1,101 @@
#!/usr/bin/env python
#
# Name: psuutil.py version: 1.0
#
# Description: Platform-specific PSU status interface for Juniper QFX5200
#
# Copyright (c) 2020, Juniper Networks, Inc.
# All rights reserved.
#
# Notice and Disclaimer: This code is licensed to you under the GNU General
# Public License as published by the Free Software Foundation, version 3 or
# any later version. This code is not an official Juniper product. You can
# obtain a copy of the License at <https://www.gnu.org/licenses/>
#
# OSS License:
#
# 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 <https://www.gnu.org/licenses/>.
#
# Third-Party Code: This code may depend on other components under separate
# copyright notice and license terms. Your use of the source code for those
# components is subject to the terms and conditions of the respective license
# as noted in the Third-Party source code file.
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"""
PSU_DIR = "/sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/psu-tmc.15"
def __init__(self):
PsuBase.__init__(self)
# Get sysfs attribute
def get_attr_value(self, attr_path):
retval = 'ERR'
if (not os.path.isfile(attr_path)):
return retval
try:
with open(attr_path, 'r') as fd:
retval = fd.read()
except Exception as error:
logging.error("Unable to open ", attr_path, " file !")
retval = retval.rstrip(' \t\n\r')
return int(retval)
def get_num_psus(self):
"""
Retrieves the number of PSUs available on the device
:return: An integer, the number of PSUs available on the device
"""
MAX_PSUS = 2
return MAX_PSUS
def get_psu_status(self, index):
"""
Retrieves the oprational status of power supply unit (PSU) defined
by index <index>
:param index: An integer, index (starts from 1) of the PSU of which to query status
:return: Boolean, True if PSU is operating properly, False if PSU is\
faulty
"""
attr_file = 'psu'+ str(index-1) +'_' + 'present'
attr_path = self.PSU_DIR +'/' + attr_file
attr_value = self.get_attr_value(attr_path)
return attr_value == 1
def get_psu_presence(self, index):
"""
Retrieves the presence status of power supply unit (PSU) defined
by index <index>
:param index: An integer, index of the PSU of which to query status
:return: Boolean, True if PSU is plugged, False if not
"""
attr_file ='psu'+ str(index-1) +'_' + 'present'
attr_path = self.PSU_DIR +'/' + attr_file
attr_value = self.get_attr_value(attr_path)
return attr_value == 1

View File

@ -0,0 +1,415 @@
#!/usr/bin/env python
#
# Name: juniper_qfx5200_eepromconv.py version: 1.0
#
# Description: This file contains the code to store the contents of Main Board EEPROM and CPU Board EEPROM in file
#
# Copyright (c) 2020, Juniper Networks, Inc.
# All rights reserved.
#
# Notice and Disclaimer: This code is licensed to you under the GNU General
# Public License as published by the Free Software Foundation, version 3 or
# any later version. This code is not an official Juniper product. You can
# obtain a copy of the License at <https://www.gnu.org/licenses/>
#
# OSS License:
#
# 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 <https://www.gnu.org/licenses/>.
#
# Third-Party Code: This code may depend on other components under separate
# copyright notice and license terms. Your use of the source code for those
# components is subject to the terms and conditions of the respective license
# as noted in the Third-Party source code file.
import os
import commands
import binascii
from sonic_eeprom import eeprom_tlvinfo
def main():
eeprom_qfx5200 = Eeprom()
FAN0_TYPE="cat /sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/refpga-tmc.15/fan0_type"
try:
status,fan0_type=commands.getstatusoutput(FAN0_TYPE)
except Exception as e:
print "Error on refpga-tmc.15 fan0_type e:" + str(e)
return False
AFO = "1"
# creating the "/var/run/eeprom" file and storing values of CPU board EEPROM and MAIN Board EEPROM in this file.
eeprom_file = open ("/var/run/eeprom", "a+")
eeprom_file.write("\n")
if fan0_type == AFO:
eeprom_file.write("Fan Type=AFO\r\n")
else:
eeprom_file.write("Fan Type=AFI\r\n")
eeprom_file.write("\n")
# Write the contents of CPU Board EEPROM to file
eeprom_file.write("CPU board eeprom (0x51)\r\n")
eeprom_file.write("===============================\r\n")
eeprom_file.write("Product Name=%s\r\n" % eeprom_qfx5200.modelstr())
eeprom_file.write("Part Number=%s\r\n" % eeprom_qfx5200.part_number_str())
eeprom_file.write("Serial Number=%s\r\n" % eeprom_qfx5200.serial_number_str())
eeprom_file.write("MAC Address=%s\r\n" % eeprom_qfx5200.base_mac_address())
eeprom_file.write("Manufacture Date=%s\r\n" % eeprom_qfx5200.manuDate_str())
eeprom_file.write("Platform Name=%s\r\n" % eeprom_qfx5200.platform_str())
eeprom_file.write("Number of MAC Addresses=%s\r\n" % eeprom_qfx5200.MACsize_str())
eeprom_file.write("Vendor Name=%s\r\n" % eeprom_qfx5200.vendor_name_str())
eeprom_file.write("Manufacture Name=%s\r\n" % eeprom_qfx5200.manufacture_name_str())
eeprom_dict = eeprom_qfx5200.system_eeprom_info()
key = '0x29'
if key in eeprom_dict.keys():
onie_version_str = eeprom_dict.get('0x29', None)
else:
onie_version_str = "N/A"
eeprom_file.write("ONIE Version=%s\r\n" % onie_version_str)
vendor_value_formatted, vendor_value_hexvalue = eeprom_qfx5200.vendor_ext_str()
eeprom_hex = '/etc/init.d/eeprom_qfx5200_hex'
with open(eeprom_hex, 'wb+') as Hexfile:
Hexfile.write(vendor_value_hexvalue)
# Assembly ID
ASMID_str = "0D83"
with open(eeprom_hex, 'rb+') as AsmID_Hexfile:
AsmID_Hexfile.seek(24, 0)
AsmID_Hexfile.write(ASMID_str)
AsmID_Hexfile.seek(0, 0)
vendorext_read = AsmID_Hexfile.read(58)
vendorext=""
vendorext += "0x" + vendorext_read[0:2]
for i in range(2,58,2):
vendorext += " 0x" + vendorext_read[i:i+2]
eeprom_file.write("Vendor Extension=%s\r\n" % str(vendorext))
with open(eeprom_hex, 'rb') as eeprom_hexfile:
eeprom_hexfile.seek(0, 0)
IANA_position_read = eeprom_hexfile.read(8)
IANA_write = binascii.unhexlify(IANA_position_read)
eeprom_file.write("\t")
eeprom_file.write("IANA=0x%s\r\n" % IANA_write)
eeprom_hexfile.seek(8, 0)
AssemblyPartRev_position_read = eeprom_hexfile.read(16)
AssemblyPartRev_write = binascii.unhexlify(AssemblyPartRev_position_read)
eeprom_file.write("\t")
eeprom_file.write("Assembly Part Number Revision=0x%s\r\n" % AssemblyPartRev_write)
eeprom_hexfile.seek(24, 0)
AssemblyID_write = eeprom_hexfile.read(4)
eeprom_file.write("\t")
eeprom_file.write("Assembly ID=0x%s\r\n" % AssemblyID_write)
eeprom_hexfile.seek(28, 0)
HWMajorRev_write = eeprom_hexfile.read(2)
eeprom_file.write("\t")
eeprom_file.write("HW Major Revision=0x%s\r\n" % HWMajorRev_write)
eeprom_hexfile.seek(30, 0)
HWMinorRev_write = eeprom_hexfile.read(2)
eeprom_file.write("\t")
eeprom_file.write("HW Minor Revision=0x%s\r\n" % HWMinorRev_write)
eeprom_hexfile.seek(32, 0)
Deviation_write = eeprom_hexfile.read(10)
eeprom_file.write("\t")
eeprom_file.write("Deviation=0x%s\r\n" % Deviation_write)
eeprom_hexfile.seek(52, 0)
JEDC_write = eeprom_hexfile.read(4)
eeprom_file.write("\t")
eeprom_file.write("JEDC=0x%s\r\n" % JEDC_write)
eeprom_hexfile.seek(56, 0)
EEPROM_version_write = eeprom_hexfile.read(2)
eeprom_file.write("\t")
eeprom_file.write("EEPROM version=0x%s\r\n" % EEPROM_version_write)
crc_str = eeprom_dict.get('0xFE', None)
eeprom_file.write("CRC=%s\r\n" % crc_str)
eeprom_file.write("\n")
eeprom_file.write("\n")
eeprom_file.write("Main board eeprom (0x57)\r\n")
eeprom_file.write("===============================\r\n")
MainEepromCreate = 'sudo echo 24c02 0x57 > /sys/bus/i2c/devices/i2c-0/new_device'
# Write the contents of Main Board EEPROM to file
try:
os.system(MainEepromCreate)
except OSError:
print 'Error: Execution of "%s" failed', MainEepromCreate
return False
MainEepromFileCmd = 'cat /sys/bus/i2c/devices/i2c-0/0-0057/eeprom > /etc/init.d/MainEeprom_qfx5200_ascii'
try:
os.system(MainEepromFileCmd)
except OSError:
print 'Error: Execution of "%s" failed', MainEepromFileCmd
return False
maineeprom_ascii = '/etc/init.d/MainEeprom_qfx5200_ascii'
# Read file contents in Hex format
with open(maineeprom_ascii, 'rb') as Hexformat:
content = Hexformat.read()
Hexformatoutput = binascii.hexlify(content)
eeprom_hex = '/etc/init.d/MainEeprom_qfx5200_hex'
#Write contents of CPU EEPROM to new file in hexa format
with open(eeprom_hex, 'wb+') as Hexfile:
Hexfile.write(Hexformatoutput)
with open(eeprom_hex, 'rb') as eeprom_hexfile:
eeprom_hexfile.seek(8, 0)
AssemblyID_read = eeprom_hexfile.read(4)
eeprom_file.write("Assembly ID=0x%s\r\n" % AssemblyID_read)
eeprom_hexfile.seek(12, 0)
MajorHWRev_read = eeprom_hexfile.read(2)
eeprom_file.write("Assembly Major Revision=0x%s\r\n" % str(MajorHWRev_read))
eeprom_hexfile.seek(14, 0)
MinorHWRev_read = eeprom_hexfile.read(2)
eeprom_file.write("Assembly Minor Revision=0x%s\r\n" % str(MinorHWRev_read))
eeprom_hexfile.seek(24, 0)
AssemblyPNRev_read = eeprom_hexfile.read(16)
AssemblyPNRev_write = binascii.unhexlify(AssemblyPNRev_read)
eeprom_file.write("Assembly Part Number Revision=0x%s\r\n" % str(AssemblyPNRev_write))
eeprom_hexfile.seek(40, 0)
AssemblyPN_read = eeprom_hexfile.read(24)
AssemblyPN_write = binascii.unhexlify(AssemblyPN_read)
eeprom_file.write("Assembly Part Number=%s\r\n" % str(AssemblyPN_write))
eeprom_hexfile.seek(64, 0)
AssemblySN_read = eeprom_hexfile.read(24)
AssemblySN_write = binascii.unhexlify(AssemblySN_read)
eeprom_file.write("Assembly Serial Number=%s\r\n" % str(AssemblySN_write))
eeprom_hexfile.seek(90, 0)
AssemblyMFGDate_read = eeprom_hexfile.read(8)
eeprom_file.write("Manufacture Date=%s\r\n" % str(AssemblyMFGDate_read))
eeprom_hexfile.seek(138, 0)
CLEICode_read = eeprom_hexfile.read(20)
CLEI_name = binascii.unhexlify(CLEICode_read)
eeprom_file.write("CLEI Code=%s\r\n" % str(CLEI_name))
eeprom_hexfile.seek(158, 0)
FRUModelNumber_read = eeprom_hexfile.read(46)
FRUModelNumber_write = binascii.unhexlify(FRUModelNumber_read)
eeprom_file.write("FRU Model Number=%s\r\n" % str(FRUModelNumber_write))
eeprom_hexfile.seek(204, 0)
FRUModelMajorNumber_read = eeprom_hexfile.read(2)
eeprom_file.write("FRU Model Major Number=0x%s\r\n" % str(FRUModelMajorNumber_read))
eeprom_hexfile.seek(206, 0)
FRUModelMinorNumber_read = eeprom_hexfile.read(4)
eeprom_file.write("FRU Model Minor Number=0x%s\r\n" % str(FRUModelMinorNumber_read))
eeprom_hexfile.seek(210, 0)
Deviation_read = eeprom_hexfile.read(10)
eeprom_file.write("Deviation=0x%s\r\n" % str(Deviation_read))
eeprom_hexfile.seek(232, 0)
SerialNumber_read = eeprom_hexfile.read(24)
SerialNumber_write = binascii.unhexlify(SerialNumber_read)
eeprom_file.write("Chassis Serial Number=%s\r\n" % str(SerialNumber_write))
eeprom_file.close()
return True
class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
def __init__(self):
self.__eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0051/eeprom"
super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True)
self.__eeprom_tlv_dict = dict()
try:
self.__eeprom_data = self.read_eeprom()
except:
self.__eeprom_data = "N/A"
raise RuntimeError("Eeprom is not Programmed")
else:
eeprom = self.__eeprom_data
if not self.is_valid_tlvinfo_header(eeprom):
return
total_length = (ord(eeprom[9]) << 8) | ord(eeprom[10])
tlv_index = self._TLV_INFO_HDR_LEN
tlv_end = self._TLV_INFO_HDR_LEN + total_length
while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end:
if not self.is_valid_tlv(eeprom[tlv_index:]):
break
tlv = eeprom[tlv_index:tlv_index + 2
+ ord(eeprom[tlv_index + 1])]
code = "0x%02X" % (ord(tlv[0]))
if ord(tlv[0]) == self._TLV_CODE_VENDOR_EXT:
value = str((ord(tlv[2]) << 24) | (ord(tlv[3]) << 16) |
(ord(tlv[4]) << 8) | ord(tlv[5]))
value += str(tlv[6:6 + ord(tlv[1])])
else:
name, value = self.decoder(None, tlv)
self.__eeprom_tlv_dict[code] = value
if ord(eeprom[tlv_index]) == self._TLV_CODE_CRC_32:
break
tlv_index += ord(eeprom[tlv_index+1]) + 2
def serial_number_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER)
if not is_valid:
return "N/A"
return results[2]
def base_mac_address(self):
(is_valid, t) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_MAC_BASE)
if not is_valid or t[1] != 6:
return super(eeprom_tlvinfo.TlvInfoDecoder, self).switchaddrstr(self.__eeprom_data)
return ":".join([binascii.b2a_hex(T) for T in t[2]])
def modelstr(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME)
if not is_valid:
return "N/A"
return results[2]
def part_number_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_PART_NUMBER)
if not is_valid:
return "N/A"
return results[2]
def serial_tag_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_SERVICE_TAG)
if not is_valid:
return "N/A"
return results[2]
def revision_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION)
if not is_valid:
return "N/A"
return results[2]
def manuDate_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_MANUF_DATE)
if not is_valid:
return "N/A"
return results[2]
def platform_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_PLATFORM_NAME)
if not is_valid:
return "N/A"
return results[2]
def MACsize_str(self):
(is_valid, t) = self.get_tlv_field(self.__eeprom_data, self._TLV_CODE_MAC_SIZE)
if not is_valid:
return "N/A"
return str((ord(t[2][0]) << 8) | ord(t[2][1]))
def vendor_name_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_VENDOR_NAME)
if not is_valid:
return "N/A"
return results[2]
def manufacture_name_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_MANUF_NAME)
if not is_valid:
return "N/A"
return results[2]
def onie_version_str(self):
value = ""
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_ONIE_VERSION)
if not is_valid:
return "N/A"
for c in results[2:2 + ord(results[1])]:
value += "0x%02X " % (ord(c),)
return value
def vendor_ext_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_VENDOR_EXT)
if not is_valid:
return "N/A"
vendor_value_formatted = ''.join( [ " 0x" + "%02X " % ord( x ) for x in results[2] ] ).strip()
vendor_value_hexvalue = ''.join( ["%02X" % ord( x ) for x in results[2] ] ).strip()
return vendor_value_formatted, vendor_value_hexvalue
def crc_str(self):
(is_valid, results) = self.get_tlv_field(
self.__eeprom_data, self._TLV_CODE_CRC_32)
if not is_valid:
return "N/A"
def system_eeprom_info(self):
"""
Returns a dictionary, where keys are the type code defined in
ONIE EEPROM format and values are their corresponding values
found in the system EEPROM.
"""
return self.__eeprom_tlv_dict
if __name__ == "__main__":
main()

View File

@ -0,0 +1,103 @@
#!/usr/bin/env python
#
# Name: juniper_sfp_init.py version: 1.0
#
# Description: Platform-specific SFP Transceiver Initialization for Juniper QFX5200
#
# Copyright (c) 2020, Juniper Networks, Inc.
# All rights reserved.
#
# Notice and Disclaimer: This code is licensed to you under the GNU General
# Public License as published by the Free Software Foundation, version 3 or
# any later version. This code is not an official Juniper product. You can
# obtain a copy of the License at <https://www.gnu.org/licenses/>
#
# OSS License:
#
# 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 <https://www.gnu.org/licenses/>.
#
# Third-Party Code: This code may depend on other components under separate
# copyright notice and license terms. Your use of the source code for those
# components is subject to the terms and conditions of the respective license
# as noted in the Third-Party source code file.
import time
import os.path
import sfputil as jnpr_sfp
from pprint import pprint
DEBUG = False
def i2c_eeprom_dev_update(port, create_eeprom):
eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"
i2c_path = "/sys/class/i2c-adapter/i2c-{0}"
i2c_port = port + jnpr_sfp.SFP_I2C_OFFSET
port_eeprom_path = eeprom_path.format(i2c_port)
port_i2c_path = i2c_path.format(i2c_port)
if create_eeprom:
if not os.path.exists(port_eeprom_path):
try:
i2c_file = open(port_i2c_path + "/new_device", "w")
i2c_file.write("optoe2 0x50")
except IOError as e:
print "Error: unable to write to i2c file: %s" % str(e)
return
else:
if os.path.exists(port_eeprom_path):
try:
i2c_file = open(port_i2c_path + "/delete_device", "w")
i2c_file.write("0x50")
except IOError as e:
print "Error: unable to write to i2c file: %s" % str(e)
return
def gpio_sfp_init():
jnpr_sfp.gpio_sfp_base_init()
time.sleep(2)
#Reset all ports
for port in range(jnpr_sfp.GPIO_PORT_START, jnpr_sfp.GPIO_PORT_END + 1):
port_inited = False
if jnpr_sfp.gpio_sfp_presence_get(port):
port_inited = jnpr_sfp.gpio_sfp_reset_set(port, 0)
if port_inited:
i2c_eeprom_dev_update(port, True)
else:
i2c_eeprom_dev_update(port, False)
time.sleep(2)
#Enable optics for all ports which have XCVRs present
for port in range(jnpr_sfp.GPIO_PORT_START, jnpr_sfp.GPIO_PORT_END + 1):
if jnpr_sfp.gpio_sfp_presence_get(port):
jnpr_sfp.gpio_sfp_lpmode_set(port, 1)
time.sleep(2)
if __name__ == '__main__':
if DEBUG == True:
print "Initializing Juniper SFP module"
gpio_sfp_init()
if DEBUG == True:
print "Juniper GPIO presence pin mapping:"
pprint(jnpr_sfp.gpio_sfp_presence)
print "Juniper GPIO reset pin mapping:"
pprint(jnpr_sfp.gpio_sfp_reset)
print "Juniper GPIO lpmode pin mapping:"
pprint(jnpr_sfp.gpio_sfp_lpmode)

View File

@ -0,0 +1,884 @@
#!/usr/bin/env python
#
# Name: sfputil.py version: 1.0
#
# Description: Platform-specific SFP transceiver interface for Juniper QFX5200
#
# Copyright (c) 2020, Juniper Networks, Inc.
# All rights reserved.
#
# Notice and Disclaimer: This code is licensed to you under the GNU General
# Public License as published by the Free Software Foundation, version 3 or
# any later version. This code is not an official Juniper product. You can
# obtain a copy of the License at <https://www.gnu.org/licenses/>
#
# OSS License:
#
# 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 <https://www.gnu.org/licenses/>.
#
# Third-Party Code: This code may depend on other components under separate
# copyright notice and license terms. Your use of the source code for those
# components is subject to the terms and conditions of the respective license
# as noted in the Third-Party source code file.
try:
import time
import os.path
import glob
from sonic_sfp.sfputilbase import SfpUtilBase
from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom
from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId
from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom
from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId
from ctypes import create_string_buffer
except ImportError as e:
raise ImportError("%s - required module not found" % str(e))
qfx5200_qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)',
'Length OM2(m)', 'Length OM1(m)',
'Length Cable Assembly(m)')
qfx5200_sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)',
'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)',
'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)')
qfx5200_sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode',
'ESCONComplianceCodes', 'SONETComplianceCodes',
'EthernetComplianceCodes','FibreChannelLinkLength',
'FibreChannelTechnology', 'SFP+CableTechnology',
'FibreChannelTransmissionMedia','FibreChannelSpeed')
qfx5200_qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes',
'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes',
'Fibre Channel link length/Transmitter Technology',
'Fibre Channel transmission media', 'Fibre Channel Speed')
GPIO_SLAVE0_PORT_START = 0
GPIO_SLAVE0_PORT_END = 15
GPIO_SLAVE1_PORT_START = 16
GPIO_SLAVE1_PORT_END = 31
GPIO_PORT_START = 0
GPIO_PORT_END = 31
GPIO_PRESENCE_OFFSET = 16
GPIO_LPMODE_OFFSET = 48
GPIO_RESET_OFFSET = 0
gpio_sfp_presence = {}
gpio_sfp_lpmode = {}
gpio_sfp_reset = {}
SFP_I2C_OFFSET = 14
# definitions of the offset and width for values in XCVR info eeprom
XCVR_INTFACE_BULK_OFFSET = 0
XCVR_INTFACE_BULK_WIDTH_QSFP = 20
XCVR_INTFACE_BULK_WIDTH_SFP = 21
XCVR_TYPE_WIDTH = 1
XCVR_VENDOR_NAME_OFFSET = 20
XCVR_VENDOR_NAME_WIDTH = 16
XCVR_VENDOR_OUI_OFFSET = 37
XCVR_VENDOR_OUI_WIDTH = 3
XCVR_VENDOR_PN_OFFSET = 40
XCVR_VENDOR_PN_WIDTH = 16
XCVR_HW_REV_OFFSET = 56
XCVR_HW_REV_WIDTH_OSFP = 2
XCVR_HW_REV_WIDTH_QSFP = 2
XCVR_HW_REV_WIDTH_SFP = 4
XCVR_VENDOR_SN_OFFSET = 68
XCVR_VENDOR_SN_WIDTH = 16
XCVR_VENDOR_DATE_OFFSET = 84
XCVR_VENDOR_DATE_WIDTH = 8
XCVR_DOM_CAPABILITY_OFFSET = 92
XCVR_DOM_CAPABILITY_WIDTH = 1
# definitions of the offset for values in OSFP info eeprom
OSFP_TYPE_OFFSET = 0
OSFP_VENDOR_NAME_OFFSET = 129
OSFP_VENDOR_PN_OFFSET = 148
OSFP_HW_REV_OFFSET = 164
OSFP_VENDOR_SN_OFFSET = 166
#definitions of the offset and width for values in DOM info eeprom
QSFP_DOM_REV_OFFSET = 1
QSFP_DOM_REV_WIDTH = 1
QSFP_TEMPE_OFFSET = 22
QSFP_TEMPE_WIDTH = 2
QSFP_VOLT_OFFSET = 26
QSFP_VOLT_WIDTH = 2
QSFP_CHANNL_MON_OFFSET = 34
QSFP_CHANNL_MON_WIDTH = 16
QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24
SFP_TEMPE_OFFSET = 96
SFP_TEMPE_WIDTH = 2
SFP_VOLT_OFFSET = 98
SFP_VOLT_WIDTH = 2
SFP_CHANNL_MON_OFFSET = 100
SFP_CHANNL_MON_WIDTH = 6
def gpio_create_file(gpio_pin):
gpio_export_path = "/sys/class/gpio/export"
gpio_pin_path = "/sys/class/gpio/gpio" + str(gpio_pin)
if not os.path.exists(gpio_pin_path):
try:
gpio_export_file = open(gpio_export_path, 'w')
gpio_export_file.write(str(gpio_pin))
gpio_export_file.close()
except IOError as e:
print "Error: unable to open export file: %s" % str(e)
return False
return True
def gpio_sfp_port_init(gpio_base, port):
presence_pin = gpio_base + GPIO_PRESENCE_OFFSET + (port % 16)
if gpio_create_file(presence_pin):
gpio_sfp_presence[port] = presence_pin
reset_pin = gpio_base + GPIO_RESET_OFFSET + (port % 16)
if gpio_create_file(reset_pin):
gpio_sfp_reset[port] = reset_pin
lpmode_pin = gpio_base + GPIO_LPMODE_OFFSET + (port % 16)
if gpio_create_file(lpmode_pin):
gpio_sfp_lpmode[port] = lpmode_pin
def gpio_sfp_slave_init(gpio_base_path, gpio_port_start, gpio_port_end):
flist = glob.glob(gpio_base_path)
if len(flist) == 1:
try:
fp = open(flist[0]+"/base")
gpio_base = int(fp.readline().rstrip())
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return
for port in range(gpio_port_start, gpio_port_end + 1):
gpio_sfp_port_init(gpio_base, port)
def gpio_sfp_base_init():
gpio_sfp_slave_init("/sys/bus/platform/drivers/gpioslave-tmc/gpioslave-tmc.21/gpio/gpio*",
GPIO_SLAVE0_PORT_START, GPIO_SLAVE0_PORT_END)
gpio_sfp_slave_init("/sys/bus/platform/drivers/gpioslave-tmc/gpioslave-tmc.22/gpio/gpio*",
GPIO_SLAVE1_PORT_START, GPIO_SLAVE1_PORT_END)
def gpio_sfp_read(gpio_pin):
gpio_pin_path = "/sys/class/gpio/gpio" + str(gpio_pin)
value = 0
try:
reg_file = open(gpio_pin_path +"/value")
value = int(reg_file.readline().rstrip())
except IOError as e:
print "error: unable to open file: %s" % str(e)
return value
def gpio_sfp_write(gpio_pin, value):
success = False
gpio_pin_path = "/sys/class/gpio/gpio" + str(gpio_pin)
try:
gpio_file = open(gpio_pin_path +"/value", 'w')
gpio_file.write(str(value))
success = True
except IOError as e:
print "error: unable to open file: %s" % str(e)
return success
def gpio_sfp_presence_get(port):
if port not in gpio_sfp_presence.keys():
print "Port:" + str(port) + " not in sfp dict"
return 0
gpio_pin = gpio_sfp_presence[port]
return gpio_sfp_read(gpio_pin)
def gpio_sfp_lpmode_get(port):
if port not in gpio_sfp_lpmode.keys():
return 0
gpio_pin = gpio_sfp_lpmode[port]
return gpio_sfp_read(gpio_pin)
def gpio_sfp_lpmode_set(port, value):
if port not in gpio_sfp_lpmode.keys():
return False
gpio_pin = gpio_sfp_lpmode[port]
return gpio_sfp_write(gpio_pin, value)
def gpio_sfp_reset_set(port, value):
if port not in gpio_sfp_reset.keys():
return False
gpio_pin = gpio_sfp_reset[port]
return gpio_sfp_write(gpio_pin, value)
class SfpUtil(SfpUtilBase):
"""Platform-specific SfpUtil class"""
PORT_START = 0
PORT_END = 31
PORTS_IN_BLOCK = 32
QSFP_PORT_START = 0
QSFP_PORT_END = 31
cmd = '/var/run/sfppresence'
_port_to_eeprom_mapping = {}
port_to_i2cbus_mapping = {
0: 14,
1: 15,
2: 16,
3: 17,
4: 18,
5: 19,
6: 20,
7: 21,
8: 22,
9: 23,
10: 24,
11: 25,
12: 26,
13: 27,
14: 28,
15: 29,
16: 30,
17: 31,
18: 32,
19: 33,
20: 34,
21: 35,
22: 36,
23: 37,
24: 38,
25: 39,
26: 40,
27: 41,
28: 42,
29: 43,
30: 44,
31: 45
}
port_ctle_settings = {
0: 7,
1: 6,
2: 6,
3: 6,
4: 6,
5: 5,
6: 6,
7: 5,
8: 5,
9: 5,
10: 7,
11: 7,
12: 6,
13: 5,
14: 4,
15: 3,
16: 4,
17: 5,
18: 6,
19: 6,
20: 7,
21: 6,
22: 5,
23: 5,
24: 5,
25: 5,
26: 6,
27: 5,
28: 6,
29: 6,
30: 7,
31: 7
}
optics_list_100g = {
"AFBR-89CDDZ-JU1",
"FTLC9551REPM-J1",
"LUX42604CO",
"EOLQ-161HG-10-LJ1",
"FTLC1151RDPL-J1",
"TR-FC13R-NJ3",
"SPQ-CE-LR-CDFB-J2"
}
def is_100g_optics(self,part_num):
ret = part_num in self.optics_list_100g
return ret
def process_TxCTLE(self, port_num, part_num):
eeprom = None
try:
if self.is_100g_optics(part_num):
# Accessing page 3 of optics
regval = 0x3
buffer = create_string_buffer(1)
buffer[0] = chr(regval)
eeprom = open(self._port_to_eeprom_mapping[port_num], "r+b")
eeprom.seek(127)
eeprom.write(buffer[0])
regval = self.port_ctle_settings[port_num]
eeprom.seek(234)
buffer[0] = eeprom.read(1)
if (buffer[0] != chr(regval)):
buffer[0] = chr(regval)
eeprom.write(buffer[0])
eeprom.seek(235)
eeprom.write(buffer[0])
else:
pass
# Moving back the optics page to 0
regval = 0x0
buffer[0] = chr(regval)
eeprom.seek(127)
eeprom.write(buffer[0])
else:
pass
except IOError as e:
print "Error: unable to open file: %s" % str(e)
finally:
if eeprom is not None:
eeprom.close
@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(0, self.PORTS_IN_BLOCK + 1)
@property
def port_to_eeprom_mapping(self):
return self._port_to_eeprom_mapping
def __init__(self):
gpio_sfp_base_init()
eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"
for x in range(0, self.port_end + 1):
self.port_to_eeprom_mapping[x] = eeprom_path.format(self.port_to_i2cbus_mapping[x])
SfpUtilBase.__init__(self)
def get_presence(self, port_num):
reg_value = gpio_sfp_presence_get(port_num)
if reg_value == 1:
return True
return False
def get_low_power_mode(self, port_num):
reg_value = gpio_sfp_lpmode_get(port_num)
if reg_value == 1:
return True
return False
def set_low_power_mode(self, port_num, lpmode):
if lpmode == False:
lpmode = 0
else:
lpmode = 1
status = gpio_sfp_lpmode_set(port_num, lpmode)
return status
def reset(self, port_num):
reset_val = 0
status = gpio_sfp_reset_set(port_num, reset_val)
return status
# Writing to a file from a list
def write_to_file(self, file_name, from_list):
try:
fp1 = open(file_name, 'w')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
for i in from_list:
fp1.write(i)
fp1.write('\n')
fp1.close()
return True
# Reading from a file to a list
def read_from_file(self, file_name):
try:
fp = open(file_name, 'r')
except IOError as e:
print "Error: unable to open file: %s" % str(e)
return False
to_list = fp.readlines()
to_list = [x.rstrip() for x in to_list]
fp.close()
return to_list
def sfp_detect(self):
port = 0
ret_dict = {}
defl_dict = {}
current_sfp_values = [0] * 32
previous_sfp_values = [0] * 32
if not os.path.isfile(self.cmd):
pass
else:
if (self.read_from_file(self.cmd) == False):
return False, defl_dict
else:
previous_sfp_values = self.read_from_file(self.cmd)
# Read the current values from sysfs
for port in range(GPIO_PORT_START, GPIO_PORT_END + 1):
sfp_present = gpio_sfp_presence_get(port)
current_sfp_values[port] = str(sfp_present)
ret_dict.update({port:current_sfp_values[port]})
if (current_sfp_values[port] != previous_sfp_values[port]):
ret_dict.update({port:current_sfp_values[port]})
if(self.write_to_file(self.cmd, current_sfp_values) == True):
return True, ret_dict
else:
return False, defl_dict
# Read out SFP type, vendor name, PN, REV, SN from eeprom.
def get_transceiver_info_dict(self, port_num):
transceiver_info_dict = {}
compliance_code_dict = {}
# ToDo: OSFP tranceiver info parsing not fully supported.
# in inf8628.py lack of some memory map definition
# will be implemented when the inf8628 memory map ready
if port_num in self.osfp_ports:
offset = 0
vendor_rev_width = XCVR_HW_REV_WIDTH_OSFP
sfpi_obj = inf8628InterfaceId()
if sfpi_obj is None:
print("Error: sfp_object open failed")
return None
file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR)
if not self._sfp_eeprom_present(file_path, 0):
print("Error, file not exist %s" % file_path)
return None
try:
sysfsfile_eeprom = open(file_path, mode="rb", buffering=0)
except IOError:
print("Error: reading sysfs file %s" % file_path)
return None
sfp_type_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + OSFP_TYPE_OFFSET), XCVR_TYPE_WIDTH)
if sfp_type_raw is not None:
sfp_type_data = sfpi_obj.parse_sfp_type(sfp_type_raw, 0)
else:
return None
sfp_vendor_name_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + OSFP_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH)
if sfp_vendor_name_raw is not None:
sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0)
else:
return None
sfp_vendor_pn_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + OSFP_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH)
if sfp_vendor_pn_raw is not None:
sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0)
else:
return None
sfp_vendor_rev_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + OSFP_HW_REV_OFFSET), vendor_rev_width)
if sfp_vendor_rev_raw is not None:
sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0)
else:
return None
sfp_vendor_sn_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + OSFP_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH)
if sfp_vendor_sn_raw is not None:
sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0)
else:
return None
try:
sysfsfile_eeprom.close()
except IOError:
print("Error: closing sysfs file %s" % file_path)
return None
transceiver_info_dict['type'] = sfp_type_data['data']['type']['value']
transceiver_info_dict['type_abbrv_name'] = sfp_type_data['data']['type_abbrv_name']['value']
transceiver_info_dict['manufacturename'] = sfp_vendor_name_data['data']['Vendor Name']['value']
transceiver_info_dict['modelname'] = sfp_vendor_pn_data['data']['Vendor PN']['value']
transceiver_info_dict['hardwarerev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value']
transceiver_info_dict['serialnum'] = sfp_vendor_sn_data['data']['Vendor SN']['value']
# Below part is added to avoid fail the xcvrd, shall be implemented later
transceiver_info_dict['vendor_oui'] = 'N/A'
transceiver_info_dict['vendor_date'] = 'N/A'
transceiver_info_dict['Connector'] = 'N/A'
transceiver_info_dict['encoding'] = 'N/A'
transceiver_info_dict['ext_identifier'] = 'N/A'
transceiver_info_dict['ext_rateselect_compliance'] = 'N/A'
transceiver_info_dict['cable_type'] = 'N/A'
transceiver_info_dict['cable_length'] = 'N/A'
transceiver_info_dict['specification_compliance'] = 'N/A'
transceiver_info_dict['nominal_bit_rate'] = 'N/A'
else:
if port_num in self.qsfp_ports:
offset = 128
vendor_rev_width = XCVR_HW_REV_WIDTH_QSFP
interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_QSFP
sfp_type = 'QSFP'
sfpi_obj = sff8436InterfaceId()
if sfpi_obj is None:
print("Error: sfp_object open failed")
return None
else:
offset = 0
vendor_rev_width = XCVR_HW_REV_WIDTH_SFP
interface_info_bulk_width = XCVR_INTFACE_BULK_WIDTH_SFP
sfp_type = 'SFP'
sfpi_obj = sff8472InterfaceId()
if sfpi_obj is None:
print("Error: sfp_object open failed")
return None
file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR)
if not self._sfp_eeprom_present(file_path, 0):
print("Error, file not exist %s" % file_path)
return None
try:
sysfsfile_eeprom = open(file_path, mode="rb", buffering=0)
except IOError:
print("Error: reading sysfs file %s" % file_path)
return None
sfp_interface_bulk_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_INTFACE_BULK_OFFSET), interface_info_bulk_width)
if sfp_interface_bulk_raw is not None:
sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw, 0)
else:
return None
sfp_vendor_name_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH)
if sfp_vendor_name_raw is not None:
sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0)
else:
return None
sfp_vendor_pn_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH)
if sfp_vendor_pn_raw is not None:
sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0)
else:
return None
sfp_vendor_rev_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_HW_REV_OFFSET), vendor_rev_width)
if sfp_vendor_rev_raw is not None:
sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0)
else:
return None
sfp_vendor_sn_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH)
if sfp_vendor_sn_raw is not None:
sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0)
else:
return None
sfp_vendor_oui_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH)
if sfp_vendor_oui_raw is not None:
sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_vendor_oui_raw, 0)
else:
return None
sfp_vendor_date_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH)
if sfp_vendor_date_raw is not None:
sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_vendor_date_raw, 0)
else:
return None
try:
sysfsfile_eeprom.close()
except IOError:
print("Error: closing sysfs file %s" % file_path)
return None
transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value']
transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value']
transceiver_info_dict['manufacturename'] = sfp_vendor_name_data['data']['Vendor Name']['value']
transceiver_info_dict['modelname'] = sfp_vendor_pn_data['data']['Vendor PN']['value']
transceiver_info_dict['hardwarerev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value']
transceiver_info_dict['serialnum'] = sfp_vendor_sn_data['data']['Vendor SN']['value']
transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value']
transceiver_info_dict['vendor_date'] = sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value']
transceiver_info_dict['Connector'] = sfp_interface_bulk_data['data']['Connector']['value']
transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value']
transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value']
transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value']
if sfp_type == 'QSFP':
for key in qfx5200_qsfp_cable_length_tup:
if key in sfp_interface_bulk_data['data']:
transceiver_info_dict['cable_type'] = key
transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value'])
break
else:
transceiver_info_dict['cable_type'] = key
transceiver_info_dict['cable_length'] = 'N/A'
for key in qfx5200_qsfp_compliance_code_tup:
if key in sfp_interface_bulk_data['data']['Specification compliance']['value']:
compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value']
transceiver_info_dict['specification_compliance'] = str(compliance_code_dict)
if sfp_interface_bulk_data['data'].has_key('Nominal Bit Rate(100Mbs)'):
transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value'])
else:
transceiver_info_dict['nominal_bit_rate'] = 'N/A'
else:
for key in qfx5200_sfp_cable_length_tup:
if key in sfp_interface_bulk_data['data']:
transceiver_info_dict['cable_type'] = key
transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value'])
else:
transceiver_info_dict['cable_type'] = key
transceiver_info_dict['cable_length'] = 'N/A'
for key in qfx5200_sfp_compliance_code_tup:
if key in sfp_interface_bulk_data['data']['Specification compliance']['value']:
compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value']
transceiver_info_dict['specification_compliance'] = str(compliance_code_dict)
if sfp_interface_bulk_data['data'].has_key('NominalSignallingRate(UnitsOf100Mbd)'):
transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value'])
else:
transceiver_info_dict['nominal_bit_rate'] = 'N/A'
sfp_pn_num = str(sfp_vendor_pn_data['data']['Vendor PN']['value'])
self.process_TxCTLE(port_num,sfp_pn_num)
return transceiver_info_dict
def get_transceiver_dom_info_dict(self, port_num):
transceiver_dom_info_dict = {}
if port_num in self.osfp_ports:
# Below part is added to avoid fail xcvrd, shall be implemented later
transceiver_dom_info_dict['temperature'] = 'N/A'
transceiver_dom_info_dict['voltage'] = 'N/A'
transceiver_dom_info_dict['rx1power'] = 'N/A'
transceiver_dom_info_dict['rx2power'] = 'N/A'
transceiver_dom_info_dict['rx3power'] = 'N/A'
transceiver_dom_info_dict['rx4power'] = 'N/A'
transceiver_dom_info_dict['tx1bias'] = 'N/A'
transceiver_dom_info_dict['tx2bias'] = 'N/A'
transceiver_dom_info_dict['tx3bias'] = 'N/A'
transceiver_dom_info_dict['tx4bias'] = 'N/A'
transceiver_dom_info_dict['tx1power'] = 'N/A'
transceiver_dom_info_dict['tx2power'] = 'N/A'
transceiver_dom_info_dict['tx3power'] = 'N/A'
transceiver_dom_info_dict['tx4power'] = 'N/A'
elif port_num in self.qsfp_ports:
offset = 0
offset_xcvr = 128
file_path = self._get_port_eeprom_path(port_num, self.IDENTITY_EEPROM_ADDR)
if not self._sfp_eeprom_present(file_path, 0):
return None
try:
sysfsfile_eeprom = open(file_path, mode="rb", buffering=0)
except IOError:
print("Error: reading sysfs file %s" % file_path)
return None
sfpd_obj = sff8436Dom()
if sfpd_obj is None:
return None
sfpi_obj = sff8436InterfaceId()
if sfpi_obj is None:
return None
# QSFP capability byte parse, through this byte can know whether it support tx_power or not.
# TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436,
# need to add more code for determining the capability and version compliance
# in SFF-8636 dom capability definitions evolving with the versions.
qsfp_dom_capability_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH)
if qsfp_dom_capability_raw is not None:
qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0)
else:
return None
dom_temperature_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_TEMPE_OFFSET), QSFP_TEMPE_WIDTH)
if dom_temperature_raw is not None:
dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0)
else:
return None
dom_voltage_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_VOLT_OFFSET), QSFP_VOLT_WIDTH)
if dom_voltage_raw is not None:
dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0)
else:
return None
qsfp_dom_rev_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_DOM_REV_OFFSET), QSFP_DOM_REV_WIDTH)
if qsfp_dom_rev_raw is not None:
qsfp_dom_rev_data = sfpd_obj.parse_sfp_dom_rev(qsfp_dom_rev_raw, 0)
else:
return None
transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
# The tx_power monitoring is only available on QSFP which compliant with SFF-8636
# and claimed that it support tx_power with one indicator bit.
dom_channel_monitor_data = {}
qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value']
qsfp_tx_power_support = qspf_dom_capability_data['data']['Tx_power_support']['value']
if (qsfp_dom_rev[0:8] != 'SFF-8636' or (qsfp_dom_rev[0:8] == 'SFF-8636' and qsfp_tx_power_support != 'on')):
dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WIDTH)
if dom_channel_monitor_raw is not None:
dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0)
else:
return None
transceiver_dom_info_dict['tx1power'] = 'N/A'
transceiver_dom_info_dict['tx2power'] = 'N/A'
transceiver_dom_info_dict['tx3power'] = 'N/A'
transceiver_dom_info_dict['tx4power'] = 'N/A'
else:
dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH)
if dom_channel_monitor_raw is not None:
dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0)
else:
return None
transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TX1Power']['value']
transceiver_dom_info_dict['tx2power'] = dom_channel_monitor_data['data']['TX2Power']['value']
transceiver_dom_info_dict['tx3power'] = dom_channel_monitor_data['data']['TX3Power']['value']
transceiver_dom_info_dict['tx4power'] = dom_channel_monitor_data['data']['TX4Power']['value']
try:
sysfsfile_eeprom.close()
except IOError:
print("Error: closing sysfs file %s" % file_path)
return None
transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RX1Power']['value']
transceiver_dom_info_dict['rx2power'] = dom_channel_monitor_data['data']['RX2Power']['value']
transceiver_dom_info_dict['rx3power'] = dom_channel_monitor_data['data']['RX3Power']['value']
transceiver_dom_info_dict['rx4power'] = dom_channel_monitor_data['data']['RX4Power']['value']
transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TX1Bias']['value']
transceiver_dom_info_dict['tx2bias'] = dom_channel_monitor_data['data']['TX2Bias']['value']
transceiver_dom_info_dict['tx3bias'] = dom_channel_monitor_data['data']['TX3Bias']['value']
transceiver_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value']
else:
offset = 256
file_path = self._get_port_eeprom_path(port_num, self.DOM_EEPROM_ADDR)
if not self._sfp_eeprom_present(file_path, 0):
return None
try:
sysfsfile_eeprom = open(file_path, mode="rb", buffering=0)
except IOError:
print("Error: reading sysfs file %s" % file_path)
return None
sfpd_obj = sff8472Dom()
if sfpd_obj is None:
return None
dom_temperature_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_TEMPE_OFFSET), SFP_TEMPE_WIDTH)
if dom_temperature_raw is not None:
dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0)
else:
return None
dom_voltage_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_VOLT_OFFSET), SFP_VOLT_WIDTH)
if dom_voltage_raw is not None:
dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0)
else:
return None
dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH)
if dom_channel_monitor_raw is not None:
dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0)
else:
return None
try:
sysfsfile_eeprom.close()
except IOError:
print("Error: closing sysfs file %s" % file_path)
return None
transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value']
transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value']
transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RXPower']['value']
transceiver_dom_info_dict['rx2power'] = 'N/A'
transceiver_dom_info_dict['rx3power'] = 'N/A'
transceiver_dom_info_dict['rx4power'] = 'N/A'
transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value']
transceiver_dom_info_dict['tx2bias'] = 'N/A'
transceiver_dom_info_dict['tx3bias'] = 'N/A'
transceiver_dom_info_dict['tx4bias'] = 'N/A'
transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value']
transceiver_dom_info_dict['tx2power'] = 'N/A'
transceiver_dom_info_dict['tx3power'] = 'N/A'
transceiver_dom_info_dict['tx4power'] = 'N/A'
return transceiver_dom_info_dict
def get_transceiver_change_event(self, timeout=2000):
time.sleep(3)
return self.sfp_detect()

View File

@ -0,0 +1,3 @@
{
"skip_thermalctld": true
}

View File

@ -57,7 +57,8 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
$(BRCM_XLR_GTS_PLATFORM_MODULE) \
$(DELTA_AG9032V2A_PLATFORM_MODULE) \
$(JUNIPER_QFX5210_PLATFORM_MODULE) \
$(CEL_SILVERSTONE_PLATFORM_MODULE)
$(CEL_SILVERSTONE_PLATFORM_MODULE) \
$(JUNIPER_QFX5200_PLATFORM_MODULE)
ifeq ($(INSTALL_DEBUG_TOOLS),y)
$(SONIC_ONE_IMAGE)_DOCKERS += $(SONIC_INSTALL_DOCKER_DBG_IMAGES)
$(SONIC_ONE_IMAGE)_DOCKERS += $(filter-out $(patsubst %-$(DBG_IMAGE_MARK).gz,%.gz, $(SONIC_INSTALL_DOCKER_DBG_IMAGES)), $(SONIC_INSTALL_DOCKER_IMAGES))

View File

@ -1,8 +1,10 @@
# Juniper Platform modules
JUNIPER_QFX5210_PLATFORM_MODULE_VERSION = 1.1
JUNIPER_QFX5200_PLATFORM_MODULE_VERSION = 1.1
export JUNIPER_QFX5210_PLATFORM_MODULE_VERSION
export JUNIPER_QFX5200_PLATFORM_MODULE_VERSION
JUNIPER_QFX5210_PLATFORM_MODULE = sonic-platform-juniper-qfx5210_$(JUNIPER_QFX5210_PLATFORM_MODULE_VERSION)_amd64.deb
$(JUNIPER_QFX5210_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-juniper
@ -10,4 +12,9 @@ $(JUNIPER_QFX5210_PLATFORM_MODULE)_DEPENDS += $(LINUX_HEADERS) $(LINUX_HEADERS_C
$(JUNIPER_QFX5210_PLATFORM_MODULE)_PLATFORM = x86_64-juniper_qfx5210-r0
SONIC_DPKG_DEBS += $(JUNIPER_QFX5210_PLATFORM_MODULE)
JUNIPER_QFX5200_PLATFORM_MODULE = sonic-platform-juniper-qfx5200_$(JUNIPER_QFX5200_PLATFORM_MODULE_VERSION)_amd64.deb
$(JUNIPER_QFX5200_PLATFORM_MODULE)_PLATFORM = x86_64-juniper_qfx5200-r0
$(eval $(call add_extra_package,$(JUNIPER_QFX5210_PLATFORM_MODULE),$(JUNIPER_QFX5200_PLATFORM_MODULE)))
SONIC_STRETCH_DEBS += $(JUNIPER_QFX5210_PLATFORM_MODULE)

View File

@ -9,3 +9,6 @@ Package: sonic-platform-juniper-qfx5210
Architecture: amd64
Description: kernel modules for platform devices such as fan, led, sfp
Package: sonic-platform-juniper-qfx5200
Architecture: amd64
Description: kernel modules for platform devices such as fan, led, sfp

View File

@ -19,7 +19,7 @@ PACKAGE_PRE_NAME := sonic-platform-juniper
KVERSION ?= $(shell uname -r)
KERNEL_SRC := /lib/modules/$(KVERSION)
MOD_SRC_DIR:= $(shell pwd)
MODULE_DIRS:= qfx5210
MODULE_DIRS:= qfx5210 qfx5200
MODULE_DIR := modules
UTILS_DIR := utils
SERVICE_DIR := service

View File

@ -0,0 +1,5 @@
qfx5200/utils/juniper_qfx5200_util.py usr/local/bin
qfx5200/utils/juniper_qfx5200_monitor.py usr/local/bin
qfx5200/sonic_platform/chassis.py usr/lib/python2.7/dist-packages/sonic_platform
qfx5200/sonic_platform/platform.py usr/lib/python2.7/dist-packages/sonic_platform
qfx5200/service/qfx5200-platform-init.service etc/systemd/system

View File

@ -0,0 +1,31 @@
#!/bin/bash
systemctl enable qfx5200-platform-init.service
systemctl start qfx5200-platform-init.service
# There are primary and secondary bios in qfx5200 platform.
# There is a problem with bios which prevents the OS booting from the
# secondary bios when the OS was installed using primary bios.
# Secondary bios fails to detect the UEFI partition. Right now
# the workaround is to have a folder structure /EFI/BOOT/BOOT64x.efi
SONIC_VERSION=$(sonic-cfggen -y /etc/sonic/sonic_version.yml -v build_version)
FIRST_BOOT_FILE="/host/image-${SONIC_VERSION}/platform/firsttime"
if [ -f $FIRST_BOOT_FILE ]; then
mkdir /tmp/sda1
mount /dev/sda1 /tmp/sda1
cd /tmp/sda1/EFI
mkdir BOOT > /dev/null 2>&1
cp SONiC-OS/grubx64.efi BOOT/BOOTX64.EFI
cd /tmp
umount sda1
# This code block ensures that no additional entries
# are added. This is applicable during SONiC image
# upgrades.
entries=`efibootmgr -v | grep "BOOTX64"`
if [ -z "$entries" ]; then
# Creating the UEFI entry for the first time.
efibootmgr -c -L "SONiC" -l "\EFI\BOOT\BOOTX64.EFI" > /var/tmp/efi_log 2>&1
fi
fi

View File

@ -0,0 +1 @@
obj-m:=jnx-tmc-core.o i2c-tmc.o jnx-refpga-tmc.o leds-jnx-tmc.o gpio-tmc.o jnx-tmc-psu.o jnx-psu-monitor.o jnx-refpga-lpcm.o

View File

@ -0,0 +1,661 @@
/*
* Juniper Networks TMC GPIO driver
*
* Copyright (C) 2020 Juniper Networks
* Author: Ashish Bhensdadia <bashish@juniper.net>
*
* This driver implement the GPIO set/get functionality
*
* 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; version 2 of the License.
*
* 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.
*/
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/errno.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/platform_device.h>
#include <linux/mfd/core.h>
#include "jnx-tmc.h"
#define TMC_GPIO_MAX_BITS_PER_REG 16
#define TMC_GPIO_SFP_MAX_BITS_PER_REG 2
#define TMC_GPIO_PTPCFG_MAX_BITS_PER_REG 8
#define TMC_GPIO_FIND_GROUP(gpio) \
((gpio) / TMC_GPIO_MAX_BITS_PER_REG)
#define TMC_GPIO_FIND_GPIO(gpio) \
((gpio) % TMC_GPIO_MAX_BITS_PER_REG)
#define TMC_GPIO_SFP_FIND_GROUP(gpio) \
((gpio) / TMC_GPIO_SFP_MAX_BITS_PER_REG)
#define TMC_GPIO_SFP_FIND_GPIO(gpio) \
((gpio) % TMC_GPIO_SFP_MAX_BITS_PER_REG)
#define TMC_GPIO_PTPCFG_FIND_GPIO(gpio) \
((gpio) % TMC_GPIO_PTPCFG_MAX_BITS_PER_REG)
#define TMC_GPIO_MAX_NGPIO_PER_GROUP 320
#define TMC_PFE_QSFP_RESET_OFFSET 0x4
#define TMC_PFE_QSFP_PRESENT_OFFSET 0x8
#define TMC_PFE_QSFP_PHY_RESET_OFFSET 0x10
#define TMC_PFE_QSFP_LPMOD_OFFSET 0x78
#define TMC_PFE_QSFP_LED_CTRL_OFFSET 0x20
#define TMC_PFE_LANES_GREEN_LED_VALUE 0x3
#define TMC_PFE_LANE0_GREEN_LED_BIT_POSITION 0
#define TMC_PFE_LANE1_GREEN_LED_BIT_POSITION 2
#define TMC_PFE_LANE2_GREEN_LED_BIT_POSITION 4
#define TMC_PFE_LANE3_GREEN_LED_BIT_POSITION 6
#define TMC_PFE_LANES_BEACON_LED_VALUE 0x2
#define TMC_PFE_LANE0_BEACON_LED_BIT_POSITION 0
#define TMC_PFE_LANE1_BEACON_LED_BIT_POSITION 2
#define TMC_PFE_LANE2_BEACON_LED_BIT_POSITION 4
#define TMC_PFE_LANE3_BEACON_LED_BIT_POSITION 6
#define TMC_PFE_LANES_FAULT_LED_VALUE 0x1
#define TMC_PFE_LANE0_FAULT_LED_BIT_POSITION 0
#define TMC_PFE_LANE1_FAULT_LED_BIT_POSITION 2
#define TMC_PFE_LANE2_FAULT_LED_BIT_POSITION 4
#define TMC_PFE_LANE3_FAULT_LED_BIT_POSITION 6
#define TMC_PFE_SFPSB0_TX_DISABLE_OFFSET 0x0
#define TMC_PFE_SFPSB0_LED_CTRL_OFFSET 0xC
#define TMC_PFE_SFPSB0_LED_ACTIVITY_OFFSET 0x14
#define TMC_PFE_SFPSB0_PRESENT_OFFSET 0x18
#define TMC_PFE_SFPSB0_LOSS_OFFSET 0x1C
#define TMC_PFE_SFPSB0_TX_FAULT_OFFSET 0x20
#define TMC_PFE_SFPSB1_TX_DISABLE_OFFSET 0x0
#define TMC_PFE_SFPSB1_LED_CTRL_OFFSET 0x8
#define TMC_PFE_SFPSB1_LED_ACTIVITY_OFFSET 0x10
#define TMC_PFE_SFPSB1_PRESENT_OFFSET 0x14
#define TMC_PFE_SFPSB1_LOSS_OFFSET 0x18
#define TMC_PFE_SFPSB1_TX_FAULT_OFFSET 0x1C
/*
* Index 4 to 15 is used for QSFP starting with
* QSFP_LED_LANE0_GREEN. To keep multibit set/get common
* starting SFP_LED_LANE0_GREEN with 16 which will avoid
* conflict with QSFP enums.
*/
#define SFP_LED_OP_START_INDEX 16
/*
* Used for off-setting SFP led op index
*/
#define SFP_LED_OP_OFFSET 0xB
/*
* SFP slave blocks
*/
#define SFP_SLAVE0_BLOCK 0x1
#define SFP_SLAVE1_BLOCK 0x2
/*
* each group represent the 16 gpios.
* QSFP_RST - QSFP_LPMODE
* each bit represent the one gpio
* exemple: bits[0:15] - bit0 - gpio0
* QSFP_LED_LANE0_GREEN - QSFP_LED_LANE3_FAULT
* here, number represent the one gpio
* exemple: bits[0:1]
* 00 - gpio off, 01 - gpio on [ gpio0]
* 00 - gpio off, 10 - gpio on [ gpio1]
* 00 - gpio off, 11 - gpio on [ gpio2]
*
*/
enum {
QSFP_RST,
QSFP_PRESENT,
QSFP_PHY_RST,
QSFP_LPMOD,
QSFP_LED_LANE0_GREEN,
QSFP_LED_LANE1_GREEN,
QSFP_LED_LANE2_GREEN,
QSFP_LED_LANE3_GREEN,
QSFP_LED_LANE0_BEACON,
QSFP_LED_LANE1_BEACON,
QSFP_LED_LANE2_BEACON,
QSFP_LED_LANE3_BEACON,
QSFP_LED_LANE0_FAULT,
QSFP_LED_LANE1_FAULT,
QSFP_LED_LANE2_FAULT,
QSFP_LED_LANE3_FAULT,
TMC_PFE_GPIO_GROUP_MAX
};
enum sfp_op {
SFP_TX_DISABLE,
SFP_LED_ACTIVITY,
SFP_PRESENT,
SFP_SFP_LOS,
SFP_TX_FAULT,
SFP_LED_LANE0_GREEN = SFP_LED_OP_START_INDEX,
SFP_LED_LANE1_GREEN,
SFP_LED_LANE2_GREEN,
SFP_LED_LANE3_GREEN,
SFP_LED_LANE0_BEACON,
SFP_LED_LANE1_BEACON,
SFP_LED_LANE2_BEACON,
SFP_LED_LANE3_BEACON,
SFP_LED_LANE0_FAULT,
SFP_LED_LANE1_FAULT,
SFP_LED_LANE2_FAULT,
SFP_LED_LANE3_FAULT,
TMC_PFE_SFP_GPIO_GROUP_MAX
};
static const u32 group_offset[TMC_PFE_GPIO_GROUP_MAX] = {
TMC_PFE_QSFP_RESET_OFFSET,
TMC_PFE_QSFP_PRESENT_OFFSET,
TMC_PFE_QSFP_PHY_RESET_OFFSET,
TMC_PFE_QSFP_LPMOD_OFFSET,
TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE0 GREEN */
TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE1 GREEN */
TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE2 GREEN */
TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE3 GREEN */
TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE0 BEACON */
TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE1 BEACON */
TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE2 BEACON */
TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE3 BEACON */
TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE0 FAULT */
TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE1 FAULT */
TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE2 FAULT */
TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE3 FAULT */
};
static const u32 sfp_slaveb0_group_offset[TMC_PFE_SFP_GPIO_GROUP_MAX] = {
TMC_PFE_SFPSB0_TX_DISABLE_OFFSET,
TMC_PFE_SFPSB0_LED_ACTIVITY_OFFSET,
TMC_PFE_SFPSB0_PRESENT_OFFSET,
TMC_PFE_SFPSB0_LOSS_OFFSET,
TMC_PFE_SFPSB0_TX_FAULT_OFFSET,
TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE0 GREEN */
TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE1 GREEN */
TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE2 GREEN */
TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE3 GREEN */
TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE0 BEACON */
TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE1 BEACON */
TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE2 BEACON */
TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE3 BEACON */
TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE0 FAULT */
TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE1 FAULT */
TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE2 FAULT */
TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE3 FAULT */
};
static const u32 sfp_slaveb1_group_offset[TMC_PFE_SFP_GPIO_GROUP_MAX] = {
TMC_PFE_SFPSB1_TX_DISABLE_OFFSET,
TMC_PFE_SFPSB1_LED_ACTIVITY_OFFSET,
TMC_PFE_SFPSB1_PRESENT_OFFSET,
TMC_PFE_SFPSB1_LOSS_OFFSET,
TMC_PFE_SFPSB1_TX_FAULT_OFFSET,
TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE0 GREEN */
TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE1 GREEN */
TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE2 GREEN */
TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE3 GREEN */
TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE0 BEACON */
TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE1 BEACON */
TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE2 BEACON */
TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE3 BEACON */
TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE0 FAULT */
TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE1 FAULT */
TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE2 FAULT */
TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE3 FAULT */
};
struct tmc_gpio_info {
int (*get)(struct gpio_chip *, unsigned int);
void (*set)(struct gpio_chip *, unsigned int, int);
int (*dirin)(struct gpio_chip *, unsigned int);
int (*dirout)(struct gpio_chip *, unsigned int, int);
};
struct tmc_gpio_chip {
const struct tmc_gpio_info *info;
void __iomem *base;
struct device *dev;
struct gpio_chip gpio;
int ngpio;
spinlock_t gpio_lock; /* gpio lock */
int sfp_slave_block;
};
/* slave gpio max */
static int gpio_max = 320;
module_param(gpio_max, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(gpio_max, "Maximum number of gpio for SLAVE TMC GPIO");
/*
* generic bit operation functions
*/
static u32 tmc_gpio_reset_bits(u32 state, u32 val, u32 shift)
{
state &= ~(val << shift);
return state;
};
static u32 tmc_gpio_set_bits(u32 state, u32 val, u32 shift)
{
state |= (val << shift);
return state;
};
static u32 tmc_gpio_find_bits_val(u32 state, u32 shift, u32 mask)
{
return ((state >> shift)) & mask;
};
#define to_tmc_chip(chip) \
container_of((chip), struct tmc_gpio_chip, gpio)
/*
* tmc_gpio_multiple_bitsop - Generic TMC GPIO multiple bits operation
*/
static void tmc_gpio_multiple_bitsop(struct tmc_gpio_chip *chip,
unsigned int gpiono, u32 group, u32 offset, bool set)
{
u32 gpio_state, led_val, bit_shift;
unsigned long flags;
void __iomem *iobase;
iobase = chip->base + offset;
dev_dbg(chip->dev, "TMC GPIO multiple bitop group=%u, "
"gpiono=%u, offet:=%u, set=%u\n", group, gpiono, offset, set);
spin_lock_irqsave(&chip->gpio_lock, flags);
switch (group) {
case QSFP_LED_LANE0_GREEN:
case SFP_LED_LANE0_GREEN:
gpio_state = ioread32(iobase+(0x004*gpiono));
led_val = TMC_PFE_LANES_GREEN_LED_VALUE;
bit_shift = TMC_PFE_LANE0_GREEN_LED_BIT_POSITION;
break;
case QSFP_LED_LANE1_GREEN:
case SFP_LED_LANE1_GREEN:
gpio_state = ioread32(iobase+(0x004*gpiono));
led_val = TMC_PFE_LANES_GREEN_LED_VALUE;
bit_shift = TMC_PFE_LANE1_GREEN_LED_BIT_POSITION;
break;
case QSFP_LED_LANE2_GREEN:
case SFP_LED_LANE2_GREEN:
gpio_state = ioread32(iobase+(0x004*gpiono));
led_val = TMC_PFE_LANES_GREEN_LED_VALUE;
bit_shift = TMC_PFE_LANE2_GREEN_LED_BIT_POSITION;
break;
case QSFP_LED_LANE3_GREEN:
case SFP_LED_LANE3_GREEN:
gpio_state = ioread32(iobase+(0x004*gpiono));
led_val = TMC_PFE_LANES_GREEN_LED_VALUE;
bit_shift = TMC_PFE_LANE3_GREEN_LED_BIT_POSITION;
break;
case QSFP_LED_LANE0_BEACON:
case SFP_LED_LANE0_BEACON:
gpio_state = ioread32(iobase+(0x004*gpiono));
led_val = TMC_PFE_LANES_BEACON_LED_VALUE;
bit_shift = TMC_PFE_LANE0_BEACON_LED_BIT_POSITION;
break;
case QSFP_LED_LANE1_BEACON:
case SFP_LED_LANE1_BEACON:
gpio_state = ioread32(iobase+(0x004*gpiono));
led_val = TMC_PFE_LANES_BEACON_LED_VALUE;
bit_shift = TMC_PFE_LANE1_BEACON_LED_BIT_POSITION;
break;
case QSFP_LED_LANE2_BEACON:
case SFP_LED_LANE2_BEACON:
gpio_state = ioread32(iobase+(0x004*gpiono));
led_val = TMC_PFE_LANES_BEACON_LED_VALUE;
bit_shift = TMC_PFE_LANE2_BEACON_LED_BIT_POSITION;
break;
case QSFP_LED_LANE3_BEACON:
case SFP_LED_LANE3_BEACON:
gpio_state = ioread32(iobase+(0x004*gpiono));
led_val = TMC_PFE_LANES_BEACON_LED_VALUE;
bit_shift = TMC_PFE_LANE3_BEACON_LED_BIT_POSITION;
break;
case QSFP_LED_LANE0_FAULT:
case SFP_LED_LANE0_FAULT:
gpio_state = ioread32(iobase+(0x004*gpiono));
led_val = TMC_PFE_LANES_FAULT_LED_VALUE;
bit_shift = TMC_PFE_LANE0_FAULT_LED_BIT_POSITION;
break;
case QSFP_LED_LANE1_FAULT:
case SFP_LED_LANE1_FAULT:
gpio_state = ioread32(iobase+(0x004*gpiono));
led_val = TMC_PFE_LANES_FAULT_LED_VALUE;
bit_shift = TMC_PFE_LANE1_FAULT_LED_BIT_POSITION;
break;
case QSFP_LED_LANE2_FAULT:
case SFP_LED_LANE2_FAULT:
gpio_state = ioread32(iobase+(0x004*gpiono));
led_val = TMC_PFE_LANES_FAULT_LED_VALUE;
bit_shift = TMC_PFE_LANE2_FAULT_LED_BIT_POSITION;
break;
case QSFP_LED_LANE3_FAULT:
case SFP_LED_LANE3_FAULT:
gpio_state = ioread32(iobase+(0x004*gpiono));
led_val = TMC_PFE_LANES_FAULT_LED_VALUE;
bit_shift = TMC_PFE_LANE3_FAULT_LED_BIT_POSITION;
break;
default:
spin_unlock_irqrestore(&chip->gpio_lock, flags);
return;
}
if (set) {
gpio_state = tmc_gpio_reset_bits(gpio_state, 0x3, bit_shift);
gpio_state = tmc_gpio_set_bits(gpio_state, led_val, bit_shift);
} else {
gpio_state = tmc_gpio_reset_bits(gpio_state, 0x3, bit_shift);
}
iowrite32(gpio_state, (iobase+(0x004*gpiono)));
spin_unlock_irqrestore(&chip->gpio_lock, flags);
return;
};
/*
* tmc_gpio_one_bitop - Generic TMC GPIO single bit operation
*/
static void tmc_gpio_one_bitop(struct tmc_gpio_chip *chip,
unsigned int bit, u32 offset, bool set)
{
u32 gpio_state;
unsigned long flags;
void __iomem *iobase;
iobase = chip->base + offset;
dev_dbg(chip->dev, "TMC GPIO one bitop bit=%u, offset=%x, "
"set=%u\n", bit, offset, set);
spin_lock_irqsave(&chip->gpio_lock, flags);
gpio_state = ioread32(iobase);
if (set)
gpio_state |= BIT(bit);
else
gpio_state &= ~BIT(bit);
iowrite32(gpio_state, iobase);
spin_unlock_irqrestore(&chip->gpio_lock, flags);
return;
}
/*
* tmc_gpio_get_multiple_bitsop - Generic TMC get GPIO multiple bits operation
*/
static int tmc_gpio_get_multiple_bitsop(struct tmc_gpio_chip *chip,
unsigned int gpiono, u32 group, u32 offset)
{
u32 gpio_state;
void __iomem *iobase;
iobase = chip->base + offset;
dev_dbg(chip->dev, "TMC GPIO get multiple bitsop group=%u, "
"gpiono=%u, offset=%u\n", group, gpiono, offset);
switch (group) {
case QSFP_LED_LANE0_GREEN:
case SFP_LED_LANE0_GREEN:
gpio_state = ioread32(iobase+(0x004*gpiono));
return (TMC_PFE_LANES_GREEN_LED_VALUE ==
tmc_gpio_find_bits_val(gpio_state,
TMC_PFE_LANE0_GREEN_LED_BIT_POSITION, 0x3));
case QSFP_LED_LANE1_GREEN:
case SFP_LED_LANE1_GREEN:
gpio_state = ioread32(iobase+(0x004*gpiono));
return (TMC_PFE_LANES_GREEN_LED_VALUE ==
tmc_gpio_find_bits_val(gpio_state,
TMC_PFE_LANE1_GREEN_LED_BIT_POSITION, 0x3));
case QSFP_LED_LANE2_GREEN:
case SFP_LED_LANE2_GREEN:
gpio_state = ioread32(iobase+(0x004*gpiono));
return (TMC_PFE_LANES_GREEN_LED_VALUE ==
tmc_gpio_find_bits_val(gpio_state,
TMC_PFE_LANE2_GREEN_LED_BIT_POSITION, 0x3));
case QSFP_LED_LANE3_GREEN:
case SFP_LED_LANE3_GREEN:
gpio_state = ioread32(iobase+(0x004*gpiono));
return (TMC_PFE_LANES_GREEN_LED_VALUE ==
tmc_gpio_find_bits_val(gpio_state,
TMC_PFE_LANE3_GREEN_LED_BIT_POSITION, 0x3));
case QSFP_LED_LANE0_BEACON:
case SFP_LED_LANE0_BEACON:
gpio_state = ioread32(iobase+(0x004*gpiono));
return (TMC_PFE_LANES_BEACON_LED_VALUE ==
tmc_gpio_find_bits_val(gpio_state,
TMC_PFE_LANE0_BEACON_LED_BIT_POSITION, 0x3));
case QSFP_LED_LANE1_BEACON:
case SFP_LED_LANE1_BEACON:
gpio_state = ioread32(iobase+(0x004*gpiono));
return (TMC_PFE_LANES_BEACON_LED_VALUE ==
tmc_gpio_find_bits_val(gpio_state,
TMC_PFE_LANE1_BEACON_LED_BIT_POSITION, 0x3));
case QSFP_LED_LANE2_BEACON:
case SFP_LED_LANE2_BEACON:
gpio_state = ioread32(iobase+(0x004*gpiono));
return (TMC_PFE_LANES_BEACON_LED_VALUE ==
tmc_gpio_find_bits_val(gpio_state,
TMC_PFE_LANE2_BEACON_LED_BIT_POSITION, 0x3));
case QSFP_LED_LANE3_BEACON:
case SFP_LED_LANE3_BEACON:
gpio_state = ioread32(iobase+(0x004*gpiono));
return (TMC_PFE_LANES_BEACON_LED_VALUE ==
tmc_gpio_find_bits_val(gpio_state,
TMC_PFE_LANE3_BEACON_LED_BIT_POSITION, 0x3));
case QSFP_LED_LANE0_FAULT:
case SFP_LED_LANE0_FAULT:
gpio_state = ioread32(iobase+(0x004*gpiono));
return (TMC_PFE_LANES_FAULT_LED_VALUE ==
tmc_gpio_find_bits_val(gpio_state,
TMC_PFE_LANE0_FAULT_LED_BIT_POSITION, 0x3));
case QSFP_LED_LANE1_FAULT:
case SFP_LED_LANE1_FAULT:
gpio_state = ioread32(iobase+(0x004*gpiono));
return (TMC_PFE_LANES_FAULT_LED_VALUE ==
tmc_gpio_find_bits_val(gpio_state,
TMC_PFE_LANE1_FAULT_LED_BIT_POSITION, 0x3));
case QSFP_LED_LANE2_FAULT:
case SFP_LED_LANE2_FAULT:
gpio_state = ioread32(iobase+(0x004*gpiono));
return (TMC_PFE_LANES_FAULT_LED_VALUE ==
tmc_gpio_find_bits_val(gpio_state,
TMC_PFE_LANE2_FAULT_LED_BIT_POSITION, 0x3));
case QSFP_LED_LANE3_FAULT:
case SFP_LED_LANE3_FAULT:
gpio_state = ioread32(iobase+(0x004*gpiono));
return (TMC_PFE_LANES_FAULT_LED_VALUE ==
tmc_gpio_find_bits_val(gpio_state,
TMC_PFE_LANE3_FAULT_LED_BIT_POSITION, 0x3));
default:
return 0;
}
};
/*
* tmc_gpio_get - Read the specified signal of the GPIO device.
*/
static int tmc_gpio_get(struct gpio_chip *gc, unsigned int gpio)
{
struct tmc_gpio_chip *chip = to_tmc_chip(gc);
unsigned int group = TMC_GPIO_FIND_GROUP(gpio);
unsigned int bit = TMC_GPIO_FIND_GPIO(gpio);
if (group >= TMC_PFE_GPIO_GROUP_MAX)
return 0;
switch (group) {
case QSFP_RST:
case QSFP_PRESENT:
case QSFP_PHY_RST:
case QSFP_LPMOD:
dev_dbg(chip->dev, "TMC GPIO get one bitop group=%u, gpio=%u, "
"bit=%u\n", group, gpio, bit);
return !!(ioread32(chip->base + group_offset[group])
& BIT(bit));
default:
return tmc_gpio_get_multiple_bitsop(chip, bit, group, group_offset[group]);
}
}
/*
* tmc_gpio_set - Write the specified signal of the GPIO device.
*/
static void tmc_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
{
struct tmc_gpio_chip *chip = to_tmc_chip(gc);
unsigned int group = TMC_GPIO_FIND_GROUP(gpio);
unsigned int bit = TMC_GPIO_FIND_GPIO(gpio);
if (group >= TMC_PFE_GPIO_GROUP_MAX)
return;
switch (group) {
case QSFP_RST:
case QSFP_PRESENT:
case QSFP_PHY_RST:
case QSFP_LPMOD:
dev_dbg(chip->dev, "TMC GPIO one bitop group=%d\n", group);
tmc_gpio_one_bitop(chip, bit, group_offset[group], val);
break;
default:
tmc_gpio_multiple_bitsop(chip, bit, group, group_offset[group], val);
break;
}
}
static struct tmc_gpio_info tmc_gpios[] = {
{
.get = tmc_gpio_get,
.set = tmc_gpio_set,
},
};
static void tmc_gpio_setup(struct tmc_gpio_chip *sgc, int id)
{
struct gpio_chip *chip = &sgc->gpio;
const struct tmc_gpio_info *info = sgc->info;
chip->get = info->get;
chip->set = info->set;
chip->direction_input = info->dirin;
chip->direction_output = info->dirout;
chip->dbg_show = NULL;
chip->can_sleep = 0;
if (id == 0) {
chip->base = 0;
} else if (id == 1) {
chip->base = (gpio_max * id);
} else {
chip->base = -1;
}
chip->ngpio = sgc->ngpio;
chip->label = dev_name(sgc->dev);
chip->parent = sgc->dev;
chip->owner = THIS_MODULE;
}
static int tmc_gpio_of_init(struct device *dev,
struct tmc_gpio_chip *chip)
{
chip->info = &tmc_gpios[0];
chip->ngpio = gpio_max;
return 0;
}
static int tmc_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct tmc_gpio_chip *chip;
struct resource *res;
int ret;
const struct mfd_cell *cell = mfd_get_cell(pdev);
dev_dbg(dev, "TMC GPIO probe\n");
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
dev_info(dev, "TMC GPIO resource 0x%llx, %llu\n",
res->start, resource_size(res));
chip->base = devm_ioremap_nocache(dev, res->start, resource_size(res));
if (!chip->base)
return -ENOMEM;
ret = tmc_gpio_of_init(dev, chip);
if (ret)
return ret;
chip->dev = dev;
spin_lock_init(&chip->gpio_lock);
tmc_gpio_setup(chip, cell->id);
ret = gpiochip_add(&chip->gpio);
if (ret) {
dev_err(dev,
"Failed to register TMC gpiochip : %d\n", ret);
return ret;
}
platform_set_drvdata(pdev, chip);
dev_info(dev, "TMC GPIO registered at 0x%lx, gpiobase: %d\n",
(long unsigned)chip->base, chip->gpio.base);
return 0;
}
static int tmc_gpio_remove(struct platform_device *pdev)
{
struct tmc_gpio_chip *chip = platform_get_drvdata(pdev);
gpiochip_remove(&chip->gpio);
return 0;
}
static struct platform_driver tmc_gpio_driver = {
.driver = {
.name = "gpioslave-tmc",
.owner = THIS_MODULE,
},
.probe = tmc_gpio_probe,
.remove = tmc_gpio_remove,
};
module_platform_driver(tmc_gpio_driver);
MODULE_DESCRIPTION("Juniper Networks TMC FPGA GPIO driver");
MODULE_AUTHOR("Ashish Bhensdadia <bashish@juniper.net>");
MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,325 @@
/*
* A hwmon PSU monitoring driver for Juniper QFX5200 platform
*
* Copyright (C) 2020 Juniper Networks.
* Ciju Rajan K <crajank@juniper.net>
*
* Based on ym2651.c by Brandon Chuang <brandon_chuang@accton.com.tw>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#define TEMP_INT_MASK (0xFFC0)
#define V_IN_INT_MASK (0xFFE0)
#define V_OUT_INT_MASK (0xFF00)
#define INVALID_READING (0xFFFF)
#define TEMP_FR_LEN 6
#define V_IN_FR_LEN 5
#define V_OUT_FR_LEN 8
static const unsigned short normal_i2c[] = { 0x58, 0x58, I2C_CLIENT_END };
struct psu_data {
struct device *hwmon_dev;
struct mutex update_lock;
char valid; /* !=0 if registers are valid */
unsigned long last_updated; /* In jiffies */
u16 v_out;
u16 i_out;
u16 v_in;
u16 i_in;
u16 temp1_input;
u16 temp2_input;
u16 temp3_input;
u16 temp4_input;
u16 fan1_input;
u16 fan2_input;
};
static ssize_t show_word(struct device *dev, struct device_attribute *da,
char *buf);
static struct psu_data *psu_update_device(struct device *dev);
enum psu_sysfs_attributes {
PSU_V_OUT,
PSU_I_OUT,
PSU_V_IN,
PSU_I_IN,
PSU_TEMP1_INPUT,
PSU_TEMP2_INPUT,
PSU_TEMP3_INPUT,
PSU_TEMP4_INPUT,
PSU_FAN1_RPM,
PSU_FAN2_RPM,
};
/*
* sysfs attributes for hwmon
*/
static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_word, NULL, PSU_V_OUT);
static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_word, NULL, PSU_I_OUT);
static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, show_word, NULL, PSU_V_IN);
static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, show_word, NULL, PSU_I_IN);
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_word, NULL, PSU_TEMP1_INPUT);
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_word, NULL, PSU_TEMP2_INPUT);
static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_word, NULL, PSU_TEMP3_INPUT);
static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_word, NULL, PSU_TEMP4_INPUT);
static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_word, NULL, PSU_FAN1_RPM);
static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_word, NULL, PSU_FAN2_RPM);
static struct attribute *psu_attributes[] = {
&sensor_dev_attr_in3_input.dev_attr.attr,
&sensor_dev_attr_curr2_input.dev_attr.attr,
&sensor_dev_attr_psu_v_in.dev_attr.attr,
&sensor_dev_attr_psu_i_in.dev_attr.attr,
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp2_input.dev_attr.attr,
&sensor_dev_attr_temp3_input.dev_attr.attr,
&sensor_dev_attr_temp4_input.dev_attr.attr,
&sensor_dev_attr_fan1_input.dev_attr.attr,
&sensor_dev_attr_fan2_input.dev_attr.attr,
NULL
};
static short convert_to_decimal(u16 value,
u16 data_mask,
u8 fr_len)
{
return (((short)value >= 0) ? ((value & data_mask) >> fr_len) :
(-((((~(value & data_mask)) >> fr_len) + 1))));
}
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 psu_data *data = psu_update_device(dev);
u32 value = 0x0000;
switch (attr->index) {
case PSU_V_OUT:
value = 1000 * convert_to_decimal(data->v_out,
V_OUT_INT_MASK,
V_OUT_FR_LEN);
break;
case PSU_V_IN:
value = convert_to_decimal(data->v_in,
V_IN_INT_MASK,
V_IN_FR_LEN);
break;
case PSU_I_IN:
value = data->i_in;
break;
case PSU_I_OUT:
value = 1000 * data->i_out / 64;
break;
case PSU_FAN1_RPM:
value = data->fan1_input;
break;
case PSU_FAN2_RPM:
value = data->fan2_input;
break;
case PSU_TEMP1_INPUT:
value = 1000 * convert_to_decimal(data->temp1_input,
TEMP_INT_MASK,
TEMP_FR_LEN);
break;
case PSU_TEMP2_INPUT:
value = 1000 * convert_to_decimal(data->temp2_input,
TEMP_INT_MASK,
TEMP_FR_LEN);
break;
case PSU_TEMP3_INPUT:
value = 1000 * convert_to_decimal(data->temp3_input,
TEMP_INT_MASK,
TEMP_FR_LEN);
break;
case PSU_TEMP4_INPUT:
value = 1000 * convert_to_decimal(data->temp4_input,
TEMP_INT_MASK,
TEMP_FR_LEN);
break;
}
return sprintf(buf, "%d\n", (int)value);
}
static const struct attribute_group jnx_psu_group = {
.attrs = psu_attributes,
};
static int jnx_psu_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
{
struct psu_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 psu_data), GFP_KERNEL);
if (!data) {
status = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
dev_dbg(&client->dev, "chip found\n");
/* Register sysfs hooks */
status = sysfs_create_group(&client->dev.kobj, &jnx_psu_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, &jnx_psu_group);
exit_free:
kfree(data);
exit:
return status;
}
static int jnx_psu_remove(struct i2c_client *client)
{
struct psu_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &jnx_psu_group);
kfree(data);
return 0;
}
enum {
JPSU,
};
static const struct i2c_device_id psu_id[] = {
{ "jpsu", JPSU },
{}
};
MODULE_DEVICE_TABLE(i2c, psu_id);
static struct i2c_driver jnx_psu_monitor_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "jnx-psu-monitor",
},
.probe = jnx_psu_probe,
.remove = jnx_psu_remove,
.id_table = psu_id,
.address_list = normal_i2c,
};
static int psu_read_word(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_word_data(client, reg);
}
struct reg_data_word {
u8 reg;
u16 *value;
};
static struct psu_data *psu_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct psu_data *data = i2c_get_clientdata(client);
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) {
int i, status;
struct reg_data_word regs_word[] = {
{0x00, &data->temp1_input},
{0x01, &data->temp2_input},
{0x02, &data->temp3_input},
{0x03, &data->temp4_input},
{0x28, &data->v_out},
{0x32, &data->v_in},
{0x33, &data->i_out},
{0x3D, &data->i_in},
{0x20, &data->fan1_input},
{0x21, &data->fan2_input}
};
dev_dbg(dev, "Starting psu monitoring update\n");
/* Read word data */
for (i = 0; i < ARRAY_SIZE(regs_word); i++) {
status = psu_read_word(client, regs_word[i].reg);
if (status < 0)
{
dev_dbg(&client->dev, "reg %d, err %d\n",
regs_word[i].reg, status);
*(regs_word[i].value) = 0;
}
else {
u16 value = (u16)status;
(INVALID_READING != value) ? (*(regs_word[i].value) = status) :
(*(regs_word[i].value) = 0);
}
}
data->last_updated = jiffies;
data->valid = 1;
}
mutex_unlock(&data->update_lock);
return data;
}
module_i2c_driver(jnx_psu_monitor_driver);
MODULE_AUTHOR("Ciju Rajan K <crajank@juniper.net>");
MODULE_DESCRIPTION("Juniper PSU monitoring driver for QFX5200");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,116 @@
/*
* Juniper Networks Re-Fpga lpc module
*
* Copyright (C) 2020 Juniper Networks
* Author: Ciju Rajan K <crajank@juniper.net>
*
* This module implements:
* - Registering Reboot handler to reset cpu
* - Reset management port
*
* 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.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <linux/errno.h>
#define REFPGA_LPC_BASE_ADDRESS 0xFED50000
#define REFPGA_LPC_WINDOW_SIZE 0x00000400
#define REFPGA_MRE_LPCM_RST_CTL_REG (0x3)
#define REFPGA_MAJOR_VERSION (0x0)
#define REFPGA_MINOR_VERSION (0x1)
#define REFPGA_CPU_RESET BIT(0)
#define REFPGA_MGMT1_PHY_RESET BIT(1)
static void __iomem *fpga = NULL;
static int qfx5200_cpu_reset(struct notifier_block *nb,
unsigned long action,
void *data)
{
int ret = 0;
switch (action) {
case SYS_POWER_OFF:
case SYS_HALT:
printk(KERN_CRIT "System halt/power_off\n");
break;
case SYS_RESTART:
printk(KERN_CRIT "System restart: qfx5200_cpu_reset\n");
iowrite8(REFPGA_CPU_RESET, (u8 *)fpga + REFPGA_MRE_LPCM_RST_CTL_REG);
msleep(100);
break;
default:
/* Do Nothing */
break;
}
return NOTIFY_DONE;
}
static struct notifier_block qfx5200_nb = {
.notifier_call = qfx5200_cpu_reset,
};
static int __init refpga_lpcm_init(void)
{
u8 major_version = 0x00;
u8 minor_version = 0x00;
if (!request_mem_region(REFPGA_LPC_BASE_ADDRESS, REFPGA_LPC_WINDOW_SIZE, "refpga-lpc")) {
printk(KERN_ERR "Cannot allocate Re-fpga memory region\n");
return -ENODEV;
}
if ((fpga = ioremap(REFPGA_LPC_BASE_ADDRESS, REFPGA_LPC_WINDOW_SIZE)) == NULL) {
release_mem_region(REFPGA_LPC_BASE_ADDRESS, REFPGA_LPC_WINDOW_SIZE);
printk(KERN_ERR "Re-Fpga address mapping failed\n");
return -1;
}
major_version = ioread8((u8 *)fpga + REFPGA_MAJOR_VERSION);
minor_version = ioread8((u8 *)fpga + REFPGA_MINOR_VERSION);
printk(KERN_INFO "Re-Fpga major version: %x minor version: %x\n", major_version, minor_version);
/*
* Register the cpld soft reset handler
*/
if(register_reboot_notifier(&qfx5200_nb)) {
printk(KERN_ALERT "Restart handler registration failed\n");
}
iowrite8(REFPGA_MGMT1_PHY_RESET, (u8 *)fpga + REFPGA_MRE_LPCM_RST_CTL_REG);
return 0;
}
static void __exit refpga_lpcm_exit(void)
{
iounmap(fpga);
release_mem_region(REFPGA_LPC_BASE_ADDRESS, REFPGA_LPC_WINDOW_SIZE);
/*
* Unregister the cpld soft reset handler
*/
if (!unregister_restart_handler(&qfx5200_nb)) {
printk(KERN_CRIT "Failed to uregister restart handler\n");
}
printk(KERN_INFO "Re-Fpga lpcm module removed\n");
}
module_init(refpga_lpcm_init);
module_exit(refpga_lpcm_exit);
MODULE_DESCRIPTION("Juniper Networks RE-FPGA lpc module");
MODULE_AUTHOR("Ciju Rajan K <crajank@juniper.net>");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,603 @@
/*
* Juniper Networks RE-FPGA qfx platform specific driver
*
* Copyright (C) 2020 Juniper Networks
* Author: Ciju Rajan K <crajank@juniper.net>
*
* This driver implements various features such as
* - ALARM led driver
* - Fan full speed reset control
* - FAN precense detection
* - FAN type detection
* - Any new QFX specific features which uses RE-FPGA
*
* 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.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/delay.h>
#include <linux/leds.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/mutex.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/gpio.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#define NUM_LEDS 7 /* Max number of Alarm + FAN LEDs */
#define ALARM_MINOR_LED 0
#define ALARM_MAJOR_LED 1
#define REFPGA_PCIE_RESET_CTRL 0x13
#define REFPGA_PCIE_ALARM 0x33
#define REFPGA_FAN0_CTRL_STAT 0x28
#define REFPGA_RESET_FAN_SPEED BIT(3)
#define REFPGA_OPER_TYPE BIT(0)
#define REFPGA_OPER_START BIT(1)
#define REFPGA_OPER_DONE BIT(2)
#define TMC_REFPGA_ADDR_REG 0x0 /* TMC offset: 0x228 */
#define TMC_REFPGA_DATA_REG 0x4 /* TMC offset: 0x22C */
#define TMC_REFPGA_CTRL_REG 0x8 /* TMC offset: 0x230 */
#define TMC_REFPGA_READ_CMD 0x3
#define TMC_REFPGA_WRITE_CMD 0x2
#define REFPGA_INTR_NR_GROUPS 1
#define REFPGA_INTR_MAX_IRQS_PG 32
#define MAX_FANS 5
#define REFPGA_IRQ_MAX_BITS_PER_REG 32
#define POLL_INTERVAL 5000
#define AFI_MASK (0x01)
#define AFO_MASK (0x02)
#define AFI_AFO_MASK (0x03)
/*
* LED specific data structures
*/
struct refpga_led {
struct led_classdev lc;
struct work_struct work;
int blink;
int on;
int bit;
void __iomem *addr;
};
struct refpga_led_data {
int num_leds;
struct refpga_led *leds;
};
static DEFINE_MUTEX(alarm_led_lock);
/*
* Common routines
*/
struct refpga_chip {
struct refpga_led_data *led;
};
static struct refpga_chip *refpga;
static DEFINE_MUTEX(refpga_lock);
static void __iomem *tmc_membase;
static void wait_for_refpga_oper(void __iomem *base_addr)
{
volatile u32 done = ~(-1);
unsigned long int timeout;
void __iomem *addr;
addr = base_addr + (TMC_REFPGA_CTRL_REG);
/*
* Wait till the transaction is complete
*/
timeout = jiffies + msecs_to_jiffies(100);
do {
usleep_range(50, 100);
done = ioread32(addr);
if (done & (REFPGA_OPER_DONE))
break;
} while(time_before(jiffies, timeout));
}
static u32 refpga_read(void __iomem *base_addr, u32 refpga_offset)
{
u32 value;
mutex_lock(&refpga_lock);
iowrite32(refpga_offset, base_addr + (TMC_REFPGA_ADDR_REG));
iowrite32(TMC_REFPGA_READ_CMD, base_addr + (TMC_REFPGA_CTRL_REG));
wait_for_refpga_oper(base_addr);
value = ioread32(base_addr + (TMC_REFPGA_DATA_REG));
mutex_unlock(&refpga_lock);
return value;
}
static void refpga_write(void __iomem *base_addr, u32 refpga_offset, u32 val)
{
mutex_lock(&refpga_lock);
iowrite32(refpga_offset, base_addr + (TMC_REFPGA_ADDR_REG));
iowrite32(val, base_addr + (TMC_REFPGA_DATA_REG));
iowrite32(TMC_REFPGA_WRITE_CMD, base_addr + (TMC_REFPGA_CTRL_REG));
wait_for_refpga_oper(base_addr);
mutex_unlock(&refpga_lock);
}
static bool get_fan_presense(u8 idx)
{
u8 value = 0x00;
u8 offset = REFPGA_FAN0_CTRL_STAT;
bool ret = 0;
value = refpga_read(tmc_membase, (offset + (idx * 2)));
/*
* Get the last two bits of REFPGA_FANx_CTRL_STAT.
* REFPGA_FANx_CTRL_STAT register of REFPGA gives the fan airflow
* status. There are 5 fans in QFX5200. Last two bits give the AFI
* & AFO status. If any of these bits are set, fan is present.
*/
value = (value & BIT(0)) | (value & BIT(1));
if (value)
ret = 1;
return ret;
}
static int get_fan_type(u8 idx)
{
u8 value = 0x00;
u8 offset = REFPGA_FAN0_CTRL_STAT;
int ret = -1;
value = refpga_read(tmc_membase, (offset + (idx * 2)));
/*
* Get the last two bits of REFPGA_FANx_CTRL_STAT.
* REFPGA_FANx_CTRL_STAT register of REFPGA gives the fan airflow
* status. There are 5 fans in QFX5200. Last two bits give the AFI
* & AFO status. If bit1 is set, it's AFO and if bit 0 is set,
* it's AFI.
*
* This function will return '1' for AFO, '0' for AFI, and '-1'
* if there is no fan or if both AFI & AFO bits are set.
*/
value &= AFI_AFO_MASK;
switch(value) {
case AFI_MASK:
ret = 0;
break;
case AFO_MASK:
ret = 1;
break;
default:
ret = -1;
break;
};
return ret;
}
enum sysfs_fan_attributes {
FAN0_PRESENT,
FAN1_PRESENT,
FAN2_PRESENT,
FAN3_PRESENT,
FAN4_PRESENT,
};
enum sysfs_fan_type_attributes {
FAN0_TYPE,
FAN1_TYPE,
FAN2_TYPE,
FAN3_TYPE,
FAN4_TYPE,
};
/*
* The sysfs files will be present in this path
* /sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/refpga-tmc.15/fan*_present
* /sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/refpga-tmc.15/fan*_type
*/
#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, refpga_fan_presense_show, NULL, FAN##index##_PRESENT)
#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr
#define DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_type, S_IRUGO, refpga_fan_type_show, NULL, FAN##index##_TYPE)
#define DECLARE_FAN_TYPE_ATTR(index) &sensor_dev_attr_fan##index##_type.dev_attr.attr
static ssize_t refpga_fan_presense_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct sensor_device_attribute *s_attr = to_sensor_dev_attr(attr);
return sprintf(buf, "%d\n", get_fan_presense(s_attr->index));
}
static ssize_t refpga_fan_type_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct sensor_device_attribute *s_attr = to_sensor_dev_attr(attr);
return sprintf(buf, "%d\n", get_fan_type(s_attr->index));
}
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(0);
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1);
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2);
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3);
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4);
DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(0);
DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(1);
DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(2);
DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(3);
DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(4);
static struct attribute *refpga_fan_attrs[] = {
DECLARE_FAN_PRESENT_ATTR(0),
DECLARE_FAN_PRESENT_ATTR(1),
DECLARE_FAN_PRESENT_ATTR(2),
DECLARE_FAN_PRESENT_ATTR(3),
DECLARE_FAN_PRESENT_ATTR(4),
DECLARE_FAN_TYPE_ATTR(0),
DECLARE_FAN_TYPE_ATTR(1),
DECLARE_FAN_TYPE_ATTR(2),
DECLARE_FAN_TYPE_ATTR(3),
DECLARE_FAN_TYPE_ATTR(4),
NULL
};
static struct attribute_group refpga_fan_attr_group = {
.attrs = refpga_fan_attrs,
};
/*
* There is only a single ALARM led in QFX5200 and that
* is used for both Major & Minor alarm indicator.
* These are represented by two different bits in RE-FPGA
* PCIE_ALARM register. Only one of the bit (either Red or
* Yellow) should be set a time. If both the bits are set,
* it's an undefined behaviour.
*
* The following table describes how the conditions are
* handled in the driver as there can be both Major & Minor
* alarms can be triggered from userspace.
*
* Major Minor Colour
*
* 0 0 Nil
* 0 1 Yellow
* 1 1 Red
* 1 0 Red
*
*/
static void manage_alarm_led(void __iomem *addr, int led_type, int value)
{
static int alarm_major = 0, alarm_minor = 0;
u32 reg = 0x0;
mutex_lock(&alarm_led_lock);
reg = refpga_read(addr, REFPGA_PCIE_ALARM);
(led_type == ALARM_MAJOR_LED) ?
((value == 1) ? (alarm_major = 1) : (alarm_major = 0)) :
((value == 1) ? (alarm_minor = 1) : (alarm_minor = 0));
if (alarm_major) {
reg &= ~BIT(ALARM_MINOR_LED);
reg |= BIT(ALARM_MAJOR_LED);
} else {
if (alarm_minor) {
reg &= ~BIT(ALARM_MAJOR_LED);
reg |= BIT(ALARM_MINOR_LED);
} else {
reg &= ~BIT(ALARM_MINOR_LED);
reg &= ~BIT(ALARM_MAJOR_LED);
}
}
refpga_write(addr, REFPGA_PCIE_ALARM, reg);
mutex_unlock(&alarm_led_lock);
}
static void manage_fan_led(void __iomem *addr, int fan_slot, int value)
{
u8 offset = REFPGA_FAN0_CTRL_STAT + (fan_slot * 2);
u32 reg = 0x0;
reg = refpga_read(addr, offset);
if(value) {
/* Turn on s/w control */
reg = reg | BIT(4);
/* Turn off green led */
reg &= ~BIT(5);
/* Turn on yellow led & make it blink */
reg |= (BIT(6) | BIT(7));
} else {
/* Clear yellow led & stop blink */
reg &= ~(BIT(6) | BIT(7));
/* Stop s/w control */
reg &= ~BIT(4);
}
refpga_write(addr, offset, reg);
}
static void refpga_led_work(struct work_struct *work)
{
struct refpga_led *led = container_of(work, struct refpga_led, work);
void __iomem *addr;
addr = led->addr;
if(strstr(led->lc.name, "fan"))
manage_fan_led(addr, led->bit, led->on);
else
manage_alarm_led(addr, led->bit, led->on);
}
static void refpga_led_brightness_set(struct led_classdev *lc,
enum led_brightness brightness)
{
struct refpga_led *led = container_of(lc, struct refpga_led, lc);
led->on = (brightness != LED_OFF);
led->blink = 0; /* always turn off hw blink on brightness_set() */
schedule_work(&led->work);
}
struct led_table
{
const char *name;
int reg;
};
static struct led_table qfx5200_led_data[] = {
{
.name = "alarm-minor",
.reg = 0,
},
{
.name = "alarm-major",
.reg = 1,
},
{
.name = "fan0-fault",
.reg = 0,
},
{
.name = "fan1-fault",
.reg = 1,
},
{
.name = "fan2-fault",
.reg = 2,
},
{
.name = "fan3-fault",
.reg = 3,
},
{
.name = "fan4-fault",
.reg = 4,
}
};
static int refpga_led_init_one(struct device *dev,
struct refpga_led_data *ild,
int num)
{
struct refpga_led *led;
int ret = 0;
led = &ild->leds[num];
led->addr = tmc_membase;
led->lc.name = qfx5200_led_data[num].name;
led->bit = qfx5200_led_data[num].reg;
led->lc.brightness = LED_OFF;
led->lc.brightness_set = refpga_led_brightness_set;
ret = devm_led_classdev_register(dev, &led->lc);
if (ret) {
dev_err(dev, "devm_led_classdev_register failed\n");
return ret;
}
INIT_WORK(&led->work, refpga_led_work);
return 0;
}
static int refpga_led_qfx5200_init(struct device *dev, struct refpga_led_data *ild)
{
int ret = 0, idx = 0;
if (!dev->parent) {
dev_err(dev, "dev->parent is null\n");
return -ENODEV;
}
ild->num_leds = NUM_LEDS;
ild->leds = devm_kzalloc(dev, sizeof(struct refpga_led) * NUM_LEDS,
GFP_KERNEL);
if (!ild->leds) {
dev_err(dev, "LED allocation failed\n");
return -ENOMEM;
}
for(idx=0; idx<NUM_LEDS; idx++){
ret = refpga_led_init_one(dev, ild, idx);
if (ret)
return ret;
}
return 0;
}
static int jnx_refpga_led_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct refpga_led_data *ild;
int ret;
ild = devm_kzalloc(dev, sizeof(*ild), GFP_KERNEL);
if (!ild) {
dev_err(dev, "ild allocation failed\n");
return -ENOMEM;
}
ret = refpga_led_qfx5200_init(dev, ild);
if (ret < 0)
return ret;
refpga->led = ild;
return 0;
}
static int jnx_refpga_led_remove(struct platform_device *pdev)
{
struct refpga_chip *drv_data = platform_get_drvdata(pdev);
struct refpga_led_data *ild = drv_data->led;
int i;
for (i = 0; i < ild->num_leds; i++) {
devm_led_classdev_unregister(&pdev->dev, &ild->leds[i].lc);
cancel_work_sync(&ild->leds[i].work);
}
if (ild) {
if (ild->leds)
devm_kfree(&pdev->dev, ild->leds);
devm_kfree(&pdev->dev, ild);
}
return 0;
}
static void reset_fan_full_speed(struct device *dev)
{
u32 val = ~(-1), tmp = ~(-1);
/*
* Reading the REFPGA_PCIE_RESET_CTRL register
*/
val = refpga_read(tmc_membase, REFPGA_PCIE_RESET_CTRL);
/*
* Clearing the fan full_speed bit
*/
val &= ~(REFPGA_RESET_FAN_SPEED);
/*
* Writing the REFPGA_PCIE_RESET_CTRL register
*/
refpga_write(tmc_membase, REFPGA_PCIE_RESET_CTRL, val);
/*
* Reading the REFPGA_PCIE_RESET_CTRL register
*/
tmp = refpga_read(tmc_membase, REFPGA_PCIE_RESET_CTRL);
dev_info(dev, "After resetting fan full speed control: %X\n", tmp);
}
static int jnx_refpga_tmc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
int ret = 0;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "resource allocation failed\n");
return -ENODEV;
}
tmc_membase = devm_ioremap_nocache(dev, res->start, resource_size(res));
if (!tmc_membase) {
dev_err(dev, "ioremap failed\n");
return -ENOMEM;
}
refpga = devm_kzalloc(dev, sizeof(*refpga), GFP_KERNEL);
if (!refpga) {
dev_err(dev, "refpga memory allocation failed\n");
return -ENOMEM;
}
reset_fan_full_speed(dev);
ret = jnx_refpga_led_probe(pdev);
if (ret != 0) {
dev_err(dev, "Refpga LED probe failed\n");
return ret;
}
dev_info(dev, "Refpga LED probe successful: TMC memoy base: %p\n",
tmc_membase);
ret = sysfs_create_group(&dev->kobj, &refpga_fan_attr_group);
if (ret != 0) {
dev_err(dev, "sysfs_create_group failed: %d\n", ret);
return ret;
}
platform_set_drvdata(pdev, refpga);
return 0;
}
static int jnx_refpga_tmc_remove(struct platform_device *pdev)
{
jnx_refpga_led_remove(pdev);
sysfs_remove_group(&pdev->dev.kobj, &refpga_fan_attr_group);
return 0;
}
static struct platform_driver jnx_refpga_tmc_driver = {
.driver = {
.name = "refpga-tmc",
.owner = THIS_MODULE,
},
.probe = jnx_refpga_tmc_probe,
.remove = jnx_refpga_tmc_remove,
};
static int __init jnx_refpga_tmc_driver_init(void)
{
int ret = -1;
ret = platform_driver_register(&jnx_refpga_tmc_driver);
return ret;
}
static void __exit jnx_refpga_tmc_driver_exit(void)
{
platform_driver_unregister(&jnx_refpga_tmc_driver);
}
module_init(jnx_refpga_tmc_driver_init);
module_exit(jnx_refpga_tmc_driver_exit);
MODULE_DESCRIPTION("Juniper Networks REFPGA / TMC driver");
MODULE_AUTHOR("Ciju Rajan K <crajank@juniper.net>");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,477 @@
/*
* Juniper Networks TMC-FPGA MFD Core driver for qfx platform
*
* Copyright (c) 2020, Juniper Networks
* Author: Ashish Bhensdadia <bashish@juniper.net>
*
* This driver implement the resource publish for below devices
* - I2C
* - GPIO
* - RE FPGA
* - PSU
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* 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.
*/
#include <linux/device.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/irqdomain.h>
#include <linux/mfd/core.h>
#include "jnx-tmc.h"
#define TMC_DO_SCRATCH_TEST 1
/*
* TMC FPGA Device IDs
*/
#define PCI_VENDOR_ID_JUNIPER 0x1304
#define PCI_DEVICE_ID_JNX_TMC_CHD 0x007B
#define PCI_DEVICE_ID_JNX_TMC_PFE 0x007C
/*
* TMC resources
*/
static struct resource tmc_resource_i2c[] = {
/* I2C AUTOMATION Block */
{
.name = "i2c-tmc",
.start = TMC_I2C_AUTOMATION_I2C_CONTROL_START,
.end = TMC_I2C_AUTOMATION_I2C_CONTROL_END,
.flags = IORESOURCE_MEM,
},
/* I2C DPMEM */
{
.name = "i2c-tmc-mem",
.start = TMC_I2C_DPMEM_ENTRY_START,
.end = TMC_I2C_DPMEM_ENTRY_END,
.flags = IORESOURCE_MEM,
},
};
#define TMC_RES_I2C_NR ARRAY_SIZE(tmc_resource_i2c)
/*
* LED resources
*/
static struct resource tmc_resource_leds[] = {
{
.name = "leds-tmc",
.start = TMC_LED_CONTROL_START,
.end = TMC_LED_CONTROL_END,
.flags = IORESOURCE_MEM,
},
};
#define TMC_RES_LEDS_NR ARRAY_SIZE(tmc_resource_leds)
/*
* TMC RE-FPGA devices
*/
static struct resource tmc_resource_refpga[] = {
{
.name = "refpga-tmc",
.start = TMC_REFPGA_ACCESS_START,
.end = TMC_REFPGA_ACCESS_END,
.flags = IORESOURCE_MEM,
},
};
#define TMC_RES_REFPGA_NR ARRAY_SIZE(tmc_resource_refpga)
static struct resource tmc_resource_gpioslave0[] = {
/* SLAVE0 Block */
{
.name = "gpioslave-tmc",
.start = TMC_GPIO_SLAVE0_START,
.end = TMC_GPIO_SLAVE0_END,
.flags = IORESOURCE_MEM,
}
};
#define TMC_RES_GPIOSLAVE0_NR ARRAY_SIZE(tmc_resource_gpioslave0)
static struct resource tmc_resource_gpioslave1[] = {
/* SLAVE1 Block */
{
.name = "gpioslave-tmc",
.start = TMC_GPIO_SLAVE1_START,
.end = TMC_GPIO_SLAVE1_END,
.flags = IORESOURCE_MEM,
}
};
#define TMC_RES_GPIOSLAVE1_NR ARRAY_SIZE(tmc_resource_gpioslave1)
static struct resource tmc_resource_psu[] = {
/* PSU Block */
{
.name = "psu-tmc",
.start = TMC_PSU_START,
.end = TMC_PSU_END,
.flags = IORESOURCE_MEM,
}
};
#define TMC_RES_PSU_NR ARRAY_SIZE(tmc_resource_psu)
/*
* CHASSISD TMC MFD devices
*/
static struct mfd_cell chassisd_tmc_mfd_devs[] = {
{
.name = "i2c-tmc",
.num_resources = ARRAY_SIZE(tmc_resource_i2c),
.resources = &tmc_resource_i2c[0],
.of_compatible = "jnx,i2c-tmc",
.id = 0,
},
{
.name = "leds-tmc",
.num_resources = ARRAY_SIZE(tmc_resource_leds),
.resources = &tmc_resource_leds[0],
.of_compatible = "jnx,leds-tmc",
.id = 0,
},
{
.name = "refpga-tmc",
.num_resources = ARRAY_SIZE(tmc_resource_refpga),
.resources = &tmc_resource_refpga[0],
.of_compatible = "jnx,refpga-tmc",
.id = 0,
},
{
.name = "psu-tmc",
.num_resources = ARRAY_SIZE(tmc_resource_psu),
.resources = &tmc_resource_psu[0],
.of_compatible = "jnx,psu-tmc",
.id = 0,
},
};
/*
* PFE TMC MFD devices
*/
static struct mfd_cell pfe_tmc_mfd_devs[] = {
{
.name = "i2c-tmc",
.num_resources = ARRAY_SIZE(tmc_resource_i2c),
.resources = &tmc_resource_i2c[0],
.of_compatible = "jnx,i2c-tmc",
.id = 1,
},
{
.name = "gpioslave-tmc",
.num_resources = ARRAY_SIZE(tmc_resource_gpioslave0),
.resources = &tmc_resource_gpioslave0[0],
.of_compatible = "jnx,gpioslave-tmc",
.id = 0,
},
{
.name = "gpioslave-tmc",
.num_resources = ARRAY_SIZE(tmc_resource_gpioslave1),
.resources = &tmc_resource_gpioslave1[0],
.of_compatible = "jnx,gpioslave-tmc",
.id = 1,
},
};
struct tmc_fpga_data {
void __iomem *membase;
struct pci_dev *pdev;
u32 major; /* Device id & Major version*/
u32 minor; /* Minor version */
u32 optic_cpld_major; /* optic cpld major version */
u32 optic_cpld_minor; /* optic cpld minor version */
u32 optic_cpld_devid; /* optic cpld device id */
};
/* sysfs entries */
static ssize_t major_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
return sprintf(buf, "0x%02X_%06X\n",
(tmc->major >> 24) & 0xff,
tmc->major & 0xffffff);
}
static ssize_t minor_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
return sprintf(buf, "%02X\n", (tmc->minor) & 0xff);
}
static ssize_t optic_cpld_major_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
return sprintf(buf, "%01X\n", tmc->optic_cpld_major & 0xf);
}
static ssize_t optic_cpld_devid_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
return sprintf(buf, "%01X\n",
(tmc->optic_cpld_major >> 4) & 0xf);
}
static ssize_t optic_cpld_minor_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
return sprintf(buf, "%02X\n", tmc->optic_cpld_minor & 0xff);
}
static ssize_t set_sys_shutdown(struct device *dev,
struct device_attribute *devattr,
const char *buf,
size_t len)
{
struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
unsigned long val;
int ret;
ret = kstrtoul(buf, 0, &val);
if (ret < 0)
return ret;
if (val != 1)
return -EINVAL;
/* Unlock the shutdown register */
iowrite32(0x12345678, tmc->membase + TMC_SYS_SHUTDOWN_LOCK);
iowrite32(0x1, tmc->membase + TMC_SYS_SHUTDOWN);
return len;
}
static DEVICE_ATTR(major, S_IRUGO, major_show, NULL);
static DEVICE_ATTR(minor, S_IRUGO, minor_show, NULL);
static DEVICE_ATTR(optic_cpld_major, S_IRUGO, optic_cpld_major_show, NULL);
static DEVICE_ATTR(optic_cpld_devid, S_IRUGO, optic_cpld_devid_show, NULL);
static DEVICE_ATTR(optic_cpld_minor, S_IRUGO, optic_cpld_minor_show, NULL);
static DEVICE_ATTR(shutdown, S_IWUSR, NULL, set_sys_shutdown);
static struct attribute *tmc_attrs[] = {
&dev_attr_major.attr,
&dev_attr_minor.attr,
&dev_attr_optic_cpld_major.attr,
&dev_attr_optic_cpld_devid.attr,
&dev_attr_optic_cpld_minor.attr,
&dev_attr_shutdown.attr,
NULL,
};
static struct attribute_group tmc_attr_group = {
.attrs = tmc_attrs,
};
#if defined TMC_DO_SCRATCH_TEST
/* Do a quick scratch access test */
static int tmc_do_test_scratch(struct tmc_fpga_data *tmc)
{
struct pci_dev *pdev = tmc->pdev;
struct device *dev = &pdev->dev;
int offset = TMC_SCRATCH;
u32 acc, val = 0xdeadbeaf;
/*
* Check rw register access -> use the scratch reg.
*/
iowrite32(val, tmc->membase + offset);
acc = ioread32(tmc->membase + offset);
if (acc != val) {
dev_err(dev, "Tmc scratch(0x%x) failed: %08x.%08x!\n",
offset, val, acc);
return -EIO;
}
for (val = 0; val < 0xf0000000; val += 0x01010101) {
iowrite32(val, tmc->membase + offset);
acc = ioread32(tmc->membase + offset);
if (acc != val) {
dev_err(dev, "Tmc scratch(0x%x) failed: %08x.%08x!\n",
offset, val, acc);
return -EIO;
}
}
/*
* Write a sig before leaving..
*/
val = 0xcafebabe;
iowrite32(val, tmc->membase + offset);
dev_dbg(dev, "Tmc scratch result: 0x%08x\n",
ioread32(tmc->membase + offset));
return 0;
}
#endif /* TMC_DO_SCRATCH_TEST */
static int tmc_fpga_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
int err;
struct tmc_fpga_data *tmc;
struct device *dev = &pdev->dev;
dev_dbg(dev, "Tmc FPGA Probe called\n");
tmc = devm_kzalloc(dev, sizeof(*tmc), GFP_KERNEL);
if (!tmc)
return -ENOMEM;
err = pcim_enable_device(pdev);
if (err) {
dev_err(&pdev->dev, "Failed to enable device %d\n", err);
return err;
}
err = pcim_iomap_regions(pdev, 1 << 0, "tmc-core");
if (err) {
dev_err(&pdev->dev, "Failed to iomap regions %d\n", err);
goto err_disable;
}
tmc->membase = pcim_iomap_table(pdev)[0];
if (IS_ERR(tmc->membase)) {
dev_err(dev, "pci_ioremap_bar() failed\n");
err = -ENOMEM;
goto err_release;
}
tmc->pdev = pdev;
pci_set_drvdata(pdev, tmc);
/* All Tmc uses MSI interrupts - enable bus mastering */
pci_set_master(pdev);
#if defined TMC_DO_SCRATCH_TEST
/* Check IO before proceeding */
dev_dbg(dev, "Tmc FPGA starting scratch test\n");
err = tmc_do_test_scratch(tmc);
if (err)
goto err_unmap;
dev_dbg(dev, "Tmc FPGA scratch test passed !!!\n");
#endif /* TMC_DO_SCRATCH_TEST */
switch (id->device) {
case PCI_DEVICE_ID_JNX_TMC_CHD:
err = mfd_add_devices(dev, pdev->bus->number,
&chassisd_tmc_mfd_devs[0],
ARRAY_SIZE(chassisd_tmc_mfd_devs),
&pdev->resource[0],
0, NULL /* tmc->irq_domain */);
break;
case PCI_DEVICE_ID_JNX_TMC_PFE:
err = mfd_add_devices(dev, pdev->bus->number,
&pfe_tmc_mfd_devs[0],
ARRAY_SIZE(pfe_tmc_mfd_devs),
&pdev->resource[0],
0, NULL /* tmc->irq_domain */);
break;
default:
dev_err(&pdev->dev, "Invalid PCI Device ID id:%d\n",
id->device);
goto err_unmap;
}
if (err < 0) {
dev_err(&pdev->dev, "Failed to add mfd devices %d\n", err);
goto err_unmap;
}
err = sysfs_create_group(&pdev->dev.kobj, &tmc_attr_group);
if (err) {
sysfs_remove_group(&pdev->dev.kobj, &tmc_attr_group);
dev_err(&pdev->dev, "Failed to create attr group\n");
goto err_remove_mfd;
}
tmc->major = ioread32(tmc->membase + TMC_REVISION);
tmc->minor = ioread32(tmc->membase + TMC_MINOR);
tmc->optic_cpld_major = ioread32(tmc->membase + TMC_OPTIC_CPLD_MAJOR);
tmc->optic_cpld_minor = ioread32(tmc->membase + TMC_OPTIC_CPLD_MINOR);
dev_info(dev, "Tmc FPGA Revision: 0x%02X_%06X, Minor: %02X\n",
(tmc->major >> 24) & 0xff,
tmc->major & 0xffffff,
(tmc->minor) & 0xff);
dev_info(dev, "Tmc FPGA optic cpld Major: 0x%01X, Minor: 0x%02X "
"Devid: 0x%01X\n", (tmc->optic_cpld_major) & 0xf,
(tmc->optic_cpld_minor) & 0xff,
(tmc->optic_cpld_major >> 4) & 0xf);
dev_info(dev, "Tmc FPGA mem:0x%lx\n",
(unsigned long)tmc->membase);
return 0;
err_remove_mfd:
mfd_remove_devices(dev);
err_unmap:
pci_iounmap(pdev, tmc->membase);
err_release:
pci_release_regions(pdev);
err_disable:
pci_disable_device(pdev);
return err;
}
static void tmc_fpga_remove(struct pci_dev *pdev)
{
struct tmc_fpga_data *tmc = dev_get_drvdata(&pdev->dev);
sysfs_remove_group(&pdev->dev.kobj, &tmc_attr_group);
mfd_remove_devices(&pdev->dev);
}
static const struct pci_device_id tmc_fpga_id_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_TMC_CHD) },
{ PCI_DEVICE(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_TMC_PFE) },
{ }
};
MODULE_DEVICE_TABLE(pci, tmc_fpga_id_tbl);
static struct pci_driver tmc_fpga_driver = {
.name = "tmc-core",
.id_table = tmc_fpga_id_tbl,
.probe = tmc_fpga_probe,
.remove = tmc_fpga_remove,
};
module_pci_driver(tmc_fpga_driver);
MODULE_DESCRIPTION("Juniper Networks TMC FPGA MFD core driver");
MODULE_AUTHOR("Ashish Bhensdadia <bashish@juniper.net>");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,173 @@
/*
* Juniper Networks TMC fpga PSU driver
*
* This driver is for detecting if the PSU is present or not
*
* Copyright (C) 2020 Juniper Networks
* Author: Ciju Rajan K <crajank@juniper.net>
*
* 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.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/hwmon.h>
#include <linux/mutex.h>
#include <linux/kernel.h>
#include <linux/hwmon-sysfs.h>
#include <linux/errno.h>
#include <linux/string.h>
/* Max PSUs supported by this driver */
#define NUM_PSU 2
struct tmc_psu_data {
int num_psu;
void __iomem *tmc_membase;
};
enum sysfs_psu_attributes {
PSU0_PRESENT,
PSU1_PRESENT,
};
static bool get_psu_presense(void *addr, u8 idx)
{
bool ret = 0;
u32 value = ~(-1);
value = ioread32(addr);
/*
* BIT(6) is for PSU 0
* BIT(7) is for PSU 1
* idx will be either 0 (PSU0) or 1 (PSU1)
*/
value &= BIT(idx+6);
if (value)
ret = 1;
return ret;
}
/*
* Sysfs files are present in this path
* /sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/psu-tmc.15/psu*_present
*/
#define DECLARE_PSU_PRESENT_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(psu##index##_present, S_IRUGO, tmc_psu_presense_show, NULL, PSU##index##_PRESENT)
#define DECLARE_PSU_PRESENT_ATTR(index) &sensor_dev_attr_psu##index##_present.dev_attr.attr
static ssize_t tmc_psu_presense_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct sensor_device_attribute *s_attr = to_sensor_dev_attr(attr);
struct platform_device *pdev = to_platform_device(dev);
struct tmc_psu_data *psu = platform_get_drvdata(pdev);
return sprintf(buf, "%d\n", get_psu_presense(psu->tmc_membase, s_attr->index));
}
DECLARE_PSU_PRESENT_SENSOR_DEV_ATTR(0);
DECLARE_PSU_PRESENT_SENSOR_DEV_ATTR(1);
static struct attribute *tmc_psu_attrs[] = {
DECLARE_PSU_PRESENT_ATTR(0),
DECLARE_PSU_PRESENT_ATTR(1),
NULL
};
static struct attribute_group tmc_psu_attr_group = {
.attrs = tmc_psu_attrs,
};
static int tmc_psu_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct tmc_psu_data *psu;
int ret;
struct resource *res;
void __iomem *addr;
psu = devm_kzalloc(dev, sizeof(*psu), GFP_KERNEL);
if (!psu) {
dev_err(dev, "psu structure allocation failed\n");
return -ENOMEM;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "res allocation failed\n");
return -ENODEV;
}
addr = devm_ioremap_nocache(dev, res->start, resource_size(res));
if (!addr) {
dev_err(dev, "ioremap failed\n");
return -ENOMEM;
}
psu->tmc_membase = addr;
psu->num_psu = NUM_PSU;
platform_set_drvdata(pdev, psu);
ret = sysfs_create_group(&dev->kobj, &tmc_psu_attr_group);
if (ret != 0) {
dev_err(dev, "jnx-tmc-psu: sysfs_create_group failed: %d\n", ret);
return ret;
}
return 0;
}
static int tmc_psu_remove(struct platform_device *pdev)
{
struct tmc_psu_data *psu = platform_get_drvdata(pdev);
if (psu) {
devm_kfree(&pdev->dev, psu);
}
sysfs_remove_group(&pdev->dev.kobj, &tmc_psu_attr_group);
return 0;
}
static struct platform_driver jnx_tmc_psu_driver = {
.driver = {
.name = "psu-tmc",
.owner = THIS_MODULE,
},
.probe = tmc_psu_probe,
.remove = tmc_psu_remove,
};
static int __init jnx_tmc_psu_driver_init(void)
{
int ret = -1;
ret = platform_driver_register(&jnx_tmc_psu_driver);
return ret;
}
static void __exit jnx_tmc_psu_driver_exit(void)
{
platform_driver_unregister(&jnx_tmc_psu_driver);
}
module_init(jnx_tmc_psu_driver_init);
module_exit(jnx_tmc_psu_driver_exit);
MODULE_DESCRIPTION("Juniper Networks TMC PSU driver");
MODULE_AUTHOR("Ciju Rajan K <crajank@juniper.net>");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,93 @@
/*
* Juniper Tmc FPGA register definitions
*
* Copyright (C) 2018 Juniper Networks
* Author: Ashish Bhensdadia <bashish@juniper.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __JNX_TMC_H__
#define __JNX_TMC_H__
#define TMC_REVISION 0x00064
#define TMC_MINOR 0x00068
#define TMC_SCRATCH 0x00098
#define TMC_OPTIC_CPLD_MAJOR 0x00104
#define TMC_OPTIC_CPLD_MINOR 0x00108
/*
* I2C Master Block
*/
#define TMC_I2C_AUTOMATION_I2C_CONTROL_START 0x07000
#define TMC_I2C_AUTOMATION_I2C_CONTROL_END 0x07500
#define TMC_I2C_DPMEM_ENTRY_START 0x10000
#define TMC_I2C_DPMEM_ENTRY_END 0x13FFC
#define TMC_LED_CONTROL_START 0x58
#define TMC_LED_CONTROL_END 0x5B
/*
* RE-FPGA block
*/
#define TMC_REFPGA_ACCESS_START 0x228
#define TMC_REFPGA_ACCESS_END 0x233
#define TMC_I2C_MASTER_NR_MSTRS 16
#define TMC_I2C_MSTR_MAX_GROUPS 66
/*
* TMC GPIO SLAVE Block
*/
#define TMC_GPIO_PTP_RESET_START 0x94
#define TMC_GPIO_PTP_RESET_END 0x97
#define TMC_GPIO_PTP_CFG_START 0xa4
#define TMC_GPIO_PTP_CFG_END 0xa7
#define TMC_GPIO_PTP_DATA_START 0xa8
#define TMC_GPIO_PTP_DATA_END 0xab
#define TMC_GPIO_SLAVE0_START 0xf0
#define TMC_GPIO_SLAVE0_END 0x16b
#define TMC_GPIO_SLAVE1_START 0x170
#define TMC_GPIO_SLAVE1_END 0x1eb
#define TMC_GPIO_SLAVE2_START 0x1f0
#define TMC_GPIO_SLAVE2_END 0x213
#define TMC_GPIO_SLAVE3_START 0x280
#define TMC_GPIO_SLAVE3_END 0x2eb
#define TMC_GPIO_SFP_SLAVE0_START 0x308
#define TMC_GPIO_SFP_SLAVE0_END 0x32b
#define TMC_GPIO_SFP_SLAVE1_START 0x32c
#define TMC_GPIO_SFP_SLAVE1_END 0x34b
/*
* TMC PSU Block
*/
#define TMC_PSU_START 0x240
#define TMC_PSU_END 0x243
/*
* TMC SHUTDOWN REG
*/
#define TMC_SYS_SHUTDOWN_LOCK 0x254
#define TMC_SYS_SHUTDOWN 0x250
/*
* TMC DS100 MUX Block
*/
#define TMC_GPIO_MUX_SLAVE_START 0x26c
#define TMC_GPIO_MUX_SLAVE_END 0x26f
#endif /* __JNX_TMC_H__ */

View File

@ -0,0 +1,223 @@
/*
* Juniper Networks TMC fpga LEDs driver
*
* Copyright (C) 2018 Juniper Networks
* Author: Ciju Rajan K <crajank@juniper.net>
*
* This driver is based on I2CS fpga LEDs driver by Georgi Vlaev
*
* 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.
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/leds.h>
#include <linux/platform_device.h>
#include <linux/io.h>
/* Max LEDs supported by this driver (2bits of control per LED in 32bit reg) */
#define NUM_LEDS 3
struct tmc_led {
struct led_classdev lc;
struct work_struct work;
int on;
int bit;
void __iomem *addr;
};
struct tmc_led_data {
int num_leds;
struct tmc_led *leds;
};
struct led_table
{
const char *name;
int reg;
};
static struct led_table qfx5200_tmc_led_data[] = {
{
.name = "system",
.reg = 0,
},
{
.name = "beacon",
.reg = 3,
},
{
.name = "master",
.reg = 5,
}
};
static void jnx_tmc_leds_work(struct work_struct *work)
{
struct tmc_led *led = container_of(work, struct tmc_led, work);
u32 value = ~(-1);
value = ioread32(led->addr);
if (led->on) {
if (!strncmp(led->lc.name, "beacon", 6)) {
value &= ~BIT(led->bit + 1);
value |= BIT(led->bit);
} else {
value |= BIT(led->bit) | BIT(led->bit + 1);
}
} else {
value &= ~(BIT(led->bit) | BIT(led->bit + 1));
}
iowrite32(value, led->addr);
}
static void jnx_tmc_leds_brightness_set(struct led_classdev *lc,
enum led_brightness brightness)
{
struct tmc_led *led = container_of(lc, struct tmc_led, lc);
led->on = (brightness != LED_OFF);
schedule_work(&led->work);
}
static int jnx_tmc_leds_init_one(struct device *dev,
struct tmc_led_data *ild,
int num, void __iomem *addr)
{
struct tmc_led *led;
int ret;
led = &ild->leds[num];
led->addr = addr;
led->lc.name = qfx5200_tmc_led_data[num].name;
led->bit = qfx5200_tmc_led_data[num].reg;
led->lc.brightness_set = jnx_tmc_leds_brightness_set;
ret = devm_led_classdev_register(dev, &led->lc);
if (ret)
return ret;
INIT_WORK(&led->work, jnx_tmc_leds_work);
return 0;
}
static int jnx_tmc_leds_init(struct device *dev, struct tmc_led_data *ild,
struct resource *res)
{
int ret, idx = 0;
void __iomem *addr;
if (!dev->parent) {
dev_err(dev, "dev->parent is null\n");
return -ENODEV;
}
addr = devm_ioremap_nocache(dev, res->start, resource_size(res));
if (!addr) {
dev_err(dev, "ioremap failed\n");
return -ENOMEM;
}
ild->num_leds = NUM_LEDS;
ild->leds = devm_kzalloc(dev, sizeof(struct tmc_led) * NUM_LEDS,
GFP_KERNEL);
if (!ild->leds) {
dev_err(dev, "LED allocation failed\n");
return -ENOMEM;
}
for (idx=0; idx<NUM_LEDS; idx++) {
ret = jnx_tmc_leds_init_one(dev, ild, idx, addr);
if (ret)
return ret;
}
return 0;
}
static int tmc_leds_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct tmc_led_data *ild;
int ret;
struct resource *res;
ild = devm_kzalloc(dev, sizeof(*ild), GFP_KERNEL);
if (!ild) {
dev_err(dev, "ild allocation failed\n");
return -ENOMEM;
}
platform_set_drvdata(pdev, ild);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "res allocation failed\n");
return -ENODEV;
}
ret = jnx_tmc_leds_init(dev, ild, res);
if (ret < 0)
return ret;
return 0;
}
static int tmc_leds_remove(struct platform_device *pdev)
{
struct tmc_led_data *ild = platform_get_drvdata(pdev);
int i;
for (i = 0; i < ild->num_leds; i++) {
devm_led_classdev_unregister(&pdev->dev, &ild->leds[i].lc);
cancel_work_sync(&ild->leds[i].work);
}
if (ild) {
if (ild->leds)
devm_kfree(&pdev->dev, ild->leds);
devm_kfree(&pdev->dev, ild);
}
return 0;
}
static struct platform_driver jnx_tmc_leds_driver = {
.driver = {
.name = "leds-tmc",
.owner = THIS_MODULE,
},
.probe = tmc_leds_probe,
.remove = tmc_leds_remove,
};
static int __init jnx_tmc_leds_driver_init(void)
{
int ret = -1;
ret = platform_driver_register(&jnx_tmc_leds_driver);
return ret;
}
static void __exit jnx_tmc_leds_driver_exit(void)
{
platform_driver_unregister(&jnx_tmc_leds_driver);
}
module_init(jnx_tmc_leds_driver_init);
module_exit(jnx_tmc_leds_driver_exit);
MODULE_DESCRIPTION("Juniper Networks TMC leds driver");
MODULE_AUTHOR("Ciju Rajan K <crajank@juniper.net>");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,144 @@
/*
* Juniper PCI ID(s) - for devices on Juniper Boards
*
* Rajat Jain <rajatjain@juniper.net>
* Copyright 2014 Juniper Networks
*
* 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.
*/
#ifndef __JNX_PCI_IDS_H__
#define __JNX_PCI_IDS_H__
#define PCI_VENDOR_ID_JUNIPER 0x1304
#define PCI_VENDOR_ID_ERICSSON 0x1519
#define PCI_VENDOR_ID_ERICSSON_AS 0x1a25
/*
* PTX SAM FPGA, device ID as present on various Juniper boards, such as
* - Sangria FPC
* - Hendricks FPC
* - Sangria 24x10GE PIC
* - Gladiator FPC
*/
#define PCI_DEVICE_ID_JNX_SAM 0x0004
/* Juniper Broadway ASIC family */
#define PCI_DEVICE_ID_JNX_TF 0x003c
#define PCI_DEVICE_ID_JNX_TL 0x003d
#define PCI_DEVICE_ID_JNX_TQ 0x003e
#define PCI_DEVICE_ID_JNX_OTN_FRAMER 0x0055
#define PCI_DEVICE_ID_JNX_PE 0x005e
#define PCI_DEVICE_ID_JNX_PF 0x005f /* Juniper Paradise ASIC */
#define PCI_DEVICE_ID_JNX_ZF 0x008d /* Juniper ZF Fabric ASIC */
#define PCI_DEVICE_ID_JNX_ZX 0x008e /* Juniper ZX ASIC */
#define PCI_DEVICE_ID_JNX_ZT 0x0090 /* Juniper ZT ASIC */
#define PCI_DEVICE_ID_JNX_BT 0x00B2 /* Juniper BT ASIC */
/* Juniper SAM FPGA - Omega SIB, Sochu SHAM, Gladiator SIB */
#define PCI_DEVICE_ID_JNX_SAM_OMEGA 0x006a
/* Juniper SAM FPGA - present on GLD FPC board */
#define PCI_DEVICE_ID_JNX_SAM_X 0x006b
/* Juniper PAM FPGA - present on PTX MLC board */
#define PCI_DEVICE_ID_JNX_PAM 0x006c
/* Juniper CBC FPGA - present on PTX1K RCB */
#define PCI_DEVICE_ID_JNX_CBC 0x006e
#define PCI_DEVICE_ID_JNX_CBC_P2 0x0079
#define PCI_DEVICE_ID_JNX_OMG_CBC 0x0083
/* Juniper Summit FPGA */
#define PCI_DEVICE_ID_JNX_SUMMIT 0x009B
/* Juniper DOON FPGA */
#define PCI_DEVICE_ID_JNX_DOON_RCB_CBC 0x0098
/* Juniper CBC FPGA in PTX-5K MTRCB */
#define PCI_DEVICE_ID_JNX_PTX5K_MTRCB_CBC 0x0071
/* Other Vendors' devices */
#define PCI_DEVICE_ID_IDT_PES12NT3_TRANS_AB 0x8058
#define PCI_DEVICE_ID_IDT_PES12NT3_TRANS_C 0x8059
#define PCI_DEVICE_ID_IDT_PES12NT3_INT_NTB_C 0x805a
#define PCI_DEVICE_ID_IDT_48H12G2 0x807a
#define PCI_DEVICE_ID_IDT_PES24NT24G2 0x808e
#define PCI_DEVICE_ID_IDT_PES16NT16G2 0x8090
#define PCI_DEVICE_ID_PLX_8614 0x8614
#define PCI_DEVICE_ID_PLX_8618 0x8618
#define PCI_DEVICE_ID_PLX_8713 0x8713
#define PCI_DEVICE_ID_PLX_8725 0x8725
#define PCI_DEVICE_ID_PLX_8749 0x8749
#define PCI_DEVICE_ID_PLX_8796 0x8796
#define PCI_DEVICE_ID_PLX_8608 0x8608
/*
* Juniper CBD FPGA Device ID(s)
*/
#define JNX_CBD_FPGA_DID_09B3 0x004D
#define JNX_CBD_FPGA_DID_0BA8 0x005A
/*
* Juniper Brackla FPGA Device IDs
* - UBAM, MBAM, PBAM, QBAM
*/
#define PCI_DEVICE_ID_JNX_UBAM 0x00A7
#define PCI_DEVICE_ID_JNX_PBAM 0x00A8
#define PCI_DEVICE_ID_JNX_MBAM 0x00A9
#define PCI_DEVICE_ID_JNX_QBAM 0x00AA
/*
* Juniper MPC11E Supercon and WAN FPGA IDs
*/
#define PCI_DEVICE_ID_JNX_MPC11CON 0x00A1
#define PCI_DEVICE_ID_JNX_MPC11WAN 0x00C4
/*
* Juniper Attella TMC and Supercon FPGA IDs
*/
#define PCI_DEVICE_ID_JNX_ARGUS 0x00B0
#define PCI_DEVICE_ID_JNX_ATIC 0x00C0
#define PCI_DEVICE_ID_JNX_ATMC_CHD 0x00C1
#define PCI_DEVICE_ID_JNX_ATMC_PFE 0x00C2
#define PCI_DEVICE_ID_JNX_AOHIO 0x00C3
/*
* Juniper TMC FPGA Device IDs
*/
#define PCI_DEVICE_ID_JNX_TMC_CHD 0x007B
#define PCI_DEVICE_ID_JNX_TMC_PFE 0x007C
#define PCI_DEVICE_ID_XILINX_1588_FPGA 0x0505
/*
* Juniper Scapa SIB/LC Supercon FPGA IDs
*/
#define PCI_DEVICE_ID_JNX_SCAPA_SIB_CTRL 0x00BA
#define PCI_DEVICE_ID_JNX_SDLC_CTRL 0x00BE
#define PCI_DEVICE_ID_JNX_LLC_CTRL 0x00C8
/*
* Deanston WANIO FPGA
*/
#define PCI_DEVICE_ID_JNX_DEANSTON_WAN 0x00C6
/*
* Juniper Ardbeg Supercon FPGA IDs
*/
#define PCI_DEVICE_ID_JNX_ARDBEG_CTRL 0x00C5
/*
* Ericsson CCM FPGA ID used in Bolan (ACX753)
*/
#define PCI_DEVICE_ID_ERIC_CCM_FPGA 0x0020
/*
* Ericsson OAM FPGA ID used in Bolan (ACX753)
*/
#define PCI_DEVICE_ID_ERIC_OAM_FPGA 0x7021
#endif /* __JNX_PCI_IDS_H__ */

View File

@ -0,0 +1,15 @@
[Unit]
Description=Juniper QFX5200 initialization service
Before=pmon.service
After=sysinit.target
DefaultDependencies=no
[Service]
ExecStartPre=/usr/local/bin/juniper_qfx5200_util.py install
ExecStart=/usr/local/bin/juniper_qfx5200_monitor.py
RemainAfterExit=yes
StandardOutput=syslog+console
StandardError=syslog+console
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,15 @@
#!/usr/bin/env python
import os
from setuptools import setup
os.listdir
setup(
name='sonic_platform',
version='1.0',
description='Module to initialize Juniper QFX5200-32C-S platforms',
packages=['sonic_platform'],
package_dir={'sonic_platform': 'qfx5200/sonic_platform'},
)

View File

@ -0,0 +1 @@
import platform

View File

@ -0,0 +1,260 @@
#!/usr/bin/env python
#
# Name: chassis.py, version: 1.0
#
# Description: Module contains the definitions of SONiC platform APIs
# which provide the chassis specific details
#
# Copyright (c) 2020, Juniper Networks, Inc.
# All rights reserved.
#
# Notice and Disclaimer: This code is licensed to you under the GNU General
# Public License as published by the Free Software Foundation, version 3 or
# any later version. This code is not an official Juniper product. You can
# obtain a copy of the License at <https://www.gnu.org/licenses/>
#
# OSS License:
#
# 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 <https://www.gnu.org/licenses/>.
#
# Third-Party Code: This code may depend on other components under separate
# copyright notice and license terms. Your use of the source code for those
# components is subject to the terms and conditions of the respective license
# as noted in the Third-Party source code file.
#
try:
import commands
import time
from sonic_platform_base.chassis_base import ChassisBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class Chassis(ChassisBase):
"""
JUNIPER QFX5200 Platform-specific Chassis class
"""
def __init__(self):
ChassisBase.__init__(self)
def get_qfx5200_parameter_value(self,parameter_name):
try:
with open("/var/run/eeprom", "r") as file:
for item in file:
content = item.split('=')
if content[0] == parameter_name:
return content[1:]
return "False"
except IOError:
print "Error: File not found"
return "False"
def get_product_name(self):
product_name_list = self.get_qfx5200_parameter_value('Product Name')
if product_name_list:
product_name = ''.join(product_name_list)
return product_name
else:
return False
def get_part_number(self):
part_number_list = self.get_qfx5200_parameter_value('Part Number')
if part_number_list:
part_number = ''.join(part_number_list)
return part_number
else:
return False
def get_serial_number(self):
serial_number_list = self.get_qfx5200_parameter_value('Serial Number')
if serial_number_list:
serial_number = ''.join(serial_number_list)
return serial_number
else:
return False
def get_base_mac(self):
mac_list = self.get_qfx5200_parameter_value('MAC Address')
if mac_list:
mac = ''.join(mac_list)
return mac
else:
return False
def get_mfg_date(self):
mfgdate_list = self.get_qfx5200_parameter_value('Manufacture Date')
if mfgdate_list:
mfgdate = ''.join(mfgdate_list)
return mfgdate
else:
return False
def get_platform_name(self):
platform_name_list = self.get_qfx5200_parameter_value('Platform Name')
if platform_name_list:
platform_name = ''.join(platform_name_list)
return platform_name
else:
return False
def get_MACnumber_name(self):
MACnumber_name_list = self.get_qfx5200_parameter_value('Number of MAC Addresses')
if MACnumber_name_list:
MACnumber_name = ''.join(MACnumber_name_list)
return MACnumber_name
else:
return False
def get_vendor_name(self):
vendor_name_list = self.get_qfx5200_parameter_value('Vendor Name')
if vendor_name_list:
vendor_name = ''.join(vendor_name_list)
return vendor_name
else:
return False
def get_mfg_name(self):
mfg_name_list = self.get_qfx5200_parameter_value('Manufacture Name')
if mfg_name_list:
mfg_name = ''.join(mfg_name_list)
return mfg_name
else:
return False
def get_vendorext_name(self):
vendorext_list = self.get_qfx5200_parameter_value('Vendor Extension')
if vendorext_list:
vendorext = ''.join(vendorext_list)
return vendorext
else:
return False
def get_vendorextIANA_name(self):
vendorext_list = self.get_qfx5200_parameter_value('IANA')
if vendorext_list:
vendorext = ''.join(vendorext_list)
return vendorext
else:
return False
def get_vendorextASMREV_name(self):
vendorext_list = self.get_qfx5200_parameter_value('Assembly Part Number Revision')
if vendorext_list:
vendorext = ''.join(vendorext_list)
return vendorext
else:
return False
def get_vendorextASMPartNum_name(self):
vendorext_list = self.get_qfx5200_parameter_value('Assembly Part Number')
if vendorext_list:
vendorext = ''.join(vendorext_list)
return vendorext
else:
return False
def get_vendorextASMID_name(self):
vendorext_list = self.get_qfx5200_parameter_value('Assembly ID')
if vendorext_list:
vendorext = ''.join(vendorext_list)
return vendorext
else:
return False
def get_vendorextASMMajNum_name(self):
vendorext_list = self.get_qfx5200_parameter_value('Assembly Major Revision')
if vendorext_list:
vendorext = ''.join(vendorext_list)
return vendorext
else:
return False
def get_vendorextASMMinNum_name(self):
vendorext_list = self.get_qfx5200_parameter_value('Assembly Minor Revision')
if vendorext_list:
vendorext = ''.join(vendorext_list)
return vendorext
else:
return False
def get_vendorextCLEI_name(self):
vendorext_list = self.get_qfx5200_parameter_value('CLEI code')
if vendorext_list:
vendorext = ''.join(vendorext_list)
return vendorext
else:
return False
def get_onieversion_name(self):
onieversion_name_list = self.get_qfx5200_parameter_value('ONIE Version')
if onieversion_name_list:
onieversion_name = ''.join(onieversion_name_list)
return onieversion_name
else:
return False
def get_crc_name(self):
crc_list = self.get_qfx5200_parameter_value('CRC')
if crc_list:
crc_name = ''.join(crc_list)
return crc_name
else:
return False
def get_fan_type(self):
fantype_list = self.get_qfx5200_parameter_value('Fan Type')
if fantype_list:
fantype_name = ''.join(fantype_list)
return fantype_name
else:
return False
def get_reboot_cause(self):
"""
Retrieves the cause of the previous reboot
"""
status, last_reboot_reason = commands.getstatusoutput("busybox devmem 0xFED50004 8")
if (status == 0):
if last_reboot_reason == "0x80":
return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)
elif last_reboot_reason == "0x40" or last_reboot_reason == "0x08":
return (ChassisBase.REBOOT_CAUSE_WATCHDOG, None)
elif last_reboot_reason == "0x20":
return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None)
elif last_reboot_reason == "0x10":
return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Swizzle Reset")
else:
return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Unknown reason")
else:
time.sleep(3)
status, last_reboot_reason = commands.getstatusoutput("busybox devmem 0xFED50004 8")
if last_reboot_reason == "0x80":
return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)
elif last_reboot_reason == "0x40" or last_reboot_reason == "0x08":
return (ChassisBase.REBOOT_CAUSE_WATCHDOG, None)
elif last_reboot_reason == "0x20":
return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None)
elif last_reboot_reason == "0x10":
return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Swizzle Reset")
else:
return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Unknown reason")

View File

@ -0,0 +1,65 @@
#!/usr/bin/env python
#
# Name: platform.py, version: 1.0
#
# Description: Module contains the definitions of SONiC platform APIs
# which provide the platform specific details
#
# Copyright (c) 2020, Juniper Networks, Inc.
# All rights reserved.
#
# Notice and Disclaimer: This code is licensed to you under the GNU General
# Public License as published by the Free Software Foundation, version 3 or
# any later version. This code is not an official Juniper product. You can
# obtain a copy of the License at <https://www.gnu.org/licenses/>
#
# OSS License:
#
# 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 <https://www.gnu.org/licenses/>.
#
# Third-Party Code: This code may depend on other components under separate
# copyright notice and license terms. Your use of the source code for those
# components is subject to the terms and conditions of the respective license
# as noted in the Third-Party source code file.
#
try:
from sonic_platform_base.platform_base import PlatformBase
except ImportError as e:
raise ImportError("%s - required module not found" % e)
platformDict = {'platform':'QFX5200-32C'}
class Platform(PlatformBase):
def __init__(self):
self.platform = self.getPlatform()
def getPlatformDict(self):
global platformDict
if platformDict:
return platformDict
def readPlatformName(self):
return self.getPlatformDict().get('platform')
def getPlatform(self):
platformCls = self.readPlatformName()
return platformCls
def get_chassis(self):
from chassis import Chassis
chassis = Chassis()
return chassis

View File

@ -0,0 +1,117 @@
Copyright (c) 2019, Juniper Networks, Inc.
All rights reserved.
Front panel LEDs
================
There are 4 system LEDs in the front panel. Master, System, Alarm, & Beacon.
LED controls can be found under /sys/class/leds. The sysfs interface &
colour mappings are as follows:
For master LED: /sys/class/leds/master/brightness
0 => off
1 => green
For system LED: /sys/class/leds/system/brightness
0 => off
1 => green
For alarm LED: /sys/class/leds/alarm/brightness
0 => off
1 => amber
2 => red
For beacon LED: /sys/class/leds/beacon/brightness
0 => off
1 => blue
For any of the above LEDs, max_brightness file can tell the maximum value
accepted.
System FANs
===========
There are 4 fans and each of the fan has 2 fan modules. Overall there are
8 fans in the system.
Fan controls can be found in /sys/bus/i2c/devices/17-0068. All the fans
are controlled by one duty cycle value, ranges from 0 to 100
Fan duty cycle can be controlled through /sys/bus/i2c/devices/17-0068/pwm1
Fan module presence is given by /sys/bus/i2c/devices/17-0068/fan[1-4]_present
file. A value of '1' indicate that fan is present & a value of '0' otherwise.
Fan rotation direction is given by /sys/bus/i2c/devices/17-0068/fan[1-4]_direction.
A value of '0' indicate the direction is AFO (Front to back airflow) or Airflow
out. A value of '1' indicate that direction is AFI (Back to front airflow) or
Airflow in.
Fan speed is given by fan[1-4]_input
Temperature sensors
===================
There are 6 temperature sensors. The readings are available in
/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input
System PSUs
===========
There are two independent PSUs. These are controlled by a dedicated CPLD.
The status registers are mapped under /sys/bus/i2c/devices/9-0050 and
/sys/bus/i2c/devices/10-0053.
SFPs
====
There are 64 QSFP+ modules supported in qfx5210 platform. EEPORMs will be
mapped under /sys/bus/i2c/devices/[25-88]-0050/ sysfs directory.
FEC should be turned on for 100G SR optics and should be turned off for
100G LR optics. If the optic is changed, please update the entry and
reload the configuration. If the FEC mode is not set as per the optic
type the port may not link up or work properly.
As an example, see this configuration for FEC for 100G SR4 optics in
/etc/sonic/config_db.json
"Ethernet4": {
"admin_status": "up",
"alias": "Ethernet4",
"fec": "rs",
"index": "1",
"lanes": "65,66,67,68",
"mtu": "9100",
"speed": "100000"
}
Sensor details
==============
LM75 supported sensor modules will be available under 'sensors' command.
If you want to get all the sensor data including the SFPs & LEDs, you can
invoke 'sudo juniper_qfx5210_util.py show'
Platform poweroff
=================
Linux poweroff commands such as 'poweroff', 'shutdown', 'halt', etc. will not
power off qfx5210 platform as there are custom CPLDs control the power off
sequences. So acpi poweroff hooks are added for powering off the qfx5210. The
following messages are displayed in the console towards end of poweroff
sequence:
[ 52.500807] System halt/power_off
[ 52.866331] reboot: Power down
[ 52.903257] pm_power_off: qfx5210_cpld_power_off
Once the above messages are seen, you can safely remove the power to the system.
Similarly platform reboot sequences are in place for system reboot. The following
messages are displayed in the console when the system is rebooted:
[ 6053.163363] System restart: qfx5210_cpld_soft_reset
Platform monitoring daemon
==========================
“juniper_qfx5210_monitor.py” is the platform monitoring script.
It implements the qfx5210 EM policy. This script will run as system service
and monitor the temperature sensors in every 20 seconds. Based on the EM
policy thresholds, it controls the fan rpm, manage alarm leds, and
shutdown the box.

View File

@ -0,0 +1,929 @@
#!/usr/bin/env python
#
# Name: juniper_qfx5200_monitor.py version: 1.0
#
# Description: This file contains the EM implementation for QFX5200 platform
#
# Copyright (c) 2020, Juniper Networks, Inc.
# All rights reserved.
#
# Notice and Disclaimer: This code is licensed to you under the GNU General
# Public License as published by the Free Software Foundation, version 3 or
# any later version. This code is not an official Juniper product. You can
# obtain a copy of the License at <https://www.gnu.org/licenses/>
#
# OSS License:
#
# 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 <https://www.gnu.org/licenses/>.
#
# Third-Party Code: This code may depend on other components under separate
# copyright notice and license terms. Your use of the source code for those
# components is subject to the terms and conditions of the respective license
# as noted in the Third-Party source code file.
try:
import os
import commands
import subprocess
import logging
import logging.config
import logging.handlers
import time
import glob
import re
except ImportError as e:
raise ImportError('%s - required module not found' % str(e))
# Deafults
VERSION = '1.0'
FUNCTION_NAME = '/var/log/juniper_qfx5200_monitor'
verbose = False
DEBUG = False
log_file = '%s.log' % FUNCTION_NAME
log_level = logging.DEBUG
isPlatformAFI = False
isFireThresholdReached = False
is35PerFlag = True
is55PerFlag = True
is75PerFlag = True
is90PerFlag = True
isFireThresholdPrint = True
FireThresholdSecsRemaining = 120
PrevASICValue = 0
temp_policy_AFI = {
0: [[35, 0, 30000], [35, 30000, 39000], [55, 39000, 0], [55, 39000, 48000], [75, 48000, 0], [75, 48000, 56000], [90, 56000, 0], [90, 56000, 65000],[100, 66000, 0],
['Yellow Alarm', 64000, 70000], ['Red Alarm', 70000, 73000], ['Fire Shut Alarm', 73000, 0]],
1: [[35, 0, 30000], [35, 30000, 39000], [55, 39000, 0], [55, 39000, 48000], [75, 48000, 0], [75, 48000, 56000], [90, 56000, 0], [90, 56000, 65000],[100, 66000, 0],
['Yellow Alarm', 64000, 70000], ['Red Alarm', 70000, 73000], ['Fire Shut Alarm', 73000, 0]],
2: [[35, 0, 40000], [35, 40000, 47000], [55, 47000, 0], [55, 47000, 55000], [75, 55000, 0], [75, 55000, 63000], [90, 62000, 0], [90, 62000, 69000],[100, 70000, 0],
['Yellow Alarm', 68000, 74000], ['Red Alarm', 74000, 77000], ['Fire Shut Alarm', 77000, 0]],
3: [[35, 0, 36000], [35, 36000, 44000], [55, 44000, 0], [55, 44000, 52000], [75, 52000, 0], [75, 52000, 60000], [90, 60000, 0], [90, 60000, 68000],[100, 69000, 0],
['Yellow Alarm', 67000, 73000], ['Red Alarm', 73000, 76000], ['Fire Shut Alarm', 76000, 0]],
4: [[35, 0, 52000], [35, 52000, 57000], [55, 57000, 0], [55, 57000, 63000], [75, 63000, 0], [75, 63000, 68000], [90, 68000, 0], [90, 68000, 73000],[100, 74000, 0],
['Yellow Alarm', 72000, 78000], ['Red Alarm', 78000, 81000], ['Fire Shut Alarm', 81000, 0]],
5: [[35, 0, 37000], [35, 37000, 45000], [55, 45000, 0], [55, 45000, 53000], [75, 53000, 0], [75, 53000, 61000], [90, 61000, 0], [90, 61000, 69000],[100, 70000, 0],
['Yellow Alarm', 68000, 74000], ['Red Alarm', 74000, 77000], ['Fire Shut Alarm', 77000, 0]],
6: [[35, 0, 37000], [35, 37000, 45000], [55, 45000, 0], [55, 45000, 53000], [75, 53000, 0], [75, 53000, 61000], [90, 61000, 0], [90, 61000, 69000],[100, 69000, 0],
['Yellow Alarm', 67000, 73000], ['Red Alarm', 73000, 76000], ['Fire Shut Alarm', 76000, 0]],
7: [[35, 0, 52000], [35, 52000, 57000], [55, 57000, 0], [55, 57000, 63000], [75, 63000, 0], [75, 63000, 68000], [90, 68000, 0], [90, 68000, 73000],[100, 74000, 0],
['Yellow Alarm', 72000, 78000], ['Red Alarm', 78000, 81000], ['Fire Shut Alarm', 81000, 0]],
8: [[35, 0, 41000], [35, 41000, 48000], [55, 48000, 0], [55, 48000, 55000], [75, 55000, 0], [75, 55000, 62000], [90, 62000, 0], [90, 62000, 69000],[100, 70000, 0],
['Yellow Alarm', 68000, 74000], ['Red Alarm', 74000, 77000], ['Fire Shut Alarm', 77000, 0]],
9: [[35, 0, 42000], [35, 42000, 49000], [55, 49000, 0], [55, 49000, 57000], [75, 57000, 0], [75, 57000, 64000], [90, 64000, 0], [90, 64000, 71000],[100, 72000, 0],
['Yellow Alarm', 70000, 76000], ['Red Alarm', 76000, 79000], ['Fire Shut Alarm', 79000, 0]],
10: [[35, 0, 68000], [35, 68000, 74000], [55, 74000, 0], [55, 74000, 80000], [75, 80000, 0], [75, 80000, 85000], [90, 85000, 0], [90, 85000, 91000],[100, 92000, 0],
['Yellow Alarm', 99000, 102000], ['Red Alarm', 102000, 105000], ['Fire Shut Alarm', 105000, 0]],
11: [[35, 0, 42000], [35, 42000, 50000], [55, 50000, 0], [55, 50000, 58000], [75, 58000, 0], [75, 58000, 66000], [90, 66000, 0], [90, 66000, 74000],[100, 75000, 0],
['Yellow Alarm', 86000, 92000], ['Red Alarm', 92000, 95000], ['Fire Shut Alarm', 95000, 0]],
}
temp_policy_AFO = {
0: [[35, 0, 42000], [35, 42000, 49000], [55, 49000, 0], [55, 49000, 55000], [75, 55000, 0], [75, 55000, 62000], [90, 62000, 0], [90, 62000, 68000],[100, 69000, 0],
['Yellow Alarm', 67000, 73000], ['Red Alarm', 73000, 76000], ['Fire Shut Alarm', 76000, 0]],
1: [[35, 0, 41000], [35, 41000, 48000], [55, 48000, 0], [55, 48000, 55000], [75, 55000, 0], [75, 55000, 61000], [90, 61000, 0], [90, 61000, 68000],[100, 69000, 0],
['Yellow Alarm', 67000, 73000], ['Red Alarm', 73000, 76000], ['Fire Shut Alarm', 76000, 0]],
2: [[35, 0, 44000], [35, 44000, 50000], [55, 50000, 0], [55, 50000, 56000], [75, 56000, 0], [75, 56000, 63000], [90, 63000, 0], [90, 63000, 69000],[100, 70000, 0],
['Yellow Alarm', 64000, 70000], ['Red Alarm', 70000, 75000], ['Fire Shut Alarm', 75000, 0]],
3: [[35, 0, 36000], [35, 36000, 43000], [55, 43000, 0], [55, 43000, 50000], [75, 50000, 0], [75, 50000, 57000], [90, 57000, 0], [90, 57000, 64000],[100, 65000, 0],
['Yellow Alarm', 63000, 69000], ['Red Alarm', 69000, 72000], ['Fire Shut Alarm', 72000, 0]],
4: [[35, 0, 49000], [35, 49000, 54000], [55, 54000, 0], [55, 54000, 60000], [75, 60000, 0], [75, 60000, 65000], [90, 65000, 0], [90, 65000, 70000],[100, 71000, 0],
['Yellow Alarm', 68000, 74000], ['Red Alarm', 74000, 77000], ['Fire Shut Alarm', 77000, 0]],
5: [[35, 0, 46000], [35, 46000, 52000], [55, 52000, 0], [55, 52000, 58000], [75, 58000, 0], [75, 58000, 63000], [90, 63000, 0], [90, 63000, 69000],[100, 70000, 0],
['Yellow Alarm', 68000, 74000], ['Red Alarm', 74000, 77000], ['Fire Shut Alarm', 77000, 0]],
6: [[35, 0, 50000], [35, 50000, 55000], [55, 55000, 0], [55, 55000, 60000], [75, 60000, 0], [75, 60000, 65000], [90, 65000, 0], [90, 65000, 70000],[100, 71000, 0],
['Yellow Alarm', 65000, 71000], ['Red Alarm', 71000, 78000], ['Fire Shut Alarm', 78000, 0]],
7: [[35, 0, 49000], [35, 49000, 55000], [55, 55000, 0], [55, 55000, 60000], [75, 60000, 0], [75, 60000, 66000], [90, 66000, 0], [90, 66000, 71000],[100, 72000, 0],
['Yellow Alarm', 70000, 76000], ['Red Alarm', 76000, 79000], ['Fire Shut Alarm', 79000, 0]],
8: [[35, 0, 41000], [35, 41000, 47000], [55, 47000, 0], [55, 47000, 54000], [75, 54000, 0], [75, 54000, 60000], [90, 60000, 0], [90, 60000, 66000],[100, 67000, 0],
['Yellow Alarm', 65000, 71000], ['Red Alarm', 71000, 74000], ['Fire Shut Alarm', 74000, 0]],
9: [[35, 0, 57000], [35, 57000, 61000], [55, 61000, 0], [55, 61000, 66000], [75, 66000, 0], [75, 66000, 70000], [90, 70000, 0], [90, 70000, 74000],[100, 75000, 0],
['Yellow Alarm', 73000, 79000], ['Red Alarm', 79000, 82000], ['Fire Shut Alarm', 82000, 0]],
10: [[35, 0, 76000], [35, 76000, 79000], [55, 79000, 0], [55, 79000, 83000], [75, 83000, 0], [75, 83000, 86000], [90, 86000, 0], [90, 86000, 89000],[100, 90000, 0],
['Yellow Alarm', 99000, 102000], ['Red Alarm', 102000, 105000], ['Fire Shut Alarm', 105000, 0]],
11: [[35, 0, 51000], [35, 51000, 58000], [55, 58000, 0], [55, 58000, 64000], [75, 64000, 0], [75, 64000, 70000], [90, 70000, 0], [90, 70000, 77000],[100, 78000, 0],
['Yellow Alarm', 86000, 92000], ['Red Alarm', 92000, 95000], ['Fire Shut Alarm', 95000, 0]],
}
class QFX5200_FanUtil(object):
"""QFX5200 Platform FanUtil class"""
PWMINPUT_PATH = '/sys/bus/i2c/devices/7-00{0}/hwmon/{1}/pwm{2}'
HWMONINPUT_PATH = '/sys/bus/i2c/devices/7-00{0}/hwmon/'
PWMINPUT_NUM_IDX = 0
PWMINPUT_NUM = 10
_pwm_input_path_mapping = {}
_hwmon_input_path_mapping = {}
# PWM NUMBERS
_pwm_input_node_mapping = ['1','2','3','4','1','2','3','4','1','2']
# I2C NUMBERS
_hwmon_input_node_mapping = ['2c','2c','2c','2c','2e','2e','2e','2e','2f','2f']
def __init__(self):
hwmoninput_path = self.HWMONINPUT_PATH
pwminput_path = self.PWMINPUT_PATH
for x in range(self.PWMINPUT_NUM):
self._hwmon_input_path_mapping[x] = hwmoninput_path.format(
self._hwmon_input_node_mapping[x])
hwmon_path = os.listdir(self._hwmon_input_path_mapping[x])
hwmon_dir = ''
for hwmon_name in hwmon_path:
hwmon_dir = hwmon_name
self._pwm_input_path_mapping[x] = pwminput_path.format(
self._hwmon_input_node_mapping[x],
hwmon_dir,
self._pwm_input_node_mapping[x])
def get_fan_duty_cycle(self):
fan_speed = {86: 35, 139: 55, 192: 75, 230: 90,255: 100}
ret_value = 0
for x in range(self.PWMINPUT_NUM):
pwm_value = 0
device_path = self._pwm_input_path_mapping[x]
cmd = ("sudo cat %s" %(device_path))
status, pwm_value = commands.getstatusoutput(cmd)
if int(pwm_value) > 0:
ret_value = fan_speed.get(int(pwm_value))
break
return int(ret_value)
def set_fan_duty_cycle(self, val):
fan_speed = {35: 86, 55: 139, 75: 192, 90: 230,100: 255}
for x in range(self.PWMINPUT_NUM):
device_path = self._pwm_input_path_mapping[x]
pwm_value = fan_speed.get(val)
pwm_value1 = str(pwm_value)
time.sleep(1)
cmd = ("sudo echo %s > %s" %(pwm_value1,device_path))
os.system(cmd)
return True
class QFX5200_ThermalUtil(object):
"""QFX5200 Platform ThermalUtil class"""
SENSOR_NUM_ON_MAIN_BOARD = 10
CORETEMP_INDEX_ON_MAIN_BOARD = 10
SENSOR_CORETEMP_NUM_ON_MAIN_BOARD = 12
CORETEMP_NUM_ON_MAIN_BOARD = 5
THERMAL_NUM_RANGE = 10
SENSOR_NUM_0_IDX = 0
SENSORS_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input'
CORETEMP_PATH = '/sys/bus/platform/devices/coretemp.0/hwmon/hwmon*/temp{0}_input'
MAJORALARM_LED_PATH = '/sys/class/leds/alarm-major/brightness'
MINORALARM_LED_PATH = '/sys/class/leds/alarm-minor/brightness'
""" Dictionary where
key1 = thermal id index (integer) starting from 1
value = path to fan device file (string) """
_sensor_to_device_path_mapping = {}
_sensor_to_device_node_mapping = [
['7', '48'],
['7', '49'],
['5', '48'],
['5', '49'],
['5', '4a'],
['5', '4b'],
['6', '48'],
['6', '49'],
['6', '4a'],
['6', '4b'],
]
_coretemp_to_device_path_mapping = {}
_coretemp_to_device_node_mapping = [1, 2, 3, 4, 5]
def __init__(self):
sensor_path = self.SENSORS_PATH
coretemp_path = self.CORETEMP_PATH
for x in range(self.SENSOR_NUM_ON_MAIN_BOARD):
self._sensor_to_device_path_mapping[x] = sensor_path.format(
self._sensor_to_device_node_mapping[x][0],
self._sensor_to_device_node_mapping[x][1])
for x in range(self.CORETEMP_NUM_ON_MAIN_BOARD):
self._coretemp_to_device_path_mapping[x] = coretemp_path.format(
self._coretemp_to_device_node_mapping[x])
""" Function reads the 5 temp inputs in CORETEMP_PATH
and returns the average of these 5 temp readings """
def get_coretempValue(self):
sum = 0
for x in range(self.CORETEMP_NUM_ON_MAIN_BOARD):
sum += self._get_coretemp_node_val(x)
avg = sum/self.CORETEMP_NUM_ON_MAIN_BOARD
return int(avg)
""" Function takes the Sensor number as input, constructs the device path,
opens sensor file, reads the temp content from the file and returns the value """
def _get_sensor_node_val(self, thermal_num):
if thermal_num < self.SENSOR_NUM_0_IDX or thermal_num >= self.SENSOR_NUM_ON_MAIN_BOARD:
logging.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:
logging.error('get_sensor_node_val: unable to open file: %s', str(e))
return None
content = val_file.readline().rstrip()
if content == '':
logging.debug('get_sensor_node_val: content is NULL. device_path:%s', device_path)
return None
try:
val_file.close()
except IOError as e:
logging.error('get_sensor_node_val: unable to close file. device_path:%s', str(e))
return None
return int(content)
""" Function takes the coretemp number as input, constructs the device path,
opens sensor file, reads the temp content from the file and returns the value """
def _get_coretemp_node_val(self, thermal_num):
device_path = self.get_coretemp_to_device_path(thermal_num)
for filename in glob.glob(device_path):
try:
val_file = open(filename, 'r')
except IOError as e:
logging.error('get_coretemp_node_val: unable to open file: %s', str(e))
return None
content = val_file.readline().rstrip()
if content == '':
logging.debug('get_coretemp_node_val: content is NULL. device_path:%s', device_path)
return None
try:
val_file.close()
except IOError as e:
logging.error('_get_coretemp_node_val: unable to close file. device_path:%s', str(e))
return None
return int(content)
def get_thermal_to_device_path(self, thermal_num):
return self._sensor_to_device_path_mapping[thermal_num]
def get_coretemp_to_device_path(self, thermal_num):
return self._coretemp_to_device_path_mapping[thermal_num]
def get_alarm_led_brightness(self):
try:
val_file = open(self.MAJORALARM_LED_PATH)
except IOError as e:
logging.error('get_alarm_led_brightness: unable to open file: %s', str(e))
return False
majoralarm_value = val_file.readline().rstrip()
val_file.close()
try:
val_file = open(self.MINORALARM_LED_PATH)
except IOError as e:
logging.error('get_alarm_led_brightness: unable to open file: %s', str(e))
return False
minoralarm_value = val_file.readline().rstrip()
val_file.close()
if (majoralarm_value == str(1)) and (minoralarm_value == str(0)):
content = 2
elif (majoralarm_value == str(0)) and (minoralarm_value == str(1)):
content = 1
elif (majoralarm_value == str(0)) and (minoralarm_value == str(0)):
content = 0
else:
pass
return int(content)
def set_alarm_led_brightness(self, val):
""" Major Alarm set"""
if val == 2:
major_alarm_val = 1
minor_alarm_val = 0
try:
val_file = open(self.MAJORALARM_LED_PATH, 'r+')
except IOError as e:
logging.error('set_alarm_led_brightness: unable to open file: %s', str(e))
return False
val_file.write(str(major_alarm_val))
val_file.close()
try:
val_file = open(self.MINORALARM_LED_PATH, 'r+')
except IOError as e:
logging.error('set_alarm_led_brightness: unable to open file: %s', str(e))
return False
val_file.write(str(minor_alarm_val))
val_file.close()
elif val == 1:
major_alarm_val = 0
minor_alarm_val = 1
try:
val_file = open(self.MAJORALARM_LED_PATH, 'r+')
except IOError as e:
logging.error('set_alarm_led_brightness: unable to open file: %s', str(e))
return False
val_file.write(str(major_alarm_val))
val_file.close()
try:
val_file = open(self.MINORALARM_LED_PATH, 'r+')
except IOError as e:
logging.error('set_alarm_led_brightness: unable to open file: %s', str(e))
return False
val_file.write(str(minor_alarm_val))
val_file.close()
else:
major_alarm_val = 0
minor_alarm_val = 0
try:
val_file = open(self.MAJORALARM_LED_PATH, 'r+')
except IOError as e:
logging.error('set_alarm_led_brightness: unable to open file: %s', str(e))
return False
val_file.write(str(major_alarm_val))
val_file.close()
try:
val_file = open(self.MINORALARM_LED_PATH, 'r+')
except IOError as e:
logging.error('set_alarm_led_brightness: unable to open file: %s', str(e))
return False
val_file.write(str(minor_alarm_val))
val_file.close()
""" Function is called periodically every 20 secs. It reads the 10 Temp sensors, 1 core Temp sensor and ASIC temp sets
Sensor flags accordingly. Also reads the Fan duty cycle and depending on the FAN duty cycle reading and temp sensor reading,
set the different parameters """
def getSensorTemp(self):
global isPlatformAFI
global is35PerFlag
global is55PerFlag
global is75PerFlag
global is90PerFlag
global isFireThresholdReached
global FireThresholdSecsRemaining
global isFireThresholdPrint
global PrevASICValue
#AFI
if (isPlatformAFI == True):
temp_policy = temp_policy_AFI
else:
#AFO
temp_policy = temp_policy_AFO
""" Dictionary where
key = thermal id index starting from 0. 0 is the sensor 1 ...
value = Different temp ranges """
SensorFlag = {
0: [0,0,0,0,0,0,0,0,0,0,0,0],
1: [0,0,0,0,0,0,0,0,0,0,0,0],
2: [0,0,0,0,0,0,0,0,0,0,0,0],
3: [0,0,0,0,0,0,0,0,0,0,0,0],
4: [0,0,0,0,0,0,0,0,0,0,0,0],
5: [0,0,0,0,0,0,0,0,0,0,0,0],
6: [0,0,0,0,0,0,0,0,0,0,0,0],
7: [0,0,0,0,0,0,0,0,0,0,0,0],
8: [0,0,0,0,0,0,0,0,0,0,0,0],
9: [0,0,0,0,0,0,0,0,0,0,0,0],
10: [0,0,0,0,0,0,0,0,0,0,0,0],
11: [0,0,0,0,0,0,0,0,0,0,0,0],
}
# if the Firethreshold Flag is set and 120 seconds have elapsed, invoking the "poweroff" to shutdown the box
if (isFireThresholdReached == True):
firethr = FireThresholdSecsRemaining - 20
if firethr == 0:
logging.critical('CRITICAL: Fire Threshold reached: System is going to shutdown now')
os.system("echo 'CRITICAL: Fire Threshold reached: System is going to shutdown now' > /dev/console")
else:
logging.critical('CRITICAL: Fire Threshold reached: System is going to shutdown in %s seconds', firethr)
os.system("echo 'CRITICAL: Fire Threshold reached: System is going to shutdown in %s seconds' > /dev/console" % firethr)
FireThresholdSecsRemaining = FireThresholdSecsRemaining - 20
logging.critical('CRITICAL: Value of FireThresholdSecsRemaining %s seconds', FireThresholdSecsRemaining)
if (FireThresholdSecsRemaining == 0):
isFireThresholdReached == False
time.sleep(20)
cmd = "poweroff"
os.system(cmd)
for x in range(self.SENSOR_CORETEMP_NUM_ON_MAIN_BOARD):
if x < self.SENSOR_NUM_ON_MAIN_BOARD:
value = self._get_sensor_node_val(x)
logging.debug('Sensor value %d : %s', x, value)
elif x == self.CORETEMP_INDEX_ON_MAIN_BOARD:
value = self.get_coretempValue()
logging.debug('Main Board CORE temp: %s', value)
else:
logging.debug('Reading ASIC Temp value using bcmcmd')
proc = subprocess.Popen("bcmcmd \"show temp\" | grep \"maximum peak temperature\" | awk '{ print $5 }' > /var/log/asic_value 2>&1 & ",shell=True)
time.sleep(2)
cmd = "kill -9 %s"%(proc.pid)
commands.getstatusoutput(cmd)
if os.stat("/var/log/asic_value").st_size == 0:
value = PrevASICValue
logging.debug('No ASIC Temp file, Prev ASIC Temp Value: %s', PrevASICValue)
else:
with open('/var/log/asic_value', 'r') as f:
value1 = f.readline()
value2 = float(value1)
value1 = value2 * 1000
value = int(value1)
PrevASICValue = value
logging.debug('Reading from ASIC Temp file: %s', value)
logging.debug('Reading from Prev ASIC Temp Value: %s', PrevASICValue)
os.system('rm /var/log/asic_value')
# 35% Duty Cycle
if value > temp_policy[x][0][1] and value <= temp_policy[x][0][2]:
SensorFlag[x][0] = True
# 35% Prev Duty Cycle
elif value > temp_policy[x][1][1] and value < temp_policy[x][1][2]:
SensorFlag[x][1] = True
# 55% Duty Cycle
elif value == temp_policy[x][2][1]:
SensorFlag[x][2] = True
# 55% Prev Duty Cycle
elif value > temp_policy[x][3][1] and value < temp_policy[x][3][2]:
SensorFlag[x][3] = True
# 75% Duty Cycle
elif value == temp_policy[x][4][1]:
SensorFlag[x][4] = True
# 75% Prev Duty Cycle
elif value > temp_policy[x][5][1] and value < temp_policy[x][5][2]:
SensorFlag[x][5] = True
# 90% Duty Cycle
elif value == temp_policy[x][6][1]:
SensorFlag[x][6] = True
# 90% Prev Duty Cycle
elif value > temp_policy[x][7][1] and value < temp_policy[x][7][2]:
SensorFlag[x][7] = True
#100% Duty Cycle
elif value >= temp_policy[x][8][1]:
SensorFlag[x][8] = True
else:
pass
# Yellow Alarm
if value >= temp_policy[x][9][1] and value < temp_policy[x][9][2]:
SensorFlag[x][9] = True
# Red Alarm
elif value >= temp_policy[x][10][1] and value < temp_policy[x][10][2]:
SensorFlag[x][10] = True
# Fire Shut down
elif value >= temp_policy[x][11][1]:
SensorFlag[x][11] = True
fan = QFX5200_FanUtil()
# CHECK IF ANY TEMPERATURE SENSORS HAS SET FIRE SHUTDOWN FLAG
if (SensorFlag[0][11] or SensorFlag[1][11] or SensorFlag[2][11] or SensorFlag[3][11] or SensorFlag[4][11] or SensorFlag[5][11] or SensorFlag[6][11] or SensorFlag[7][11]
or SensorFlag[8][11] or SensorFlag[9][11] or SensorFlag[10][11] or SensorFlag[11][11]):
isFireThresholdReached = True
if (isFireThresholdPrint == True):
logging.critical('CRITICAL: Fire Threshold reached: System is going to shutdown in 120 seconds')
os.system("echo 'CRITICAL: Fire Threshold reached: System is going to shutdown in 120 seconds' > /dev/console")
isFireThresholdPrint = False
logging.debug('Temp Sensor is set to FIRE SHUTDOWN Flag')
fan.set_fan_duty_cycle(100)
self.set_alarm_led_brightness(2)
# CHECK IF ANY TEMPERATURE SENSORS HAS SET 'RED' ALARM FLAG, IF YES, SET THE ALARM LED TO 'RED'
elif (SensorFlag[0][10] or SensorFlag[1][10] or SensorFlag[2][10] or SensorFlag[3][10] or SensorFlag[4][10] or SensorFlag[5][10] or SensorFlag[6][10] or SensorFlag[7][10]
or SensorFlag[8][10] or SensorFlag[9][10] or SensorFlag[10][10] or SensorFlag[11][10]):
fan.set_fan_duty_cycle(100)
self.set_alarm_led_brightness(2)
logging.debug('Temp Sensor is set to Red Alarm Flag')
if (isFireThresholdReached == True):
logging.critical('CRITICAL: System Stabilized, not shutting down')
os.system("echo 'CRITICAL: System Stabilized, not shutting down' > /dev/console")
FireThresholdSecsRemaining = 120
isFireThresholdReached = False
# CHECK IF ANY TEMPERATURE SENSORS HAS SET 'YELLOW' ALARM FLAG, IF YES, SET THE ALARM LED TO 'YELLOW'
elif (SensorFlag[0][9] or SensorFlag[1][9] or SensorFlag[2][9] or SensorFlag[3][9] or SensorFlag[4][9] or SensorFlag[5][9] or SensorFlag[6][9] or SensorFlag[7][9]
or SensorFlag[8][9] or SensorFlag[9][9] or SensorFlag[10][9] or SensorFlag[11][9]):
fan.set_fan_duty_cycle(100)
self.set_alarm_led_brightness(1)
logging.debug('Temp Sensor is set to Yellow Alarm Flag')
if (isFireThresholdReached == True):
logging.critical('CRITICAL: System Stabilized, not shutting down')
os.system("echo 'CRITICAL: System Stabilized, not shutting down' > /dev/console")
FireThresholdSecsRemaining = 120
isFireThresholdReached = False
#CHECK IF ANY TEMPERATURE SENSORS HAS SET 100% DUTY CYCLE FLAG, IF YES, SET THE FAN DUTY CYCLE TO 100%
elif (SensorFlag[0][8] or SensorFlag[1][8] or SensorFlag[2][8] or SensorFlag[3][8] or SensorFlag[4][8] or SensorFlag[5][8] or SensorFlag[6][8] or SensorFlag[7][8]
or SensorFlag[8][8] or SensorFlag[9][8] or SensorFlag[10][8] or SensorFlag[11][8]):
if (fan.get_fan_duty_cycle < 100):
fan.set_fan_duty_cycle(100)
elif (fan.get_fan_duty_cycle == 100):
pass
else:
pass
value = self.get_alarm_led_brightness()
if ( value > 0):
self.set_alarm_led_brightness(0)
logging.debug('Temp Sensor is set to 100% Duty Cycle Flag')
# CHECK IF ANY TEMPERATURE SENSORS HAS SET 90% PREV DUTY CYCLE FLAG, IF YES, SET THE FAN DUTY CYCLE TO 90%
elif (SensorFlag[0][7] or SensorFlag[1][7] or SensorFlag[2][7] or SensorFlag[3][7] or SensorFlag[4][7] or SensorFlag[5][7] or SensorFlag[6][7] or SensorFlag[7][7]
or SensorFlag[8][7] or SensorFlag[9][7] or SensorFlag[10][7] or SensorFlag[11][7]):
if (is90PerFlag == True):
fan.set_fan_duty_cycle(90)
is90PerFlag = False
else:
pass
value = self.get_alarm_led_brightness()
if ( value > 0):
self.set_alarm_led_brightness(0)
if (isFireThresholdReached == True):
logging.critical('CRITICAL: System Stabilized, not shutting down')
os.system("echo 'CRITICAL: System Stabilized, not shutting down' > /dev/console")
FireThresholdSecsRemaining = 120
logging.debug('Temp Sensor is set to 90% Prev Duty Cycle Flag')
# CHECK IF ANY TEMPERATURE SENSORS HAS SET 90% DUTY CYCLE FLAG, IF YES, SET THE FAN DUTY CYCLE TO 90%
elif (SensorFlag[0][6] or SensorFlag[1][6] or SensorFlag[2][6] or SensorFlag[3][6] or SensorFlag[4][6] or SensorFlag[5][6] or SensorFlag[6][6] or SensorFlag[7][6]
or SensorFlag[8][6] or SensorFlag[9][6] or SensorFlag[10][6] or SensorFlag[11][6]):
if (fan.get_fan_duty_cycle < 90):
fan.set_fan_duty_cycle(90)
elif (fan.get_fan_duty_cycle > 90):
if (SensorFlag[0][6] and SensorFlag[1][6] and SensorFlag[2][6] and SensorFlag[3][6] and SensorFlag[4][6] and SensorFlag[5][6] and SensorFlag[6][6] and SensorFlag[7][6]
and SensorFlag[8][6] and SensorFlag[9][6] and SensorFlag[10][6] and SensorFlag[11][6]):
fan.set_fan_duty_cycle(90)
else:
pass
value = self.get_alarm_led_brightness()
if ( value > 0):
self.set_alarm_led_brightness(0)
is90PerFlag = True
if (isFireThresholdReached == True):
logging.critical('CRITICAL: System Stabilized, not shutting down')
os.system("echo 'CRITICAL: System Stabilized, not shutting down' > /dev/console")
FireThresholdSecsRemaining = 120
isFireThresholdReached = False
logging.debug('Temp Sensor is set to 90% Duty Cycle Flag')
# CHECK IF ANY TEMPERATURE SENSORS HAS SET 75% PREV DUTY CYCLE FLAG, IF YES, SET THE FAN DUTY CYCLE TO 75%
elif (SensorFlag[0][5] or SensorFlag[1][5] or SensorFlag[2][5] or SensorFlag[3][5] or SensorFlag[4][5] or SensorFlag[5][5] or SensorFlag[6][5] or SensorFlag[7][5]
or SensorFlag[8][5] or SensorFlag[9][5] or SensorFlag[10][5] or SensorFlag[11][5]):
if (is75PerFlag == True):
fan.set_fan_duty_cycle(75)
is75PerFlag = False
else:
pass
value = self.get_alarm_led_brightness()
if ( value > 0):
self.set_alarm_led_brightness(0)
if (isFireThresholdReached == True):
logging.critical('CRITICAL: System Stabilized, not shutting down')
os.system("echo 'CRITICAL: System Stabilized, not shutting down' > /dev/console")
FireThresholdSecsRemaining = 120
isFireThresholdReached = False
logging.debug('Temp Sensor is set to 75% Prev Duty Cycle Flag')
# CHECK IF ANY TEMPERATURE SENSORS HAS SET 75% DUTY CYCLE FLAG, IF YES, SET THE FAN DUTY CYCLE TO 75%
elif (SensorFlag[0][4] or SensorFlag[1][4] or SensorFlag[2][4] or SensorFlag[3][4] or SensorFlag[4][4] or SensorFlag[5][4] or SensorFlag[6][4] or SensorFlag[7][4]
or SensorFlag[8][4] or SensorFlag[9][4] or SensorFlag[10][4] or SensorFlag[11][4]):
if (fan.get_fan_duty_cycle < 75):
fan.set_fan_duty_cycle(75)
elif (fan.get_fan_duty_cycle > 75):
if (SensorFlag[0][4] and SensorFlag[1][4] and SensorFlag[2][4] and SensorFlag[3][4] and SensorFlag[4][4] and SensorFlag[5][4] and SensorFlag[6][4] and SensorFlag[7][4]
and SensorFlag[8][4] and SensorFlag[9][4] and SensorFlag[10][4] and SensorFlag[11][4]):
fan.set_fan_duty_cycle(75)
else:
pass
value = self.get_alarm_led_brightness()
if ( value > 0):
self.set_alarm_led_brightness(0)
is75PerFlag = True
logging.debug('Temp Sensor is set to 75% Duty Cycle Flag')
# CHECK IF ANY TEMPERATURE SENSORS HAS SET 55% DUTY CYCLE PREV FLAG, IF YES, SET THE FAN DUTY CYCLE TO 55%
elif (SensorFlag[0][3] or SensorFlag[1][3] or SensorFlag[2][3] or SensorFlag[3][3] or SensorFlag[4][3] or SensorFlag[5][3] or SensorFlag[6][3] or SensorFlag[7][3]
or SensorFlag[8][3] or SensorFlag[9][3] or SensorFlag[10][3] or SensorFlag[11][3]):
if (is55PerFlag == True):
fan.set_fan_duty_cycle(55)
is55PerFlag = False
else:
pass
value = self.get_alarm_led_brightness()
if ( value > 0):
self.set_alarm_led_brightness(0)
if (isFireThresholdReached == True):
logging.critical('CRITICAL: System Stabilized, not shutting down')
os.system("echo 'CRITICAL: System Stabilized, not shutting down' > /dev/console")
FireThresholdSecsRemaining = 120
isFireThresholdReached = False
logging.debug('Temp Sensor is set to 55% Prev Duty Cycle Flag')
# CHECK IF ANY TEMPERATURE SENSORS HAS SET 55% DUTY CYCLE FLAG, IF YES, SET THE FAN DUTY CYCLE TO 55%
elif (SensorFlag[0][2] or SensorFlag[1][2] or SensorFlag[2][2] or SensorFlag[3][2] or SensorFlag[4][2] or SensorFlag[5][2] or SensorFlag[6][2] or SensorFlag[7][2]
or SensorFlag[8][2] or SensorFlag[9][2] or SensorFlag[10][2] or SensorFlag[11][2]):
if (fan.get_fan_duty_cycle < 55):
fan.set_fan_duty_cycle(55)
elif (fan.get_fan_duty_cycle > 55):
if (SensorFlag[0][2] and SensorFlag[1][2] and SensorFlag[2][2] and SensorFlag[3][2] and SensorFlag[4][2] and SensorFlag[5][2] and SensorFlag[6][2] and SensorFlag[7][2]
and SensorFlag[8][6] and SensorFlag[9][6] and SensorFlag[10][6] and SensorFlag[11][6]):
fan.set_fan_duty_cycle(55)
else:
pass
value = self.get_alarm_led_brightness()
if ( value > 0):
self.set_alarm_led_brightness(0)
is55PerFlag = True
if (isFireThresholdReached == True):
logging.critical('CRITICAL: System Stabilized, not shutting down')
os.system("echo 'CRITICAL: System Stabilized, not shutting down' > /dev/console")
FireThresholdSecsRemaining = 120
isFireThresholdReached = False
logging.debug('Temp Sensor is set to 55% Duty Cycle Flag')
# CHECK IF ANY TEMPERATURE SENSORS HAS SET 35% PREV DUTY CYCLE FLAG, IF YES, SET THE FAN DUTY CYCLE TO 35%
elif (SensorFlag[0][1] or SensorFlag[1][1] or SensorFlag[2][1] or SensorFlag[3][1] or SensorFlag[4][1] or SensorFlag[5][1] or SensorFlag[6][1] or SensorFlag[7][1]
or SensorFlag[8][1] or SensorFlag[9][1] or SensorFlag[10][1] or SensorFlag[11][1]):
if (is35PerFlag == True):
fan.set_fan_duty_cycle(35)
is35PerFlag = False
else:
pass
value = self.get_alarm_led_brightness()
if ( value > 0):
self.set_alarm_led_brightness(0)
if (isFireThresholdReached == True):
logging.critical('CRITICAL: System Stabilized, not shutting down')
os.system("echo 'CRITICAL: System Stabilized, not shutting down' > /dev/console")
FireThresholdSecsRemaining = 120
isFireThresholdReached = False
logging.debug('Temp Sensor is set to 35% Prev Duty Cycle Flag')
# CHECK IF ANY TEMPERATURE SENSORS HAS SET 35% DUTY CYCLE FLAG, IF YES, SET THE FAN DUTY CYCLE TO 35%
elif (SensorFlag[0][0] or SensorFlag[1][0] or SensorFlag[2][0] or SensorFlag[3][0] or SensorFlag[4][0] or SensorFlag[5][0] or SensorFlag[6][0] or SensorFlag[7][0]
or SensorFlag[8][0] or SensorFlag[9][0] or SensorFlag[10][0] or SensorFlag[11][0]):
if (fan.get_fan_duty_cycle == 35):
fan.set_fan_duty_cycle(35)
elif (fan.get_fan_duty_cycle > 35):
if (SensorFlag[0][0] and SensorFlag[1][0] and SensorFlag[2][0] and SensorFlag[3][0] and SensorFlag[4][0] and SensorFlag[5][0] and SensorFlag[6][0] and SensorFlag[7][0]
and SensorFlag[8][0] and SensorFlag[9][0] and SensorFlag[10][0] and SensorFlag[11][0]):
fan.set_fan_duty_cycle(35)
else:
pass
value = self.get_alarm_led_brightness()
if ( value > 0):
self.set_alarm_led_brightness(0)
is35PerFlag = True
if (isFireThresholdReached == True):
logging.critical('CRITICAL: System Stabilized, not shutting down')
os.system("echo 'CRITICAL: System Stabilized, not shutting down' > /dev/console")
FireThresholdSecsRemaining = 120
isFireThresholdReached = False
logging.debug('Temp Sensor is set to 35% Duty Cycle Flag')
else:
pass
# RESET ALL THE SENSOR FLAGS
for x in range(self.SENSOR_CORETEMP_NUM_ON_MAIN_BOARD):
for y in range(self.SENSOR_CORETEMP_NUM_ON_MAIN_BOARD):
SensorFlag[x][y] = 0
class device_monitor(object):
MASTER_LED_PATH = '/sys/class/leds/master/brightness'
SYSTEM_LED_PATH = '/sys/class/leds/system/brightness'
PWMINPUT_PATH = '/sys/bus/i2c/devices/7-00{0}/hwmon/{1}/pwm{2}'
HWMONINPUT_PATH = '/sys/bus/i2c/devices/7-00{0}/hwmon/'
PWMINPUT_NUM = 10
_pwm_input_path_mapping = {}
_hwmon_input_path_mapping = {}
# PWM NUMBERS
_pwm_input_node_mapping = ['1','2','3','4','1','2','3','4','1','2']
# I2C NUMBERS
_hwmon_input_node_mapping = ['2c','2c','2c','2c','2e','2e','2e','2e','2f','2f']
def __init__(self, log_file, log_level):
global DEBUG
global isPlatformAFI
hwmoninput_path = self.HWMONINPUT_PATH
pwminput_path = self.PWMINPUT_PATH
for x in range(self.PWMINPUT_NUM):
self._hwmon_input_path_mapping[x] = hwmoninput_path.format(
self._hwmon_input_node_mapping[x])
hwmon_path = os.listdir(self._hwmon_input_path_mapping[x])
hwmon_dir = ''
for hwmon_name in hwmon_path:
hwmon_dir = hwmon_name
self._pwm_input_path_mapping[x] = pwminput_path.format(
self._hwmon_input_node_mapping[x],
hwmon_dir,
self._pwm_input_node_mapping[x])
"""Needs a logger and a logger level."""
# set up logging to file
logging.basicConfig(
filename=log_file,
filemode='w',
level=log_level,
format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s',
datefmt='%H:%M:%S'
)
if DEBUG == True:
# set up logging to console
if log_level == logging.DEBUG:
console = logging.StreamHandler()
console.setLevel(log_level)
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
console.setFormatter(formatter)
logging.getLogger('').addHandler(console)
filename = "/var/run/eeprom"
AFO_str = "AFO"
pattern = re.compile(r"Fan Type", re.IGNORECASE)
with open(filename, "rt") as myfile:
for line in myfile:
if pattern.search(line) != None:
fan_type = str(line)
if "=" in fan_type:
user=fan_type[fan_type.find("=")+1:].split()[0]
if user == AFO_str:
isPlatformAFI = False
else:
isPlatformAFI = True
master_led_value = 1
try:
masterLED_file = open(self.MASTER_LED_PATH, 'r+')
except IOError as e:
logging.error('device_monitor: unable to open Master LED file: %s', str(e))
masterLED_file.write(str(master_led_value))
masterLED_file.close()
system_led_value = 1
try:
systemLED_file = open(self.SYSTEM_LED_PATH, 'r+')
except IOError as e:
logging.error('device_monitor: unable to open System LED file: %s', str(e))
systemLED_file.write(str(system_led_value))
systemLED_file.close()
self.set_DefaultFAN_duty_cycle(35)
def set_DefaultFAN_duty_cycle(self, val):
fan_speed = {35: 86, 55: 139, 75: 192, 90: 230,100: 255}
for x in range(self.PWMINPUT_NUM):
device_path = self._pwm_input_path_mapping[x]
pwm_value = fan_speed.get(val)
pwm_value1 = str(pwm_value)
time.sleep(1)
cmd = ("sudo echo %s > %s" %(pwm_value1,device_path))
os.system(cmd)
return True
def manage_device(self):
thermal = QFX5200_ThermalUtil()
thermal.getSensorTemp()
def main():
#Introducing sleep of 150 seconds to wait for all the docker containers to start before starting the EM policy.
time.sleep(150)
monitor = device_monitor(log_file, log_level)
while True:
monitor.manage_device()
time.sleep(20)
if __name__ == '__main__':
main()

View File

@ -0,0 +1,203 @@
#!/usr/bin/env python
#
# Description: This file contains the Juniper QFX5200 Platform Initialization routines
#
# Copyright (c) 2020, Juniper Networks, Inc.
# All rights reserved.
#
# 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/>.
import os
import commands
import sys
import logging
import time
PROJECT_NAME = 'QFX5200-32C'
verbose = False
DEBUG = False
FORCE = 0
if DEBUG == True:
print sys.argv[0]
print 'ARGV :', sys.argv[1:]
i2c_prefix = '/sys/bus/i2c/devices/'
kos = [
'modprobe i2c-mux',
'modprobe mfd-core',
'modprobe tmp401',
'modprobe ads7828',
'modprobe jnx-tmc-core',
'modprobe leds-jnx-tmc',
'modprobe jnx-refpga-tmc',
'modprobe adt7470',
'modprobe i2c-tmc',
'modprobe gpio-tmc',
'modprobe jnx-tmc-psu',
'modprobe jnx-psu-monitor',
'modprobe jnx-refpga-lpcm'
]
mknod =[
'echo tmp435 0x48 > /sys/bus/i2c/devices/i2c-5/new_device',
'echo tmp435 0x49 > /sys/bus/i2c/devices/i2c-5/new_device',
'echo tmp435 0x4A > /sys/bus/i2c/devices/i2c-5/new_device',
'echo tmp435 0x4B > /sys/bus/i2c/devices/i2c-5/new_device',
'echo tmp435 0x48 > /sys/bus/i2c/devices/i2c-6/new_device',
'echo tmp435 0x49 > /sys/bus/i2c/devices/i2c-6/new_device',
'echo tmp435 0x4A > /sys/bus/i2c/devices/i2c-6/new_device',
'echo tmp435 0x4B > /sys/bus/i2c/devices/i2c-6/new_device',
'echo tmp435 0x48 > /sys/bus/i2c/devices/i2c-7/new_device',
'echo tmp435 0x49 > /sys/bus/i2c/devices/i2c-7/new_device',
'echo adt7470 0x2C > /sys/bus/i2c/devices/i2c-7/new_device',
'echo adt7470 0x2E > /sys/bus/i2c/devices/i2c-7/new_device',
'echo adt7470 0x2F > /sys/bus/i2c/devices/i2c-7/new_device',
'echo ads7830 0x4A > /sys/bus/i2c/devices/i2c-2/new_device',
'echo jpsu 0x58 > /sys/bus/i2c/devices/i2c-3/new_device',
'echo jpsu 0x58 > /sys/bus/i2c/devices/i2c-4/new_device',
]
def my_log(txt):
if DEBUG == True:
print txt
return
def log_os_system(cmd, show):
logging.info('Run :'+cmd)
status, output = commands.getstatusoutput(cmd)
my_log (cmd +"with result:" + str(status))
my_log (" output:"+output)
if status:
logging.info('Failed :'+cmd)
if show:
print('Failed :'+cmd)
return status, output
def driver_install():
global FORCE
log_os_system("depmod", 1)
for i in range(0,len(kos)):
status, output = log_os_system(kos[i], 1)
time.sleep(2)
if status:
if FORCE == 0:
return status
return 0
def device_exist():
ret1, log = log_os_system("ls "+i2c_prefix+"5-0049", 0)
ret2, log = log_os_system("ls "+i2c_prefix+"7-002c", 0)
return not(ret1 or ret2)
def device_install():
global FORCE
for i in range(0,len(mknod)):
status, output = log_os_system(mknod[i], 1)
if status:
print output
if FORCE == 0:
return status
def do_install():
status = driver_install()
if status:
if FORCE == 0:
return status
if not device_exist():
logging.info('No device, installing....')
status = device_install()
if status:
if FORCE == 0:
return status
else:
print PROJECT_NAME.upper()+" devices detected...."
return
def main():
# Enabling REFPGA
EnableREFFGACmd = 'busybox devmem 0xFED50011 8 0x53'
try:
os.system(EnableREFFGACmd)
except OSError:
print 'Error: Execution of "%s" failed', EnableREFFGACmd
return False
time.sleep(2)
# Create CPU Board EEPROM device
CreateEEPROMdeviceCmd = 'sudo echo 24c02 0x51 > /sys/bus/i2c/devices/i2c-0/new_device'
try:
os.system(CreateEEPROMdeviceCmd)
except OSError:
print 'Error: Execution of "%s" failed', CreateEEPROMdeviceCmd
return False
time.sleep(1)
#Retrieve the Base MAC Address from EEPROM
status, macAddress = commands.getstatusoutput("decode-syseeprom -m 0x24")
if status:
print 'Error: Could not retrieve BASE MAC Address from EEPROM'
return False
#Make eth0 interface down
status, eth0Down = commands.getstatusoutput("ifconfig eth0 down")
if status:
print 'Error: Could not make eth0 interface down'
return False
#Assign BASE MAC ADDRESS retieved from CPU board EEPROM to eth0 interface
mac_address_prog = "ifconfig eth0 hw ether " + str(macAddress)
status, MACAddressProg = commands.getstatusoutput(mac_address_prog)
if status:
print 'Error: Could not set up "macAddress" for eth0 interface'
return False
#Make eth0 interface up
status, eth0UP = commands.getstatusoutput("ifconfig eth0 up")
if status:
print 'Error: Could not make eth0 interface up'
return False
# Juniper QFX5200 platform drivers install
do_install()
time.sleep(2)
# Juniper SFP Intialization
JuniperSFPInitCmd = 'python /usr/share/sonic/device/x86_64-juniper_qfx5200-r0/plugins/qfx5200_sfp_init.py'
try:
os.system(JuniperSFPInitCmd)
except OSError:
print 'Error: Execution of "%s" failed', JuniperSFPInitCmd
return False
time.sleep(1)
# Invoking the script which retrieves the data from CPU Board and Main Board EEPROM and storing in file
EEPROMDataCmd = 'python /usr/share/sonic/device/x86_64-juniper_qfx5200-r0/plugins/qfx5200_eeprom_data.py'
try:
os.system(EEPROMDataCmd)
except OSError:
print 'Error: Execution of "%s" failed', EEPROMDataCmd
return False
return True
if __name__ == "__main__":
main()