[Inventec] Add support for D6332 platform (#5304)
Add support for D6332 platform Signed-off-by: cynthia <wu.cynthia@inventec.com>
This commit is contained in:
parent
d19d1dd569
commit
38bd6be609
@ -0,0 +1,2 @@
|
|||||||
|
{%- set default_topo = 't1' %}
|
||||||
|
{%- include 'buffers_config.j2' %}
|
@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
{%- set default_cable = '40m' %}
|
||||||
|
|
||||||
|
{%- set PORT_ALL = [] %}
|
||||||
|
|
||||||
|
{%- for port in PORT %}
|
||||||
|
{%- if PORT_ALL.append(port) %}{%- endif %}
|
||||||
|
{%- endfor %}
|
||||||
|
|
||||||
|
{%- macro generate_buffer_pool_and_profiles() %}
|
||||||
|
"BUFFER_POOL": {
|
||||||
|
"ingress_lossless_pool": {
|
||||||
|
"size": "27678784",
|
||||||
|
"type": "ingress",
|
||||||
|
"mode": "dynamic",
|
||||||
|
"xoff": "4194112"
|
||||||
|
},
|
||||||
|
"egress_lossy_pool": {
|
||||||
|
"size": "26045524",
|
||||||
|
"type": "egress",
|
||||||
|
"mode": "dynamic"
|
||||||
|
},
|
||||||
|
"egress_lossless_pool": {
|
||||||
|
"size": "32786432",
|
||||||
|
"type": "egress",
|
||||||
|
"mode": "static"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"BUFFER_PROFILE": {
|
||||||
|
"ingress_lossy_profile": {
|
||||||
|
"pool":"[BUFFER_POOL|ingress_lossless_pool]",
|
||||||
|
"size":"0",
|
||||||
|
"dynamic_th":"3"
|
||||||
|
},
|
||||||
|
"egress_lossless_profile": {
|
||||||
|
"pool":"[BUFFER_POOL|egress_lossless_pool]",
|
||||||
|
"size":"1518",
|
||||||
|
"static_th":"3995680"
|
||||||
|
},
|
||||||
|
"egress_lossy_profile": {
|
||||||
|
"pool":"[BUFFER_POOL|egress_lossy_pool]",
|
||||||
|
"size":"1518",
|
||||||
|
"dynamic_th":"3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{%- endmacro %}
|
@ -0,0 +1,17 @@
|
|||||||
|
# PG lossless profiles.
|
||||||
|
# speed cable size xon xoff threshold xon_offset
|
||||||
|
10000 5m 1248 2288 35776 -4 2288
|
||||||
|
25000 5m 1248 2288 53248 -4 2288
|
||||||
|
40000 5m 1248 2288 66560 -4 2288
|
||||||
|
50000 5m 1248 2288 79872 -4 2288
|
||||||
|
100000 5m 1248 2288 165568 -4 2288
|
||||||
|
10000 40m 1248 2288 37024 -4 2288
|
||||||
|
25000 40m 1248 2288 56160 -4 2288
|
||||||
|
40000 40m 1248 2288 71552 -4 2288
|
||||||
|
50000 40m 1248 2288 85696 -4 2288
|
||||||
|
100000 40m 1248 2288 177632 -4 2288
|
||||||
|
10000 300m 1248 2288 46176 -4 2288
|
||||||
|
25000 300m 1248 2288 79040 -4 2288
|
||||||
|
40000 300m 1248 2288 108160 -4 2288
|
||||||
|
50000 300m 1248 2288 131456 -4 2288
|
||||||
|
100000 300m 1248 2288 268736 -4 2288
|
33
device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/port_config.ini
Executable file
33
device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/port_config.ini
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
# name lanes index speed autoneg
|
||||||
|
Ethernet0 21,22,23,24 0 100000 0
|
||||||
|
Ethernet4 17,18,19,20 1 100000 0
|
||||||
|
Ethernet8 25,26,27,28 2 100000 0
|
||||||
|
Ethernet12 29,30,31,32 3 100000 0
|
||||||
|
Ethernet16 37,38,39,40 4 100000 0
|
||||||
|
Ethernet20 33,34,35,36 5 100000 0
|
||||||
|
Ethernet24 41,42,43,44 6 100000 0
|
||||||
|
Ethernet28 45,46,47,48 7 100000 0
|
||||||
|
Ethernet32 5,6,7,8 8 100000 0
|
||||||
|
Ethernet36 1,2,3,4 9 100000 0
|
||||||
|
Ethernet40 9,10,11,12 10 100000 0
|
||||||
|
Ethernet44 13,14,15,16 11 100000 0
|
||||||
|
Ethernet48 53,54,55,56 12 100000 0
|
||||||
|
Ethernet52 49,50,51,52 13 100000 0
|
||||||
|
Ethernet56 57,58,59,60 14 100000 0
|
||||||
|
Ethernet60 61,62,63,64 15 100000 0
|
||||||
|
Ethernet64 69,70,71,72 16 100000 0
|
||||||
|
Ethernet68 65,66,67,68 17 100000 0
|
||||||
|
Ethernet72 73,74,75,76 18 100000 0
|
||||||
|
Ethernet76 77,78,79,80 19 100000 0
|
||||||
|
Ethernet80 117,118,119,120 20 100000 0
|
||||||
|
Ethernet84 113,114,115,116 21 100000 0
|
||||||
|
Ethernet88 121,122,123,124 22 100000 0
|
||||||
|
Ethernet92 125,126,127,128 23 100000 0
|
||||||
|
Ethernet96 85,86,87,88 24 100000 0
|
||||||
|
Ethernet100 81,82,83,84 25 100000 0
|
||||||
|
Ethernet104 89,90,91,92 26 100000 0
|
||||||
|
Ethernet108 93,94,95,96 27 100000 0
|
||||||
|
Ethernet112 101,102,103,104 28 100000 0
|
||||||
|
Ethernet116 97,98,99,100 29 100000 0
|
||||||
|
Ethernet120 105,106,107,108 30 100000 0
|
||||||
|
Ethernet124 109,110,111,112 31 100000 0
|
@ -0,0 +1,161 @@
|
|||||||
|
{%- set PORT_ALL = [] %}
|
||||||
|
|
||||||
|
{%- for port in PORT %}
|
||||||
|
{%- if PORT_ALL.append(port) %}{%- endif %}
|
||||||
|
{%- endfor %}
|
||||||
|
|
||||||
|
{
|
||||||
|
"TC_TO_PRIORITY_GROUP_MAP": {
|
||||||
|
"AZURE": {
|
||||||
|
"0": "0",
|
||||||
|
"1": "1",
|
||||||
|
"2": "2",
|
||||||
|
"3": "3",
|
||||||
|
"4": "4",
|
||||||
|
"5": "5",
|
||||||
|
"6": "6",
|
||||||
|
"7": "7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MAP_PFC_PRIORITY_TO_QUEUE": {
|
||||||
|
"AZURE": {
|
||||||
|
"0": "0",
|
||||||
|
"1": "1",
|
||||||
|
"2": "2",
|
||||||
|
"3": "3",
|
||||||
|
"4": "4",
|
||||||
|
"5": "5",
|
||||||
|
"6": "6",
|
||||||
|
"7": "7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"TC_TO_QUEUE_MAP": {
|
||||||
|
"AZURE": {
|
||||||
|
"0": "0",
|
||||||
|
"1": "1",
|
||||||
|
"2": "2",
|
||||||
|
"3": "3",
|
||||||
|
"4": "4",
|
||||||
|
"5": "5",
|
||||||
|
"6": "6",
|
||||||
|
"7": "7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DSCP_TO_TC_MAP": {
|
||||||
|
"AZURE": {
|
||||||
|
"0":"0",
|
||||||
|
"1":"0",
|
||||||
|
"2":"0",
|
||||||
|
"3":"3",
|
||||||
|
"4":"4",
|
||||||
|
"5":"0",
|
||||||
|
"6":"0",
|
||||||
|
"7":"0",
|
||||||
|
"8":"1",
|
||||||
|
"9":"0",
|
||||||
|
"10":"0",
|
||||||
|
"11":"0",
|
||||||
|
"12":"0",
|
||||||
|
"13":"0",
|
||||||
|
"14":"0",
|
||||||
|
"15":"0",
|
||||||
|
"16":"0",
|
||||||
|
"17":"0",
|
||||||
|
"18":"0",
|
||||||
|
"19":"0",
|
||||||
|
"20":"0",
|
||||||
|
"21":"0",
|
||||||
|
"22":"0",
|
||||||
|
"23":"0",
|
||||||
|
"24":"0",
|
||||||
|
"25":"0",
|
||||||
|
"26":"0",
|
||||||
|
"27":"0",
|
||||||
|
"28":"0",
|
||||||
|
"29":"0",
|
||||||
|
"30":"0",
|
||||||
|
"31":"0",
|
||||||
|
"32":"0",
|
||||||
|
"33":"0",
|
||||||
|
"34":"0",
|
||||||
|
"35":"0",
|
||||||
|
"36":"0",
|
||||||
|
"37":"0",
|
||||||
|
"38":"0",
|
||||||
|
"39":"0",
|
||||||
|
"40":"0",
|
||||||
|
"41":"0",
|
||||||
|
"42":"0",
|
||||||
|
"43":"0",
|
||||||
|
"44":"0",
|
||||||
|
"45":"0",
|
||||||
|
"46":"0",
|
||||||
|
"47":"0",
|
||||||
|
"48":"0",
|
||||||
|
"49":"0",
|
||||||
|
"50":"0",
|
||||||
|
"51":"0",
|
||||||
|
"52":"0",
|
||||||
|
"53":"0",
|
||||||
|
"54":"0",
|
||||||
|
"55":"0",
|
||||||
|
"56":"0",
|
||||||
|
"57":"0",
|
||||||
|
"58":"0",
|
||||||
|
"59":"0",
|
||||||
|
"60":"0",
|
||||||
|
"61":"0",
|
||||||
|
"62":"0",
|
||||||
|
"63":"0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SCHEDULER": {
|
||||||
|
"scheduler.0" : {
|
||||||
|
"type":"DWRR",
|
||||||
|
"weight": "25"
|
||||||
|
},
|
||||||
|
"scheduler.1" : {
|
||||||
|
"type":"DWRR",
|
||||||
|
"weight": "30"
|
||||||
|
},
|
||||||
|
"scheduler.2" : {
|
||||||
|
"type":"DWRR",
|
||||||
|
"weight": "20"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PORT_QOS_MAP": {
|
||||||
|
"{{ PORT_ALL|join(',') }}": {
|
||||||
|
"dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]",
|
||||||
|
"tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]",
|
||||||
|
"tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]",
|
||||||
|
"pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]",
|
||||||
|
"pfc_enable": "3,4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"WRED_PROFILE": {
|
||||||
|
"AZURE_LOSSLESS" : {
|
||||||
|
"wred_green_enable":"true",
|
||||||
|
"wred_yellow_enable":"true",
|
||||||
|
"wred_red_enable":"true",
|
||||||
|
"ecn":"ecn_all",
|
||||||
|
"red_max_threshold":"312000",
|
||||||
|
"red_min_threshold":"104000",
|
||||||
|
"yellow_max_threshold":"312000",
|
||||||
|
"yellow_min_threshold":"104000",
|
||||||
|
"green_max_threshold": "312000",
|
||||||
|
"green_min_threshold": "104000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"QUEUE": {
|
||||||
|
"{{ PORT_ALL|join(',') }}|3-4" : {
|
||||||
|
"scheduler" : "[SCHEDULER|scheduler.0]",
|
||||||
|
"wred_profile" : "[WRED_PROFILE|AZURE_LOSSLESS]"
|
||||||
|
},
|
||||||
|
"{{ PORT_ALL|join(',') }}|0" : {
|
||||||
|
"scheduler" : "[SCHEDULER|scheduler.1]"
|
||||||
|
},
|
||||||
|
"{{ PORT_ALL|join(',') }}|1" : {
|
||||||
|
"scheduler" : "[SCHEDULER|scheduler.2]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/sai.profile
Executable file
2
device/inventec/x86_64-inventec_d6332-r0/INVENTEC-D6332/sai.profile
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-d6332-32x100G-SR4.config.bcm
|
||||||
|
SAI_NUM_ECMP_MEMBERS=32
|
@ -0,0 +1,668 @@
|
|||||||
|
### fix for sonic
|
||||||
|
ptp_ts_pll_fref=50000000
|
||||||
|
ptp_bs_fref_0=50000000
|
||||||
|
ptp_bs_fref_1=50000000
|
||||||
|
ifp_inports_support_enable=1
|
||||||
|
### end fix
|
||||||
|
|
||||||
|
core_clock_frequency=1525
|
||||||
|
dpp_clock_ratio=2:3
|
||||||
|
|
||||||
|
oversubscribe_mode=1
|
||||||
|
pbmp_xport_xe=0xc888888888888888e2222222222222222
|
||||||
|
|
||||||
|
l2_mem_entries=32768
|
||||||
|
l3_mem_entries=16384
|
||||||
|
fpem_mem_entries=16384
|
||||||
|
l2xmsg_mode=1
|
||||||
|
|
||||||
|
pdma_descriptor_prefetch_enable=1
|
||||||
|
|
||||||
|
port_flex_enable=1
|
||||||
|
stable_size=0x5500000
|
||||||
|
|
||||||
|
|
||||||
|
### Loopback port
|
||||||
|
#portmap_65=130:10
|
||||||
|
#portmap_131=131:10
|
||||||
|
|
||||||
|
portmap_1=1:100
|
||||||
|
portmap_5=5:100
|
||||||
|
portmap_9=9:100
|
||||||
|
portmap_13=13:100
|
||||||
|
portmap_17=17:100
|
||||||
|
portmap_21=21:100
|
||||||
|
portmap_25=25:100
|
||||||
|
portmap_29=29:100
|
||||||
|
|
||||||
|
### Pipeline0, halfpipe 1 (8x100G)
|
||||||
|
portmap_33=33:100
|
||||||
|
portmap_37=37:100
|
||||||
|
portmap_41=41:100
|
||||||
|
portmap_45=45:100
|
||||||
|
portmap_49=49:100
|
||||||
|
portmap_53=53:100
|
||||||
|
portmap_57=57:100
|
||||||
|
portmap_61=61:100
|
||||||
|
|
||||||
|
### Pipeline 1
|
||||||
|
### First management port
|
||||||
|
#portmap_66=129:10:m
|
||||||
|
### Second management port
|
||||||
|
#portmap_130=128:10:m
|
||||||
|
|
||||||
|
### Pipeline 1, halfpipe 0 (8x100G)
|
||||||
|
portmap_67=65:100
|
||||||
|
portmap_71=69:100
|
||||||
|
portmap_75=73:100
|
||||||
|
portmap_79=77:100
|
||||||
|
portmap_83=81:100
|
||||||
|
portmap_87=85:100
|
||||||
|
portmap_91=89:100
|
||||||
|
portmap_95=93:100
|
||||||
|
|
||||||
|
### Pipeline 1, halfpipe 1 (8x100G)
|
||||||
|
portmap_99=97:100
|
||||||
|
portmap_103=101:100
|
||||||
|
portmap_107=105:100
|
||||||
|
portmap_111=109:100
|
||||||
|
portmap_115=113:100
|
||||||
|
portmap_119=117:100
|
||||||
|
portmap_123=121:100
|
||||||
|
portmap_127=125:100
|
||||||
|
|
||||||
|
|
||||||
|
#dport part
|
||||||
|
dport_map_port_21=1
|
||||||
|
dport_map_port_17=2
|
||||||
|
dport_map_port_25=3
|
||||||
|
dport_map_port_29=4
|
||||||
|
dport_map_port_37=5
|
||||||
|
dport_map_port_33=6
|
||||||
|
dport_map_port_41=7
|
||||||
|
dport_map_port_45=8
|
||||||
|
dport_map_port_5=9
|
||||||
|
dport_map_port_1=10
|
||||||
|
dport_map_port_9=11
|
||||||
|
dport_map_port_13=12
|
||||||
|
dport_map_port_53=13
|
||||||
|
dport_map_port_49=14
|
||||||
|
dport_map_port_57=15
|
||||||
|
dport_map_port_61=16
|
||||||
|
dport_map_port_71=17
|
||||||
|
dport_map_port_67=18
|
||||||
|
dport_map_port_75=19
|
||||||
|
dport_map_port_79=20
|
||||||
|
dport_map_port_119=21
|
||||||
|
dport_map_port_115=22
|
||||||
|
dport_map_port_123=23
|
||||||
|
dport_map_port_127=24
|
||||||
|
dport_map_port_87=25
|
||||||
|
dport_map_port_83=26
|
||||||
|
dport_map_port_91=27
|
||||||
|
dport_map_port_95=28
|
||||||
|
dport_map_port_103=29
|
||||||
|
dport_map_port_99=30
|
||||||
|
dport_map_port_107=31
|
||||||
|
dport_map_port_111=32
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#Polarity flips
|
||||||
|
#FC0
|
||||||
|
phy_chain_rx_polarity_flip_physical{1.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{2.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{3.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{4.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{1.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{2.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{3.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{4.0}=0x1
|
||||||
|
|
||||||
|
#FC1
|
||||||
|
phy_chain_rx_polarity_flip_physical{5.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{6.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{7.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{8.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{5.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{6.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{7.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{8.0}=0x1
|
||||||
|
|
||||||
|
#FC2
|
||||||
|
phy_chain_rx_polarity_flip_physical{9.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{10.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{11.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{12.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{9.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{10.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{11.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{12.0}=0x1
|
||||||
|
|
||||||
|
#FC3
|
||||||
|
phy_chain_rx_polarity_flip_physical{13.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{14.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{15.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{16.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{13.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{14.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{15.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{16.0}=0x1
|
||||||
|
|
||||||
|
#FC4
|
||||||
|
phy_chain_rx_polarity_flip_physical{17.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{18.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{19.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{20.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{17.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{18.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{19.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{20.0}=0x1
|
||||||
|
|
||||||
|
#FC5
|
||||||
|
phy_chain_rx_polarity_flip_physical{21.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{22.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{23.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{24.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{21.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{22.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{23.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{24.0}=0x1
|
||||||
|
|
||||||
|
#FC6
|
||||||
|
phy_chain_rx_polarity_flip_physical{25.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{26.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{27.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{28.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{25.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{26.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{27.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{28.0}=0x1
|
||||||
|
|
||||||
|
#FC7
|
||||||
|
phy_chain_rx_polarity_flip_physical{29.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{30.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{31.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{32.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{29.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{30.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{31.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{32.0}=0x1
|
||||||
|
|
||||||
|
#FC8
|
||||||
|
phy_chain_rx_polarity_flip_physical{33.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{34.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{35.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{36.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{33.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{34.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{35.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{36.0}=0x1
|
||||||
|
|
||||||
|
#FC9
|
||||||
|
phy_chain_rx_polarity_flip_physical{37.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{38.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{39.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{40.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{37.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{38.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{39.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{40.0}=0x1
|
||||||
|
|
||||||
|
#FC10
|
||||||
|
phy_chain_rx_polarity_flip_physical{41.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{42.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{43.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{44.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{41.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{42.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{43.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{44.0}=0x1
|
||||||
|
|
||||||
|
#FC11
|
||||||
|
phy_chain_rx_polarity_flip_physical{45.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{46.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{47.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{48.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{45.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{46.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{47.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{48.0}=0x1
|
||||||
|
|
||||||
|
#FC12
|
||||||
|
phy_chain_rx_polarity_flip_physical{49.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{50.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{51.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{52.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{49.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{50.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{51.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{52.0}=0x1
|
||||||
|
|
||||||
|
#FC13
|
||||||
|
phy_chain_rx_polarity_flip_physical{53.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{54.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{55.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{56.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{53.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{54.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{55.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{56.0}=0x0
|
||||||
|
|
||||||
|
#FC14
|
||||||
|
phy_chain_rx_polarity_flip_physical{57.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{58.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{59.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{60.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{57.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{58.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{59.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{60.0}=0x0
|
||||||
|
|
||||||
|
#FC15
|
||||||
|
phy_chain_rx_polarity_flip_physical{61.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{62.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{63.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{64.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{61.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{62.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{63.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{64.0}=0x0
|
||||||
|
|
||||||
|
#FC16
|
||||||
|
phy_chain_rx_polarity_flip_physical{65.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{66.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{67.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{68.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{65.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{66.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{67.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{68.0}=0x1
|
||||||
|
|
||||||
|
#FC17
|
||||||
|
phy_chain_rx_polarity_flip_physical{69.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{70.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{71.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{72.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{69.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{70.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{71.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{72.0}=0x1
|
||||||
|
|
||||||
|
#FC18
|
||||||
|
phy_chain_rx_polarity_flip_physical{73.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{74.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{75.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{76.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{73.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{74.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{75.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{76.0}=0x1
|
||||||
|
|
||||||
|
#FC19
|
||||||
|
phy_chain_rx_polarity_flip_physical{77.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{78.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{79.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{80.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{77.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{78.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{79.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{80.0}=0x1
|
||||||
|
|
||||||
|
#FC20
|
||||||
|
phy_chain_rx_polarity_flip_physical{81.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{82.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{83.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{84.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{81.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{82.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{83.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{84.0}=0x1
|
||||||
|
|
||||||
|
#FC21
|
||||||
|
phy_chain_rx_polarity_flip_physical{85.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{86.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{87.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{88.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{85.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{86.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{87.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{88.0}=0x1
|
||||||
|
|
||||||
|
#FC22
|
||||||
|
phy_chain_rx_polarity_flip_physical{89.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{90.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{91.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{92.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{89.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{90.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{91.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{92.0}=0x1
|
||||||
|
|
||||||
|
#FC23
|
||||||
|
phy_chain_rx_polarity_flip_physical{93.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{94.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{95.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{96.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{93.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{94.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{95.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{96.0}=0x1
|
||||||
|
|
||||||
|
#FC24
|
||||||
|
phy_chain_rx_polarity_flip_physical{97.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{98.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{99.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{100.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{97.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{98.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{99.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{100.0}=0x1
|
||||||
|
|
||||||
|
#FC25
|
||||||
|
phy_chain_rx_polarity_flip_physical{101.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{102.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{103.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{104.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{101.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{102.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{103.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{104.0}=0x1
|
||||||
|
|
||||||
|
#FC26
|
||||||
|
phy_chain_rx_polarity_flip_physical{105.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{106.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{107.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{108.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{105.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{106.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{107.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{108.0}=0x1
|
||||||
|
|
||||||
|
#FC27
|
||||||
|
phy_chain_rx_polarity_flip_physical{109.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{110.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{111.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{112.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{109.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{110.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{111.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{112.0}=0x1
|
||||||
|
|
||||||
|
#FC28
|
||||||
|
phy_chain_rx_polarity_flip_physical{113.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{114.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{115.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{116.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{113.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{114.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{115.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{116.0}=0x1
|
||||||
|
|
||||||
|
#FC29
|
||||||
|
phy_chain_rx_polarity_flip_physical{117.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{118.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{119.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{120.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{117.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{118.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{119.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{120.0}=0x1
|
||||||
|
|
||||||
|
#FC30
|
||||||
|
phy_chain_rx_polarity_flip_physical{121.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{122.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{123.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{124.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{121.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{122.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{123.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{124.0}=0x1
|
||||||
|
|
||||||
|
#FC31
|
||||||
|
phy_chain_rx_polarity_flip_physical{125.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{126.0}=0x0
|
||||||
|
phy_chain_rx_polarity_flip_physical{127.0}=0x1
|
||||||
|
phy_chain_rx_polarity_flip_physical{128.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{125.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{126.0}=0x0
|
||||||
|
phy_chain_tx_polarity_flip_physical{127.0}=0x1
|
||||||
|
phy_chain_tx_polarity_flip_physical{128.0}=0x1
|
||||||
|
|
||||||
|
#lanes swap
|
||||||
|
#FC0~FC7
|
||||||
|
phy_chain_rx_lane_map_physical{1.0}=0x1302
|
||||||
|
phy_chain_tx_lane_map_physical{1.0}=0x2031
|
||||||
|
phy_chain_rx_lane_map_physical{5.0}=0x3120
|
||||||
|
phy_chain_tx_lane_map_physical{5.0}=0x2031
|
||||||
|
phy_chain_rx_lane_map_physical{9.0}=0x1302
|
||||||
|
phy_chain_tx_lane_map_physical{9.0}=0x2031
|
||||||
|
phy_chain_rx_lane_map_physical{13.0}=0x3120
|
||||||
|
phy_chain_tx_lane_map_physical{13.0}=0x0213
|
||||||
|
phy_chain_rx_lane_map_physical{17.0}=0x1302
|
||||||
|
phy_chain_tx_lane_map_physical{17.0}=0x2031
|
||||||
|
phy_chain_rx_lane_map_physical{21.0}=0x3120
|
||||||
|
phy_chain_tx_lane_map_physical{21.0}=0x0213
|
||||||
|
phy_chain_rx_lane_map_physical{25.0}=0x1302
|
||||||
|
phy_chain_tx_lane_map_physical{25.0}=0x2031
|
||||||
|
phy_chain_rx_lane_map_physical{29.0}=0x3120
|
||||||
|
phy_chain_tx_lane_map_physical{29.0}=0x0213
|
||||||
|
|
||||||
|
#FC8~FC15
|
||||||
|
phy_chain_rx_lane_map_physical{33.0}=0x1302
|
||||||
|
phy_chain_tx_lane_map_physical{33.0}=0x2031
|
||||||
|
phy_chain_rx_lane_map_physical{37.0}=0x3120
|
||||||
|
phy_chain_tx_lane_map_physical{37.0}=0x0213
|
||||||
|
phy_chain_rx_lane_map_physical{41.0}=0x1302
|
||||||
|
phy_chain_tx_lane_map_physical{41.0}=0x2031
|
||||||
|
phy_chain_rx_lane_map_physical{45.0}=0x3120
|
||||||
|
phy_chain_tx_lane_map_physical{45.0}=0x0213
|
||||||
|
phy_chain_rx_lane_map_physical{49.0}=0x2301
|
||||||
|
phy_chain_tx_lane_map_physical{49.0}=0x2031
|
||||||
|
phy_chain_rx_lane_map_physical{53.0}=0x3120
|
||||||
|
phy_chain_tx_lane_map_physical{53.0}=0x2031
|
||||||
|
phy_chain_rx_lane_map_physical{57.0}=0x1302
|
||||||
|
phy_chain_tx_lane_map_physical{57.0}=0x2031
|
||||||
|
phy_chain_rx_lane_map_physical{61.0}=0x3120
|
||||||
|
phy_chain_tx_lane_map_physical{61.0}=0x0213
|
||||||
|
|
||||||
|
#FC16~FC23
|
||||||
|
phy_chain_rx_lane_map_physical{65.0}=0x2031
|
||||||
|
phy_chain_tx_lane_map_physical{65.0}=0x1302
|
||||||
|
phy_chain_rx_lane_map_physical{69.0}=0x0213
|
||||||
|
phy_chain_tx_lane_map_physical{69.0}=0x3201
|
||||||
|
phy_chain_rx_lane_map_physical{73.0}=0x2031
|
||||||
|
phy_chain_tx_lane_map_physical{73.0}=0x1302
|
||||||
|
phy_chain_rx_lane_map_physical{77.0}=0x0123
|
||||||
|
phy_chain_tx_lane_map_physical{77.0}=0x3120
|
||||||
|
phy_chain_rx_lane_map_physical{81.0}=0x2031
|
||||||
|
phy_chain_tx_lane_map_physical{81.0}=0x1302
|
||||||
|
phy_chain_rx_lane_map_physical{85.0}=0x0213
|
||||||
|
phy_chain_tx_lane_map_physical{85.0}=0x1302
|
||||||
|
phy_chain_rx_lane_map_physical{89.0}=0x2031
|
||||||
|
phy_chain_tx_lane_map_physical{89.0}=0x1302
|
||||||
|
phy_chain_rx_lane_map_physical{93.0}=0x0213
|
||||||
|
phy_chain_tx_lane_map_physical{93.0}=0x3120
|
||||||
|
|
||||||
|
#FC24~FC31
|
||||||
|
phy_chain_rx_lane_map_physical{97.0}=0x2031
|
||||||
|
phy_chain_tx_lane_map_physical{97.0}=0x1302
|
||||||
|
phy_chain_rx_lane_map_physical{101.0}=0x2031
|
||||||
|
phy_chain_tx_lane_map_physical{101.0}=0x1302
|
||||||
|
phy_chain_rx_lane_map_physical{105.0}=0x2031
|
||||||
|
phy_chain_tx_lane_map_physical{105.0}=0x1302
|
||||||
|
phy_chain_rx_lane_map_physical{109.0}=0x0213
|
||||||
|
phy_chain_tx_lane_map_physical{109.0}=0x3120
|
||||||
|
phy_chain_rx_lane_map_physical{113.0}=0x2031
|
||||||
|
phy_chain_tx_lane_map_physical{113.0}=0x1302
|
||||||
|
phy_chain_rx_lane_map_physical{117.0}=0x0213
|
||||||
|
phy_chain_tx_lane_map_physical{117.0}=0x1302
|
||||||
|
phy_chain_rx_lane_map_physical{121.0}=0x2031
|
||||||
|
phy_chain_tx_lane_map_physical{121.0}=0x1302
|
||||||
|
phy_chain_rx_lane_map_physical{125.0}=0x0213
|
||||||
|
phy_chain_tx_lane_map_physical{125.0}=0x3120
|
||||||
|
|
||||||
|
|
||||||
|
serdes_preemphasis_lane0_21=0x11490A
|
||||||
|
serdes_preemphasis_lane1_21=0x11490A
|
||||||
|
serdes_preemphasis_lane2_21=0x11490A
|
||||||
|
serdes_preemphasis_lane3_21=0x11490A
|
||||||
|
serdes_preemphasis_lane0_17=0x12480A
|
||||||
|
serdes_preemphasis_lane1_17=0x12480A
|
||||||
|
serdes_preemphasis_lane2_17=0x12480A
|
||||||
|
serdes_preemphasis_lane3_17=0x12480A
|
||||||
|
serdes_preemphasis_lane0_25=0x104A0A
|
||||||
|
serdes_preemphasis_lane1_25=0x104A0A
|
||||||
|
serdes_preemphasis_lane2_25=0x104A0A
|
||||||
|
serdes_preemphasis_lane3_25=0x104A0A
|
||||||
|
serdes_preemphasis_lane0_29=0x104A0A
|
||||||
|
serdes_preemphasis_lane1_29=0x104A0A
|
||||||
|
serdes_preemphasis_lane2_29=0x104A0A
|
||||||
|
serdes_preemphasis_lane3_29=0x104A0A
|
||||||
|
serdes_preemphasis_lane0_37=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane1_37=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane2_37=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane3_37=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane0_33=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane1_33=0x104A0A
|
||||||
|
serdes_preemphasis_lane2_33=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane3_33=0x104A0A
|
||||||
|
serdes_preemphasis_lane0_41=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane1_41=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane2_41=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane3_41=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane0_45=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane1_45=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane2_45=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane3_45=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane0_5=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane1_5=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane2_5=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane3_5=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane0_1=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane1_1=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane2_1=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane3_1=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane0_9=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane1_9=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane2_9=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane3_9=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane0_13=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane1_13=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane2_13=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane3_13=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane0_53=0x05550A
|
||||||
|
serdes_preemphasis_lane1_53=0x07530A
|
||||||
|
serdes_preemphasis_lane2_53=0x05550A
|
||||||
|
serdes_preemphasis_lane3_53=0x07530A
|
||||||
|
serdes_preemphasis_lane0_49=0x07530A
|
||||||
|
serdes_preemphasis_lane1_49=0x0A500A
|
||||||
|
serdes_preemphasis_lane2_49=0x07530A
|
||||||
|
serdes_preemphasis_lane3_49=0x0A500A
|
||||||
|
serdes_preemphasis_lane0_57=0x05550A
|
||||||
|
serdes_preemphasis_lane1_57=0x05550A
|
||||||
|
serdes_preemphasis_lane2_57=0x05550A
|
||||||
|
serdes_preemphasis_lane3_57=0x07530A
|
||||||
|
serdes_preemphasis_lane0_61=0x07530A
|
||||||
|
serdes_preemphasis_lane1_61=0x07530A
|
||||||
|
serdes_preemphasis_lane2_61=0x07530A
|
||||||
|
serdes_preemphasis_lane3_61=0x0A500A
|
||||||
|
serdes_preemphasis_lane0_71=0x05550A
|
||||||
|
serdes_preemphasis_lane1_71=0x05550A
|
||||||
|
serdes_preemphasis_lane2_71=0x05550A
|
||||||
|
serdes_preemphasis_lane3_71=0x05550A
|
||||||
|
serdes_preemphasis_lane0_67=0x07530A
|
||||||
|
serdes_preemphasis_lane1_67=0x07530A
|
||||||
|
serdes_preemphasis_lane2_67=0x05550A
|
||||||
|
serdes_preemphasis_lane3_67=0x07530A
|
||||||
|
serdes_preemphasis_lane0_75=0x05550A
|
||||||
|
serdes_preemphasis_lane1_75=0x07530A
|
||||||
|
serdes_preemphasis_lane2_75=0x05550A
|
||||||
|
serdes_preemphasis_lane3_75=0x05550A
|
||||||
|
serdes_preemphasis_lane0_79=0x07530A
|
||||||
|
serdes_preemphasis_lane1_79=0x0A500A
|
||||||
|
serdes_preemphasis_lane2_79=0x07530A
|
||||||
|
serdes_preemphasis_lane3_79=0x0A500A
|
||||||
|
serdes_preemphasis_lane0_119=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane1_119=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane2_119=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane3_119=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane0_115=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane1_115=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane2_115=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane3_115=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane0_123=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane1_123=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane2_123=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane3_123=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane0_127=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane1_127=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane2_127=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane3_127=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane0_87=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane1_87=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane2_87=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane3_87=0x0E4C0A
|
||||||
|
serdes_preemphasis_lane0_83=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane1_83=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane2_83=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane3_83=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane0_91=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane1_91=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane2_91=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane3_91=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane0_95=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane1_95=0x104A0A
|
||||||
|
serdes_preemphasis_lane2_95=0x0F4B0A
|
||||||
|
serdes_preemphasis_lane3_95=0x104A0A
|
||||||
|
serdes_preemphasis_lane0_103=0x104A0A
|
||||||
|
serdes_preemphasis_lane1_103=0x104A0A
|
||||||
|
serdes_preemphasis_lane2_103=0x104A0A
|
||||||
|
serdes_preemphasis_lane3_103=0x104A0A
|
||||||
|
serdes_preemphasis_lane0_99=0x104A0A
|
||||||
|
serdes_preemphasis_lane1_99=0x104A0A
|
||||||
|
serdes_preemphasis_lane2_99=0x104A0A
|
||||||
|
serdes_preemphasis_lane3_99=0x104A0A
|
||||||
|
serdes_preemphasis_lane0_107=0x104A0A
|
||||||
|
serdes_preemphasis_lane1_107=0x11490A
|
||||||
|
serdes_preemphasis_lane2_107=0x104A0A
|
||||||
|
serdes_preemphasis_lane3_107=0x11490A
|
||||||
|
serdes_preemphasis_lane0_111=0x11490A
|
||||||
|
serdes_preemphasis_lane1_111=0x12480A
|
||||||
|
serdes_preemphasis_lane2_111=0x11490A
|
||||||
|
serdes_preemphasis_lane3_111=0x12480A
|
||||||
|
|
||||||
|
|
||||||
|
serdes_if_type_21=28
|
||||||
|
serdes_if_type_17=28
|
||||||
|
serdes_if_type_25=28
|
||||||
|
serdes_if_type_29=28
|
||||||
|
serdes_if_type_37=28
|
||||||
|
serdes_if_type_33=28
|
||||||
|
serdes_if_type_41=28
|
||||||
|
serdes_if_type_45=28
|
||||||
|
serdes_if_type_5=28
|
||||||
|
serdes_if_type_1=28
|
||||||
|
serdes_if_type_9=28
|
||||||
|
serdes_if_type_13=28
|
||||||
|
serdes_if_type_53=28
|
||||||
|
serdes_if_type_49=28
|
||||||
|
serdes_if_type_57=28
|
||||||
|
serdes_if_type_61=28
|
||||||
|
serdes_if_type_71=28
|
||||||
|
serdes_if_type_67=28
|
||||||
|
serdes_if_type_75=28
|
||||||
|
serdes_if_type_79=28
|
||||||
|
serdes_if_type_119=28
|
||||||
|
serdes_if_type_115=28
|
||||||
|
serdes_if_type_123=28
|
||||||
|
serdes_if_type_127=28
|
||||||
|
serdes_if_type_87=28
|
||||||
|
serdes_if_type_83=28
|
||||||
|
serdes_if_type_91=28
|
||||||
|
serdes_if_type_95=28
|
||||||
|
serdes_if_type_103=28
|
||||||
|
serdes_if_type_99=28
|
||||||
|
serdes_if_type_107=28
|
||||||
|
serdes_if_type_111=28
|
@ -0,0 +1,3 @@
|
|||||||
|
phy xe AN_X4_LD_BASE_ABIL3r BASE_25G_CR1_EN=1
|
||||||
|
phy ce AN_X4_LD_BASE_ABIL1r 0x01ff
|
||||||
|
setreg CLMAC_TX_MAC_SA 0x{{ DEVICE_METADATA.localhost.mac|replace(":","")}}
|
BIN
device/inventec/x86_64-inventec_d6332-r0/custom_led.bin
Normal file
BIN
device/inventec/x86_64-inventec_d6332-r0/custom_led.bin
Normal file
Binary file not shown.
1
device/inventec/x86_64-inventec_d6332-r0/default_sku
Normal file
1
device/inventec/x86_64-inventec_d6332-r0/default_sku
Normal file
@ -0,0 +1 @@
|
|||||||
|
INVENTEC-D6332 t1
|
4
device/inventec/x86_64-inventec_d6332-r0/installer.conf
Normal file
4
device/inventec/x86_64-inventec_d6332-r0/installer.conf
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
CONSOLE_PORT=0x3f8
|
||||||
|
CONSOLE_DEV=0
|
||||||
|
CONSOLE_SPEED=115200
|
||||||
|
VAR_LOG_SIZE=1024
|
@ -0,0 +1,5 @@
|
|||||||
|
led auto off
|
||||||
|
led stop
|
||||||
|
m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin
|
||||||
|
led auto on
|
||||||
|
led start
|
22
device/inventec/x86_64-inventec_d6332-r0/plugins/eeprom.py
Normal file
22
device/inventec/x86_64-inventec_d6332-r0/plugins/eeprom.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# Inventec d6356j
|
||||||
|
#
|
||||||
|
# Platform and model specific eeprom subclass, inherits from the base class,
|
||||||
|
# and provides the followings:
|
||||||
|
# - the eeprom format definition
|
||||||
|
# - specific encoder/decoder if there is special need
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
try:
|
||||||
|
from sonic_eeprom import eeprom_tlvinfo
|
||||||
|
except ImportError, e:
|
||||||
|
raise ImportError (str(e) + "- required module not found")
|
||||||
|
|
||||||
|
|
||||||
|
class board(eeprom_tlvinfo.TlvInfoDecoder):
|
||||||
|
|
||||||
|
def __init__(self, name, path, cpld_root, ro):
|
||||||
|
self.eeprom_path = "/sys/bus/i2c/devices/0-0055/eeprom"
|
||||||
|
super(board, self).__init__(self.eeprom_path, 0, '', True)
|
89
device/inventec/x86_64-inventec_d6332-r0/plugins/psuutil.py
Executable file
89
device/inventec/x86_64-inventec_d6332-r0/plugins/psuutil.py
Executable file
@ -0,0 +1,89 @@
|
|||||||
|
#
|
||||||
|
# psuutil.py
|
||||||
|
# Platform-specific PSU status interface for SONiC
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
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"""
|
||||||
|
|
||||||
|
"""CPLD address"""
|
||||||
|
PSU_DIR = "/sys/bus/i2c/devices/i2c-inv_cpld/"
|
||||||
|
|
||||||
|
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 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 of the PSU of which to query status
|
||||||
|
:return: Boolean, True if PSU is operating properly, False if PSU is\
|
||||||
|
faulty
|
||||||
|
"""
|
||||||
|
status = 0
|
||||||
|
attr_file ='psu'+ str(index)
|
||||||
|
attr_path = self.PSU_DIR +'/' + attr_file
|
||||||
|
normal_attr_value = '1:normal'
|
||||||
|
unpower_attr_value = '0:unpowered'
|
||||||
|
attr_value = self.get_attr_value(attr_path)
|
||||||
|
if (attr_value != 'ERR'):
|
||||||
|
# Check for PSU presence
|
||||||
|
if (attr_value == normal_attr_value):
|
||||||
|
status = 1
|
||||||
|
elif (attr_value == unpower_attr_value):
|
||||||
|
status = 0
|
||||||
|
return status
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
status = 0
|
||||||
|
attr_file ='psu'+ str(index)
|
||||||
|
attr_path = self.PSU_DIR +'/' + attr_file
|
||||||
|
normal_attr_value = '1:normal'
|
||||||
|
unpower_attr_value = '0:unpowered'
|
||||||
|
attr_value = self.get_attr_value(attr_path)
|
||||||
|
if (attr_value != 'ERR'):
|
||||||
|
# Check for PSU presence
|
||||||
|
if (attr_value == normal_attr_value):
|
||||||
|
status = 1
|
||||||
|
if (attr_value == unpower_attr_value):
|
||||||
|
status = 1
|
||||||
|
return status
|
348
device/inventec/x86_64-inventec_d6332-r0/plugins/sfputil.py
Executable file
348
device/inventec/x86_64-inventec_d6332-r0/plugins/sfputil.py
Executable file
@ -0,0 +1,348 @@
|
|||||||
|
# sfputil.py
|
||||||
|
#
|
||||||
|
# Platform-specific SFP transceiver interface for SONiC
|
||||||
|
#
|
||||||
|
|
||||||
|
try:
|
||||||
|
import time
|
||||||
|
import os, re, socket
|
||||||
|
from sonic_sfp.sfputilbase import SfpUtilBase
|
||||||
|
from collections import OrderedDict
|
||||||
|
from sonic_sfp.sff8472 import sff8472Dom
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError("%s - required module not found" % str(e))
|
||||||
|
|
||||||
|
SFP_TEMPE_OFFSET = 96
|
||||||
|
SFP_TEMPE_WIDTH = 2
|
||||||
|
SFP_VLOT_OFFSET = 98
|
||||||
|
SFP_VOLT_WIDTH = 2
|
||||||
|
SFP_CHANNL_MON_OFFSET = 100
|
||||||
|
SFP_CHANNL_MON_WIDTH = 6
|
||||||
|
|
||||||
|
NETLINK_KOBJECT_UEVENT = 15
|
||||||
|
monitor = None
|
||||||
|
|
||||||
|
class SWPSEventMonitor(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.recieved_events = OrderedDict()
|
||||||
|
self.socket = socket.socket(socket.AF_NETLINK, socket.SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self.socket.bind((os.getpid(), -1))
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.socket.close()
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self.start()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_value, traceback):
|
||||||
|
self.stop()
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
global monitor
|
||||||
|
while True:
|
||||||
|
for item in monitor.next_events():
|
||||||
|
yield item
|
||||||
|
|
||||||
|
def next_events(self):
|
||||||
|
data = self.socket.recv(16384)
|
||||||
|
event = {}
|
||||||
|
for item in data.split(b'\x00'):
|
||||||
|
if not item:
|
||||||
|
# check if we have an event and if we already received it
|
||||||
|
if event and event['SEQNUM'] not in self.recieved_events:
|
||||||
|
self.recieved_events[event['SEQNUM']] = None
|
||||||
|
if (len(self.recieved_events) > 100):
|
||||||
|
self.recieved_events.popitem(last=False)
|
||||||
|
yield event
|
||||||
|
event = {}
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
k, v = item.split(b'=', 1)
|
||||||
|
event[k.decode('ascii')] = v.decode('ascii')
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SfpUtil(SfpUtilBase):
|
||||||
|
"""Platform-specific SfpUtil class"""
|
||||||
|
|
||||||
|
PORT_START = 0
|
||||||
|
PORT_END = 31
|
||||||
|
PORTS_IN_BLOCK = 32
|
||||||
|
|
||||||
|
_port_to_eeprom_mapping = {}
|
||||||
|
port_to_i2cbus_mapping = {
|
||||||
|
0:12,
|
||||||
|
1:13,
|
||||||
|
2:14,
|
||||||
|
3:15,
|
||||||
|
4:16,
|
||||||
|
5:17,
|
||||||
|
6:18,
|
||||||
|
7:19,
|
||||||
|
8:20,
|
||||||
|
9:21,
|
||||||
|
10:22,
|
||||||
|
11:23,
|
||||||
|
12:24,
|
||||||
|
13:25,
|
||||||
|
14:26,
|
||||||
|
15:27,
|
||||||
|
16:28,
|
||||||
|
17:29,
|
||||||
|
18:30,
|
||||||
|
19:31,
|
||||||
|
20:32,
|
||||||
|
21:33,
|
||||||
|
22:34,
|
||||||
|
23:35,
|
||||||
|
24:36,
|
||||||
|
25:37,
|
||||||
|
26:38,
|
||||||
|
27:39,
|
||||||
|
28:40,
|
||||||
|
29:41,
|
||||||
|
30:42,
|
||||||
|
31:43
|
||||||
|
}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def port_start(self):
|
||||||
|
return self.PORT_START
|
||||||
|
|
||||||
|
@property
|
||||||
|
def port_end(self):
|
||||||
|
return self.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):
|
||||||
|
eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"
|
||||||
|
|
||||||
|
for x in range(0, self.port_end + 1):
|
||||||
|
port_eeprom_path = eeprom_path.format(self.port_to_i2cbus_mapping[x])
|
||||||
|
self.port_to_eeprom_mapping[x] = port_eeprom_path
|
||||||
|
self.phy_port_dict = {}
|
||||||
|
SfpUtilBase.__init__(self)
|
||||||
|
|
||||||
|
def get_presence(self, port_num):
|
||||||
|
# Check for invalid port_num
|
||||||
|
if port_num < self.port_start or port_num > self.port_end:
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
reg_file = open("/sys/class/swps/port"+str(port_num)+"/present")
|
||||||
|
except IOError as e:
|
||||||
|
print "Error: unable to open file: %s" % str(e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
reg_value = int(reg_file.readline().rstrip())
|
||||||
|
|
||||||
|
if reg_value == 0:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_low_power_mode(self, port_num):
|
||||||
|
# Check for invalid port_num
|
||||||
|
if port_num < self.port_start or port_num > self.port_end:
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod")
|
||||||
|
except IOError as e:
|
||||||
|
print "Error: unable to open file: %s" % str(e)
|
||||||
|
|
||||||
|
reg_value = int(reg_file.readline().rstrip())
|
||||||
|
|
||||||
|
if reg_value == 0:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def set_low_power_mode(self, port_num, lpmode):
|
||||||
|
# Check for invalid port_num
|
||||||
|
if port_num < self.port_start or port_num > self.port_end:
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
reg_file = open("/sys/class/swps/port"+str(port_num)+"/lpmod", "r+")
|
||||||
|
except IOError as e:
|
||||||
|
print "Error: unable to open file: %s" % str(e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
lpmode = int(reg_file.readline().rstrip())
|
||||||
|
|
||||||
|
# LPMode is active high; set or clear the bit accordingly
|
||||||
|
if lpmode is True:
|
||||||
|
reg_value = 1
|
||||||
|
else:
|
||||||
|
reg_value = 0
|
||||||
|
|
||||||
|
reg_file.write(hex(reg_value))
|
||||||
|
reg_file.close()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def reset(self, port_num):
|
||||||
|
QSFP_RESET_REGISTER_DEVICE_FILE = "/sys/class/swps/port"+str(port_num)+"/reset"
|
||||||
|
# Check for invalid port_num
|
||||||
|
if port_num < self.port_start or port_num > self.port_end:
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+")
|
||||||
|
except IOError as e:
|
||||||
|
print "Error: unable to open file: %s" % str(e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
reg_value = 0
|
||||||
|
reg_file.write(hex(reg_value))
|
||||||
|
reg_file.close()
|
||||||
|
|
||||||
|
# Sleep 2 second to allow it to settle
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
# Flip the value back write back to the register to take port out of reset
|
||||||
|
try:
|
||||||
|
reg_file = open(QSFP_RESET_REGISTER_DEVICE_FILE, "r+")
|
||||||
|
except IOError as e:
|
||||||
|
print "Error: unable to open file: %s" % str(e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
reg_value = 1
|
||||||
|
reg_file.write(hex(reg_value))
|
||||||
|
reg_file.close()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _get_port_eeprom_path(self, port_num, devid):
|
||||||
|
sysfs_i2c_adapter_base_path = "/sys/class/i2c-adapter"
|
||||||
|
if devid == self.IDENTITY_EEPROM_ADDR :
|
||||||
|
return SfpUtilBase._get_port_eeprom_path(self, port_num, devid)
|
||||||
|
else:
|
||||||
|
i2c_adapter_id = self._get_port_i2c_adapter_id(port_num)
|
||||||
|
if i2c_adapter_id is None:
|
||||||
|
print("Error getting i2c bus num")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Get i2c virtual bus path for the sfp
|
||||||
|
sysfs_sfp_i2c_adapter_path = "%s/i2c-%s" % (sysfs_i2c_adapter_base_path,
|
||||||
|
str(i2c_adapter_id))
|
||||||
|
|
||||||
|
# If i2c bus for port does not exist
|
||||||
|
if not os.path.exists(sysfs_sfp_i2c_adapter_path):
|
||||||
|
print("Could not find i2c bus %s. Driver not loaded?" % sysfs_sfp_i2c_adapter_path)
|
||||||
|
return None
|
||||||
|
|
||||||
|
sysfs_sfp_i2c_client_path = "%s/%s-00%s" % (sysfs_sfp_i2c_adapter_path,
|
||||||
|
str(i2c_adapter_id),
|
||||||
|
hex(devid)[-2:])
|
||||||
|
|
||||||
|
# If sfp device is not present on bus, Add it
|
||||||
|
if not os.path.exists(sysfs_sfp_i2c_client_path):
|
||||||
|
ret = self._add_new_sfp_device(
|
||||||
|
sysfs_sfp_i2c_adapter_path, devid)
|
||||||
|
if ret != 0:
|
||||||
|
print("Error adding sfp device")
|
||||||
|
return None
|
||||||
|
|
||||||
|
sysfs_sfp_i2c_client_eeprom_path = "%s/eeprom" % sysfs_sfp_i2c_client_path
|
||||||
|
|
||||||
|
return sysfs_sfp_i2c_client_eeprom_path
|
||||||
|
|
||||||
|
def get_transceiver_dom_info_dict(self, port_num):
|
||||||
|
if port_num in self.qsfp_ports:
|
||||||
|
return SfpUtilBase.get_transceiver_dom_info_dict(self, port_num)
|
||||||
|
else:
|
||||||
|
transceiver_dom_info_dict = {}
|
||||||
|
|
||||||
|
offset = 0
|
||||||
|
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, "rb")
|
||||||
|
except IOError:
|
||||||
|
print("Error: reading sysfs file %s" % file_path)
|
||||||
|
return None
|
||||||
|
|
||||||
|
sfpd_obj = sff8472Dom(None, 1)
|
||||||
|
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:
|
||||||
|
print(dom_temperature_raw)
|
||||||
|
dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0)
|
||||||
|
print(dom_temperature_data)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
dom_voltage_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_VLOT_OFFSET), SFP_VOLT_WIDTH)
|
||||||
|
if dom_voltage_raw is not None:
|
||||||
|
print(dom_voltage_raw)
|
||||||
|
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=0):
|
||||||
|
global monitor
|
||||||
|
port_dict = {}
|
||||||
|
with SWPSEventMonitor() as monitor:
|
||||||
|
for event in monitor:
|
||||||
|
if event['SUBSYSTEM'] == 'swps':
|
||||||
|
#print('SWPS event. From %s, ACTION %s, IF_TYPE %s, IF_LANE %s' % (event['DEVPATH'], event['ACTION'], event['IF_TYPE'], event['IF_LANE']))
|
||||||
|
portname = event['DEVPATH'].split("/")[-1]
|
||||||
|
rc = re.match(r"port(?P<num>\d+)",portname)
|
||||||
|
if rc is not None:
|
||||||
|
if event['ACTION'] == "remove":
|
||||||
|
remove_num = int(rc.group("num"))
|
||||||
|
port_dict[remove_num] = "0"
|
||||||
|
#port_dict[rc.group("num")] = "0"
|
||||||
|
if event['ACTION'] == "add":
|
||||||
|
add_num = int(rc.group("num"))
|
||||||
|
port_dict[add_num] = "1"
|
||||||
|
#port_dict[rc.group("num")] = "1"
|
||||||
|
return True, port_dict
|
||||||
|
return False, {}
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"skip_ledd": true
|
||||||
|
}
|
69
device/inventec/x86_64-inventec_d6332-r0/sensors.conf
Normal file
69
device/inventec/x86_64-inventec_d6332-r0/sensors.conf
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# libsensors configuration file
|
||||||
|
chip "ucd90160-*"
|
||||||
|
ignore temp1
|
||||||
|
|
||||||
|
chip "pch_haswell-*"
|
||||||
|
label temp1 "PCH Temperature"
|
||||||
|
|
||||||
|
chip "tmp75-i2c-*-0048"
|
||||||
|
label temp1 "CPU Board Temperature"
|
||||||
|
|
||||||
|
chip "tmp75-i2c-*-004a"
|
||||||
|
label temp1 "FrontSide Temperature"
|
||||||
|
|
||||||
|
chip "tmp75-i2c-*-004e"
|
||||||
|
label temp1 "NearASIC Temperature"
|
||||||
|
|
||||||
|
chip "tmp75-i2c-*-004d"
|
||||||
|
label temp1 "RearSide Temperature"
|
||||||
|
|
||||||
|
chip "inv_cpld-i2c-*-77"
|
||||||
|
label fan1 "FanModule1 Front RPM"
|
||||||
|
label fan2 "FanModule1 Rear RPM"
|
||||||
|
label fan3 "FanModule2 Front RPM"
|
||||||
|
label fan4 "FanModule2 Rear RPM"
|
||||||
|
label fan5 "FanModule3 Front RPM"
|
||||||
|
label fan6 "FanModule3 Rear RPM"
|
||||||
|
label fan7 "FanModule4 Front RPM"
|
||||||
|
label fan8 "FanModule4 Rear RPM"
|
||||||
|
label fan9 "FanModule5 Front RPM"
|
||||||
|
label fan10 "FanModule5 Rear RPM"
|
||||||
|
label pwm1 "FanModule1 PWM (0-255)"
|
||||||
|
label pwm2 "FanModule2 PWM (0-255)"
|
||||||
|
label pwm3 "FanModule3 PWM (0-255)"
|
||||||
|
label pwm4 "FanModule4 PWM (0-255)"
|
||||||
|
label pwm5 "FanModule5 PWM (0-255)"
|
||||||
|
label temp1 "ASIC Temperature"
|
||||||
|
|
||||||
|
chip "pmbus-i2c-*-005a"
|
||||||
|
ignore power3
|
||||||
|
ignore curr3
|
||||||
|
ignore fan2
|
||||||
|
label fan1 "PSU1 Fan RPM"
|
||||||
|
label temp1 "PSU1 Temperature1"
|
||||||
|
label temp2 "PSU1 Temperature2"
|
||||||
|
label temp3 "PSU1 Temperature3"
|
||||||
|
label in1 "PSU1 Input Voltage"
|
||||||
|
label curr1 "PSU1 Input Current"
|
||||||
|
label power1 "PSU1 Input Power"
|
||||||
|
label in2 "PSU1 Output Voltage"
|
||||||
|
label curr2 "PSU1 Output Current"
|
||||||
|
label power2 "PSU1 Output Power"
|
||||||
|
label pwm1 "PSU1 PWM (0-100)"
|
||||||
|
|
||||||
|
chip "pmbus-i2c-*-005b"
|
||||||
|
ignore power3
|
||||||
|
ignore curr3
|
||||||
|
ignore fan2
|
||||||
|
label fan1 "PSU2 Fan RPM"
|
||||||
|
label temp1 "PSU2 Temperature1"
|
||||||
|
label temp2 "PSU2 Temperature2"
|
||||||
|
label temp3 "PSU2 Temperature3"
|
||||||
|
label in1 "PSU2 Input Voltage"
|
||||||
|
label curr1 "PSU2 Input Current"
|
||||||
|
label power1 "PSU2 Input Power"
|
||||||
|
label in2 "PSU2 Output Voltage"
|
||||||
|
label curr2 "PSU2 Output Current"
|
||||||
|
label power2 "PSU2 Output Power"
|
||||||
|
label pwm1 "PSU2 PWM (0-100)"
|
||||||
|
|
@ -39,6 +39,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
|
|||||||
$(INVENTEC_D7054Q28B_PLATFORM_MODULE) \
|
$(INVENTEC_D7054Q28B_PLATFORM_MODULE) \
|
||||||
$(INVENTEC_D7264Q28B_PLATFORM_MODULE) \
|
$(INVENTEC_D7264Q28B_PLATFORM_MODULE) \
|
||||||
$(INVENTEC_D6356_PLATFORM_MODULE) \
|
$(INVENTEC_D6356_PLATFORM_MODULE) \
|
||||||
|
$(INVENTEC_D6332_PLATFORM_MODULE) \
|
||||||
$(CEL_DX010_PLATFORM_MODULE) \
|
$(CEL_DX010_PLATFORM_MODULE) \
|
||||||
$(CEL_HALIBURTON_PLATFORM_MODULE) \
|
$(CEL_HALIBURTON_PLATFORM_MODULE) \
|
||||||
$(CEL_SEASTONE2_PLATFORM_MODULE) \
|
$(CEL_SEASTONE2_PLATFORM_MODULE) \
|
||||||
|
@ -6,6 +6,7 @@ INVENTEC_D6254QS_PLATFORM_MODULE_VERSION = 1.1.0
|
|||||||
INVENTEC_D6556_PLATFORM_MODULE_VERSION = 1.1.0
|
INVENTEC_D6556_PLATFORM_MODULE_VERSION = 1.1.0
|
||||||
INVENTEC_D6356_PLATFORM_MODULE_VERSION = 1.1.0
|
INVENTEC_D6356_PLATFORM_MODULE_VERSION = 1.1.0
|
||||||
INVENTEC_D7264Q28B_PLATFORM_MODULE_VERSION = 1.1.0
|
INVENTEC_D7264Q28B_PLATFORM_MODULE_VERSION = 1.1.0
|
||||||
|
INVENTEC_D6332_PLATFORM_MODULE_VERSION = 1.1.0
|
||||||
|
|
||||||
export INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION
|
export INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION
|
||||||
export INVENTEC_D7054Q28B_PLATFORM_MODULE_VERSION
|
export INVENTEC_D7054Q28B_PLATFORM_MODULE_VERSION
|
||||||
@ -13,6 +14,7 @@ export INVENTEC_D6254QS_PLATFORM_MODULE_VERSION
|
|||||||
export INVENTEC_D6556_PLATFORM_MODULE_VERSION
|
export INVENTEC_D6556_PLATFORM_MODULE_VERSION
|
||||||
export INVENTEC_D6356_PLATFORM_MODULE_VERSION
|
export INVENTEC_D6356_PLATFORM_MODULE_VERSION
|
||||||
export INVENTEC_D7264Q28B_PLATFORM_MODULE_VERSION
|
export INVENTEC_D7264Q28B_PLATFORM_MODULE_VERSION
|
||||||
|
export INVENTEC_D6332_PLATFORM_MODULE_VERSION
|
||||||
|
|
||||||
INVENTEC_D7032Q28B_PLATFORM_MODULE = platform-modules-d7032q28b_$(INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION)_amd64.deb
|
INVENTEC_D7032Q28B_PLATFORM_MODULE = platform-modules-d7032q28b_$(INVENTEC_D7032Q28B_PLATFORM_MODULE_VERSION)_amd64.deb
|
||||||
$(INVENTEC_D7032Q28B_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-inventec
|
$(INVENTEC_D7032Q28B_PLATFORM_MODULE)_SRC_PATH = $(PLATFORM_PATH)/sonic-platform-modules-inventec
|
||||||
@ -40,3 +42,7 @@ INVENTEC_D7264Q28B_PLATFORM_MODULE = platform-modules-d7264q28b_$(INVENTEC_D7264
|
|||||||
$(INVENTEC_D7264Q28B_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d7264q28b-r0
|
$(INVENTEC_D7264Q28B_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d7264q28b-r0
|
||||||
$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D7264Q28B_PLATFORM_MODULE)))
|
$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D7264Q28B_PLATFORM_MODULE)))
|
||||||
|
|
||||||
|
INVENTEC_D6332_PLATFORM_MODULE = platform-modules-d6332_$(INVENTEC_D6332_PLATFORM_MODULE_VERSION)_amd64.deb
|
||||||
|
$(INVENTEC_D6332_PLATFORM_MODULE)_PLATFORM = x86_64-inventec_d6332-r0
|
||||||
|
$(eval $(call add_extra_package,$(INVENTEC_D7032Q28B_PLATFORM_MODULE),$(INVENTEC_D6332_PLATFORM_MODULE)))
|
||||||
|
|
||||||
|
8
platform/broadcom/sonic-platform-modules-inventec/d6332/modules/Makefile
Executable file
8
platform/broadcom/sonic-platform-modules-inventec/d6332/modules/Makefile
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
obj-m += gpio-ich.o
|
||||||
|
obj-m += lpc_ich.o
|
||||||
|
obj-m += inv_cpld.o
|
||||||
|
obj-m += inv_platform.o
|
||||||
|
obj-m += inv_eeprom.o
|
||||||
|
obj-m += i2c-mux-pca9541.o
|
||||||
|
obj-m += swps.o
|
||||||
|
swps-objs := inv_swps.o inv_mux.o io_expander.o transceiver.o
|
@ -0,0 +1,513 @@
|
|||||||
|
/*
|
||||||
|
* Intel ICH6-10, Series 5 and 6, Atom C2000 (Avoton/Rangeley) GPIO driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Extreme Engineering Solutions.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||||
|
|
||||||
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/gpio.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/mfd/lpc_ich.h>
|
||||||
|
|
||||||
|
#define DRV_NAME "gpio_ich"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GPIO register offsets in GPIO I/O space.
|
||||||
|
* Each chunk of 32 GPIOs is manipulated via its own USE_SELx, IO_SELx, and
|
||||||
|
* LVLx registers. Logic in the read/write functions takes a register and
|
||||||
|
* an absolute bit number and determines the proper register offset and bit
|
||||||
|
* number in that register. For example, to read the value of GPIO bit 50
|
||||||
|
* the code would access offset ichx_regs[2(=GPIO_LVL)][1(=50/32)],
|
||||||
|
* bit 18 (50%32).
|
||||||
|
*/
|
||||||
|
enum GPIO_REG {
|
||||||
|
GPIO_USE_SEL = 0,
|
||||||
|
GPIO_IO_SEL,
|
||||||
|
GPIO_LVL,
|
||||||
|
GPO_BLINK
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u8 ichx_regs[4][3] = {
|
||||||
|
{0x00, 0x30, 0x40}, /* USE_SEL[1-3] offsets */
|
||||||
|
{0x04, 0x34, 0x44}, /* IO_SEL[1-3] offsets */
|
||||||
|
{0x0c, 0x38, 0x48}, /* LVL[1-3] offsets */
|
||||||
|
{0x18, 0x18, 0x18}, /* BLINK offset */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u8 ichx_reglen[3] = {
|
||||||
|
0x30, 0x10, 0x10,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u8 avoton_regs[4][3] = {
|
||||||
|
{0x00, 0x80, 0x00},
|
||||||
|
{0x04, 0x84, 0x00},
|
||||||
|
{0x08, 0x88, 0x00},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u8 avoton_reglen[3] = {
|
||||||
|
0x10, 0x10, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ICHX_WRITE(val, reg, base_res) outl(val, (reg) + (base_res)->start)
|
||||||
|
#define ICHX_READ(reg, base_res) inl((reg) + (base_res)->start)
|
||||||
|
|
||||||
|
struct ichx_desc {
|
||||||
|
/* Max GPIO pins the chipset can have */
|
||||||
|
uint ngpio;
|
||||||
|
|
||||||
|
/* chipset registers */
|
||||||
|
const u8 (*regs)[3];
|
||||||
|
const u8 *reglen;
|
||||||
|
|
||||||
|
/* GPO_BLINK is available on this chipset */
|
||||||
|
bool have_blink;
|
||||||
|
|
||||||
|
/* Whether the chipset has GPIO in GPE0_STS in the PM IO region */
|
||||||
|
bool uses_gpe0;
|
||||||
|
|
||||||
|
/* USE_SEL is bogus on some chipsets, eg 3100 */
|
||||||
|
u32 use_sel_ignore[3];
|
||||||
|
|
||||||
|
/* Some chipsets have quirks, let these use their own request/get */
|
||||||
|
int (*request)(struct gpio_chip *chip, unsigned offset);
|
||||||
|
int (*get)(struct gpio_chip *chip, unsigned offset);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some chipsets don't let reading output values on GPIO_LVL register
|
||||||
|
* this option allows driver caching written output values
|
||||||
|
*/
|
||||||
|
bool use_outlvl_cache;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
spinlock_t lock;
|
||||||
|
struct platform_device *dev;
|
||||||
|
struct gpio_chip chip;
|
||||||
|
struct resource *gpio_base; /* GPIO IO base */
|
||||||
|
struct resource *pm_base; /* Power Mangagment IO base */
|
||||||
|
struct ichx_desc *desc; /* Pointer to chipset-specific description */
|
||||||
|
u32 orig_gpio_ctrl; /* Orig CTRL value, used to restore on exit */
|
||||||
|
u8 use_gpio; /* Which GPIO groups are usable */
|
||||||
|
int outlvl_cache[3]; /* cached output values */
|
||||||
|
} ichx_priv;
|
||||||
|
|
||||||
|
static int modparam_gpiobase = 0; /* dynamic */
|
||||||
|
module_param_named(gpiobase, modparam_gpiobase, int, 0444);
|
||||||
|
MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, "
|
||||||
|
"which is the default.");
|
||||||
|
|
||||||
|
static int ichx_write_bit(int reg, unsigned nr, int val, int verify)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
u32 data, tmp;
|
||||||
|
int reg_nr = nr / 32;
|
||||||
|
int bit = nr & 0x1f;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ichx_priv.lock, flags);
|
||||||
|
|
||||||
|
if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache)
|
||||||
|
data = ichx_priv.outlvl_cache[reg_nr];
|
||||||
|
else
|
||||||
|
data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr],
|
||||||
|
ichx_priv.gpio_base);
|
||||||
|
|
||||||
|
if (val)
|
||||||
|
data |= 1 << bit;
|
||||||
|
else
|
||||||
|
data &= ~(1 << bit);
|
||||||
|
ICHX_WRITE(data, ichx_priv.desc->regs[reg][reg_nr],
|
||||||
|
ichx_priv.gpio_base);
|
||||||
|
if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache)
|
||||||
|
ichx_priv.outlvl_cache[reg_nr] = data;
|
||||||
|
|
||||||
|
tmp = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr],
|
||||||
|
ichx_priv.gpio_base);
|
||||||
|
if (verify && data != tmp)
|
||||||
|
ret = -EPERM;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&ichx_priv.lock, flags);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ichx_read_bit(int reg, unsigned nr)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
u32 data;
|
||||||
|
int reg_nr = nr / 32;
|
||||||
|
int bit = nr & 0x1f;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ichx_priv.lock, flags);
|
||||||
|
|
||||||
|
data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr],
|
||||||
|
ichx_priv.gpio_base);
|
||||||
|
|
||||||
|
if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache)
|
||||||
|
data = ichx_priv.outlvl_cache[reg_nr] | data;
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&ichx_priv.lock, flags);
|
||||||
|
|
||||||
|
return data & (1 << bit) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr)
|
||||||
|
{
|
||||||
|
return !!(ichx_priv.use_gpio & (1 << (nr / 32)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ichx_gpio_get_direction(struct gpio_chip *gpio, unsigned nr)
|
||||||
|
{
|
||||||
|
return ichx_read_bit(GPIO_IO_SEL, nr) ? GPIOF_DIR_IN : GPIOF_DIR_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Try setting pin as an input and verify it worked since many pins
|
||||||
|
* are output-only.
|
||||||
|
*/
|
||||||
|
if (ichx_write_bit(GPIO_IO_SEL, nr, 1, 1))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
|
||||||
|
int val)
|
||||||
|
{
|
||||||
|
/* Disable blink hardware which is available for GPIOs from 0 to 31. */
|
||||||
|
if (nr < 32 && ichx_priv.desc->have_blink)
|
||||||
|
ichx_write_bit(GPO_BLINK, nr, 0, 0);
|
||||||
|
|
||||||
|
/* Set GPIO output value. */
|
||||||
|
ichx_write_bit(GPIO_LVL, nr, val, 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try setting pin as an output and verify it worked since many pins
|
||||||
|
* are input-only.
|
||||||
|
*/
|
||||||
|
if (ichx_write_bit(GPIO_IO_SEL, nr, 0, 1))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ichx_gpio_get(struct gpio_chip *chip, unsigned nr)
|
||||||
|
{
|
||||||
|
return ichx_read_bit(GPIO_LVL, nr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
u32 data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GPI 0 - 15 need to be read from the power management registers on
|
||||||
|
* a ICH6/3100 bridge.
|
||||||
|
*/
|
||||||
|
if (nr < 16) {
|
||||||
|
if (!ichx_priv.pm_base)
|
||||||
|
return -ENXIO;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&ichx_priv.lock, flags);
|
||||||
|
|
||||||
|
/* GPI 0 - 15 are latched, write 1 to clear*/
|
||||||
|
ICHX_WRITE(1 << (16 + nr), 0, ichx_priv.pm_base);
|
||||||
|
data = ICHX_READ(0, ichx_priv.pm_base);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&ichx_priv.lock, flags);
|
||||||
|
|
||||||
|
return (data >> 16) & (1 << nr) ? 1 : 0;
|
||||||
|
} else {
|
||||||
|
return ichx_gpio_get(chip, nr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr)
|
||||||
|
{
|
||||||
|
if (!ichx_gpio_check_available(chip, nr))
|
||||||
|
return -ENXIO;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note we assume the BIOS properly set a bridge's USE value. Some
|
||||||
|
* chips (eg Intel 3100) have bogus USE values though, so first see if
|
||||||
|
* the chipset's USE value can be trusted for this specific bit.
|
||||||
|
* If it can't be trusted, assume that the pin can be used as a GPIO.
|
||||||
|
*/
|
||||||
|
if (ichx_priv.desc->use_sel_ignore[nr / 32] & (1 << (nr & 0x1f)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ich6_gpio_request(struct gpio_chip *chip, unsigned nr)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Fixups for bits 16 and 17 are necessary on the Intel ICH6/3100
|
||||||
|
* bridge as they are controlled by USE register bits 0 and 1. See
|
||||||
|
* "Table 704 GPIO_USE_SEL1 register" in the i3100 datasheet for
|
||||||
|
* additional info.
|
||||||
|
*/
|
||||||
|
if (nr == 16 || nr == 17)
|
||||||
|
nr -= 16;
|
||||||
|
|
||||||
|
return ichx_gpio_request(chip, nr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ichx_gpio_set(struct gpio_chip *chip, unsigned nr, int val)
|
||||||
|
{
|
||||||
|
ichx_write_bit(GPIO_LVL, nr, val, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ichx_gpiolib_setup(struct gpio_chip *chip)
|
||||||
|
{
|
||||||
|
chip->owner = THIS_MODULE;
|
||||||
|
chip->label = DRV_NAME;
|
||||||
|
chip->parent = &ichx_priv.dev->dev;
|
||||||
|
|
||||||
|
/* Allow chip-specific overrides of request()/get() */
|
||||||
|
chip->request = ichx_priv.desc->request ?
|
||||||
|
ichx_priv.desc->request : ichx_gpio_request;
|
||||||
|
chip->get = ichx_priv.desc->get ?
|
||||||
|
ichx_priv.desc->get : ichx_gpio_get;
|
||||||
|
|
||||||
|
chip->set = ichx_gpio_set;
|
||||||
|
chip->get_direction = ichx_gpio_get_direction;
|
||||||
|
chip->direction_input = ichx_gpio_direction_input;
|
||||||
|
chip->direction_output = ichx_gpio_direction_output;
|
||||||
|
chip->base = modparam_gpiobase;
|
||||||
|
chip->ngpio = ichx_priv.desc->ngpio;
|
||||||
|
chip->can_sleep = false;
|
||||||
|
chip->dbg_show = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ICH6-based, 631xesb-based */
|
||||||
|
static struct ichx_desc ich6_desc = {
|
||||||
|
/* Bridges using the ICH6 controller need fixups for GPIO 0 - 17 */
|
||||||
|
.request = ich6_gpio_request,
|
||||||
|
.get = ich6_gpio_get,
|
||||||
|
|
||||||
|
/* GPIO 0-15 are read in the GPE0_STS PM register */
|
||||||
|
.uses_gpe0 = true,
|
||||||
|
|
||||||
|
.ngpio = 50,
|
||||||
|
.have_blink = true,
|
||||||
|
.regs = ichx_regs,
|
||||||
|
.reglen = ichx_reglen,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Intel 3100 */
|
||||||
|
static struct ichx_desc i3100_desc = {
|
||||||
|
/*
|
||||||
|
* Bits 16,17, 20 of USE_SEL and bit 16 of USE_SEL2 always read 0 on
|
||||||
|
* the Intel 3100. See "Table 712. GPIO Summary Table" of 3100
|
||||||
|
* Datasheet for more info.
|
||||||
|
*/
|
||||||
|
.use_sel_ignore = {0x00130000, 0x00010000, 0x0},
|
||||||
|
|
||||||
|
/* The 3100 needs fixups for GPIO 0 - 17 */
|
||||||
|
.request = ich6_gpio_request,
|
||||||
|
.get = ich6_gpio_get,
|
||||||
|
|
||||||
|
/* GPIO 0-15 are read in the GPE0_STS PM register */
|
||||||
|
.uses_gpe0 = true,
|
||||||
|
|
||||||
|
.ngpio = 50,
|
||||||
|
.regs = ichx_regs,
|
||||||
|
.reglen = ichx_reglen,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ICH7 and ICH8-based */
|
||||||
|
static struct ichx_desc ich7_desc = {
|
||||||
|
.ngpio = 50,
|
||||||
|
.have_blink = true,
|
||||||
|
.regs = ichx_regs,
|
||||||
|
.reglen = ichx_reglen,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ICH9-based */
|
||||||
|
static struct ichx_desc ich9_desc = {
|
||||||
|
.ngpio = 61,
|
||||||
|
.have_blink = true,
|
||||||
|
.regs = ichx_regs,
|
||||||
|
.reglen = ichx_reglen,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ICH10-based - Consumer/corporate versions have different amount of GPIO */
|
||||||
|
static struct ichx_desc ich10_cons_desc = {
|
||||||
|
.ngpio = 61,
|
||||||
|
.have_blink = true,
|
||||||
|
.regs = ichx_regs,
|
||||||
|
.reglen = ichx_reglen,
|
||||||
|
};
|
||||||
|
static struct ichx_desc ich10_corp_desc = {
|
||||||
|
.ngpio = 72,
|
||||||
|
.have_blink = true,
|
||||||
|
.regs = ichx_regs,
|
||||||
|
.reglen = ichx_reglen,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Intel 5 series, 6 series, 3400 series, and C200 series */
|
||||||
|
static struct ichx_desc intel5_desc = {
|
||||||
|
.ngpio = 76,
|
||||||
|
.regs = ichx_regs,
|
||||||
|
.reglen = ichx_reglen,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Avoton */
|
||||||
|
static struct ichx_desc avoton_desc = {
|
||||||
|
/* Avoton has only 59 GPIOs, but we assume the first set of register
|
||||||
|
* (Core) has 32 instead of 31 to keep gpio-ich compliance
|
||||||
|
*/
|
||||||
|
.ngpio = 60,
|
||||||
|
.regs = avoton_regs,
|
||||||
|
.reglen = avoton_reglen,
|
||||||
|
.use_outlvl_cache = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ichx_gpio_request_regions(struct device *dev,
|
||||||
|
struct resource *res_base, const char *name, u8 use_gpio)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!res_base || !res_base->start || !res_base->end)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) {
|
||||||
|
if (!(use_gpio & (1 << i)))
|
||||||
|
continue;
|
||||||
|
if (!devm_request_region(dev,
|
||||||
|
res_base->start + ichx_priv.desc->regs[0][i],
|
||||||
|
ichx_priv.desc->reglen[i], name))
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ichx_gpio_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct resource *res_base, *res_pm;
|
||||||
|
int err;
|
||||||
|
struct lpc_ich_info *ich_info = dev_get_platdata(&pdev->dev);
|
||||||
|
|
||||||
|
if (!ich_info)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
ichx_priv.dev = pdev;
|
||||||
|
|
||||||
|
switch (ich_info->gpio_version) {
|
||||||
|
case ICH_I3100_GPIO:
|
||||||
|
ichx_priv.desc = &i3100_desc;
|
||||||
|
break;
|
||||||
|
case ICH_V5_GPIO:
|
||||||
|
ichx_priv.desc = &intel5_desc;
|
||||||
|
break;
|
||||||
|
case ICH_V6_GPIO:
|
||||||
|
ichx_priv.desc = &ich6_desc;
|
||||||
|
break;
|
||||||
|
case ICH_V7_GPIO:
|
||||||
|
ichx_priv.desc = &ich7_desc;
|
||||||
|
break;
|
||||||
|
case ICH_V9_GPIO:
|
||||||
|
ichx_priv.desc = &ich9_desc;
|
||||||
|
break;
|
||||||
|
case ICH_V10CORP_GPIO:
|
||||||
|
ichx_priv.desc = &ich10_corp_desc;
|
||||||
|
break;
|
||||||
|
case ICH_V10CONS_GPIO:
|
||||||
|
ichx_priv.desc = &ich10_cons_desc;
|
||||||
|
break;
|
||||||
|
case AVOTON_GPIO:
|
||||||
|
ichx_priv.desc = &avoton_desc;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock_init(&ichx_priv.lock);
|
||||||
|
res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO);
|
||||||
|
ichx_priv.use_gpio = ich_info->use_gpio;
|
||||||
|
err = ichx_gpio_request_regions(&pdev->dev, res_base, pdev->name,
|
||||||
|
ichx_priv.use_gpio);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
ichx_priv.gpio_base = res_base;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If necessary, determine the I/O address of ACPI/power management
|
||||||
|
* registers which are needed to read the the GPE0 register for GPI pins
|
||||||
|
* 0 - 15 on some chipsets.
|
||||||
|
*/
|
||||||
|
if (!ichx_priv.desc->uses_gpe0)
|
||||||
|
goto init;
|
||||||
|
|
||||||
|
res_pm = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPE0);
|
||||||
|
if (!res_pm) {
|
||||||
|
pr_warn("ACPI BAR is unavailable, GPI 0 - 15 unavailable\n");
|
||||||
|
goto init;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!devm_request_region(&pdev->dev, res_pm->start,
|
||||||
|
resource_size(res_pm), pdev->name)) {
|
||||||
|
pr_warn("ACPI BAR is busy, GPI 0 - 15 unavailable\n");
|
||||||
|
goto init;
|
||||||
|
}
|
||||||
|
|
||||||
|
ichx_priv.pm_base = res_pm;
|
||||||
|
|
||||||
|
init:
|
||||||
|
ichx_gpiolib_setup(&ichx_priv.chip);
|
||||||
|
err = gpiochip_add_data(&ichx_priv.chip, NULL);
|
||||||
|
if (err) {
|
||||||
|
pr_err("Failed to register GPIOs\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_info("GPIO from %d to %d on %s\n", ichx_priv.chip.base,
|
||||||
|
ichx_priv.chip.base + ichx_priv.chip.ngpio - 1, DRV_NAME);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ichx_gpio_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
gpiochip_remove(&ichx_priv.chip);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver ichx_gpio_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = DRV_NAME,
|
||||||
|
},
|
||||||
|
.probe = ichx_gpio_probe,
|
||||||
|
.remove = ichx_gpio_remove,
|
||||||
|
};
|
||||||
|
|
||||||
|
module_platform_driver(ichx_gpio_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Peter Tyser <ptyser@xes-inc.com>");
|
||||||
|
MODULE_DESCRIPTION("GPIO interface for Intel ICH series");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_ALIAS("platform:"DRV_NAME);
|
@ -0,0 +1,290 @@
|
|||||||
|
/*
|
||||||
|
* Bitbanging I2C bus driver using the GPIO API
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Atmel Corporation
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/i2c-algo-bit.h>
|
||||||
|
#include <linux/i2c-gpio.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/gpio.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_gpio.h>
|
||||||
|
|
||||||
|
struct i2c_gpio_private_data {
|
||||||
|
struct i2c_adapter adap;
|
||||||
|
struct i2c_algo_bit_data bit_data;
|
||||||
|
struct i2c_gpio_platform_data pdata;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Toggle SDA by changing the direction of the pin */
|
||||||
|
static void i2c_gpio_setsda_dir(void *data, int state)
|
||||||
|
{
|
||||||
|
struct i2c_gpio_platform_data *pdata = data;
|
||||||
|
|
||||||
|
if (state)
|
||||||
|
gpio_direction_input(pdata->sda_pin);
|
||||||
|
else
|
||||||
|
gpio_direction_output(pdata->sda_pin, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Toggle SDA by changing the output value of the pin. This is only
|
||||||
|
* valid for pins configured as open drain (i.e. setting the value
|
||||||
|
* high effectively turns off the output driver.)
|
||||||
|
*/
|
||||||
|
static void i2c_gpio_setsda_val(void *data, int state)
|
||||||
|
{
|
||||||
|
struct i2c_gpio_platform_data *pdata = data;
|
||||||
|
|
||||||
|
gpio_set_value(pdata->sda_pin, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Toggle SCL by changing the direction of the pin. */
|
||||||
|
static void i2c_gpio_setscl_dir(void *data, int state)
|
||||||
|
{
|
||||||
|
struct i2c_gpio_platform_data *pdata = data;
|
||||||
|
|
||||||
|
if (state)
|
||||||
|
gpio_direction_input(pdata->scl_pin);
|
||||||
|
else
|
||||||
|
gpio_direction_output(pdata->scl_pin, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Toggle SCL by changing the output value of the pin. This is used
|
||||||
|
* for pins that are configured as open drain and for output-only
|
||||||
|
* pins. The latter case will break the i2c protocol, but it will
|
||||||
|
* often work in practice.
|
||||||
|
*/
|
||||||
|
static void i2c_gpio_setscl_val(void *data, int state)
|
||||||
|
{
|
||||||
|
struct i2c_gpio_platform_data *pdata = data;
|
||||||
|
|
||||||
|
gpio_set_value(pdata->scl_pin, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int i2c_gpio_getsda(void *data)
|
||||||
|
{
|
||||||
|
struct i2c_gpio_platform_data *pdata = data;
|
||||||
|
|
||||||
|
return gpio_get_value(pdata->sda_pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int i2c_gpio_getscl(void *data)
|
||||||
|
{
|
||||||
|
struct i2c_gpio_platform_data *pdata = data;
|
||||||
|
|
||||||
|
return gpio_get_value(pdata->scl_pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int of_i2c_gpio_get_pins(struct device_node *np,
|
||||||
|
unsigned int *sda_pin, unsigned int *scl_pin)
|
||||||
|
{
|
||||||
|
if (of_gpio_count(np) < 2)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
*sda_pin = of_get_gpio(np, 0);
|
||||||
|
*scl_pin = of_get_gpio(np, 1);
|
||||||
|
|
||||||
|
if (*sda_pin == -EPROBE_DEFER || *scl_pin == -EPROBE_DEFER)
|
||||||
|
return -EPROBE_DEFER;
|
||||||
|
|
||||||
|
if (!gpio_is_valid(*sda_pin) || !gpio_is_valid(*scl_pin)) {
|
||||||
|
pr_err("%s: invalid GPIO pins, sda=%d/scl=%d\n",
|
||||||
|
np->full_name, *sda_pin, *scl_pin);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void of_i2c_gpio_get_props(struct device_node *np,
|
||||||
|
struct i2c_gpio_platform_data *pdata)
|
||||||
|
{
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
of_property_read_u32(np, "i2c-gpio,delay-us", &pdata->udelay);
|
||||||
|
|
||||||
|
if (!of_property_read_u32(np, "i2c-gpio,timeout-ms", ®))
|
||||||
|
pdata->timeout = msecs_to_jiffies(reg);
|
||||||
|
|
||||||
|
pdata->sda_is_open_drain =
|
||||||
|
of_property_read_bool(np, "i2c-gpio,sda-open-drain");
|
||||||
|
pdata->scl_is_open_drain =
|
||||||
|
of_property_read_bool(np, "i2c-gpio,scl-open-drain");
|
||||||
|
pdata->scl_is_output_only =
|
||||||
|
of_property_read_bool(np, "i2c-gpio,scl-output-only");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int i2c_gpio_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct i2c_gpio_private_data *priv;
|
||||||
|
struct i2c_gpio_platform_data *pdata;
|
||||||
|
struct i2c_algo_bit_data *bit_data;
|
||||||
|
struct i2c_adapter *adap;
|
||||||
|
unsigned int sda_pin, scl_pin;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* First get the GPIO pins; if it fails, we'll defer the probe. */
|
||||||
|
if (pdev->dev.of_node) {
|
||||||
|
ret = of_i2c_gpio_get_pins(pdev->dev.of_node,
|
||||||
|
&sda_pin, &scl_pin);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
if (!dev_get_platdata(&pdev->dev))
|
||||||
|
return -ENXIO;
|
||||||
|
pdata = dev_get_platdata(&pdev->dev);
|
||||||
|
sda_pin = pdata->sda_pin;
|
||||||
|
scl_pin = pdata->scl_pin;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = devm_gpio_request(&pdev->dev, sda_pin, "sda");
|
||||||
|
if (ret) {
|
||||||
|
if (ret == -EINVAL)
|
||||||
|
ret = -EPROBE_DEFER; /* Try again later */
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ret = devm_gpio_request(&pdev->dev, scl_pin, "scl");
|
||||||
|
if (ret) {
|
||||||
|
if (ret == -EINVAL)
|
||||||
|
ret = -EPROBE_DEFER; /* Try again later */
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||||
|
if (!priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
adap = &priv->adap;
|
||||||
|
bit_data = &priv->bit_data;
|
||||||
|
pdata = &priv->pdata;
|
||||||
|
|
||||||
|
if (pdev->dev.of_node) {
|
||||||
|
pdata->sda_pin = sda_pin;
|
||||||
|
pdata->scl_pin = scl_pin;
|
||||||
|
of_i2c_gpio_get_props(pdev->dev.of_node, pdata);
|
||||||
|
} else {
|
||||||
|
memcpy(pdata, dev_get_platdata(&pdev->dev), sizeof(*pdata));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdata->sda_is_open_drain) {
|
||||||
|
gpio_direction_output(pdata->sda_pin, 1);
|
||||||
|
bit_data->setsda = i2c_gpio_setsda_val;
|
||||||
|
} else {
|
||||||
|
gpio_direction_input(pdata->sda_pin);
|
||||||
|
bit_data->setsda = i2c_gpio_setsda_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdata->scl_is_open_drain || pdata->scl_is_output_only) {
|
||||||
|
gpio_direction_output(pdata->scl_pin, 1);
|
||||||
|
bit_data->setscl = i2c_gpio_setscl_val;
|
||||||
|
} else {
|
||||||
|
gpio_direction_input(pdata->scl_pin);
|
||||||
|
bit_data->setscl = i2c_gpio_setscl_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pdata->scl_is_output_only)
|
||||||
|
bit_data->getscl = i2c_gpio_getscl;
|
||||||
|
bit_data->getsda = i2c_gpio_getsda;
|
||||||
|
|
||||||
|
if (pdata->udelay)
|
||||||
|
bit_data->udelay = pdata->udelay;
|
||||||
|
else if (pdata->scl_is_output_only)
|
||||||
|
bit_data->udelay = 50; /* 10 kHz */
|
||||||
|
else
|
||||||
|
bit_data->udelay = 5; /* 100 kHz */
|
||||||
|
|
||||||
|
if (pdata->timeout)
|
||||||
|
bit_data->timeout = pdata->timeout;
|
||||||
|
else
|
||||||
|
bit_data->timeout = HZ / 10; /* 100 ms */
|
||||||
|
|
||||||
|
bit_data->data = pdata;
|
||||||
|
|
||||||
|
adap->owner = THIS_MODULE;
|
||||||
|
if (pdev->dev.of_node)
|
||||||
|
strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));
|
||||||
|
else
|
||||||
|
snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
|
||||||
|
|
||||||
|
adap->algo_data = bit_data;
|
||||||
|
adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||||
|
adap->dev.parent = &pdev->dev;
|
||||||
|
adap->dev.of_node = pdev->dev.of_node;
|
||||||
|
|
||||||
|
adap->nr = pdev->id;
|
||||||
|
ret = i2c_bit_add_numbered_bus(adap);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, priv);
|
||||||
|
|
||||||
|
dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n",
|
||||||
|
pdata->sda_pin, pdata->scl_pin,
|
||||||
|
pdata->scl_is_output_only
|
||||||
|
? ", no clock stretching" : "");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int i2c_gpio_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct i2c_gpio_private_data *priv;
|
||||||
|
struct i2c_adapter *adap;
|
||||||
|
|
||||||
|
priv = platform_get_drvdata(pdev);
|
||||||
|
adap = &priv->adap;
|
||||||
|
|
||||||
|
i2c_del_adapter(adap);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_OF)
|
||||||
|
static const struct of_device_id i2c_gpio_dt_ids[] = {
|
||||||
|
{ .compatible = "i2c-gpio", },
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_DEVICE_TABLE(of, i2c_gpio_dt_ids);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct platform_driver i2c_gpio_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "i2c-gpio",
|
||||||
|
.of_match_table = of_match_ptr(i2c_gpio_dt_ids),
|
||||||
|
},
|
||||||
|
.probe = i2c_gpio_probe,
|
||||||
|
.remove = i2c_gpio_remove,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init i2c_gpio_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = platform_driver_register(&i2c_gpio_driver);
|
||||||
|
if (ret)
|
||||||
|
printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
subsys_initcall(i2c_gpio_init);
|
||||||
|
|
||||||
|
static void __exit i2c_gpio_exit(void)
|
||||||
|
{
|
||||||
|
platform_driver_unregister(&i2c_gpio_driver);
|
||||||
|
}
|
||||||
|
module_exit(i2c_gpio_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
|
||||||
|
MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_ALIAS("platform:i2c-gpio");
|
@ -0,0 +1,355 @@
|
|||||||
|
/*
|
||||||
|
* I2C multiplexer driver for PCA9541 bus master selector
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010 Ericsson AB.
|
||||||
|
*
|
||||||
|
* Author: Guenter Roeck <linux@roeck-us.net>
|
||||||
|
*
|
||||||
|
* Derived from:
|
||||||
|
* pca954x.c
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it>
|
||||||
|
* Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it>
|
||||||
|
*
|
||||||
|
* This file is licensed under the terms of the GNU General Public
|
||||||
|
* License version 2. This program is licensed "as is" without any
|
||||||
|
* warranty of any kind, whether express or implied.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/i2c-mux.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/platform_data/pca954x.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The PCA9541 is a bus master selector. It supports two I2C masters connected
|
||||||
|
* to a single slave bus.
|
||||||
|
*
|
||||||
|
* Before each bus transaction, a master has to acquire bus ownership. After the
|
||||||
|
* transaction is complete, bus ownership has to be released. This fits well
|
||||||
|
* into the I2C multiplexer framework, which provides select and release
|
||||||
|
* functions for this purpose. For this reason, this driver is modeled as
|
||||||
|
* single-channel I2C bus multiplexer.
|
||||||
|
*
|
||||||
|
* This driver assumes that the two bus masters are controlled by two different
|
||||||
|
* hosts. If a single host controls both masters, platform code has to ensure
|
||||||
|
* that only one of the masters is instantiated at any given time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PCA9541_CONTROL 0x01
|
||||||
|
#define PCA9541_ISTAT 0x02
|
||||||
|
|
||||||
|
#define PCA9541_CTL_MYBUS (1 << 0)
|
||||||
|
#define PCA9541_CTL_NMYBUS (1 << 1)
|
||||||
|
#define PCA9541_CTL_BUSON (1 << 2)
|
||||||
|
#define PCA9541_CTL_NBUSON (1 << 3)
|
||||||
|
#define PCA9541_CTL_BUSINIT (1 << 4)
|
||||||
|
#define PCA9541_CTL_TESTON (1 << 6)
|
||||||
|
#define PCA9541_CTL_NTESTON (1 << 7)
|
||||||
|
|
||||||
|
#define PCA9541_ISTAT_INTIN (1 << 0)
|
||||||
|
#define PCA9541_ISTAT_BUSINIT (1 << 1)
|
||||||
|
#define PCA9541_ISTAT_BUSOK (1 << 2)
|
||||||
|
#define PCA9541_ISTAT_BUSLOST (1 << 3)
|
||||||
|
#define PCA9541_ISTAT_MYTEST (1 << 6)
|
||||||
|
#define PCA9541_ISTAT_NMYTEST (1 << 7)
|
||||||
|
|
||||||
|
#define BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON)
|
||||||
|
#define MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS)
|
||||||
|
#define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS)
|
||||||
|
#define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON)
|
||||||
|
|
||||||
|
/* arbitration timeouts, in jiffies */
|
||||||
|
#define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */
|
||||||
|
#define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */
|
||||||
|
|
||||||
|
/* arbitration retry delays, in us */
|
||||||
|
#define SELECT_DELAY_SHORT 50
|
||||||
|
#define SELECT_DELAY_LONG 1000
|
||||||
|
|
||||||
|
struct pca9541 {
|
||||||
|
struct i2c_client *client;
|
||||||
|
unsigned long select_timeout;
|
||||||
|
unsigned long arb_timeout;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct i2c_device_id pca9541_id[] = {
|
||||||
|
{"pca9541", 0},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_DEVICE_TABLE(i2c, pca9541_id);
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
static const struct of_device_id pca9541_of_match[] = {
|
||||||
|
{ .compatible = "nxp,pca9541" },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, pca9541_of_match);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
|
||||||
|
* as they will try to lock the adapter a second time.
|
||||||
|
*/
|
||||||
|
static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val)
|
||||||
|
{
|
||||||
|
struct i2c_adapter *adap = client->adapter;
|
||||||
|
union i2c_smbus_data data = { .byte = val };
|
||||||
|
|
||||||
|
return __i2c_smbus_xfer(adap, client->addr, client->flags,
|
||||||
|
I2C_SMBUS_WRITE, command,
|
||||||
|
I2C_SMBUS_BYTE_DATA, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer()
|
||||||
|
* as they will try to lock adapter a second time.
|
||||||
|
*/
|
||||||
|
static int pca9541_reg_read(struct i2c_client *client, u8 command)
|
||||||
|
{
|
||||||
|
struct i2c_adapter *adap = client->adapter;
|
||||||
|
union i2c_smbus_data data;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = __i2c_smbus_xfer(adap, client->addr, client->flags,
|
||||||
|
I2C_SMBUS_READ, command,
|
||||||
|
I2C_SMBUS_BYTE_DATA, &data);
|
||||||
|
|
||||||
|
return ret ?: data.byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arbitration management functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Release bus. Also reset NTESTON and BUSINIT if it was set. */
|
||||||
|
static void pca9541_release_bus(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
int reg;
|
||||||
|
|
||||||
|
reg = pca9541_reg_read(client, PCA9541_CONTROL);
|
||||||
|
if (reg >= 0 && !busoff(reg) && mybus(reg))
|
||||||
|
pca9541_reg_write(client, PCA9541_CONTROL,
|
||||||
|
(reg & PCA9541_CTL_NBUSON) >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arbitration is defined as a two-step process. A bus master can only activate
|
||||||
|
* the slave bus if it owns it; otherwise it has to request ownership first.
|
||||||
|
* This multi-step process ensures that access contention is resolved
|
||||||
|
* gracefully.
|
||||||
|
*
|
||||||
|
* Bus Ownership Other master Action
|
||||||
|
* state requested access
|
||||||
|
* ----------------------------------------------------
|
||||||
|
* off - yes wait for arbitration timeout or
|
||||||
|
* for other master to drop request
|
||||||
|
* off no no take ownership
|
||||||
|
* off yes no turn on bus
|
||||||
|
* on yes - done
|
||||||
|
* on no - wait for arbitration timeout or
|
||||||
|
* for other master to release bus
|
||||||
|
*
|
||||||
|
* The main contention point occurs if the slave bus is off and both masters
|
||||||
|
* request ownership at the same time. In this case, one master will turn on
|
||||||
|
* the slave bus, believing that it owns it. The other master will request
|
||||||
|
* bus ownership. Result is that the bus is turned on, and master which did
|
||||||
|
* _not_ own the slave bus before ends up owning it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Control commands per PCA9541 datasheet */
|
||||||
|
static const u8 pca9541_control[16] = {
|
||||||
|
4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Channel arbitration
|
||||||
|
*
|
||||||
|
* Return values:
|
||||||
|
* <0: error
|
||||||
|
* 0 : bus not acquired
|
||||||
|
* 1 : bus acquired
|
||||||
|
*/
|
||||||
|
static int pca9541_arbitrate(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct i2c_mux_core *muxc = i2c_get_clientdata(client);
|
||||||
|
struct pca9541 *data = i2c_mux_priv(muxc);
|
||||||
|
int reg;
|
||||||
|
|
||||||
|
reg = pca9541_reg_read(client, PCA9541_CONTROL);
|
||||||
|
if (reg < 0)
|
||||||
|
return reg;
|
||||||
|
|
||||||
|
if (busoff(reg)) {
|
||||||
|
int istat;
|
||||||
|
/*
|
||||||
|
* Bus is off. Request ownership or turn it on unless
|
||||||
|
* other master requested ownership.
|
||||||
|
*/
|
||||||
|
istat = pca9541_reg_read(client, PCA9541_ISTAT);
|
||||||
|
if (!(istat & PCA9541_ISTAT_NMYTEST)
|
||||||
|
|| time_is_before_eq_jiffies(data->arb_timeout)) {
|
||||||
|
/*
|
||||||
|
* Other master did not request ownership,
|
||||||
|
* or arbitration timeout expired. Take the bus.
|
||||||
|
*/
|
||||||
|
pca9541_reg_write(client,
|
||||||
|
PCA9541_CONTROL,
|
||||||
|
pca9541_control[reg & 0x0f]
|
||||||
|
| PCA9541_CTL_NTESTON);
|
||||||
|
data->select_timeout = SELECT_DELAY_SHORT;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Other master requested ownership.
|
||||||
|
* Set extra long timeout to give it time to acquire it.
|
||||||
|
*/
|
||||||
|
data->select_timeout = SELECT_DELAY_LONG * 2;
|
||||||
|
}
|
||||||
|
} else if (mybus(reg)) {
|
||||||
|
/*
|
||||||
|
* Bus is on, and we own it. We are done with acquisition.
|
||||||
|
* Reset NTESTON and BUSINIT, then return success.
|
||||||
|
*/
|
||||||
|
if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT))
|
||||||
|
pca9541_reg_write(client,
|
||||||
|
PCA9541_CONTROL,
|
||||||
|
reg & ~(PCA9541_CTL_NTESTON
|
||||||
|
| PCA9541_CTL_BUSINIT));
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Other master owns the bus.
|
||||||
|
* If arbitration timeout has expired, force ownership.
|
||||||
|
* Otherwise request it.
|
||||||
|
*/
|
||||||
|
data->select_timeout = SELECT_DELAY_LONG;
|
||||||
|
if (time_is_before_eq_jiffies(data->arb_timeout)) {
|
||||||
|
/* Time is up, take the bus and reset it. */
|
||||||
|
pca9541_reg_write(client,
|
||||||
|
PCA9541_CONTROL,
|
||||||
|
pca9541_control[reg & 0x0f]
|
||||||
|
| PCA9541_CTL_BUSINIT
|
||||||
|
| PCA9541_CTL_NTESTON);
|
||||||
|
} else {
|
||||||
|
/* Request bus ownership if needed */
|
||||||
|
if (!(reg & PCA9541_CTL_NTESTON))
|
||||||
|
pca9541_reg_write(client,
|
||||||
|
PCA9541_CONTROL,
|
||||||
|
reg | PCA9541_CTL_NTESTON);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan)
|
||||||
|
{
|
||||||
|
struct pca9541 *data = i2c_mux_priv(muxc);
|
||||||
|
struct i2c_client *client = data->client;
|
||||||
|
int ret;
|
||||||
|
unsigned long timeout = jiffies + ARB2_TIMEOUT;
|
||||||
|
/* give up after this time */
|
||||||
|
|
||||||
|
data->arb_timeout = jiffies + ARB_TIMEOUT;
|
||||||
|
/* force bus ownership after this time */
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = pca9541_arbitrate(client);
|
||||||
|
if (ret)
|
||||||
|
return ret < 0 ? ret : 0;
|
||||||
|
|
||||||
|
if (data->select_timeout == SELECT_DELAY_SHORT)
|
||||||
|
udelay(data->select_timeout);
|
||||||
|
else
|
||||||
|
msleep(data->select_timeout / 1000);
|
||||||
|
} while (time_is_after_eq_jiffies(timeout));
|
||||||
|
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan)
|
||||||
|
{
|
||||||
|
struct pca9541 *data = i2c_mux_priv(muxc);
|
||||||
|
struct i2c_client *client = data->client;
|
||||||
|
|
||||||
|
pca9541_release_bus(client);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I2C init/probing/exit functions
|
||||||
|
*/
|
||||||
|
static int pca9541_probe(struct i2c_client *client,
|
||||||
|
const struct i2c_device_id *id)
|
||||||
|
{
|
||||||
|
struct i2c_adapter *adap = client->adapter;
|
||||||
|
struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||||
|
struct i2c_mux_core *muxc;
|
||||||
|
struct pca9541 *data;
|
||||||
|
int force;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I2C accesses are unprotected here.
|
||||||
|
* We have to lock the I2C segment before releasing the bus.
|
||||||
|
*/
|
||||||
|
i2c_lock_bus(adap, I2C_LOCK_SEGMENT);
|
||||||
|
pca9541_release_bus(client);
|
||||||
|
i2c_unlock_bus(adap, I2C_LOCK_SEGMENT);
|
||||||
|
|
||||||
|
/* Create mux adapter */
|
||||||
|
|
||||||
|
force = 0;
|
||||||
|
if (pdata)
|
||||||
|
force = pdata->modes[0].adap_id;
|
||||||
|
muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data),
|
||||||
|
I2C_MUX_ARBITRATOR,
|
||||||
|
pca9541_select_chan, pca9541_release_chan);
|
||||||
|
if (!muxc)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
data = i2c_mux_priv(muxc);
|
||||||
|
data->client = client;
|
||||||
|
|
||||||
|
i2c_set_clientdata(client, muxc);
|
||||||
|
|
||||||
|
ret = i2c_mux_add_adapter(muxc, force, 0, 0);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
dev_info(&client->dev, "registered master selector for I2C %s\n",
|
||||||
|
client->name);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pca9541_remove(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct i2c_mux_core *muxc = i2c_get_clientdata(client);
|
||||||
|
|
||||||
|
i2c_mux_del_adapters(muxc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct i2c_driver pca9541_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "pca9541",
|
||||||
|
.of_match_table = of_match_ptr(pca9541_of_match),
|
||||||
|
},
|
||||||
|
.probe = pca9541_probe,
|
||||||
|
.remove = pca9541_remove,
|
||||||
|
.id_table = pca9541_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
module_i2c_driver(pca9541_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
|
||||||
|
MODULE_DESCRIPTION("PCA9541 I2C master selector driver");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,180 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* Size of EEPROM in bytes */
|
||||||
|
#define EEPROM_SIZE 256
|
||||||
|
|
||||||
|
#define SLICE_BITS (6)
|
||||||
|
#define SLICE_SIZE (1 << SLICE_BITS)
|
||||||
|
#define SLICE_NUM (EEPROM_SIZE/SLICE_SIZE)
|
||||||
|
|
||||||
|
/* Each client has this additional data */
|
||||||
|
struct eeprom_data {
|
||||||
|
struct mutex update_lock;
|
||||||
|
u8 valid; /* bitfield, bit!=0 if slice is valid */
|
||||||
|
unsigned long last_updated[SLICE_NUM]; /* In jiffies, 8 slices */
|
||||||
|
u8 data[EEPROM_SIZE]; /* Register values */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void inv_eeprom_update_client(struct i2c_client *client, u8 slice)
|
||||||
|
{
|
||||||
|
struct eeprom_data *data = i2c_get_clientdata(client);
|
||||||
|
int i, j;
|
||||||
|
int ret;
|
||||||
|
int addr;
|
||||||
|
|
||||||
|
|
||||||
|
mutex_lock(&data->update_lock);
|
||||||
|
|
||||||
|
if (!(data->valid & (1 << slice)) ||
|
||||||
|
time_after(jiffies, data->last_updated[slice] + 300 * HZ)) {
|
||||||
|
dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
|
||||||
|
|
||||||
|
addr = slice << SLICE_BITS;
|
||||||
|
|
||||||
|
ret = i2c_smbus_write_byte_data(client, ((u8)addr >> 8) & 0xFF, (u8)addr & 0xFF);
|
||||||
|
/* select the eeprom address */
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(&client->dev, "address set failed\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = slice << SLICE_BITS; i < (slice + 1) << SLICE_BITS; i+= SLICE_SIZE) {
|
||||||
|
for (j = i; j < (i+SLICE_SIZE); j++) {
|
||||||
|
int res;
|
||||||
|
|
||||||
|
res = i2c_smbus_read_byte(client);
|
||||||
|
if (res < 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->data[j] = res & 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data->last_updated[slice] = jiffies;
|
||||||
|
data->valid |= (1 << slice);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
mutex_unlock(&data->update_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t inv_eeprom_read(struct file *filp, struct kobject *kobj,
|
||||||
|
struct bin_attribute *bin_attr,
|
||||||
|
char *buf, loff_t off, size_t count)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
|
||||||
|
struct eeprom_data *data = i2c_get_clientdata(client);
|
||||||
|
u8 slice;
|
||||||
|
|
||||||
|
|
||||||
|
if (off > EEPROM_SIZE) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (off + count > EEPROM_SIZE) {
|
||||||
|
count = EEPROM_SIZE - off;
|
||||||
|
}
|
||||||
|
if (count == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only refresh slices which contain requested bytes */
|
||||||
|
for (slice = off >> SLICE_BITS; slice <= (off + count - 1) >> SLICE_BITS; slice++) {
|
||||||
|
inv_eeprom_update_client(client, slice);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf, &data->data[off], count);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct bin_attribute inv_eeprom_attr = {
|
||||||
|
.attr = {
|
||||||
|
.name = "eeprom",
|
||||||
|
.mode = S_IRUGO,
|
||||||
|
},
|
||||||
|
.size = EEPROM_SIZE,
|
||||||
|
.read = inv_eeprom_read,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int inv_eeprom_probe(struct i2c_client *client,
|
||||||
|
const struct i2c_device_id *id)
|
||||||
|
{
|
||||||
|
struct eeprom_data *data;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(data->data, 0xff, EEPROM_SIZE);
|
||||||
|
i2c_set_clientdata(client, data);
|
||||||
|
mutex_init(&data->update_lock);
|
||||||
|
|
||||||
|
/* create the sysfs eeprom file */
|
||||||
|
err = sysfs_create_bin_file(&client->dev.kobj, &inv_eeprom_attr);
|
||||||
|
if (err) {
|
||||||
|
goto exit_kfree;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
exit_kfree:
|
||||||
|
kfree(data);
|
||||||
|
exit:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int inv_eeprom_remove(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
sysfs_remove_bin_file(&client->dev.kobj, &inv_eeprom_attr);
|
||||||
|
kfree(i2c_get_clientdata(client));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct i2c_device_id inv_eeprom_id[] = {
|
||||||
|
{ "inv_eeprom", 0 },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct i2c_driver inv_eeprom_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "inv_eeprom",
|
||||||
|
},
|
||||||
|
.probe = inv_eeprom_probe,
|
||||||
|
.remove = inv_eeprom_remove,
|
||||||
|
.id_table = inv_eeprom_id,
|
||||||
|
};
|
||||||
|
|
||||||
|
module_i2c_driver(inv_eeprom_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Inventec");
|
||||||
|
MODULE_DESCRIPTION("Inventec D6556 Mother Board EEPROM driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
@ -0,0 +1,545 @@
|
|||||||
|
#include <asm/io.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/gpio.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include "io_expander.h"
|
||||||
|
#include "inv_mux.h"
|
||||||
|
|
||||||
|
/* For build single module using (Ex: ONL platform) */
|
||||||
|
#include <linux/module.h>
|
||||||
|
//#include <linux/inventec/d5254/io_expander.h>
|
||||||
|
//#include <linux/inventec/d5254/inv_mux.h>
|
||||||
|
|
||||||
|
static struct mux_obj_s *mux_head_p = NULL;
|
||||||
|
|
||||||
|
/* ========== MUX object functions ==========
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
_setup_i2c_value(struct mux_obj_s *self, int offset, int value){
|
||||||
|
|
||||||
|
return i2c_smbus_write_byte_data(self->i2c_client_p, offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
_setup_i2c_client(struct mux_obj_s *self, int chan_id, int addr){
|
||||||
|
|
||||||
|
struct i2c_adapter *adap = NULL;
|
||||||
|
char *emsg = "ERR";
|
||||||
|
|
||||||
|
adap = i2c_get_adapter(chan_id);
|
||||||
|
if (!adap){
|
||||||
|
emsg = "can't get adapter";
|
||||||
|
goto err_setup_i2c_client;
|
||||||
|
}
|
||||||
|
self->i2c_client_p = kzalloc(sizeof(*self->i2c_client_p), GFP_KERNEL);
|
||||||
|
if (!self->i2c_client_p){
|
||||||
|
emsg = "can't kzalloc client";
|
||||||
|
goto err_setup_i2c_client;
|
||||||
|
}
|
||||||
|
self->i2c_client_p->adapter = adap;
|
||||||
|
self->i2c_client_p->addr = addr;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_setup_i2c_client:
|
||||||
|
SWPS_ERR("%s: %s\n", __func__, emsg);
|
||||||
|
return ERR_MUX_UNEXCPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
_common_force_pull_gpio(int mem_addr,
|
||||||
|
int input,
|
||||||
|
int bit_offset){
|
||||||
|
|
||||||
|
unsigned int val = 0;
|
||||||
|
unsigned int targ = 0;
|
||||||
|
|
||||||
|
/* Get current value */
|
||||||
|
val = inl(mem_addr);
|
||||||
|
if (val == 0) {
|
||||||
|
SWPS_ERR("%s: inl:%d fail!\n", __func__, val);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* Count target value */
|
||||||
|
switch (input) {
|
||||||
|
case 0: /* Pull Low */
|
||||||
|
targ = (val & (~(1 << bit_offset)));
|
||||||
|
break;
|
||||||
|
case 1: /* Pull high */
|
||||||
|
targ = (val | (1 << bit_offset));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SWPS_ERR("%s: input state:%d incorrect!\n",
|
||||||
|
__func__, input);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* Setup gpio */
|
||||||
|
outl(targ, mem_addr);
|
||||||
|
if (targ != inl(mem_addr)){
|
||||||
|
SWPS_ERR("%s: outl:%d fail!\n", __func__, targ);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
SWPS_DEBUG("%s: done.\n", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
rangeley_force_pull_high(struct mux_obj_s *self){
|
||||||
|
SWPS_ERR("%s: not ready!\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
rangeley_force_pull_low(struct mux_obj_s *self){
|
||||||
|
SWPS_ERR("%s: not ready!\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
hedera_force_pull_high(struct mux_obj_s *self){
|
||||||
|
return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 1, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
hedera_force_pull_low(struct mux_obj_s *self){
|
||||||
|
return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 0, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
normal_gpio_pull_high(struct mux_obj_s *self){
|
||||||
|
return gpio_direction_output(self->gpio_num, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
normal_gpio_pull_low(struct mux_obj_s *self){
|
||||||
|
return gpio_direction_output(self->gpio_num, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
cpld_rst_all_4_pull_low(struct mux_obj_s *self){
|
||||||
|
|
||||||
|
char *emsg = "ERR";
|
||||||
|
int err = ERR_MUX_UNEXCPT;
|
||||||
|
|
||||||
|
switch(self->gpio_num) {
|
||||||
|
case MUX_RST_CPLD_C0_A77_70_74_RST_ALL:
|
||||||
|
goto setlow_cpld_rst_all_4_c0_a77_70_74_rst_all;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
emsg = "Undefined case";
|
||||||
|
goto err_cpld_rst_all_4_pull_low;
|
||||||
|
|
||||||
|
setlow_cpld_rst_all_4_c0_a77_70_74_rst_all:
|
||||||
|
err = _setup_i2c_value(self, 0x70, 0x0);
|
||||||
|
if (err < 0) {
|
||||||
|
emsg = "setup 0x70 fail";
|
||||||
|
goto err_cpld_rst_all_4_pull_low;
|
||||||
|
}
|
||||||
|
err = _setup_i2c_value(self, 0x74, 0x01);
|
||||||
|
if (err < 0) {
|
||||||
|
emsg = "setup 0x74 fail";
|
||||||
|
goto err_cpld_rst_all_4_pull_low;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_cpld_rst_all_4_pull_low:
|
||||||
|
SWPS_INFO("%s: %s <type>:%d <err>:%d\n",
|
||||||
|
__func__, emsg, self->gpio_num, err);
|
||||||
|
return ERR_MUX_UNEXCPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
cpld_rst_all_4_pull_high(struct mux_obj_s *self){
|
||||||
|
|
||||||
|
char *emsg = "ERR";
|
||||||
|
int err = ERR_MUX_UNEXCPT;
|
||||||
|
|
||||||
|
switch(self->gpio_num) {
|
||||||
|
case MUX_RST_CPLD_C0_A77_70_74_RST_ALL:
|
||||||
|
goto sethigh_cpld_rst_all_4_c0_a77_70_74_rst_all;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
emsg = "Undefined case";
|
||||||
|
goto err_cpld_rst_all_4_pull_high;
|
||||||
|
|
||||||
|
sethigh_cpld_rst_all_4_c0_a77_70_74_rst_all:
|
||||||
|
err = _setup_i2c_value(self, 0x70, 0xfe);
|
||||||
|
if (err < 0) {
|
||||||
|
emsg = "setup 0x70 fail";
|
||||||
|
goto err_cpld_rst_all_4_pull_high;
|
||||||
|
}
|
||||||
|
err = _setup_i2c_value(self, 0x74, 0x03);
|
||||||
|
if (err < 0) {
|
||||||
|
emsg = "setup 0x74 fail";
|
||||||
|
goto err_cpld_rst_all_4_pull_high;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_cpld_rst_all_4_pull_high:
|
||||||
|
SWPS_INFO("%s: %s <type>:%d <err>:%d\n",
|
||||||
|
__func__, emsg, self->gpio_num, err);
|
||||||
|
return ERR_MUX_UNEXCPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
pca9548_reset_mux_all(struct mux_obj_s *self){
|
||||||
|
/* [Note] Power-on reset (PCA9548A-NXP)
|
||||||
|
* When power is applied to VDD, an internal Power-On Reset (POR)
|
||||||
|
* holds the PCA9548A in a reset condition until VDD has reached
|
||||||
|
* VPOR. At this point, the reset condition is released and the
|
||||||
|
* PCA9548A register and I2C-bus state machine are initialized to
|
||||||
|
* their default states (all zeroes) causing all the channels to
|
||||||
|
* be deselected. Thereafter, VDD must be lowered below 0.2 V for
|
||||||
|
* at least 5 us in order to reset the device.
|
||||||
|
*/
|
||||||
|
if (self->_pull_low(self) < 0) {
|
||||||
|
SWPS_ERR("%s: _pull_low fail!\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mdelay(MUX_RST_WAIT_MS_PCA9548);
|
||||||
|
if (self->_pull_high(self) < 0) {
|
||||||
|
SWPS_ERR("%s: _pull_high fail!\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mdelay(MUX_RST_WAIT_MS_PCA9548);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
cpld_reset_mux_all(struct mux_obj_s *self){
|
||||||
|
|
||||||
|
char *emsg = "ERR";
|
||||||
|
int err = ERR_MUX_UNEXCPT;
|
||||||
|
|
||||||
|
switch(self->gpio_num) {
|
||||||
|
case MUX_RST_CPLD_C0_A77_70_74_RST_ALL:
|
||||||
|
goto reset_cpld_rst_all_4_c0_a77_70_74_rst_all;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
emsg = "Undefined case";
|
||||||
|
goto err_cpld_reset_mux_all;
|
||||||
|
|
||||||
|
reset_cpld_rst_all_4_c0_a77_70_74_rst_all:
|
||||||
|
if (self->_pull_low(self) < 0) {
|
||||||
|
emsg = "_pull_low fail";
|
||||||
|
goto err_cpld_reset_mux_all;
|
||||||
|
}
|
||||||
|
mdelay(MUX_RST_WAIT_MS_CPLD);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_cpld_reset_mux_all:
|
||||||
|
SWPS_INFO("%s: %s <type>:%d <err>:%d\n",
|
||||||
|
__func__, emsg, self->gpio_num, err);
|
||||||
|
return ERR_MUX_UNEXCPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
common_reset_mux_all(struct mux_obj_s *self){
|
||||||
|
SWPS_ERR("%s: not ready!\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
init_gpio_4_force(struct mux_obj_s *self){
|
||||||
|
|
||||||
|
if (self->_pull_high(self) < 0) {
|
||||||
|
SWPS_ERR("%s: setup default fail!\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
init_gpio_4_normal(struct mux_obj_s *self){
|
||||||
|
|
||||||
|
int err = 0;
|
||||||
|
char *emsg = "ERR";
|
||||||
|
|
||||||
|
if (!gpio_is_valid(self->gpio_num)) {
|
||||||
|
emsg = "GPIO invalid";
|
||||||
|
goto err_init_gpio_4_normal;
|
||||||
|
}
|
||||||
|
err = gpio_request(self->gpio_num, MUX_GPIO_LABEL);
|
||||||
|
if (err < 0) {
|
||||||
|
emsg = "gpio_request fail";
|
||||||
|
goto err_init_gpio_4_normal;
|
||||||
|
}
|
||||||
|
err = self->_pull_high(self);
|
||||||
|
if (err < 0) {
|
||||||
|
emsg = "setup default fail";
|
||||||
|
goto err_init_gpio_4_normal;
|
||||||
|
}
|
||||||
|
SWPS_DEBUG("%s: gpio_request:%d ok.\n", __func__, self->gpio_num);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_init_gpio_4_normal:
|
||||||
|
SWPS_ERR("%s: %s <gpio>:%d <err>:%d\n",
|
||||||
|
__func__, emsg, self->gpio_num, err);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
init_cpld_4_rst_all(struct mux_obj_s *self){
|
||||||
|
|
||||||
|
char *emsg = "ERR";
|
||||||
|
int err = ERR_MUX_UNEXCPT;
|
||||||
|
int chan = ERR_MUX_UNEXCPT;
|
||||||
|
int addr = ERR_MUX_UNEXCPT;
|
||||||
|
|
||||||
|
switch(self->gpio_num) {
|
||||||
|
case MUX_RST_CPLD_C0_A77_70_74_RST_ALL:
|
||||||
|
goto init_cpld_i2c_c0_a77_70_74_rst_all;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
emsg = "Undefined case";
|
||||||
|
goto err_init_cpld_4_rst_all;
|
||||||
|
|
||||||
|
init_cpld_i2c_c0_a77_70_74_rst_all:
|
||||||
|
chan = 0;
|
||||||
|
addr = 0x77;
|
||||||
|
err = _setup_i2c_client(self, chan, addr);
|
||||||
|
if (err < 0) {
|
||||||
|
emsg = "_setup_i2c_client fail";
|
||||||
|
goto err_init_cpld_4_rst_all;
|
||||||
|
}
|
||||||
|
err = self->_pull_high(self);
|
||||||
|
if (err < 0) {
|
||||||
|
emsg = "setup default value fail";
|
||||||
|
goto err_init_cpld_4_rst_all;
|
||||||
|
}
|
||||||
|
SWPS_DEBUG("%s: init_cpld_i2c_c0_a77_70_74_rst_all ok", __func__);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_init_cpld_4_rst_all:
|
||||||
|
SWPS_INFO("%s: %s <type>:%d <err>:%d\n",
|
||||||
|
__func__, emsg, self->gpio_num, err);
|
||||||
|
return ERR_MUX_UNEXCPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
clean_gpio_4_common(struct mux_obj_s *self){
|
||||||
|
|
||||||
|
if (!self) return 0;
|
||||||
|
if (!gpio_is_valid(self->gpio_num)) return 0;
|
||||||
|
self->_pull_high(self);
|
||||||
|
gpio_free(mux_head_p->gpio_num);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
clean_cpld_4_rst_all(struct mux_obj_s *self){
|
||||||
|
|
||||||
|
if (!self) return 0;
|
||||||
|
self->_pull_high(self);
|
||||||
|
if (self->i2c_client_p) {
|
||||||
|
i2c_put_adapter(self->i2c_client_p->adapter);
|
||||||
|
kfree(self->i2c_client_p);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
_setup_muxctl_cb(struct mux_obj_s *self,
|
||||||
|
unsigned gpio){
|
||||||
|
|
||||||
|
char mod_dsc[32] = "ERR";
|
||||||
|
|
||||||
|
switch (gpio) {
|
||||||
|
case MUX_RST_GPIO_FORCE_RANGELEY:
|
||||||
|
self->gpio_num = gpio;
|
||||||
|
self->_pull_low = rangeley_force_pull_low;
|
||||||
|
self->_pull_high = rangeley_force_pull_high;
|
||||||
|
self->_init = init_gpio_4_force;
|
||||||
|
self->_clean = clean_gpio_4_common;
|
||||||
|
self->reset = pca9548_reset_mux_all;
|
||||||
|
memset(mod_dsc, 0, 32);
|
||||||
|
snprintf(mod_dsc, 31, "Rangeley force mode");
|
||||||
|
goto ok_setup_muxctl_cb;
|
||||||
|
|
||||||
|
case MUX_RST_GPIO_FORCE_HEDERA:
|
||||||
|
self->gpio_num = gpio;
|
||||||
|
self->_pull_low = hedera_force_pull_low;
|
||||||
|
self->_pull_high = hedera_force_pull_high;
|
||||||
|
self->_init = init_gpio_4_force;
|
||||||
|
self->_clean = clean_gpio_4_common;
|
||||||
|
self->reset = pca9548_reset_mux_all;
|
||||||
|
memset(mod_dsc, 0, 32);
|
||||||
|
snprintf(mod_dsc, 31, "Hedera force mode");
|
||||||
|
goto ok_setup_muxctl_cb;
|
||||||
|
|
||||||
|
case MUX_RST_GPIO_48_PCA9548:
|
||||||
|
case MUX_RST_GPIO_69_PCA9548:
|
||||||
|
case MUX_RST_GPIO_249_PCA9548:
|
||||||
|
case MUX_RST_GPIO_500_PCA9548:
|
||||||
|
case MUX_RST_GPIO_505_PCA9548:
|
||||||
|
self->gpio_num = gpio;
|
||||||
|
self->_pull_low = normal_gpio_pull_low;
|
||||||
|
self->_pull_high = normal_gpio_pull_high;
|
||||||
|
self->_init = init_gpio_4_normal;
|
||||||
|
self->_clean = clean_gpio_4_common;
|
||||||
|
self->reset = pca9548_reset_mux_all;
|
||||||
|
memset(mod_dsc, 0, 32);
|
||||||
|
snprintf(mod_dsc, 31, "Normal mode <gpio>:%d", (int)gpio);
|
||||||
|
goto ok_setup_muxctl_cb;
|
||||||
|
|
||||||
|
case MUX_RST_CPLD_C0_A77_70_74_RST_ALL:
|
||||||
|
self->gpio_num = gpio;
|
||||||
|
self->_pull_low = cpld_rst_all_4_pull_low;
|
||||||
|
self->_pull_high = cpld_rst_all_4_pull_high;
|
||||||
|
self->_init = init_cpld_4_rst_all;
|
||||||
|
self->_clean = clean_cpld_4_rst_all;
|
||||||
|
self->reset = cpld_reset_mux_all;
|
||||||
|
memset(mod_dsc, 0, 32);
|
||||||
|
snprintf(mod_dsc, 31, "CPLD mode <type>:%d", (int)gpio);
|
||||||
|
goto ok_setup_muxctl_cb;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SWPS_ERR("%s: Unexpected GPIO:%d\n", __func__, gpio);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ok_setup_muxctl_cb:
|
||||||
|
SWPS_INFO("muxctl: %s.\n", mod_dsc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ========== MUX public functions ==========
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clean_mux_objs(void){
|
||||||
|
|
||||||
|
struct mux_obj_s *curr_p = mux_head_p;
|
||||||
|
struct mux_obj_s *next_p = NULL;
|
||||||
|
|
||||||
|
if (!curr_p) {
|
||||||
|
SWPS_DEBUG("%s: mux_head_p is NULL\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (curr_p) {
|
||||||
|
next_p = curr_p->next;
|
||||||
|
curr_p->_clean(curr_p);
|
||||||
|
kfree(curr_p);
|
||||||
|
curr_p = next_p;
|
||||||
|
}
|
||||||
|
SWPS_DEBUG("%s: done.\n", __func__);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(clean_mux_objs);
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
reset_mux_objs(void){
|
||||||
|
|
||||||
|
if (!mux_head_p) {
|
||||||
|
SWPS_ERR("%s: MUX ctl object doesn't exist!\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (mux_head_p->reset(mux_head_p) < 0){
|
||||||
|
SWPS_ERR("%s: reset fail!\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(reset_mux_objs);
|
||||||
|
|
||||||
|
|
||||||
|
struct mux_obj_s *
|
||||||
|
_create_mux_obj(unsigned gpio){
|
||||||
|
|
||||||
|
char *emsg = "ERR";
|
||||||
|
struct mux_obj_s *obj_p = NULL;
|
||||||
|
|
||||||
|
obj_p = kzalloc(sizeof(struct mux_obj_s), GFP_KERNEL);
|
||||||
|
if (!obj_p) {
|
||||||
|
emsg = "kzalloc fail!";
|
||||||
|
goto err_create_mux_obj_1;
|
||||||
|
}
|
||||||
|
if (_setup_muxctl_cb(obj_p, gpio) < 0){
|
||||||
|
emsg = "_setup_muxctl_cb fail!";
|
||||||
|
goto err_create_mux_obj_2;
|
||||||
|
}
|
||||||
|
if (obj_p->_init(obj_p) < 0) {
|
||||||
|
emsg = "_init() fail!";
|
||||||
|
goto err_create_mux_obj_2;
|
||||||
|
}
|
||||||
|
SWPS_DEBUG("%s: created MUX object <id>:%d\n", __func__, gpio);
|
||||||
|
return obj_p;
|
||||||
|
|
||||||
|
err_create_mux_obj_2:
|
||||||
|
kfree(obj_p);
|
||||||
|
err_create_mux_obj_1:
|
||||||
|
SWPS_ERR("%s: %s <type>:%d\n", __func__, emsg, gpio);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
init_mux_objs(unsigned gpio){
|
||||||
|
|
||||||
|
struct mux_obj_s *curr_p = NULL;
|
||||||
|
char *emsg = "ERR";
|
||||||
|
|
||||||
|
/* Create MUX control object */
|
||||||
|
if (mux_head_p) {
|
||||||
|
SWPS_DEBUG("%s: mux_head_p is not NULL!\n", __func__);
|
||||||
|
clean_mux_objs();
|
||||||
|
}
|
||||||
|
/* Currently, it is using single muxctl architecture.
|
||||||
|
* In the future, it may use the multi-muxctl.
|
||||||
|
* (Ex: Gulmohar's advance I2C control / Peony's reset single mux)
|
||||||
|
*/
|
||||||
|
curr_p = _create_mux_obj(gpio);
|
||||||
|
if (!curr_p) {
|
||||||
|
emsg = "_create_mux_obj fail";
|
||||||
|
goto err_init_mux_objs;
|
||||||
|
}
|
||||||
|
curr_p->next = NULL;
|
||||||
|
mux_head_p = curr_p;
|
||||||
|
SWPS_DEBUG("%s: all done. <type>:%d\n", __func__, gpio);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_init_mux_objs:
|
||||||
|
clean_mux_objs();
|
||||||
|
SWPS_ERR("%s: %s\n", __func__, emsg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(init_mux_objs);
|
||||||
|
|
||||||
|
|
||||||
|
/* For single ko module
|
||||||
|
* => You need to declare MODULE_LICENSE If you want to build single module along.
|
||||||
|
* => Ex: For ONL platform
|
||||||
|
*/
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
|||||||
|
#ifndef INV_MUX_H
|
||||||
|
#define INV_MUX_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
/* MUX basic information */
|
||||||
|
#define MUX_GPIO_LABEL "SWPS_RST_MUX"
|
||||||
|
|
||||||
|
/* MUX reset GPIO define */
|
||||||
|
#define MUX_RST_GPIO_FORCE (30100)
|
||||||
|
#define MUX_RST_GPIO_FORCE_RANGELEY (30101)
|
||||||
|
#define MUX_RST_GPIO_FORCE_HEDERA (30102)
|
||||||
|
#define MUX_RST_GPIO_48_PCA9548 (48)
|
||||||
|
#define MUX_RST_GPIO_69_PCA9548 (69)
|
||||||
|
#define MUX_RST_GPIO_249_PCA9548 (249)
|
||||||
|
#define MUX_RST_GPIO_500_PCA9548 (500)
|
||||||
|
#define MUX_RST_GPIO_505_PCA9548 (505)
|
||||||
|
#define MUX_RST_CPLD_C0_A77_70_74_RST_ALL (30201)
|
||||||
|
|
||||||
|
/* MUX relate value define */
|
||||||
|
#define MUX_RST_WAIT_MS_PCA9548 (1)
|
||||||
|
#define MUX_RST_WAIT_MS_CPLD (10)
|
||||||
|
#define MUX_RST_MEM_ADDR_RANGELEY (0) // TBD
|
||||||
|
#define MUX_RST_MEM_ADDR_HEDERA (0x548)
|
||||||
|
|
||||||
|
/* MUX error code define */
|
||||||
|
#define ERR_MUX_UNEXCPT (-399)
|
||||||
|
|
||||||
|
struct mux_obj_s {
|
||||||
|
struct i2c_client *i2c_client_p;
|
||||||
|
struct mux_obj_s *next;
|
||||||
|
unsigned gpio_num;
|
||||||
|
int (*_pull_high)(struct mux_obj_s *self);
|
||||||
|
int (*_pull_low)(struct mux_obj_s *self);
|
||||||
|
int (*_init)(struct mux_obj_s *self);
|
||||||
|
int (*_clean)(struct mux_obj_s *self);
|
||||||
|
int (*reset)(struct mux_obj_s *self);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void clean_mux_objs(void);
|
||||||
|
int reset_mux_objs(void);
|
||||||
|
int init_mux_objs(unsigned gpio);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* INV_MUX_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,228 @@
|
|||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/platform_data/i2c-gpio.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/platform_data/pca954x.h>
|
||||||
|
#include <linux/platform_data/at24.h>
|
||||||
|
#include <linux/gpio/machine.h>
|
||||||
|
|
||||||
|
struct inv_i2c_board_info {
|
||||||
|
int ch;
|
||||||
|
int size;
|
||||||
|
struct i2c_board_info *board_info;
|
||||||
|
int probe;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define bus_id(id) (id)
|
||||||
|
#define SCL_PIN 58
|
||||||
|
#define SDA_PIN 75
|
||||||
|
|
||||||
|
static struct pca954x_platform_mode mux_modes_0[] = {
|
||||||
|
{.adap_id = bus_id(2),}, {.adap_id = bus_id(3),},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct pca954x_platform_mode mux_modes_1[] = {
|
||||||
|
{.adap_id = bus_id(4),}, {.adap_id = bus_id(5),},
|
||||||
|
{.adap_id = bus_id(6),}, {.adap_id = bus_id(7),},
|
||||||
|
{.adap_id = bus_id(8),}, {.adap_id = bus_id(9),},
|
||||||
|
{.adap_id = bus_id(10),}, {.adap_id = bus_id(11),},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct pca954x_platform_mode mux_modes_2_0[] = {
|
||||||
|
{.adap_id = bus_id(12),}, {.adap_id = bus_id(13),},
|
||||||
|
{.adap_id = bus_id(14),}, {.adap_id = bus_id(15),},
|
||||||
|
{.adap_id = bus_id(16),}, {.adap_id = bus_id(17),},
|
||||||
|
{.adap_id = bus_id(18),}, {.adap_id = bus_id(19),},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct pca954x_platform_mode mux_modes_2_1[] = {
|
||||||
|
{.adap_id = bus_id(20),}, {.adap_id = bus_id(21),},
|
||||||
|
{.adap_id = bus_id(22),}, {.adap_id = bus_id(23),},
|
||||||
|
{.adap_id = bus_id(24),}, {.adap_id = bus_id(25),},
|
||||||
|
{.adap_id = bus_id(26),}, {.adap_id = bus_id(27),},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct pca954x_platform_mode mux_modes_2_2[] = {
|
||||||
|
{.adap_id = bus_id(28),}, {.adap_id = bus_id(29),},
|
||||||
|
{.adap_id = bus_id(30),}, {.adap_id = bus_id(31),},
|
||||||
|
{.adap_id = bus_id(32),}, {.adap_id = bus_id(33),},
|
||||||
|
{.adap_id = bus_id(34),}, {.adap_id = bus_id(35),},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct pca954x_platform_mode mux_modes_2_3[] = {
|
||||||
|
{.adap_id = bus_id(36),}, {.adap_id = bus_id(37),},
|
||||||
|
{.adap_id = bus_id(38),}, {.adap_id = bus_id(39),},
|
||||||
|
{.adap_id = bus_id(40),}, {.adap_id = bus_id(41),},
|
||||||
|
{.adap_id = bus_id(42),}, {.adap_id = bus_id(43),},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static struct pca954x_platform_data mux_data_0 = {
|
||||||
|
.modes = mux_modes_0,
|
||||||
|
.num_modes = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct pca954x_platform_data mux_data_1 = {
|
||||||
|
.modes = mux_modes_1,
|
||||||
|
.num_modes = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct pca954x_platform_data mux_data_2_0 = {
|
||||||
|
.modes = mux_modes_2_0,
|
||||||
|
.num_modes = 8,
|
||||||
|
};
|
||||||
|
static struct pca954x_platform_data mux_data_2_1 = {
|
||||||
|
.modes = mux_modes_2_1,
|
||||||
|
.num_modes = 8,
|
||||||
|
};
|
||||||
|
static struct pca954x_platform_data mux_data_2_2 = {
|
||||||
|
.modes = mux_modes_2_2,
|
||||||
|
.num_modes = 8,
|
||||||
|
};
|
||||||
|
static struct pca954x_platform_data mux_data_2_3 = {
|
||||||
|
.modes = mux_modes_2_3,
|
||||||
|
.num_modes = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct i2c_board_info i2c_device_info0[] __initdata = {
|
||||||
|
{"inv_cpld", 0, 0x77, "inv_cpld", 0, 0, 0}, // CPLD driver
|
||||||
|
// {"24c512", 0, 0x55, 0, 0, 0}, // OEM1 VPD
|
||||||
|
// {"24c512", 0, 0x54, 0, 0, 0}, // OEM2 VPD
|
||||||
|
{"pca9543", 0, 0x73, "pca9543", &mux_data_0, 0, 0}, // MUX
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct i2c_board_info i2c_device_info1[] __initdata = {
|
||||||
|
{"pca9548", 0, 0x70, "pca9548-1", &mux_data_1, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct i2c_board_info i2c_device_info2[] __initdata ={
|
||||||
|
{"ucd90160", 0, 0x34, "ucd90160", 0, 0 ,0},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct i2c_board_info i2c_device_info11[] __initdata ={
|
||||||
|
{"pmbus", 0, 0x5A, "pmbus-1", 0, 0 ,0}, //PSU1 DVT
|
||||||
|
{"pmbus", 0, 0x5B, "pmbus-2", 0, 0 ,0}, //PSU2 DVT
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct i2c_board_info i2c_device_info3[] __initdata ={
|
||||||
|
{"tmp75", 0, 0x48, "tmp75-1", 0, 0 ,0}, //CPU Board Temperature
|
||||||
|
{"tmp75", 0, 0x4A, "tmp75-2", 0, 0 ,0}, //Front Panel Inlet Temperature
|
||||||
|
{"tmp75", 0, 0x4D, "tmp75-3", 0, 0 ,0},
|
||||||
|
{"tmp75", 0, 0x4E, "tmp75-4", 0, 0 ,0}, //Near ASIC Temperature
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct i2c_board_info i2c_device_info4[] __initdata = {
|
||||||
|
{"pca9548", 0, 0x72, "pca9548-2", &mux_data_2_0, 0, 0},
|
||||||
|
};
|
||||||
|
static struct i2c_board_info i2c_device_info5[] __initdata = {
|
||||||
|
{"pca9548", 0, 0x72, "pca9548-3", &mux_data_2_1, 0, 0},
|
||||||
|
};
|
||||||
|
static struct i2c_board_info i2c_device_info6[] __initdata = {
|
||||||
|
{"pca9548", 0, 0x72, "pca9548-4", &mux_data_2_2, 0, 0},
|
||||||
|
};
|
||||||
|
static struct i2c_board_info i2c_device_info7[] __initdata = {
|
||||||
|
{"pca9548", 0, 0x72, "pca9548-5", &mux_data_2_3, 0, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct inv_i2c_board_info i2cdev_list[] = {
|
||||||
|
{bus_id(0), ARRAY_SIZE(i2c_device_info0), i2c_device_info0 , 0}, //i2c-0 smbus
|
||||||
|
{bus_id(0), ARRAY_SIZE(i2c_device_info1), i2c_device_info1 , 1}, //i2c-0 smbus (for DVT)
|
||||||
|
{bus_id(1), ARRAY_SIZE(i2c_device_info1), i2c_device_info1 , 1}, //i2c-1 i2c-gpio (for EVT)
|
||||||
|
{bus_id(3), ARRAY_SIZE(i2c_device_info3), i2c_device_info3 , 0}, //mux 0x73 channel 1
|
||||||
|
{bus_id(2), ARRAY_SIZE(i2c_device_info2), i2c_device_info2 , 0}, //mux 0x73 channel 0
|
||||||
|
{bus_id(2), ARRAY_SIZE(i2c_device_info11), i2c_device_info11, 1}, //mux 0x73 channel 0
|
||||||
|
{bus_id(4), ARRAY_SIZE(i2c_device_info4), i2c_device_info4 , 1}, //mux 0x70 channel 0
|
||||||
|
{bus_id(5), ARRAY_SIZE(i2c_device_info5), i2c_device_info5 , 1}, //mux 0x70 channel 1
|
||||||
|
{bus_id(6), ARRAY_SIZE(i2c_device_info6), i2c_device_info6 , 1}, //mux 0x70 channel 2
|
||||||
|
{bus_id(7), ARRAY_SIZE(i2c_device_info7), i2c_device_info7 , 1}, //mux 0x70 channel 3
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gpiod_lookup_table inv_i2c_gpiod_table = {
|
||||||
|
.dev_id = "i2c-gpio.1",
|
||||||
|
.table = {
|
||||||
|
GPIO_LOOKUP_IDX("gpio_ich", SDA_PIN, NULL, 0, GPIO_OPEN_DRAIN), //I2C_SDA
|
||||||
|
GPIO_LOOKUP_IDX("gpio_ich", SCL_PIN, NULL, 1, GPIO_OPEN_DRAIN), //I2C_SCL
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct i2c_gpio_platform_data i2c_platform_data = {
|
||||||
|
.udelay = 5, //5:100kHz
|
||||||
|
//.sda_is_open_drain = 0,
|
||||||
|
//.scl_is_open_drain = 0,
|
||||||
|
//.scl_is_output_only = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void i2cgpio_device_release(struct device *dev)
|
||||||
|
{
|
||||||
|
gpiod_remove_lookup_table(&inv_i2c_gpiod_table);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_device device_i2c_gpio0 = {
|
||||||
|
.name = "i2c-gpio",
|
||||||
|
.id = 1,
|
||||||
|
.dev = {
|
||||||
|
.platform_data = &i2c_platform_data,
|
||||||
|
.release = i2cgpio_device_release,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init inv_platform_init(void)
|
||||||
|
{
|
||||||
|
struct i2c_adapter *adap = NULL;
|
||||||
|
struct i2c_client *e = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
int i,j,k;
|
||||||
|
|
||||||
|
//use i2c-gpio
|
||||||
|
//register gpio
|
||||||
|
outl( inl(0x533) | (1<<2), 0x533); //i2c-gpio sdl(58)
|
||||||
|
outl( inl(0x541) | (1<<3), 0x541); //i2c gpio sda(75)
|
||||||
|
outl( inl(0x540) | (1<<5), 0x540); //RST_I2C_MUX_N(69)
|
||||||
|
outl( inl(0x503) | (1)|(1<<2)|(1<<3), 0x503); //WDT_IRQ_N(24) PSOC_HEART_BEAT(26) CPLD_HEART_BEAT(27)
|
||||||
|
outl( inl(0x501) | (1<<4), 0x501); //RSTBTN_IN_N(12)
|
||||||
|
outl( inl(0x533) | (1<<5), 0x533); //RST_BTN_5S_N(61)
|
||||||
|
|
||||||
|
gpiod_add_lookup_table(&inv_i2c_gpiod_table);
|
||||||
|
|
||||||
|
ret = platform_device_register(&device_i2c_gpio0);
|
||||||
|
if (ret) {
|
||||||
|
printk(KERN_ERR "i2c-gpio: platform_device_register fail %d\n", ret);
|
||||||
|
}
|
||||||
|
msleep(10);
|
||||||
|
|
||||||
|
for(i=0; i<ARRAY_SIZE(i2cdev_list); i++) {
|
||||||
|
adap = i2c_get_adapter( i2cdev_list[i].ch );
|
||||||
|
if (adap == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
i2c_put_adapter(adap);
|
||||||
|
for(j=0; j<i2cdev_list[i].size; j++) {
|
||||||
|
for(k=0; k<3; k++) {
|
||||||
|
if (i2cdev_list[i].probe == 1) {
|
||||||
|
short unsigned int i2c_address[2]={i2cdev_list[i].board_info[j].addr, I2C_CLIENT_END};
|
||||||
|
e = i2c_new_probed_device(adap, &i2cdev_list[i].board_info[j] ,i2c_address, NULL);
|
||||||
|
} else {
|
||||||
|
e = i2c_new_device(adap, &i2cdev_list[i].board_info[j]);
|
||||||
|
}
|
||||||
|
if(e == NULL) msleep(10); else break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit inv_platform_exit(void)
|
||||||
|
{
|
||||||
|
platform_device_unregister(&device_i2c_gpio0);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(inv_platform_init);
|
||||||
|
module_exit(inv_platform_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Inventec");
|
||||||
|
MODULE_DESCRIPTION("Switch Platform devices");
|
||||||
|
MODULE_LICENSE("GPL");
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,189 @@
|
|||||||
|
#ifndef IO_EXPANDER_H
|
||||||
|
#define IO_EXPANDER_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* IOEXP type define (SFP series) */
|
||||||
|
#define IOEXP_TYPE_MAGINOLIA_NAB (10101)
|
||||||
|
#define IOEXP_TYPE_MAGINOLIA_4AB (10102)
|
||||||
|
#define IOEXP_TYPE_MAPLE_NABC (10104)
|
||||||
|
#define IOEXP_TYPE_GULMOHAR_NABC (10105)
|
||||||
|
#define IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC (10106)
|
||||||
|
#define IOEXP_TYPE_SFP_8P_LAYOUT_1 (10107)
|
||||||
|
#define IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC (10108)
|
||||||
|
#define IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC (10109)
|
||||||
|
|
||||||
|
/* IOEXP type define (QSFP series) */
|
||||||
|
#define IOEXP_TYPE_MAGINOLIA_7AB (10201)
|
||||||
|
#define IOEXP_TYPE_REDWOOD_P01P08 (10202)
|
||||||
|
#define IOEXP_TYPE_REDWOOD_P09P16 (10203)
|
||||||
|
#define IOEXP_TYPE_HUDSON32IGA_P01P08 (10204)
|
||||||
|
#define IOEXP_TYPE_HUDSON32IGA_P09P16 (10205)
|
||||||
|
#define IOEXP_TYPE_SPRUCE_7AB (10206)
|
||||||
|
#define IOEXP_TYPE_CYPRESS_7ABC (10207)
|
||||||
|
#define IOEXP_TYPE_TAHOE_5A (10208)
|
||||||
|
#define IOEXP_TYPE_TAHOE_6ABC (10209)
|
||||||
|
#define IOEXP_TYPE_SEQUOIA_NABC (10210)
|
||||||
|
#define IOEXP_TYPE_LAVENDER_P65 (10211)
|
||||||
|
#define IOEXP_TYPE_MAPLE_0ABC (10212)
|
||||||
|
#define IOEXP_TYPE_GULMOHAR_7ABC (10213)
|
||||||
|
#define IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC (10214)
|
||||||
|
#define IOEXP_TYPE_QSFP_6P_LAYOUT_1 (10215)
|
||||||
|
#define IOEXP_TYPE_CEDAR_0ABC (10216)
|
||||||
|
|
||||||
|
/* CPLD type define */
|
||||||
|
#define CPLD_TYPE_COTTONWOOD (10301)
|
||||||
|
|
||||||
|
/* IOEXP mode define */
|
||||||
|
#define IOEXP_MODE_POLLING (19000)
|
||||||
|
#define IOEXP_MODE_DIRECT (19001)
|
||||||
|
|
||||||
|
/* IOEXP state define */
|
||||||
|
#define STATE_IOEXP_NORMAL (0)
|
||||||
|
#define STATE_IOEXP_INIT (-1)
|
||||||
|
#define STATE_IOEXP_ABNORMAL (-2)
|
||||||
|
|
||||||
|
/* IOEXP error code define */
|
||||||
|
#define ERR_IOEXP_NOTSUPPORT (-100)
|
||||||
|
#define ERR_IOEXP_UNINIT (-101)
|
||||||
|
#define ERR_IOEXP_BADCONF (-102)
|
||||||
|
#define ERR_IOEXP_ABNORMAL (-103)
|
||||||
|
#define ERR_IOEXP_NOSTATE (-104)
|
||||||
|
#define ERR_IOEXP_BADINPUT (-105)
|
||||||
|
#define ERR_IOEXP_UNEXCPT (-199)
|
||||||
|
|
||||||
|
#define SWPS_INFO(fmt, args...) printk( KERN_INFO "[SWPS] " fmt, ##args)
|
||||||
|
#define SWPS_WARN(fmt, args...) printk( KERN_WARNING "[SWPS] " fmt, ##args)
|
||||||
|
#define SWPS_ERR(fmt, args...) printk( KERN_ERR "[SWPS] " fmt, ##args)
|
||||||
|
|
||||||
|
#ifdef DEBUG_SWPS
|
||||||
|
# define SWPS_DEBUG(fmt, args...) printk( KERN_DEBUG "[SWPS] " fmt, ##args)
|
||||||
|
#else
|
||||||
|
# define SWPS_DEBUG(fmt, args...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ioexp_addr_s {
|
||||||
|
int chan_id;
|
||||||
|
int chip_addr;
|
||||||
|
int read_offset[8];
|
||||||
|
int write_offset[8];
|
||||||
|
int conf_offset[8];
|
||||||
|
uint8_t data_default[8];
|
||||||
|
uint8_t conf_default[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ioexp_i2c_s {
|
||||||
|
int chip_id;
|
||||||
|
struct i2c_client *i2c_client_p;
|
||||||
|
struct ioexp_i2c_s *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ioexp_bitmap_s {
|
||||||
|
int chip_id; /* IOEXP chip id */
|
||||||
|
int ioexp_voffset; /* IOEXP virtual offset */
|
||||||
|
int bit_shift;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ioexp_map_s {
|
||||||
|
int chip_amount; /* Number of chips that IOEXP object content */
|
||||||
|
int data_width; /* Number of (Read/Write/Config) bytes */
|
||||||
|
struct ioexp_addr_s *map_addr; /* Chip address info */
|
||||||
|
struct ioexp_bitmap_s map_present[10]; /* IOEXP for SFP / QSFP */
|
||||||
|
struct ioexp_bitmap_s map_tx_disable[10]; /* IOEXP for SFP */
|
||||||
|
struct ioexp_bitmap_s map_tx_fault[10]; /* IOEXP for SFP */
|
||||||
|
struct ioexp_bitmap_s map_rxlos[10]; /* IOEXP for SFP */
|
||||||
|
struct ioexp_bitmap_s map_reset[10]; /* IOEXP for QSFP */
|
||||||
|
struct ioexp_bitmap_s map_lpmod[10]; /* IOEXP for QSFP */
|
||||||
|
struct ioexp_bitmap_s map_modsel[10]; /* IOEXP for QSFP */
|
||||||
|
struct ioexp_bitmap_s map_hard_rs0[10]; /* IOEXP for QSFP */
|
||||||
|
struct ioexp_bitmap_s map_hard_rs1[10]; /* IOEXP for QSFP */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ioexp_data_s {
|
||||||
|
uint8_t data[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ioexp_obj_s {
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
* Object public property
|
||||||
|
* ============================
|
||||||
|
*/
|
||||||
|
int ioexp_id;
|
||||||
|
int ioexp_type;
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
* Object private property
|
||||||
|
* ============================
|
||||||
|
*/
|
||||||
|
struct ioexp_data_s chip_data[16]; /* Max: 8-ioexp in one virt-ioexp(ioexp_obj) */
|
||||||
|
struct ioexp_map_s *ioexp_map_p;
|
||||||
|
struct ioexp_obj_s *next;
|
||||||
|
struct ioexp_i2c_s *i2c_head_p;
|
||||||
|
struct mutex lock;
|
||||||
|
int mode;
|
||||||
|
int state;
|
||||||
|
|
||||||
|
/* ===========================================
|
||||||
|
* Object public functions
|
||||||
|
* ===========================================
|
||||||
|
*/
|
||||||
|
int (*get_present)(struct ioexp_obj_s *self, int virt_offset);
|
||||||
|
int (*get_tx_fault)(struct ioexp_obj_s *self, int virt_offset);
|
||||||
|
int (*get_rxlos)(struct ioexp_obj_s *self, int virt_offset);
|
||||||
|
int (*get_tx_disable)(struct ioexp_obj_s *self, int virt_offset);
|
||||||
|
int (*get_reset)(struct ioexp_obj_s *self, int virt_offset);
|
||||||
|
int (*get_lpmod)(struct ioexp_obj_s *self, int virt_offset);
|
||||||
|
int (*get_modsel)(struct ioexp_obj_s *self, int virt_offset);
|
||||||
|
int (*get_hard_rs0)(struct ioexp_obj_s *self, int virt_offset);
|
||||||
|
int (*get_hard_rs1)(struct ioexp_obj_s *self, int virt_offset);
|
||||||
|
int (*set_tx_disable)(struct ioexp_obj_s *self, int virt_offset, int input_val);
|
||||||
|
int (*set_reset)(struct ioexp_obj_s *self, int virt_offset, int input_val);
|
||||||
|
int (*set_lpmod)(struct ioexp_obj_s *self, int virt_offset, int input_val);
|
||||||
|
int (*set_modsel)(struct ioexp_obj_s *self, int virt_offset, int input_val);
|
||||||
|
int (*set_hard_rs0)(struct ioexp_obj_s *self, int virt_offset, int input_val);
|
||||||
|
int (*set_hard_rs1)(struct ioexp_obj_s *self, int virt_offset, int input_val);
|
||||||
|
|
||||||
|
/* ===========================================
|
||||||
|
* Object private functions
|
||||||
|
* ===========================================
|
||||||
|
*/
|
||||||
|
int (*init)(struct ioexp_obj_s *self);
|
||||||
|
int (*check)(struct ioexp_obj_s *self);
|
||||||
|
int (*update_all)(struct ioexp_obj_s *self, int show_err, char *caller_name);
|
||||||
|
int (*fsm_4_direct)(struct ioexp_obj_s* self);
|
||||||
|
int (*fsm_4_polling)(struct ioexp_obj_s* self);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ioexp_obj_s* get_ioexp_obj(int ioexp_id);
|
||||||
|
int create_ioexp_obj(int ioexp_id,
|
||||||
|
int ioexp_type,
|
||||||
|
struct ioexp_addr_s *addr_map_p,
|
||||||
|
int run_mode);
|
||||||
|
int init_ioexp_objs(void);
|
||||||
|
int check_ioexp_objs(void);
|
||||||
|
void clean_ioexp_objs(void);
|
||||||
|
|
||||||
|
void unlock_ioexp_all(void);
|
||||||
|
int lock_ioexp_all(void);
|
||||||
|
|
||||||
|
int check_channel_tier_1(void);
|
||||||
|
int resync_channel_tier_1(void);
|
||||||
|
|
||||||
|
/* Macro for bit control */
|
||||||
|
#define SWP_BIT_SET(byte_val,bit_shift) ((byte_val) |= (1<<(bit_shift)))
|
||||||
|
#define SWP_BIT_CLEAR(byte_val,bit_shift) ((byte_val) &= ~(1<<(bit_shift)))
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* IO_EXPANDER_H */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,804 @@
|
|||||||
|
#ifndef TRANSCEIVER_H
|
||||||
|
#define TRANSCEIVER_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
/* advanced features control */
|
||||||
|
#define TRANSVR_INFO_DUMP_ENABLE (1)
|
||||||
|
#define TRANSVR_INFO_CACHE_ENABLE (1)
|
||||||
|
#define TRANSVR_UEVENT_ENABLE (1)
|
||||||
|
|
||||||
|
/* Transceiver type define */
|
||||||
|
#define TRANSVR_TYPE_UNKNOW_1 (0x00)
|
||||||
|
#define TRANSVR_TYPE_UNKNOW_2 (0xff)
|
||||||
|
#define TRANSVR_TYPE_SFP (0x03) /* Define for SFP, SFP+, SFP28 */
|
||||||
|
#define TRANSVR_TYPE_QSFP (0x0c)
|
||||||
|
#define TRANSVR_TYPE_QSFP_PLUS (0x0d)
|
||||||
|
#define TRANSVR_TYPE_QSFP_28 (0x11)
|
||||||
|
#define TRANSVR_TYPE_UNPLUGGED (0xfa) /* Define for ERROR handle */
|
||||||
|
#define TRANSVR_TYPE_FAKE (0xfc) /* Define for ERROR handle */
|
||||||
|
#define TRANSVR_TYPE_INCONSISTENT (0xfd) /* Define for ERROR handle */
|
||||||
|
#define TRANSVR_TYPE_ERROR (0xfe) /* Define for ERROR handle */
|
||||||
|
|
||||||
|
/* Transceiver class for base info */
|
||||||
|
#define TRANSVR_CLASS_UNSPECIFIED (0)
|
||||||
|
#define TRANSVR_CLASS_ERROR (-26001)
|
||||||
|
#define TRANSVR_CLASS_1G (26001)
|
||||||
|
#define TRANSVR_CLASS_10G (26011)
|
||||||
|
#define TRANSVR_CLASS_25G (26021)
|
||||||
|
#define TRANSVR_CLASS_40G (26041)
|
||||||
|
#define TRANSVR_CLASS_100G (26101)
|
||||||
|
#define TRANSVR_CLASS_NO_SPERARABLE (26901)
|
||||||
|
#define TRANSVR_CLASS_EXTEND_COMP (26902)
|
||||||
|
/* Transceiver class for Optical 1G */
|
||||||
|
#define TRANSVR_CLASS_OPTICAL (27000)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_100 (27001)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_1G (27002)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_1G_AOC (27003)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_1G_SX (27004)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_1G_LX (27005)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_1G_EX (27006)
|
||||||
|
/* Transceiver class for Optical 10G */
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_10G (27010)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_10G_S_AOC (27011)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_10G_S_SR (27012)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_10G_S_LR (27013)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_10G_S_ER (27014)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_10G_Q_AOC (27015)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_10G_Q_SR (27016)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_10G_Q_LR (27017)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_10G_Q_ER (27018)
|
||||||
|
/* Transceiver class for Optical 25G */
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_25G (27020)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_25G_AOC (27021)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_25G_SR (27022)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_25G_LR (27023)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_25G_ER (27024)
|
||||||
|
/* Transceiver class for Optical 40G */
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_40G (27040)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_40G_AOC (27041)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_40G_SR4 (27042)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_40G_LR4 (27043)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_40G_ER4 (27044)
|
||||||
|
/* Transceiver class for Optical 100G */
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_100G (27100)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_100G_AOC (27101)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_100G_SR4 (27102)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_100G_LR4 (27103)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_100G_ER4 (27104)
|
||||||
|
#define TRANSVR_CLASS_OPTICAL_100G_PSM4 (27105)
|
||||||
|
/* Transceiver class for Copper */
|
||||||
|
#define TRANSVR_CLASS_COPPER (28000)
|
||||||
|
#define TRANSVR_CLASS_COPPER_L1_1G (28001)
|
||||||
|
#define TRANSVR_CLASS_COPPER_L1_10G (28011)
|
||||||
|
#define TRANSVR_CLASS_COPPER_L4_10G (28012)
|
||||||
|
#define TRANSVR_CLASS_COPPER_L1_25G (28021)
|
||||||
|
#define TRANSVR_CLASS_COPPER_L4_40G (28041)
|
||||||
|
#define TRANSVR_CLASS_COPPER_L4_100G (28101)
|
||||||
|
/* Transceiver class for Base-T */
|
||||||
|
#define TRANSVR_CLASS_BASE_T_1000 (29001)
|
||||||
|
#define TRANSVR_CLASS_BASE_T_1000_up (29002)
|
||||||
|
/* For uevent message */
|
||||||
|
#define TRANSVR_UEVENT_KEY_IF "IF_TYPE"
|
||||||
|
#define TRANSVR_UEVENT_KEY_SP "IF_SPEED"
|
||||||
|
#define TRANSVR_UEVENT_KEY_LANE "IF_LANE"
|
||||||
|
#define TRANSVR_UEVENT_UNKNOW "UNKNOW"
|
||||||
|
#define TRANSVR_IF_KR "KR"
|
||||||
|
#define TRANSVR_IF_KR4 "KR4"
|
||||||
|
#define TRANSVR_IF_SR "SR"
|
||||||
|
#define TRANSVR_IF_SR4 "SR4"
|
||||||
|
#define TRANSVR_IF_SFI "SFI"
|
||||||
|
#define TRANSVR_IF_IF_GMII "GMII"
|
||||||
|
#define TRANSVR_IF_IF_XGMII "XGMII"
|
||||||
|
#define TRANSVR_IF_SP_100 "100"
|
||||||
|
#define TRANSVR_IF_SP_1G "1000"
|
||||||
|
#define TRANSVR_IF_SP_10G "10000"
|
||||||
|
#define TRANSVR_IF_SP_25G "25000"
|
||||||
|
#define TRANSVR_IF_SP_40G "40000"
|
||||||
|
#define TRANSVR_IF_SP_100G "100000"
|
||||||
|
|
||||||
|
/* Transceiver mode define */
|
||||||
|
#define TRANSVR_MODE_DIRECT (21000)
|
||||||
|
#define TRANSVR_MODE_POLLING (21001)
|
||||||
|
|
||||||
|
/* Transceiver state define
|
||||||
|
* [Note]
|
||||||
|
* 1. State is used to represent the state of "Transceiver" and "Object".
|
||||||
|
* 2. State for different target has different means. The description as following:
|
||||||
|
*/
|
||||||
|
#define STATE_TRANSVR_CONNECTED (0) /* [Transvr]:Be plugged in. [Obj]:Link up, and work normally. */
|
||||||
|
#define STATE_TRANSVR_NEW (-100) /* [Transvr]:(Not used) [Obj]:Create */
|
||||||
|
#define STATE_TRANSVR_INIT (-101) /* [Transvr]:Be plugged in. [Obj]:Link up, and in initial process. */
|
||||||
|
#define STATE_TRANSVR_ISOLATED (-102) /* [Transvr]:Be plugged in. [Obj]:Isolate, and not provide service. */
|
||||||
|
#define STATE_TRANSVR_SWAPPED (-200) /* [Transvr]:Be plugged in. [Obj]:(Not used) */
|
||||||
|
#define STATE_TRANSVR_DISCONNECTED (-300) /* [Transvr]:Un-plugged. [Obj]:Link down, and not provide service. */
|
||||||
|
#define STATE_TRANSVR_UNEXCEPTED (-901) /* [Transvr]:Any [Obj]:Any, and not in expect case. */
|
||||||
|
|
||||||
|
/* Task state define */
|
||||||
|
#define STATE_T_TASK_WAIT (110)
|
||||||
|
#define STATE_T_TASK_DONE (0)
|
||||||
|
#define STATE_T_TASK_INIT (-110)
|
||||||
|
#define STATE_T_TASK_FAIL (-410)
|
||||||
|
|
||||||
|
|
||||||
|
/* Event for task handling */
|
||||||
|
#define EVENT_TRANSVR_TASK_WAIT (2101)
|
||||||
|
#define EVENT_TRANSVR_TASK_DONE (0)
|
||||||
|
#define EVENT_TRANSVR_TASK_FAIL (-2101)
|
||||||
|
/* Event for initial handling */
|
||||||
|
#define EVENT_TRANSVR_INIT_UP (2201)
|
||||||
|
#define EVENT_TRANSVR_INIT_DOWN (1)
|
||||||
|
#define EVENT_TRANSVR_INIT_REINIT (-2201)
|
||||||
|
#define EVENT_TRANSVR_INIT_FAIL (-2202)
|
||||||
|
/* Event for others */
|
||||||
|
#define EVENT_TRANSVR_RELOAD_FAIL (-2301)
|
||||||
|
#define EVENT_TRANSVR_EXCEP_INIT (-2401)
|
||||||
|
#define EVENT_TRANSVR_EXCEP_UP (-2402)
|
||||||
|
#define EVENT_TRANSVR_EXCEP_DOWN (-2403)
|
||||||
|
#define EVENT_TRANSVR_EXCEP_SWAP (-2404)
|
||||||
|
#define EVENT_TRANSVR_EXCEP_EXCEP (-2405)
|
||||||
|
#define EVENT_TRANSVR_EXCEP_ISOLATED (-2406)
|
||||||
|
#define EVENT_TRANSVR_I2C_CRASH (-2501)
|
||||||
|
|
||||||
|
/* Transceiver error code define */
|
||||||
|
#define ERR_TRANSVR_UNINIT (-201)
|
||||||
|
#define ERR_TRANSVR_UNPLUGGED (-202)
|
||||||
|
#define ERR_TRANSVR_ABNORMAL (-203)
|
||||||
|
#define ERR_TRANSVR_NOSTATE (-204)
|
||||||
|
#define ERR_TRANSVR_NOTSUPPORT (-205)
|
||||||
|
#define ERR_TRANSVR_BADINPUT (-206)
|
||||||
|
#define ERR_TRANSVR_UPDATE_FAIL (-207)
|
||||||
|
#define ERR_TRANSVR_RELOAD_FAIL (-208)
|
||||||
|
#define ERR_TRANSVR_INIT_FAIL (-209)
|
||||||
|
#define ERR_TRANSVR_UNDEFINED (-210)
|
||||||
|
#define ERR_TRANSVR_TASK_FAIL (-211)
|
||||||
|
#define ERR_TRANSVR_TASK_BUSY (-212)
|
||||||
|
#define ERR_TRANSVR_UEVENT_FAIL (-213)
|
||||||
|
#define ERR_TRANSVR_FUNC_DISABLE (-214)
|
||||||
|
#define ERR_TRANSVR_I2C_CRASH (-297)
|
||||||
|
#define ERR_TRNASVR_BE_ISOLATED (-298)
|
||||||
|
#define ERR_TRANSVR_UNEXCPT (-299)
|
||||||
|
|
||||||
|
/* For debug */
|
||||||
|
#define DEBUG_TRANSVR_INT_VAL (-99)
|
||||||
|
#define DEBUG_TRANSVR_HEX_VAL (0xfe)
|
||||||
|
#define DEBUG_TRANSVR_STR_VAL "ERROR"
|
||||||
|
|
||||||
|
/* For system internal */
|
||||||
|
#define VAL_TRANSVR_COMID_ARREESS (0x50)
|
||||||
|
#define VAL_TRANSVR_COMID_OFFSET (0x00)
|
||||||
|
#define VAL_TRANSVR_EXTPHY_ADDR_56 (0x56)
|
||||||
|
#define VAL_TRANSVR_8472_READY_ADDR (0x51)
|
||||||
|
#define VAL_TRANSVR_8472_READY_PAGE (-1)
|
||||||
|
#define VAL_TRANSVR_8472_READY_OFFSET (110)
|
||||||
|
#define VAL_TRANSVR_8472_READY_BIT (0)
|
||||||
|
#define VAL_TRANSVR_8472_READY_VALUE (0)
|
||||||
|
#define VAL_TRANSVR_8472_READY_ABNORMAL (0xff)
|
||||||
|
#define VAL_TRANSVR_8436_READY_ADDR (0x50)
|
||||||
|
#define VAL_TRANSVR_8436_READY_PAGE (-1)
|
||||||
|
#define VAL_TRANSVR_8436_READY_OFFSET (2)
|
||||||
|
#define VAL_TRANSVR_8436_READY_BIT (0)
|
||||||
|
#define VAL_TRANSVR_8436_READY_VALUE (0)
|
||||||
|
#define VAL_TRANSVR_8436_READY_ABNORMAL (0xff)
|
||||||
|
#define VAL_TRANSVR_8436_PWD_ADDR (0x50)
|
||||||
|
#define VAL_TRANSVR_8436_PWD_PAGE (-1)
|
||||||
|
#define VAL_TRANSVR_8436_PWD_OFFSET (123)
|
||||||
|
#define VAL_TRANSVR_PAGE_FREE (-99)
|
||||||
|
#define VAL_TRANSVR_PAGE_SELECT_OFFSET (127)
|
||||||
|
#define VAL_TRANSVR_PAGE_SELECT_DELAY (5)
|
||||||
|
#define VAL_TRANSVR_TASK_RETRY_FOREVER (-999)
|
||||||
|
#define VAL_TRANSVR_FUNCTION_DISABLE (-1)
|
||||||
|
#define STR_TRANSVR_SFP "SFP"
|
||||||
|
#define STR_TRANSVR_QSFP "QSFP"
|
||||||
|
#define STR_TRANSVR_QSFP_PLUS "QSFP+"
|
||||||
|
#define STR_TRANSVR_QSFP28 "QSFP28"
|
||||||
|
|
||||||
|
/* For transvr buf len */
|
||||||
|
#define LEN_TRANSVR_S_STR (16)
|
||||||
|
#define LEN_TRANSVR_M_STR (32)
|
||||||
|
#define LEN_TRANSVR_L_STR (64)
|
||||||
|
|
||||||
|
/* Optical wavelength */
|
||||||
|
#define VAL_OPTICAL_WAVELENGTH_SR (850)
|
||||||
|
#define VAL_OPTICAL_WAVELENGTH_LR (1310)
|
||||||
|
#define VAL_OPTICAL_WAVELENGTH_ER (1550)
|
||||||
|
|
||||||
|
/* Switch chip type define */
|
||||||
|
#define CHIP_TYPE_MAGNOLIA (31001) /* Magnolia, Hudson32i, Spruce */
|
||||||
|
#define CHIP_TYPE_REDWOOD (31002) /* Redwood, Cypress, Sequoia */
|
||||||
|
#define CHIP_TYPE_MAPLE (31003) /* Maple */
|
||||||
|
|
||||||
|
#define CHIP_TYPE_LAVENDER (31011) /* Lavender */
|
||||||
|
|
||||||
|
/* Info from transceiver EEPROM */
|
||||||
|
struct eeprom_map_s {
|
||||||
|
int addr_br; int page_br; int offset_br; int length_br;
|
||||||
|
int addr_cdr; int page_cdr; int offset_cdr; int length_cdr;
|
||||||
|
int addr_comp_rev; int page_comp_rev; int offset_comp_rev; int length_comp_rev;
|
||||||
|
int addr_connector; int page_connector; int offset_connector; int length_connector;
|
||||||
|
int addr_diag_type; int page_diag_type; int offset_diag_type; int length_diag_type;
|
||||||
|
int addr_extbr; int page_extbr; int offset_extbr; int length_extbr;
|
||||||
|
int addr_ext_id; int page_ext_id; int offset_ext_id; int length_ext_id;
|
||||||
|
int addr_id; int page_id; int offset_id; int length_id;
|
||||||
|
int addr_len_sm; int page_len_sm; int offset_len_sm; int length_len_sm;
|
||||||
|
int addr_len_smf; int page_len_smf; int offset_len_smf; int length_len_smf;
|
||||||
|
int addr_len_om1; int page_len_om1; int offset_len_om1; int length_len_om1;
|
||||||
|
int addr_len_om2; int page_len_om2; int offset_len_om2; int length_len_om2;
|
||||||
|
int addr_len_om3; int page_len_om3; int offset_len_om3; int length_len_om3;
|
||||||
|
int addr_len_om4; int page_len_om4; int offset_len_om4; int length_len_om4;
|
||||||
|
int addr_option; int page_option; int offset_option; int length_option;
|
||||||
|
int addr_rate_id; int page_rate_id; int offset_rate_id; int length_rate_id;
|
||||||
|
int addr_rx_am; int page_rx_am; int offset_rx_am; int length_rx_am;
|
||||||
|
int addr_rx_em; int page_rx_em; int offset_rx_em; int length_rx_em;
|
||||||
|
int addr_rx_los; int page_rx_los; int offset_rx_los; int length_rx_los;
|
||||||
|
int addr_rx_power; int page_rx_power; int offset_rx_power; int length_rx_power;
|
||||||
|
int addr_soft_rs0; int page_soft_rs0; int offset_soft_rs0; int length_soft_rs0;
|
||||||
|
int addr_soft_rs1; int page_soft_rs1; int offset_soft_rs1; int length_soft_rs1;
|
||||||
|
int addr_temp; int page_temp; int offset_temp; int length_temp;
|
||||||
|
int addr_trancomp; int page_trancomp; int offset_trancomp; int length_trancomp;
|
||||||
|
int addr_trancomp_ext; int page_trancomp_ext; int offset_trancomp_ext; int length_trancomp_ext;
|
||||||
|
int addr_tx_bias; int page_tx_bias; int offset_tx_bias; int length_tx_bias;
|
||||||
|
int addr_tx_disable; int page_tx_disable; int offset_tx_disable; int length_tx_disable;
|
||||||
|
int addr_tx_eq; int page_tx_eq; int offset_tx_eq; int length_tx_eq;
|
||||||
|
int addr_tx_fault; int page_tx_fault; int offset_tx_fault; int length_tx_fault;
|
||||||
|
int addr_tx_power; int page_tx_power; int offset_tx_power; int length_tx_power;
|
||||||
|
int addr_vendor_name; int page_vendor_name; int offset_vendor_name; int length_vendor_name;
|
||||||
|
int addr_vendor_pn; int page_vendor_pn; int offset_vendor_pn; int length_vendor_pn;
|
||||||
|
int addr_vendor_rev; int page_vendor_rev; int offset_vendor_rev; int length_vendor_rev;
|
||||||
|
int addr_vendor_sn; int page_vendor_sn; int offset_vendor_sn; int length_vendor_sn;
|
||||||
|
int addr_voltage; int page_voltage; int offset_voltage; int length_voltage;
|
||||||
|
int addr_wavelength; int page_wavelength; int offset_wavelength; int length_wavelength;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct transvr_worker_s;
|
||||||
|
|
||||||
|
/* Class of transceiver object */
|
||||||
|
struct transvr_obj_s {
|
||||||
|
|
||||||
|
/* ========== Object private property ==========
|
||||||
|
* [Prop]: id
|
||||||
|
* [Desc]: Type of serial transceiver.
|
||||||
|
* [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh /QSFP28:11h
|
||||||
|
*/
|
||||||
|
uint8_t id;
|
||||||
|
|
||||||
|
/* [Prop]: connector
|
||||||
|
* [Desc]: Connector type.
|
||||||
|
* [Note]: SFP : A0h / 2
|
||||||
|
* QSFP: 00h / 130
|
||||||
|
*/
|
||||||
|
uint8_t connector;
|
||||||
|
|
||||||
|
/* [Prop]: transvr_comp
|
||||||
|
* [Desc]: Transceiver compliance code.
|
||||||
|
* [Note]: SFP: SFF-8472
|
||||||
|
* - Normal : A0h / offset 3-10
|
||||||
|
* - Extended: A0h / offset 36
|
||||||
|
* QSFP: SFF-8436 & SFF-8636
|
||||||
|
* - Normal : 00h / offset 131-138
|
||||||
|
* - Extended: 00h / offset 192
|
||||||
|
*/
|
||||||
|
uint8_t transvr_comp[8];
|
||||||
|
uint8_t transvr_comp_ext;
|
||||||
|
|
||||||
|
/* [Prop]: vendor_name
|
||||||
|
* [Desc]: SFP vendor name (ASCII 16 byte char).
|
||||||
|
* [Note]: ex:FINISAR CORP.
|
||||||
|
*/
|
||||||
|
char *vendor_name;
|
||||||
|
|
||||||
|
/* [Prop]: vendor_pn
|
||||||
|
* [Desc]: Part number provided by SFP vendor (ASCII 16 byte char).
|
||||||
|
* [Note]:
|
||||||
|
*/
|
||||||
|
char *vendor_pn;
|
||||||
|
|
||||||
|
/* [Prop]: vendor_rev
|
||||||
|
* [Desc]: Revision level for part number provided by vendor (ASCII 4 byte char).
|
||||||
|
* [Note]:
|
||||||
|
*/
|
||||||
|
char *vendor_rev;
|
||||||
|
|
||||||
|
/* [Prop]: vendor_sn
|
||||||
|
* [Desc]: Serial number provided by vendor (ASCII 16 byte char).
|
||||||
|
* [Note]:
|
||||||
|
*/
|
||||||
|
char *vendor_sn;
|
||||||
|
|
||||||
|
/* [Prop]: Extended identifier
|
||||||
|
* [Desc]: SFP:
|
||||||
|
* => None
|
||||||
|
*
|
||||||
|
* QSFP:
|
||||||
|
* => This byte contained two information:
|
||||||
|
* (1) Power consumption class
|
||||||
|
* (2) CDR function present
|
||||||
|
* [Note]: Bit description as below:
|
||||||
|
* [SFP]
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* [QSFP]
|
||||||
|
* (1) Power consumption class:
|
||||||
|
* Class 1: 1.5W (Bit6-7 = 00:)
|
||||||
|
* Class 2: 2.0W (Bit6-7 = 01:)
|
||||||
|
* Class 3: 2.5W (Bit6-7 = 10:)
|
||||||
|
* Class 4: 3.5W (Bit6-7 = 11:)
|
||||||
|
* Class 5: 4.0W (Bit0-1 = 01:)
|
||||||
|
* Class 6: 4.5W (Bit0-1 = 10:)
|
||||||
|
* Class 7: 5.0W (Bit0-1 = 11:)
|
||||||
|
* (2) CDR function present:
|
||||||
|
* Bit2: 0 = No CDR in RX
|
||||||
|
* 1 = CDR present in RX
|
||||||
|
* Bit3: 0 = No CDR in TX
|
||||||
|
* 1 = CDR present in TX
|
||||||
|
*/
|
||||||
|
uint8_t ext_id;
|
||||||
|
|
||||||
|
/* [Prop]: br
|
||||||
|
* [Desc]: Nominal bit rate, units of 100 MBits/sec.
|
||||||
|
* [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh
|
||||||
|
* has val: 0x67
|
||||||
|
* no val :
|
||||||
|
*/
|
||||||
|
uint8_t br;
|
||||||
|
|
||||||
|
/* [Prop]: extbr
|
||||||
|
* [Desc]: Extended br (00h/222)
|
||||||
|
* [Desc]: Nominal bit rate per channel, units of 250 Mbps.
|
||||||
|
* Complements. Byte 140. See Table 32A.
|
||||||
|
*/
|
||||||
|
uint8_t extbr;
|
||||||
|
|
||||||
|
/* [Prop]: len_sm
|
||||||
|
* [Desc]: Length (single mode)-(100's)m
|
||||||
|
* [Note]: This value specifies the link length that is supported by the transceiver
|
||||||
|
* while operating in compliance with the applicable standards using single mode
|
||||||
|
* fiber. The value is in units of 100 meters. A value of 255 means that the
|
||||||
|
* transceiver supports a link length greater than 25.4 km. A value of zero means
|
||||||
|
* that the transceiver does not support single mode fiber or that the length
|
||||||
|
* information must be determined from the transceiver technology.
|
||||||
|
*/
|
||||||
|
int len_sm;
|
||||||
|
|
||||||
|
/* [Prop]: len_smf
|
||||||
|
* [Desc]: Length (single mode)-km
|
||||||
|
* [Note]: Addition to EEPROM data from original GBIC definition. This value specifies
|
||||||
|
* the link length that is supported by the transceiver while operating in
|
||||||
|
* compliance with the applicable standards using single mode fiber. The value
|
||||||
|
* is in units of kilometers. A value of 255 means that the transceiver supports
|
||||||
|
* a link length greater than 254 km. A value of zero means that the transceiver
|
||||||
|
* does not support single mode fiber or that the length information must be
|
||||||
|
* determined from the transceiver technology.
|
||||||
|
*/
|
||||||
|
int len_smf;
|
||||||
|
|
||||||
|
/* [Prop]: len_om1
|
||||||
|
* [Desc]: Link length supported for 62.5 um OM1 fiber, units of 10 m
|
||||||
|
* [Note]: The value is in units of 10 meters. A value of 255 means that the
|
||||||
|
* transceiver supports a link length greater than 2.54 km. A value of
|
||||||
|
* zero means that the transceiver does not support 50 micron multi-mode
|
||||||
|
* fiber or that the length information must be determined from the transceiver
|
||||||
|
* technology.
|
||||||
|
*/
|
||||||
|
int len_om1;
|
||||||
|
|
||||||
|
/* [Prop]: len_om2
|
||||||
|
* [Desc]: Link length supported for 50 um OM2 fiber, units of 10 m
|
||||||
|
* [Note]: The value is in units of 10 meters. A value of 255 means that the
|
||||||
|
* transceiver supports a link length greater than 2.54 km. A value of
|
||||||
|
* zero means that the transceiver does not support 50 micron multi-mode
|
||||||
|
* fiber or that the length information must be determined from the transceiver
|
||||||
|
* technology.
|
||||||
|
*/
|
||||||
|
int len_om2;
|
||||||
|
|
||||||
|
/* [Prop]: len_om3
|
||||||
|
* [Desc]: Length (50um, OM3)
|
||||||
|
* [Note]: This value specifies link length that is supported by the transceiver while
|
||||||
|
* operating in compliance with applicable standards using 50 micron multimode
|
||||||
|
* OM3 [2000 MHz*km] fiber. The value is in units of 10 meters. A value of 255
|
||||||
|
* means that the transceiver supports a link length greater than 2.54 km. A value
|
||||||
|
* of zero means that the transceiver does not support 50 micron multimode fiber
|
||||||
|
* or that the length information must be determined from the transceiver technology.
|
||||||
|
*/
|
||||||
|
int len_om3;
|
||||||
|
|
||||||
|
/* [Prop]: len_om4
|
||||||
|
* [Desc]: Length (50um, OM4) and Length (Active Cable or Copper)
|
||||||
|
* [Note]: For optical links, this value specifies link length that is supported by the
|
||||||
|
* transceiver while operating in compliance with applicable standards using 50 micron
|
||||||
|
* multimode OM4 [4700 MHz*km] fiber. The value is in units of 10 meters. A value of
|
||||||
|
* 255 means that the transceiver supports a link length greater than 2.54 km. A value
|
||||||
|
* of zero means that the transceiver does not support 50 micron multimode fiber or that
|
||||||
|
* the length information must be determined from the transceiver codes specified in Table 5-3.
|
||||||
|
*
|
||||||
|
* For copper links, this value specifies minimum link length supported by the transceiver
|
||||||
|
* while operating in compliance with applicable standards using copper cable. For active
|
||||||
|
* cable, this value represents actual length. The value is in units of 1 meter. A value of 255
|
||||||
|
* means the transceiver supports a link length greater than 254 meters. A value of zero means
|
||||||
|
* the transceiver does not support copper or active cables or the length information must be
|
||||||
|
* determined from transceiver technology. Further information about cable design, equalization,
|
||||||
|
* and connectors is usually required to guarantee meeting a particular length requirement.
|
||||||
|
*/
|
||||||
|
int len_om4;
|
||||||
|
|
||||||
|
/* [Prop]: comp_rev
|
||||||
|
* [Desc]: SFF spec revision compliance
|
||||||
|
* [Note]: Indicates which revision of SFF SFF-8472 (SFP) / SFF-8636 (QSFP) the transceiver
|
||||||
|
* complies with. (unsigned integer)
|
||||||
|
*/
|
||||||
|
uint8_t comp_rev;
|
||||||
|
|
||||||
|
/* [Prop]: CDR
|
||||||
|
* [Desc]: For transceivers with CDR capability, setting the CDR to ON engages the internal
|
||||||
|
* retiming function. Setting the CDR to OFF enables an internal bypassing mode ,which
|
||||||
|
* directs traffic around the internal CDR. (Reference: SFF-8636)
|
||||||
|
* [Note]: value=0xff: ON.
|
||||||
|
* value=0x00: OFF.
|
||||||
|
*/
|
||||||
|
uint8_t cdr;
|
||||||
|
|
||||||
|
/* [Prop]: rate_id
|
||||||
|
* [Desc]: Soft Rate Select 0(RX).
|
||||||
|
* [Note]: 1. Addr: A0h / Offset: 13
|
||||||
|
* 2. Value description:
|
||||||
|
* 00h Unspecified
|
||||||
|
* 01h SFF-8079 (4/2/1G Rate_Select & AS0/AS1)
|
||||||
|
* 02h SFF-8431 (8/4/2G Rx Rate_Select only)
|
||||||
|
* 03h Unspecified *
|
||||||
|
* 04h SFF-8431 (8/4/2G Tx Rate_Select only)
|
||||||
|
* 05h Unspecified *
|
||||||
|
* 06h SFF-8431 (8/4/2G Independent Rx & Tx Rate_select)
|
||||||
|
* 07h Unspecified *
|
||||||
|
* 08h FC-PI-5 (16/8/4G Rx Rate_select only) High=16G only, Low=8G/4G
|
||||||
|
* 09h Unspecified *
|
||||||
|
* 0Ah FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) High=16G only,
|
||||||
|
* Low=8G/4G
|
||||||
|
* 0Bh Unspecified *
|
||||||
|
* 0Ch FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select)
|
||||||
|
* High=32G only, Low = 16G/8G
|
||||||
|
* 0Dh Unspecified *
|
||||||
|
* 0Eh 10/8G Rx and Tx Rate_Select controlling the operation or locking
|
||||||
|
* modes of the internal signal conditioner, retimer or CDR, according
|
||||||
|
* to the logic table defined in Table 10-2, High Bit Rate
|
||||||
|
* (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = 8.5 Gb/s. In this mode,
|
||||||
|
* the default value of bit 110.3 (Soft Rate Select RS(0), Table 9-11)
|
||||||
|
* and of bit 118.3 (Soft Rate Select RS(1), Table 10-1) is 1.
|
||||||
|
* 0Fh Unspecified *
|
||||||
|
* 10h-FFh Unallocated
|
||||||
|
*/
|
||||||
|
int rate_id;
|
||||||
|
|
||||||
|
/* [Prop]: soft_rs0
|
||||||
|
* [Desc]: Soft Rate Select 0(RX).
|
||||||
|
* [Note]: 1. Writing '1' selects full bandwidth operation.
|
||||||
|
* 2. This bit is "OR'd with the hard Rate_Select, AS(0) or RS(0) pin value.
|
||||||
|
* 3. Default at power up is logic zero/low
|
||||||
|
* 4. Addr: A2h / Offset: 110 / Bit: 3
|
||||||
|
*/
|
||||||
|
uint8_t soft_rs0;
|
||||||
|
|
||||||
|
/* [Prop]: soft_rs1
|
||||||
|
* [Desc]: Soft Rate Select 1(TX).
|
||||||
|
* [Note]: 1. Writing '1' selects full bandwidth TX operation.
|
||||||
|
* 2. This bit is "OR'd with the hard Rate_Select, AS(1) or RS(1) pin value.
|
||||||
|
* 3. Default at power up is logic zero/low
|
||||||
|
* 4. Addr: A2h / Offset: 118 / Bit: 3
|
||||||
|
*/
|
||||||
|
uint8_t soft_rs1;
|
||||||
|
|
||||||
|
/* [Prop]: diag_type
|
||||||
|
* [Desc]: DIAGNOSTIC MONITORING TYPE (A0h/92)
|
||||||
|
* [Note]: Description in SFF-8472 as below:
|
||||||
|
* Bit7: Reserved for legacy diagnostic implementations. Must be '0' for compliance
|
||||||
|
* with this document.
|
||||||
|
* Bit6: Digital diagnostic monitoring implemented (described in this document).
|
||||||
|
* Must be '1' for compliance with this document.
|
||||||
|
* Bit5 Internally calibrated
|
||||||
|
* Bit4 Externally calibrated
|
||||||
|
* Bit3 Received power measurement type.0 = OMA, 1 = average power
|
||||||
|
* Bit2 Address change required see section above, "addressing modes"
|
||||||
|
* Bit1-0 Unallocated
|
||||||
|
*/
|
||||||
|
uint8_t diag_type;
|
||||||
|
|
||||||
|
/* [Prop]: curr_temp
|
||||||
|
* [Desc]: Transceiver Current Temperature (A2h/96-97)
|
||||||
|
* [Note]: 1. Dependent on diag_type.
|
||||||
|
* 2. 96: High byte
|
||||||
|
* 3. 97: Low byte
|
||||||
|
* 4. This feature only for SFP
|
||||||
|
*/
|
||||||
|
uint8_t curr_temp[2];
|
||||||
|
|
||||||
|
/* [Prop]: curr_vol
|
||||||
|
* [Desc]: Transceiver Current Voltage (SFP:A2h/108-109; QSFP:00h/22-23)
|
||||||
|
* [Note]: 1. Dependent on diag_type.
|
||||||
|
* 2. 98: High byte
|
||||||
|
* 3. 99: Low byte
|
||||||
|
* 4. This feature only for SFP
|
||||||
|
* 5. Internally measured transceiver supply voltage. Represented
|
||||||
|
* as a 16 bit unsigned integer with the voltage defined as the
|
||||||
|
* full 16 bit value (0-65535) with LSB equal to 100 uVolt,
|
||||||
|
* yielding a total range of 0 to +6.55 Volts
|
||||||
|
*/
|
||||||
|
uint8_t curr_voltage[2];
|
||||||
|
|
||||||
|
/* [Prop]: curr_tx_bias
|
||||||
|
* [Desc]: Transceiver TX Bias Current (SFP:A2h/100-101; QSFP:00h/26-27)
|
||||||
|
* [Note]: 1. Dependent on diag_type.
|
||||||
|
* 2. 100: High byte
|
||||||
|
* 3. 101: Low byte
|
||||||
|
* 4. This feature only for SFP
|
||||||
|
* 5. Measured TX bias current in uA. Represented as a 16 bit unsigned
|
||||||
|
* integer with the current defined as the full 16 bit value (0-65535)
|
||||||
|
* with LSB equal to 2 uA, yielding a total range of 0 to 131 mA.
|
||||||
|
* Accuracy is vendor specific but must be better than 10% of the
|
||||||
|
* manufacturer's nominal value over specified operating temperature
|
||||||
|
* and voltage.
|
||||||
|
*/
|
||||||
|
uint8_t curr_tx_bias[8];
|
||||||
|
|
||||||
|
/* [Prop]: curr_tx_power
|
||||||
|
* [Desc]: Transceiver TX Output Power (A2h/102-103)
|
||||||
|
* [Note]: 1. Dependent on diag_type.
|
||||||
|
* 2. 102: High byte
|
||||||
|
* 3. 103: Low byte
|
||||||
|
* 4. This feature only for SFP
|
||||||
|
* 5. Measured TX output power in mW. Represented as a 16 bit unsigned
|
||||||
|
* integer with the power defined as the full 16 bit value (0-65535)
|
||||||
|
* with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW
|
||||||
|
* (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of
|
||||||
|
* laser monitor photodiode current. It is factory calibrated to absolute
|
||||||
|
* units using the most representative fiber output type. Accuracy is
|
||||||
|
* vendor specific but must be better than 3dB over specified temperature
|
||||||
|
* and voltage. Data is not valid when the transmitter is disabled.
|
||||||
|
*/
|
||||||
|
uint8_t curr_tx_power[8];
|
||||||
|
|
||||||
|
/* [Prop]: curr_tx_power
|
||||||
|
* [Desc]: Transceiver TX Output Power (A2h/102-103)
|
||||||
|
* [Note]: 1. Dependent on diag_type.
|
||||||
|
* 2. 102: High byte
|
||||||
|
* 3. 103: Low byte
|
||||||
|
* 4. This feature only for SFP
|
||||||
|
* 5. Measured RX received optical power in mW. Value can represent either
|
||||||
|
* average received power or OMA depending upon how bit 3 of byte 92 (A0h)
|
||||||
|
* is set. Represented as a 16 bit unsigned integer with the power defined
|
||||||
|
* as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a
|
||||||
|
* total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is
|
||||||
|
* dependent upon the exact optical wavelength. For the vendor specified
|
||||||
|
* wavelength, accuracy shall be better than 3dB over specified temperature
|
||||||
|
* and voltage.
|
||||||
|
*/
|
||||||
|
uint8_t curr_rx_power[8];
|
||||||
|
|
||||||
|
/* [Prop]: wavelength
|
||||||
|
* [Desc]: Wavelength or Copper Cable Attenuation
|
||||||
|
* [Note]: (Following is info from SFF-8636)
|
||||||
|
* For optical free side devices, this parameter identifies the nominal
|
||||||
|
* transmitter output wavelength at room temperature. This parameter is a
|
||||||
|
* 16-bit hex value with Byte 186 as high order byte and Byte 187 as low
|
||||||
|
* order byte. The laser wavelength is equal to the 16-bit integer value
|
||||||
|
* divided by 20 in nm (units of 0.05 nm). This resolution should be adequate
|
||||||
|
* to cover all relevant wavelengths yet provide enough resolution for all
|
||||||
|
* expected DWDM applications. For accurate representation of controlled
|
||||||
|
* wavelength applications, this value should represent the center of the
|
||||||
|
* guaranteed wavelength range. If the free side device is identified as
|
||||||
|
* copper cable these registers will be used to define the cable attenuation.
|
||||||
|
* An indication of 0 dB attenuation refers to the case where the attenuation
|
||||||
|
* is not known or is unavailable.
|
||||||
|
* Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB.
|
||||||
|
* Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB.
|
||||||
|
*/
|
||||||
|
uint8_t wavelength[2];
|
||||||
|
|
||||||
|
/* [Prop]: Amplitude control
|
||||||
|
* [Desc]: Amplitude control
|
||||||
|
* [Note]: QSFP28 => SFF-8636 03H Byte-238/239
|
||||||
|
*/
|
||||||
|
uint8_t rx_am[2];
|
||||||
|
|
||||||
|
/* [Prop]: Emphasis control
|
||||||
|
* [Desc]: Emphasis control
|
||||||
|
* [Note]: SFP+/28 => SFF-8472 A2H Byte-115
|
||||||
|
* QSFP28 => SFF-8636 03H Byte-236/237
|
||||||
|
*/
|
||||||
|
uint8_t rx_em[2];
|
||||||
|
|
||||||
|
/* [Prop]: Soft Rx LOS
|
||||||
|
* [Desc]: Soft Rx LOS which provide by transceiver
|
||||||
|
* [Note]: (Following is info from SFF-8636)
|
||||||
|
* Byte 3:
|
||||||
|
* - Bit 0: L-Rx1 LOS
|
||||||
|
* - Bit 1: L-Rx2 LOS
|
||||||
|
* - Bit 2: L-Rx3 LOS
|
||||||
|
* - Bit 3: L-Rx4 LOS
|
||||||
|
*/
|
||||||
|
uint8_t rx_los;
|
||||||
|
|
||||||
|
/* [Prop]: Soft Tx Disable
|
||||||
|
* [Desc]: Soft Tx Disable which provide by transceiver
|
||||||
|
* [Note]: (Following is info from SFF-8636)
|
||||||
|
* Byte 86:
|
||||||
|
* - Bit 0: Tx1 Disable
|
||||||
|
* - Bit 1: Tx2 Disable
|
||||||
|
* - Bit 2: Tx3 Disable
|
||||||
|
* - Bit 3: Tx4 Disable
|
||||||
|
*/
|
||||||
|
uint8_t tx_disable;
|
||||||
|
|
||||||
|
/* [Prop]: Soft Tx Fault
|
||||||
|
* [Desc]: Soft Tx Fault which provide by transceiver
|
||||||
|
* [Note]: (Following is info from SFF-8636)
|
||||||
|
* Byte 86:
|
||||||
|
* - Bit 0: Tx1 Fault
|
||||||
|
* - Bit 1: Tx2 Fault
|
||||||
|
* - Bit 2: Tx3 Fault
|
||||||
|
* - Bit 3: Tx4 Fault
|
||||||
|
*/
|
||||||
|
uint8_t tx_fault;
|
||||||
|
|
||||||
|
/* [Prop]: Transceiver EQUALIZATION
|
||||||
|
* [Desc]: Transceiver EQUALIZATION
|
||||||
|
* [Note]: SFP+/28 => SFF-8472 A2H Byte-114
|
||||||
|
* QSFP28 => SFF-8636 03H Byte-234/235
|
||||||
|
*/
|
||||||
|
uint8_t tx_eq[2];
|
||||||
|
|
||||||
|
/* [Prop]: OPTION VALUES
|
||||||
|
* [Desc]: The bits in the option field shall specify the options implemented in the transceiver.
|
||||||
|
* [Note]: SFP+/28 => SFF-8472 A0H Byte-64/65
|
||||||
|
* QSFP+/28 => SFF-8636 00H Byte-193/195
|
||||||
|
*/
|
||||||
|
uint8_t option[3];
|
||||||
|
|
||||||
|
/* [Prop]: External PHY offset
|
||||||
|
* [Desc]: It needs to be setup first if you want to access transceiver external phy.
|
||||||
|
* [Note]: This feature dependent on transceiver.
|
||||||
|
* Currently, only 1G-RJ45 transceiver supported it.
|
||||||
|
*/
|
||||||
|
uint8_t extphy_offset;
|
||||||
|
|
||||||
|
/* ========== Object private property ==========
|
||||||
|
*/
|
||||||
|
struct device *transvr_dev_p;
|
||||||
|
struct eeprom_map_s *eeprom_map_p;
|
||||||
|
struct i2c_client *i2c_client_p;
|
||||||
|
struct ioexp_obj_s *ioexp_obj_p;
|
||||||
|
struct transvr_worker_s *worker_p;
|
||||||
|
struct mutex lock;
|
||||||
|
char swp_name[32];
|
||||||
|
int auto_config;
|
||||||
|
int auto_tx_disable;
|
||||||
|
int chan_id;
|
||||||
|
int chipset_type;
|
||||||
|
int curr_page;
|
||||||
|
int info;
|
||||||
|
int ioexp_virt_offset;
|
||||||
|
int lane_id[8];
|
||||||
|
int layout;
|
||||||
|
int mode;
|
||||||
|
int retry;
|
||||||
|
int state;
|
||||||
|
int temp;
|
||||||
|
int type;
|
||||||
|
|
||||||
|
/* ========== Object public functions ==========
|
||||||
|
*/
|
||||||
|
int (*get_id)(struct transvr_obj_s *self);
|
||||||
|
int (*get_ext_id)(struct transvr_obj_s *self);
|
||||||
|
int (*get_connector)(struct transvr_obj_s *self);
|
||||||
|
int (*get_vendor_name)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_vendor_pn)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_vendor_rev)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_vendor_sn)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_power_cls)(struct transvr_obj_s *self);
|
||||||
|
int (*get_br)(struct transvr_obj_s *self);
|
||||||
|
int (*get_len_sm)(struct transvr_obj_s *self);
|
||||||
|
int (*get_len_smf)(struct transvr_obj_s *self);
|
||||||
|
int (*get_len_om1)(struct transvr_obj_s *self);
|
||||||
|
int (*get_len_om2)(struct transvr_obj_s *self);
|
||||||
|
int (*get_len_om3)(struct transvr_obj_s *self);
|
||||||
|
int (*get_len_om4)(struct transvr_obj_s *self);
|
||||||
|
int (*get_comp_rev)(struct transvr_obj_s *self);
|
||||||
|
int (*get_comp_eth_1)(struct transvr_obj_s *self);
|
||||||
|
int (*get_comp_eth_10)(struct transvr_obj_s *self);
|
||||||
|
int (*get_comp_eth_10_40)(struct transvr_obj_s *self);
|
||||||
|
int (*get_comp_extend)(struct transvr_obj_s *self);
|
||||||
|
int (*get_cdr)(struct transvr_obj_s *self);
|
||||||
|
int (*get_rate_id)(struct transvr_obj_s *self);
|
||||||
|
int (*get_soft_rs0)(struct transvr_obj_s *self);
|
||||||
|
int (*get_soft_rs1)(struct transvr_obj_s *self);
|
||||||
|
int (*get_info)(struct transvr_obj_s *self);
|
||||||
|
int (*get_if_type)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_if_speed)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_if_lane)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_curr_temp)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_curr_vol)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_soft_rx_los)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_soft_tx_disable)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_soft_tx_fault)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_auto_tx_disable)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_tx_bias)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_tx_power)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_rx_power)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_tx_eq)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_rx_am)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_rx_em)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_wavelength)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_extphy_offset)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*get_extphy_reg)(struct transvr_obj_s *self, char *buf_p);
|
||||||
|
int (*set_cdr)(struct transvr_obj_s *self, int input_val);
|
||||||
|
int (*set_soft_rs0)(struct transvr_obj_s *self, int input_val);
|
||||||
|
int (*set_soft_rs1)(struct transvr_obj_s *self, int input_val);
|
||||||
|
int (*set_soft_tx_disable)(struct transvr_obj_s *self, int input_val);
|
||||||
|
int (*set_auto_tx_disable)(struct transvr_obj_s *self, int input_val);
|
||||||
|
int (*set_tx_eq)(struct transvr_obj_s *self, int input_val);
|
||||||
|
int (*set_rx_am)(struct transvr_obj_s *self, int input_val);
|
||||||
|
int (*set_rx_em)(struct transvr_obj_s *self, int input_val);
|
||||||
|
int (*set_extphy_offset)(struct transvr_obj_s *self, int input_val);
|
||||||
|
int (*set_extphy_reg)(struct transvr_obj_s *self, int input_val);
|
||||||
|
|
||||||
|
/* ========== Object private functions ==========
|
||||||
|
*/
|
||||||
|
int (*init)(struct transvr_obj_s *self);
|
||||||
|
int (*clean)(struct transvr_obj_s *self);
|
||||||
|
int (*check)(struct transvr_obj_s *self);
|
||||||
|
int (*update_all)(struct transvr_obj_s *self, int show_err);
|
||||||
|
int (*fsm_4_direct)(struct transvr_obj_s* self, char *caller_name);
|
||||||
|
int (*fsm_4_polling)(struct transvr_obj_s* self, char *caller_name);
|
||||||
|
int (*send_uevent)(struct transvr_obj_s* self, enum kobject_action u_action);
|
||||||
|
int (*dump_all)(struct transvr_obj_s* self);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* For AVL Mapping */
|
||||||
|
struct transvr_avl_s {
|
||||||
|
char vendor_name[32];
|
||||||
|
char vendor_pn[32];
|
||||||
|
int (*init)(struct transvr_obj_s *self);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Worker for long term task of transceiver */
|
||||||
|
struct transvr_worker_s {
|
||||||
|
/* Task Parameter */
|
||||||
|
struct transvr_obj_s *transvr_p;
|
||||||
|
struct transvr_worker_s *next_p;
|
||||||
|
struct transvr_worker_s *pre_p;
|
||||||
|
unsigned long trigger_time;
|
||||||
|
char func_name[64];
|
||||||
|
int retry;
|
||||||
|
int state;
|
||||||
|
|
||||||
|
/* Task private data */
|
||||||
|
void *p_data;
|
||||||
|
|
||||||
|
/* Call back function */
|
||||||
|
int (*main_task)(struct transvr_worker_s *task);
|
||||||
|
int (*post_task)(struct transvr_worker_s *task);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct transvr_obj_s *
|
||||||
|
create_transvr_obj(char *swp_name,
|
||||||
|
int chan_id,
|
||||||
|
struct ioexp_obj_s *ioexp_obj_p,
|
||||||
|
int ioexp_virt_offset,
|
||||||
|
int transvr_type,
|
||||||
|
int chipset_type,
|
||||||
|
int run_mode);
|
||||||
|
|
||||||
|
void lock_transvr_obj(struct transvr_obj_s *self);
|
||||||
|
void unlock_transvr_obj(struct transvr_obj_s *self);
|
||||||
|
int isolate_transvr_obj(struct transvr_obj_s *self);
|
||||||
|
|
||||||
|
int resync_channel_tier_2(struct transvr_obj_s *self);
|
||||||
|
|
||||||
|
void alarm_msg_2_user(struct transvr_obj_s *self, char *emsg);
|
||||||
|
|
||||||
|
#endif /* TRANSCEIVER_H */
|
||||||
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import os
|
||||||
|
from setuptools import setup
|
||||||
|
os.listdir
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='sonic_platform',
|
||||||
|
version='1.0',
|
||||||
|
description='Module to initialize Ivnetec D6332 platforms',
|
||||||
|
|
||||||
|
packages=['sonic_platform'],
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,3 @@
|
|||||||
|
__all__ = ["platform", "chassis"]
|
||||||
|
from sonic_platform import *
|
||||||
|
|
@ -0,0 +1,242 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Name: chassis.py, version: 1.0
|
||||||
|
#
|
||||||
|
# Description: Module contains the definitions of SONiC platform APIs
|
||||||
|
#
|
||||||
|
|
||||||
|
try:
|
||||||
|
import re
|
||||||
|
from sonic_platform_base.chassis_base import ChassisBase
|
||||||
|
from sonic_platform.eeprom import Eeprom
|
||||||
|
from sonic_platform.fan import Fan
|
||||||
|
from sonic_platform.psu import Psu
|
||||||
|
from sonic_platform.qsfp import QSfp
|
||||||
|
from sonic_platform.event_monitor import EventMonitor
|
||||||
|
from sonic_platform.thermal import Thermal
|
||||||
|
from sonic_platform.component import Component
|
||||||
|
from sonic_platform.watchdog import Watchdog
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
|
PMON_REBOOT_CAUSE_PATH = "/usr/share/sonic/platform/reboot-cause/"
|
||||||
|
REBOOT_CAUSE_FILE = "reboot-cause.txt"
|
||||||
|
PREV_REBOOT_CAUSE_FILE = "previous-reboot-cause.txt"
|
||||||
|
monitor = None
|
||||||
|
|
||||||
|
class Chassis(ChassisBase):
|
||||||
|
|
||||||
|
__num_of_fans = 5
|
||||||
|
__num_of_psus = 2
|
||||||
|
__num_of_sfps = 32
|
||||||
|
__start_of_qsfp = 1
|
||||||
|
__num_of_thermals = 15
|
||||||
|
__num_of_components= 4
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
ChassisBase.__init__(self)
|
||||||
|
|
||||||
|
# Initialize EEPROM
|
||||||
|
self._eeprom = Eeprom()
|
||||||
|
self._eeprom_data = self._eeprom.get_eeprom_data()
|
||||||
|
|
||||||
|
# Initialize FAN
|
||||||
|
for index in range(self.__num_of_fans):
|
||||||
|
fan = Fan(index)
|
||||||
|
self._fan_list.append(fan)
|
||||||
|
|
||||||
|
# Initialize PSU
|
||||||
|
for index in range(self.__num_of_psus):
|
||||||
|
psu = Psu(index)
|
||||||
|
self._psu_list.append(psu)
|
||||||
|
|
||||||
|
# Initialize SFP
|
||||||
|
for index in range(self.__num_of_sfps):
|
||||||
|
sfp = QSfp(index) #only qsfp on platform D6332
|
||||||
|
self._sfp_list.append(sfp)
|
||||||
|
|
||||||
|
# Initialize THERMAL
|
||||||
|
for index in range(self.__num_of_thermals):
|
||||||
|
thermal = Thermal(index)
|
||||||
|
self._thermal_list.append(thermal)
|
||||||
|
|
||||||
|
# Initialize COMPONENT
|
||||||
|
for index in range(self.__num_of_components):
|
||||||
|
component = Component(index)
|
||||||
|
self._component_list.append(component)
|
||||||
|
|
||||||
|
# Initialize WATCHDOG
|
||||||
|
self._watchdog = Watchdog()
|
||||||
|
|
||||||
|
|
||||||
|
def __read_txt_file(self, file_path):
|
||||||
|
try:
|
||||||
|
with open(file_path, 'r') as fd:
|
||||||
|
data = fd.read()
|
||||||
|
return data.strip()
|
||||||
|
except IOError:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
# Device methods
|
||||||
|
##############################################
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
"""
|
||||||
|
Retrieves the name of the chassis
|
||||||
|
Returns:
|
||||||
|
string: The name of the chassis
|
||||||
|
"""
|
||||||
|
return self._eeprom.modelstr(self._eeprom_data)
|
||||||
|
|
||||||
|
def get_presence(self):
|
||||||
|
"""
|
||||||
|
Retrieves the presence of the chassis
|
||||||
|
Returns:
|
||||||
|
bool: True if chassis is present, False if not
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_model(self):
|
||||||
|
"""
|
||||||
|
Retrieves the model number (or part number) of the chassis
|
||||||
|
Returns:
|
||||||
|
string: Model/part number of chassis
|
||||||
|
"""
|
||||||
|
return self._eeprom.part_number_str()
|
||||||
|
|
||||||
|
def get_serial(self):
|
||||||
|
"""
|
||||||
|
Retrieves the serial number of the chassis
|
||||||
|
Returns:
|
||||||
|
string: Serial number of chassis
|
||||||
|
"""
|
||||||
|
return self._eeprom.serial_number_str(self._eeprom_data)
|
||||||
|
|
||||||
|
def get_status(self):
|
||||||
|
"""
|
||||||
|
Retrieves the operational status of the chassis
|
||||||
|
Returns:
|
||||||
|
bool: A boolean value, True if chassis is operating properly
|
||||||
|
False if not
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
# Chassis methods
|
||||||
|
##############################################
|
||||||
|
|
||||||
|
def get_base_mac(self):
|
||||||
|
"""
|
||||||
|
Retrieves the base MAC address for the chassis
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A string containing the MAC address in the format
|
||||||
|
'XX:XX:XX:XX:XX:XX'
|
||||||
|
"""
|
||||||
|
return self._eeprom.base_mac_addr(self._eeprom_data)
|
||||||
|
|
||||||
|
def get_serial_number(self):
|
||||||
|
"""
|
||||||
|
Retrieves the hardware serial number for the chassis
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A string containing the hardware serial number for this chassis.
|
||||||
|
"""
|
||||||
|
return self._eeprom.serial_number_str(self._eeprom_data)
|
||||||
|
|
||||||
|
def get_system_eeprom_info(self):
|
||||||
|
"""
|
||||||
|
Retrieves the full content of system EEPROM information for the chassis
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A dictionary where keys are the type code defined in
|
||||||
|
OCP ONIE TlvInfo EEPROM format and values are their corresponding
|
||||||
|
values.
|
||||||
|
Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821',
|
||||||
|
'0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00',
|
||||||
|
'0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'}
|
||||||
|
"""
|
||||||
|
return self._eeprom.system_eeprom_info()
|
||||||
|
|
||||||
|
def get_reboot_cause(self):
|
||||||
|
"""
|
||||||
|
Retrieves the cause of the previous reboot
|
||||||
|
Returns:
|
||||||
|
A tuple (string, string) where the first element is a string
|
||||||
|
containing the cause of the previous reboot. This string must be
|
||||||
|
one of the predefined strings in this class. If the first string
|
||||||
|
is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used
|
||||||
|
to pass a description of the reboot cause.
|
||||||
|
"""
|
||||||
|
description = 'None'
|
||||||
|
reboot_cause = self.REBOOT_CAUSE_HARDWARE_OTHER
|
||||||
|
|
||||||
|
reboot_cause_path = PMON_REBOOT_CAUSE_PATH + REBOOT_CAUSE_FILE
|
||||||
|
prev_reboot_cause_path = PMON_REBOOT_CAUSE_PATH + PREV_REBOOT_CAUSE_FILE
|
||||||
|
|
||||||
|
sw_reboot_cause = self.__read_txt_file(reboot_cause_path) or "Unknown"
|
||||||
|
prev_sw_reboot_cause = self.__read_txt_file(prev_reboot_cause_path) or "Unknown"
|
||||||
|
|
||||||
|
if sw_reboot_cause == "Unknown" and (prev_sw_reboot_cause == "Unknown" or prev_sw_reboot_cause == self.REBOOT_CAUSE_POWER_LOSS):
|
||||||
|
reboot_cause = self.REBOOT_CAUSE_POWER_LOSS
|
||||||
|
description = prev_sw_reboot_cause
|
||||||
|
elif sw_reboot_cause != "Unknown":
|
||||||
|
reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE
|
||||||
|
description = sw_reboot_cause
|
||||||
|
elif prev_reboot_cause_path != "Unknown":
|
||||||
|
reboot_cause = self.REBOOT_CAUSE_NON_HARDWARE
|
||||||
|
description = prev_sw_reboot_cause
|
||||||
|
|
||||||
|
return (reboot_cause, description)
|
||||||
|
|
||||||
|
def get_change_event(self, timeout=0):
|
||||||
|
"""
|
||||||
|
Returns a nested dictionary containing all devices which have
|
||||||
|
experienced a change at chassis level
|
||||||
|
|
||||||
|
Args:
|
||||||
|
timeout: Timeout in milliseconds (optional). If timeout == 0,
|
||||||
|
this method will block until a change is detected.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(bool, dict):
|
||||||
|
- True if call successful, False if not;
|
||||||
|
- A nested dictionary where key is a device type,
|
||||||
|
value is a dictionary with key:value pairs in the format of
|
||||||
|
{'device_id':'device_event'},
|
||||||
|
where device_id is the device ID for this device and
|
||||||
|
device_event,
|
||||||
|
status='1' represents device inserted,
|
||||||
|
status='0' represents device removed.
|
||||||
|
Ex. {'fan':{'0':'0', '2':'1'}, 'sfp':{'11':'0'}}
|
||||||
|
indicates that fan 0 has been removed, fan 2
|
||||||
|
has been inserted and sfp 11 has been removed.
|
||||||
|
"""
|
||||||
|
global monitor
|
||||||
|
port_dict = {}
|
||||||
|
while True:
|
||||||
|
with EventMonitor(timeout) as monitor:
|
||||||
|
while True:
|
||||||
|
event = monitor.get_events()
|
||||||
|
|
||||||
|
if not bool(event):
|
||||||
|
return True, {'sfp':port_dict}
|
||||||
|
else:
|
||||||
|
if event['SUBSYSTEM'] == 'swps':
|
||||||
|
portname = event['DEVPATH'].split("/")[-1]
|
||||||
|
rc = re.match(r"port(?P<num>\d+)",portname)
|
||||||
|
if rc is not None:
|
||||||
|
if event['ACTION'] == "remove":
|
||||||
|
remove_num = int(rc.group("num"))
|
||||||
|
port_dict[remove_num] = "0"
|
||||||
|
elif event['ACTION'] == "add":
|
||||||
|
add_num = int(rc.group("num"))
|
||||||
|
port_dict[add_num] = "1"
|
||||||
|
return True, {'sfp':port_dict}
|
||||||
|
else:
|
||||||
|
return False, {'sfp':port_dict}
|
||||||
|
else:
|
||||||
|
pass
|
@ -0,0 +1,196 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
try:
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
from sonic_platform_base.component_base import ComponentBase
|
||||||
|
from sonic_platform.inv_const import Common
|
||||||
|
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
|
|
||||||
|
OS_SYSTEM_SUCCESS = 0
|
||||||
|
|
||||||
|
CPLD1_INFO_PATH = Common.I2C_PREFIX+"/0-0077/info"
|
||||||
|
CPLD2_INFO_PATH = Common.I2C_PREFIX+"/0-0077/info" #info of 2 cpld are combined by inv_cpld under this path
|
||||||
|
BIOS_VER_PATH = "/sys/class/dmi/id/bios_version"
|
||||||
|
BIOS_CS_PATH = Common.I2C_PREFIX+"/0-0077/bios_cs"
|
||||||
|
|
||||||
|
CPLD1_INDEX = 0
|
||||||
|
CPLD2_INDEX = 1
|
||||||
|
MAIN_BIOS_INDEX = 2
|
||||||
|
BACKUP_BIOS_INDEX = 3
|
||||||
|
|
||||||
|
|
||||||
|
COMPONENT_NAME_LIST = [
|
||||||
|
"CPLD1",
|
||||||
|
"CPLD2",
|
||||||
|
"Main BIOS",
|
||||||
|
"Backup BIOS",
|
||||||
|
]
|
||||||
|
|
||||||
|
COMPONENT_DESC_LIST = [
|
||||||
|
"platform management and control LED",
|
||||||
|
"platform management and control LED",
|
||||||
|
"Main Basic Input/Output System",
|
||||||
|
"Backup Basic Input/Output System",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
BIOS_ID_MAPPING_TABLE = {
|
||||||
|
0: MAIN_BIOS_INDEX,
|
||||||
|
1: BACKUP_BIOS_INDEX
|
||||||
|
}
|
||||||
|
|
||||||
|
class Component(ComponentBase):
|
||||||
|
|
||||||
|
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 retval
|
||||||
|
|
||||||
|
def __set_attr_value(self, attr_path, value):
|
||||||
|
try:
|
||||||
|
with open(attr_path, 'r+') as reg_file:
|
||||||
|
reg_file.write(value)
|
||||||
|
except IOError as e:
|
||||||
|
logging.error("Error: unable to open file: %s" % str(e))
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __get_current_bios(self):
|
||||||
|
current_bios=self.__get_attr_value(BIOS_CS_PATH)
|
||||||
|
if current_bios != 'ERR':
|
||||||
|
'''
|
||||||
|
Get first char to convert to bios ID
|
||||||
|
'''
|
||||||
|
current_bios = int(current_bios[:1])
|
||||||
|
else:
|
||||||
|
current_bios = None
|
||||||
|
|
||||||
|
return current_bios
|
||||||
|
|
||||||
|
def __get_cpld_version(self):
|
||||||
|
'''
|
||||||
|
The info output would be like:
|
||||||
|
The CPLD release date is 06/13/2019.
|
||||||
|
The PCB version is 5
|
||||||
|
The CPLD version is 1.1
|
||||||
|
'''
|
||||||
|
cpld_version = None
|
||||||
|
ret_str = None
|
||||||
|
path = None
|
||||||
|
target=""
|
||||||
|
|
||||||
|
if self.index == CPLD1_INDEX:
|
||||||
|
path = CPLD1_INFO_PATH
|
||||||
|
target="The CPLD version is "
|
||||||
|
elif self.index == CPLD2_INDEX:
|
||||||
|
path = CPLD2_INFO_PATH
|
||||||
|
target="The CPLD2 version is "
|
||||||
|
else:
|
||||||
|
logging.error("Unable support index %d", self.index)
|
||||||
|
|
||||||
|
if path !=None:
|
||||||
|
try:
|
||||||
|
with open(path, 'r') as file:
|
||||||
|
ret_str = file.read()
|
||||||
|
except Exception as error:
|
||||||
|
logging.error("Unable to open file %s", path)
|
||||||
|
|
||||||
|
if ret_str!=None:
|
||||||
|
start_idx=ret_str.find(target)
|
||||||
|
if start_idx > 0:
|
||||||
|
start_idx = start_idx+len(target)
|
||||||
|
offset = ret_str[start_idx:].find('\n')
|
||||||
|
if offset > 0:
|
||||||
|
end_idx=start_idx+offset
|
||||||
|
cpld_version=ret_str[start_idx:end_idx].strip('\n')
|
||||||
|
|
||||||
|
if cpld_version is None:
|
||||||
|
logging.error("Unable to parse cpld info %d", self.index)
|
||||||
|
|
||||||
|
return cpld_version
|
||||||
|
|
||||||
|
|
||||||
|
def __get_bios_version(self):
|
||||||
|
bios_version = None
|
||||||
|
current_bios_id=self.__get_current_bios()
|
||||||
|
|
||||||
|
if current_bios_id != None :
|
||||||
|
if self.index == BIOS_ID_MAPPING_TABLE[current_bios_id]:
|
||||||
|
try:
|
||||||
|
with open(BIOS_VER_PATH, 'r') as file:
|
||||||
|
bios_version = file.read().strip('\n')
|
||||||
|
except Exception as error:
|
||||||
|
logging.error("Unable to open file %s", BIOS_VER_PATH)
|
||||||
|
else:
|
||||||
|
logging.error("Only support bios version of current running BIOS")
|
||||||
|
bios_version = "N/A"
|
||||||
|
|
||||||
|
return bios_version
|
||||||
|
|
||||||
|
def __install_cpld_firmware(self,image_path):
|
||||||
|
logging.error("[Component][__install_cpld_firmware] Currently not support FW update on platform D6332")
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def __install_bios_firmware(self,image_path):
|
||||||
|
logging.error("[Component][__install_bios_firmware] Currently not support FW update on platform D6332")
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
__get_version_callback_list = {
|
||||||
|
CPLD1_INDEX:__get_cpld_version,
|
||||||
|
CPLD2_INDEX:__get_cpld_version,
|
||||||
|
MAIN_BIOS_INDEX:__get_bios_version,
|
||||||
|
BACKUP_BIOS_INDEX:__get_bios_version,
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, component_index):
|
||||||
|
self.index = component_index
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
"""
|
||||||
|
Retrieves the name of the component
|
||||||
|
Returns:
|
||||||
|
A string containing the name of the component
|
||||||
|
"""
|
||||||
|
return COMPONENT_NAME_LIST[self.index]
|
||||||
|
|
||||||
|
def get_description(self):
|
||||||
|
"""
|
||||||
|
Retrieves the description of the component
|
||||||
|
Returns:
|
||||||
|
A string containing the description of the component
|
||||||
|
"""
|
||||||
|
return COMPONENT_DESC_LIST[self.index]
|
||||||
|
|
||||||
|
def get_firmware_version(self):
|
||||||
|
"""
|
||||||
|
Retrieves the firmware version of the component
|
||||||
|
Returns:
|
||||||
|
A string containing the firmware version of the component
|
||||||
|
"""
|
||||||
|
return self.__get_version_callback_list[self.index](self)
|
||||||
|
|
||||||
|
def install_firmware(self, image_path):
|
||||||
|
"""
|
||||||
|
Installs firmware to the component
|
||||||
|
Args:
|
||||||
|
image_path: A string, path to firmware image
|
||||||
|
Returns:
|
||||||
|
A boolean, True if install was successful, False if not
|
||||||
|
"""
|
||||||
|
logging.error("[Component][install_firmware] Currently not support FW update on platform D6332")
|
||||||
|
raise NotImplementedError
|
@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Name: eeprom.py, version: 1.0
|
||||||
|
#
|
||||||
|
# Description: Module contains the definitions of SONiC platform APIs
|
||||||
|
#
|
||||||
|
|
||||||
|
try:
|
||||||
|
from sonic_eeprom import eeprom_tlvinfo
|
||||||
|
except ( ImportError, e ):
|
||||||
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
|
EEPROM_TOTAL_LEN_HIGH_OFFSET = 9
|
||||||
|
EEPROM_TOTAL_LEN_LOW_OFFSET = 10
|
||||||
|
EEPROM_TLV_TYPE_OFFSET = 0
|
||||||
|
EEPROM_TLV_LEN_OFFSET = 1
|
||||||
|
EEPROM_TLV_VALUE_OFFSET = 2
|
||||||
|
|
||||||
|
class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.__eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0055/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[EEPROM_TOTAL_LEN_HIGH_OFFSET]) << 8) | ord(eeprom[EEPROM_TOTAL_LEN_LOW_OFFSET])
|
||||||
|
tlv_index = self._TLV_INFO_HDR_LEN
|
||||||
|
tlv_end = self._TLV_INFO_HDR_LEN + total_length
|
||||||
|
|
||||||
|
while (tlv_index + EEPROM_TLV_VALUE_OFFSET) < len(eeprom) and tlv_index < tlv_end:
|
||||||
|
if not self.is_valid_tlv(eeprom[tlv_index:]):
|
||||||
|
break
|
||||||
|
|
||||||
|
tlv = eeprom[tlv_index:tlv_index + EEPROM_TLV_VALUE_OFFSET
|
||||||
|
+ ord(eeprom[tlv_index + EEPROM_TLV_LEN_OFFSET])]
|
||||||
|
code = "0x%02X" % (ord(tlv[EEPROM_TLV_TYPE_OFFSET]))
|
||||||
|
|
||||||
|
if ord(tlv[EEPROM_TLV_TYPE_OFFSET]) == self._TLV_CODE_VENDOR_EXT:
|
||||||
|
value = str((ord(tlv[EEPROM_TLV_VALUE_OFFSET]) << 24) | (ord(tlv[EEPROM_TLV_VALUE_OFFSET+1]) << 16) |
|
||||||
|
(ord(tlv[EEPROM_TLV_VALUE_OFFSET+2]) << 8) | ord(tlv[EEPROM_TLV_VALUE_OFFSET+3]))
|
||||||
|
value += str(tlv[6:6 + ord(tlv[EEPROM_TLV_LEN_OFFSET])])
|
||||||
|
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+EEPROM_TLV_LEN_OFFSET]) + EEPROM_TLV_VALUE_OFFSET
|
||||||
|
|
||||||
|
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 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
|
||||||
|
|
||||||
|
def get_eeprom_data(self):
|
||||||
|
return self.__eeprom_data
|
@ -0,0 +1,94 @@
|
|||||||
|
#
|
||||||
|
# event_monitor.py
|
||||||
|
# Description: module to minitor events
|
||||||
|
#
|
||||||
|
|
||||||
|
try:
|
||||||
|
import socket
|
||||||
|
from collections import OrderedDict
|
||||||
|
import os
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError("%s - required module not found" % str(e))
|
||||||
|
|
||||||
|
|
||||||
|
NETLINK_KOBJECT_UEVENT = 15
|
||||||
|
|
||||||
|
class EventMonitor(object):
|
||||||
|
|
||||||
|
def __init__(self, timeout):
|
||||||
|
self.recieved_events = OrderedDict()
|
||||||
|
self.socket = socket.socket(socket.AF_NETLINK, socket.SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)
|
||||||
|
self.timeout = timeout
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self.socket.bind((os.getpid(), -1))
|
||||||
|
|
||||||
|
if 0 == self.timeout:
|
||||||
|
self.socket.settimeout(None)
|
||||||
|
else:
|
||||||
|
self.socket.settimeout(self.timeout/1000.0)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.socket.close()
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self.start()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_value, traceback):
|
||||||
|
self.stop()
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
while True:
|
||||||
|
for item in self.next_events():
|
||||||
|
yield item
|
||||||
|
|
||||||
|
def next_events(self):
|
||||||
|
try:
|
||||||
|
data = self.socket.recv(16384)
|
||||||
|
event = {}
|
||||||
|
for item in data.split(b'\x00'):
|
||||||
|
if not item:
|
||||||
|
# check if we have an event and if we already received it
|
||||||
|
if event and event['SEQNUM'] not in self.recieved_events:
|
||||||
|
self.recieved_events[event['SEQNUM']] = None
|
||||||
|
if (len(self.recieved_events) > 100):
|
||||||
|
self.recieved_events.popitem(last=False)
|
||||||
|
yield event
|
||||||
|
event = {}
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
k, v = item.split(b'=', 1)
|
||||||
|
event[k.decode('ascii')] = v.decode('ascii')
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
except socket.timeout:
|
||||||
|
yield event
|
||||||
|
|
||||||
|
def get_events(self):
|
||||||
|
event = {}
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data = self.socket.recv(16384)
|
||||||
|
|
||||||
|
for item in data.split(b'\x00'):
|
||||||
|
if not item:
|
||||||
|
# check if we have an event and if we already received it
|
||||||
|
# if no item and event empty, means received garbled
|
||||||
|
if bool(event):
|
||||||
|
if event['SEQNUM'] not in self.recieved_events:
|
||||||
|
self.recieved_events[event['SEQNUM']] = None
|
||||||
|
if (len(self.recieved_events) > 100):
|
||||||
|
self.recieved_events.popitem(last=False)
|
||||||
|
return event
|
||||||
|
else:
|
||||||
|
event = {}
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
k, v = item.split(b'=', 1)
|
||||||
|
event[k] = v
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
except socket.timeout:
|
||||||
|
return event
|
||||||
|
|
@ -0,0 +1,330 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Name: fan.py, version: 1.0
|
||||||
|
#
|
||||||
|
# Description: Module contains the definitions of SONiC platform APIs
|
||||||
|
#
|
||||||
|
|
||||||
|
try:
|
||||||
|
import math
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
from sonic_platform_base.fan_base import FanBase
|
||||||
|
from sonic_platform.inv_const import FanConst , PsuConst, Common
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
|
MAX_SPEED_OF_FAN_FRONT = 23500
|
||||||
|
MAX_SPEED_OF_FAN_BACK = 19900
|
||||||
|
MAX_SPEED_OF_FAN_PSU = 26000
|
||||||
|
MAX_PWM_OF_FAN = 255
|
||||||
|
|
||||||
|
class Fan(FanBase):
|
||||||
|
|
||||||
|
__name_of_fans = ['FAN1','FAN2','FAN3','FAN4','FAN5','PSU1_FAN1','PSU2_FAN1']
|
||||||
|
__start_of_psu_fans = FanConst().PSU_FAN_START_INDEX
|
||||||
|
|
||||||
|
def __init__(self, index):
|
||||||
|
self.__index = index
|
||||||
|
|
||||||
|
if self.__index >= self.__start_of_psu_fans:
|
||||||
|
psu_id=self.__index- self.__start_of_psu_fans
|
||||||
|
self.__presence_attr = "{}/i2c-inv_cpld/psu{}".format(Common.I2C_PREFIX,psu_id+1)
|
||||||
|
self.__rpm1_attr = "{}/psu{}/fan1_input".format(Common.INFO_PREFIX, psu_id+1)
|
||||||
|
else:
|
||||||
|
self.__fan_type = "{}/i2c-inv_cpld/fanmodule{}_type".format(Common.I2C_PREFIX, self.__index + 1)
|
||||||
|
self.__rpm1_attr = "{}/i2c-inv_cpld/fan{}_input".format(Common.I2C_PREFIX, 2*self.__index + 1)
|
||||||
|
self.__rpm2_attr = "{}/i2c-inv_cpld/fan{}_input".format(Common.I2C_PREFIX, 2*self.__index + 2)
|
||||||
|
self.__pwm_attr = "{}/i2c-inv_cpld/pwm{}".format(Common.I2C_PREFIX, self.__index + 1)
|
||||||
|
|
||||||
|
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 retval
|
||||||
|
|
||||||
|
def read_fru(self, attr_type):
|
||||||
|
fan_addr=FanConst.FAN_VPD_ADDR_BASE+self.__index
|
||||||
|
path="/sys/bus/i2c/devices/{}-00{}/eeprom".format(FanConst.FAN_VPD_CHANNEL, hex(fan_addr)[2:] )
|
||||||
|
content=[]
|
||||||
|
attr_idx=0
|
||||||
|
attr_length=0
|
||||||
|
|
||||||
|
if(os.path.exists(path)):
|
||||||
|
with open(path,'rw') as f:
|
||||||
|
content=f.read()
|
||||||
|
target_offset=ord(content[FanConst.TLV_PRODUCT_INFO_OFFSET_IDX-1])
|
||||||
|
target_offset*=8 #spec defined: offset are in multiples of 8 bytes
|
||||||
|
|
||||||
|
attr_idx=target_offset+FanConst.TLV_PRODUCT_INFO_AREA_START
|
||||||
|
for i in range(1,attr_type):
|
||||||
|
if attr_idx > len(content):
|
||||||
|
raise SyntaxError
|
||||||
|
attr_length=(ord(content[attr_idx]))&(0x3f)
|
||||||
|
attr_idx+=(attr_length+1);
|
||||||
|
|
||||||
|
attr_length=(ord(content[attr_idx]))&(0x3f)
|
||||||
|
attr_idx+=1
|
||||||
|
else:
|
||||||
|
logging.error("[FAN] Can't find path to eeprom : %s" % path)
|
||||||
|
return SyntaxError
|
||||||
|
|
||||||
|
return content[attr_idx:attr_idx+attr_length]
|
||||||
|
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
# Device methods
|
||||||
|
##############################################
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
"""
|
||||||
|
Retrieves the name of the device
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string: The name of the device
|
||||||
|
"""
|
||||||
|
return self.__name_of_fans[self.__index]
|
||||||
|
|
||||||
|
def get_presence(self):
|
||||||
|
"""
|
||||||
|
Retrieves the presence of the device
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if device is present, False if not
|
||||||
|
"""
|
||||||
|
presence = False
|
||||||
|
|
||||||
|
if self.__index >= self.__start_of_psu_fans:
|
||||||
|
#check fan of psu presence if psu presence
|
||||||
|
attr_path = self.__presence_attr
|
||||||
|
attr_rv = self.__get_attr_value(attr_path)
|
||||||
|
if (attr_rv != 'ERR'):
|
||||||
|
if (attr_rv == PsuConst.PSU_TYPE_LIST[0] or attr_rv == PsuConst.PSU_TYPE_LIST[1]):
|
||||||
|
presence = True
|
||||||
|
else:
|
||||||
|
raise SyntaxError
|
||||||
|
else:
|
||||||
|
attr_path = self.__fan_type
|
||||||
|
attr_rv = self.__get_attr_value(attr_path)
|
||||||
|
if (attr_rv != 'ERR'):
|
||||||
|
if(attr_rv==FanConst.FAN_TYPE_LIST[0] or attr_rv==FanConst.FAN_TYPE_LIST[1]):
|
||||||
|
presence = True
|
||||||
|
else:
|
||||||
|
raise SyntaxError
|
||||||
|
|
||||||
|
return presence
|
||||||
|
|
||||||
|
def get_model(self):
|
||||||
|
"""
|
||||||
|
Retrieves the model number (or part number) of the device
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string: Model/part number of device
|
||||||
|
"""
|
||||||
|
if self.__index >= self.__start_of_psu_fans:
|
||||||
|
return NotImplementedError
|
||||||
|
else:
|
||||||
|
model=self.read_fru(FanConst.TLV_ATTR_TYPE_MODEL)
|
||||||
|
if not model:
|
||||||
|
return NotImplementedError
|
||||||
|
|
||||||
|
return model
|
||||||
|
|
||||||
|
def get_serial(self):
|
||||||
|
"""
|
||||||
|
Retrieves the serial number of the device
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string: Serial number of device
|
||||||
|
"""
|
||||||
|
if self.__index >= self.__start_of_psu_fans:
|
||||||
|
return NotImplementedError
|
||||||
|
else:
|
||||||
|
serial=self.read_fru(FanConst.TLV_ATTR_TYPE_SERIAL)
|
||||||
|
if not serial:
|
||||||
|
return NotImplementedError
|
||||||
|
|
||||||
|
return serial
|
||||||
|
|
||||||
|
def get_status(self):
|
||||||
|
"""
|
||||||
|
Retrieves the operational status of the device
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A boolean value, True if device is operating properly, False if not
|
||||||
|
"""
|
||||||
|
status = False
|
||||||
|
|
||||||
|
if self.__index >= self.__start_of_psu_fans:
|
||||||
|
#check fan of psu presence if psu presence
|
||||||
|
attr_path = self.__presence_attr
|
||||||
|
attr_rv = self.__get_attr_value(attr_path)
|
||||||
|
if (attr_rv != 'ERR'):
|
||||||
|
if (attr_rv == PsuConst.PSU_TYPE_LIST[1]):
|
||||||
|
status = True
|
||||||
|
else:
|
||||||
|
raise SyntaxError
|
||||||
|
else:
|
||||||
|
status = self.get_presence()
|
||||||
|
|
||||||
|
return status
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
# FAN methods
|
||||||
|
##############################################
|
||||||
|
|
||||||
|
def get_direction(self):
|
||||||
|
"""
|
||||||
|
Retrieves the direction of fan
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST
|
||||||
|
depending on fan direction
|
||||||
|
"""
|
||||||
|
direction = 'N/A'
|
||||||
|
|
||||||
|
if self.__index >= self.__start_of_psu_fans:
|
||||||
|
raise NotImplementedError
|
||||||
|
else:
|
||||||
|
attr_path = self.__fan_type
|
||||||
|
attr_rv = self.__get_attr_value(attr_path)
|
||||||
|
if (attr_rv != 'ERR'):
|
||||||
|
|
||||||
|
#"Normal Type", //00
|
||||||
|
#"REVERSAL Type", //01
|
||||||
|
#"UNPLUGGED", //10
|
||||||
|
#"UNPLUGGED", //11
|
||||||
|
|
||||||
|
if(attr_rv==FanConst.FAN_TYPE_LIST[0]):
|
||||||
|
direction = 'FAN_DIRECTION_EXHAUST'
|
||||||
|
elif(attr_rv==FanConst.FAN_TYPE_LIST[1]):
|
||||||
|
direction = 'FAN_DIRECTION_INTAKE'
|
||||||
|
else:
|
||||||
|
raise SyntaxError
|
||||||
|
|
||||||
|
return direction
|
||||||
|
|
||||||
|
def get_speed(self):
|
||||||
|
"""
|
||||||
|
Retrieves the speed of fan as a percentage of full speed
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
An integer, the percentage of full fan speed, in the range 0 (off)
|
||||||
|
to 100 (full speed)
|
||||||
|
"""
|
||||||
|
speed = 0
|
||||||
|
|
||||||
|
if self.__index >= self.__start_of_psu_fans:
|
||||||
|
attr_rv1 = self.__get_attr_value(self.__presence_attr)
|
||||||
|
if( attr_rv1 == PsuConst.PSU_TYPE_LIST[0] or attr_rv1 == PsuConst.PSU_TYPE_LIST[1] ):
|
||||||
|
attr_path1 = self.__rpm1_attr
|
||||||
|
attr_rv1 = self.__get_attr_value(attr_path1)
|
||||||
|
if (attr_rv1 != 'ERR' ):
|
||||||
|
speed = int(attr_rv1) * 100 / MAX_SPEED_OF_FAN_PSU
|
||||||
|
elif(attr_rv1 == 'ERR' ):
|
||||||
|
raise SyntaxError
|
||||||
|
else:
|
||||||
|
attr_path1 = self.__rpm1_attr
|
||||||
|
attr_path2 = self.__rpm2_attr
|
||||||
|
|
||||||
|
if self.get_presence() and None != attr_path1:
|
||||||
|
attr_rv1 = self.__get_attr_value(attr_path1)
|
||||||
|
attr_rv2 = self.__get_attr_value(attr_path2)
|
||||||
|
if (attr_rv1 != 'ERR' and attr_rv2 != 'ERR'):
|
||||||
|
fan1_input = int(attr_rv1)
|
||||||
|
speed = math.ceil(float(fan1_input * 100 / MAX_SPEED_OF_FAN_FRONT))
|
||||||
|
fan2_input = int(attr_rv2)
|
||||||
|
speed += math.ceil(float(fan2_input * 100 / MAX_SPEED_OF_FAN_BACK))
|
||||||
|
speed /= 2
|
||||||
|
elif (attr_rv1 != 'ERR'):
|
||||||
|
fan1_input = int(attr_rv1)
|
||||||
|
if self.__index >= self.__start_of_psu_fans:
|
||||||
|
speed = speed = math.ceil(float(fan1_input * 100 / MAX_SPEED_OF_FAN_PSU))
|
||||||
|
else:
|
||||||
|
speed = math.ceil(float(fan1_input * 100 / MAX_SPEED_OF_FAN_FRONT))
|
||||||
|
elif (attr_rv2 != 'ERR'):
|
||||||
|
fan2_input = int(attr_rv2)
|
||||||
|
speed += math.ceil(float(fan2_input * 100 / MAX_SPEED_OF_FAN_BACK))
|
||||||
|
else:
|
||||||
|
raise SyntaxError
|
||||||
|
|
||||||
|
return speed
|
||||||
|
|
||||||
|
def get_target_speed(self):
|
||||||
|
"""
|
||||||
|
Retrieves the target (expected) speed of the fan
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
An integer, the percentage of full fan speed, in the range 0 (off)
|
||||||
|
to 100 (full speed)
|
||||||
|
"""
|
||||||
|
speed = 0
|
||||||
|
|
||||||
|
if self.__index >= self.__start_of_psu_fans:
|
||||||
|
return NotImplementedError
|
||||||
|
else:
|
||||||
|
attr_path = self.__pwm_attr
|
||||||
|
|
||||||
|
if self.get_presence() and None != attr_path:
|
||||||
|
attr_rv = self.__get_attr_value(attr_path)
|
||||||
|
if (attr_rv != 'ERR'):
|
||||||
|
pwm = int(attr_rv)
|
||||||
|
speed = math.ceil(float(pwm * 100 / MAX_PWM_OF_FAN))
|
||||||
|
else:
|
||||||
|
raise SyntaxError
|
||||||
|
|
||||||
|
return speed
|
||||||
|
|
||||||
|
def get_speed_tolerance(self):
|
||||||
|
"""
|
||||||
|
Retrieves the speed tolerance of the fan
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
An integer, the percentage of variance from target speed which is
|
||||||
|
considered tolerable
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def set_speed(self, speed):
|
||||||
|
"""
|
||||||
|
Sets the fan speed
|
||||||
|
|
||||||
|
Args:
|
||||||
|
speed: An integer, the percentage of full fan speed to set fan to,
|
||||||
|
in the range 0 (off) to 100 (full speed)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A boolean, True if speed is set successfully, False if not
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def set_status_led(self, color):
|
||||||
|
"""
|
||||||
|
Sets the state of the fan module status LED
|
||||||
|
|
||||||
|
Args:
|
||||||
|
color: A string representing the color with which to set the
|
||||||
|
fan module status LED
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if status LED state is set successfully, False if not
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_status_led(self):
|
||||||
|
"""
|
||||||
|
Gets the state of the fan status LED
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A string, one of the predefined STATUS_LED_COLOR_* strings above
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
class Common():
|
||||||
|
INFO_PREFIX = "/usr/share/sonic/platform"
|
||||||
|
I2C_PREFIX = "/sys/bus/i2c/devices"
|
||||||
|
|
||||||
|
class FanConst():
|
||||||
|
#fan vpd info
|
||||||
|
FAN_VPD_CHANNEL= 1
|
||||||
|
FAN_VPD_ADDR_BASE=0x52
|
||||||
|
#fru status
|
||||||
|
TLV_PRODUCT_INFO_OFFSET_IDX=5
|
||||||
|
TLV_PRODUCT_INFO_AREA_START=3
|
||||||
|
TLV_ATTR_TYPE_SERIAL=5
|
||||||
|
TLV_ATTR_TYPE_MODEL=2
|
||||||
|
|
||||||
|
PSU_FAN_START_INDEX = 5
|
||||||
|
FAN_TYPE_LIST=["0:Normal Type","1:REVERSAL Type","2:UNPLUGGED","3:UNPLUGGED"] #defined in inv_cpld
|
||||||
|
|
||||||
|
class PsuConst():
|
||||||
|
PSU_TYPE_LIST=["0:unpowered","1:normal","2:not installed","3:not installed"] #defined in inv_cpld
|
||||||
|
PSU_I2C_ADDR=["2-005a","2-005b"]
|
@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Name: platform.py, version: 1.0
|
||||||
|
#
|
||||||
|
# Description: Module contains the definitions of SONiC platform APIs
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
from sonic_platform_base.platform_base import PlatformBase
|
||||||
|
from sonic_platform.chassis import Chassis
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
|
|
||||||
|
class Platform(PlatformBase):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
PlatformBase.__init__(self)
|
||||||
|
self._chassis = Chassis()
|
@ -0,0 +1,254 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Name: psu.py, version: 1.0
|
||||||
|
#
|
||||||
|
# Description: Module contains the definitions of SONiC platform APIs
|
||||||
|
#
|
||||||
|
|
||||||
|
try:
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
from sonic_platform_base.psu_base import PsuBase
|
||||||
|
from sonic_platform.fan import Fan
|
||||||
|
from sonic_platform.inv_const import FanConst , PsuConst, Common
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
|
VOLTAGE_UPPER_LIMIT = 14
|
||||||
|
VOLTAGE_LOWER_LIMIT = 10
|
||||||
|
|
||||||
|
class Psu(PsuBase):
|
||||||
|
|
||||||
|
__num_of_fans = 1
|
||||||
|
__name_of_psus = ['PSU1','PSU2']
|
||||||
|
|
||||||
|
def __init__(self, index):
|
||||||
|
self.__index = index
|
||||||
|
psu_id = self.__index + 1
|
||||||
|
|
||||||
|
self.__psu_presence_attr = "{}/i2c-inv_cpld/psu{}".format(Common.I2C_PREFIX,psu_id)
|
||||||
|
self.__psu_voltage_out_attr = "{}/psu{}/in2_input".format(Common.INFO_PREFIX, psu_id)
|
||||||
|
self.__psu_current_out_attr = "{}/psu{}/curr2_input".format(Common.INFO_PREFIX, psu_id)
|
||||||
|
self.__psu_power_out_attr = "{}/psu{}/power2_input".format(Common.INFO_PREFIX, psu_id)
|
||||||
|
|
||||||
|
# Get the start index of fan list
|
||||||
|
self.__fan_psu_start_index = self.__index + FanConst().PSU_FAN_START_INDEX
|
||||||
|
|
||||||
|
# Overriding _fan_list class variable defined in PsuBase, to make it unique per Psu object
|
||||||
|
self._fan_list = []
|
||||||
|
|
||||||
|
# Initialize FAN
|
||||||
|
for x in range(self.__fan_psu_start_index, self.__fan_psu_start_index + self.__num_of_fans):
|
||||||
|
fan = Fan(x)
|
||||||
|
self._fan_list.append(fan)
|
||||||
|
|
||||||
|
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 retval
|
||||||
|
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
# Device methods
|
||||||
|
##############################################
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
"""
|
||||||
|
Retrieves the name of the device
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string: The name of the device
|
||||||
|
"""
|
||||||
|
return self.__name_of_psus[self.__index]
|
||||||
|
|
||||||
|
def get_presence(self):
|
||||||
|
"""
|
||||||
|
Retrieves the presence of the device
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if device is present, False if not
|
||||||
|
"""
|
||||||
|
presence = False
|
||||||
|
attr_path = self.__psu_presence_attr
|
||||||
|
|
||||||
|
attr_rv = self.__get_attr_value(attr_path)
|
||||||
|
if (attr_rv != 'ERR'):
|
||||||
|
if (attr_rv == PsuConst.PSU_TYPE_LIST[0] or attr_rv == PsuConst.PSU_TYPE_LIST[1]):
|
||||||
|
presence = True
|
||||||
|
else:
|
||||||
|
raise SyntaxError
|
||||||
|
|
||||||
|
return presence
|
||||||
|
|
||||||
|
def get_model(self):
|
||||||
|
"""
|
||||||
|
Retrieves the model number (or part number) of the device
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string: Model/part number of device
|
||||||
|
"""
|
||||||
|
#model = 'Unknow'
|
||||||
|
#attr_path = self.__psu_model_attr
|
||||||
|
|
||||||
|
#attr_rv = self.__get_attr_value(attr_path)
|
||||||
|
#if (attr_rv != 'ERR'):
|
||||||
|
# if (attr_rv != ''):
|
||||||
|
# model = attr_rv
|
||||||
|
#else:
|
||||||
|
# raise SyntaxError
|
||||||
|
|
||||||
|
#return model
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_serial(self):
|
||||||
|
"""
|
||||||
|
Retrieves the serial number of the device
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string: Serial number of device
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
serial = 'Unknow'
|
||||||
|
attr_path = self.__psu_serial_attr
|
||||||
|
|
||||||
|
attr_rv = self.__get_attr_value(attr_path)
|
||||||
|
if (attr_rv != 'ERR'):
|
||||||
|
if (attr_rv != ''):
|
||||||
|
serial = attr_rv
|
||||||
|
else:
|
||||||
|
raise SyntaxError
|
||||||
|
|
||||||
|
return serial
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_status(self):
|
||||||
|
"""
|
||||||
|
Retrieves the operational status of the device
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A boolean value, True if device is operating properly, False if not
|
||||||
|
"""
|
||||||
|
status = False
|
||||||
|
attr_path = self.__psu_presence_attr
|
||||||
|
|
||||||
|
attr_rv = self.__get_attr_value(attr_path)
|
||||||
|
if (attr_rv != 'ERR'):
|
||||||
|
if (attr_rv == PsuConst.PSU_TYPE_LIST[1]):
|
||||||
|
status = True
|
||||||
|
else:
|
||||||
|
raise SyntaxError
|
||||||
|
|
||||||
|
return status
|
||||||
|
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
# PSU methods
|
||||||
|
##############################################
|
||||||
|
|
||||||
|
def get_voltage(self):
|
||||||
|
"""
|
||||||
|
Retrieves current PSU voltage output
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A float number, the output voltage in volts,
|
||||||
|
e.g. 12.1
|
||||||
|
"""
|
||||||
|
voltage_out = 0.0
|
||||||
|
attr_path = self.__psu_voltage_out_attr
|
||||||
|
|
||||||
|
if(self.get_presence()):
|
||||||
|
attr_rv = self.__get_attr_value(attr_path)
|
||||||
|
if (attr_rv != 'ERR'):
|
||||||
|
voltage_out = float(attr_rv) / 1000
|
||||||
|
else:
|
||||||
|
raise SyntaxError
|
||||||
|
|
||||||
|
return voltage_out
|
||||||
|
|
||||||
|
def get_current(self):
|
||||||
|
"""
|
||||||
|
Retrieves present electric current supplied by PSU
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A float number, the electric current in amperes, e.g 15.4
|
||||||
|
"""
|
||||||
|
current_out = 0.0
|
||||||
|
attr_path = self.__psu_current_out_attr
|
||||||
|
|
||||||
|
if(self.get_presence()):
|
||||||
|
attr_rv = self.__get_attr_value(attr_path)
|
||||||
|
if (attr_rv != 'ERR'):
|
||||||
|
current_out = float(attr_rv) / 1000
|
||||||
|
else:
|
||||||
|
raise SyntaxError
|
||||||
|
|
||||||
|
return current_out
|
||||||
|
|
||||||
|
def get_power(self):
|
||||||
|
"""
|
||||||
|
Retrieves current energy supplied by PSU
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A float number, the power in watts, e.g. 302.6
|
||||||
|
"""
|
||||||
|
power_out = 0.0
|
||||||
|
attr_path = self.__psu_power_out_attr
|
||||||
|
|
||||||
|
if(self.get_presence()):
|
||||||
|
attr_rv = self.__get_attr_value(attr_path)
|
||||||
|
if (attr_rv != 'ERR'):
|
||||||
|
power_out = float(attr_rv) / 1000
|
||||||
|
else:
|
||||||
|
raise SyntaxError
|
||||||
|
|
||||||
|
return power_out
|
||||||
|
|
||||||
|
def get_powergood_status(self):
|
||||||
|
"""
|
||||||
|
Retrieves the powergood status of PSU
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A boolean, True if PSU has stablized its output voltages and passed all
|
||||||
|
its internal self-tests, False if not.
|
||||||
|
"""
|
||||||
|
powergood_status = False
|
||||||
|
voltage_out = self.get_voltage()
|
||||||
|
|
||||||
|
#Check the voltage out with 12V, plus or minus 20 percentage.
|
||||||
|
if (VOLTAGE_LOWER_LIMIT <= voltage_out and voltage_out <= VOLTAGE_UPPER_LIMIT ):
|
||||||
|
powergood_status = True
|
||||||
|
|
||||||
|
return powergood_status
|
||||||
|
|
||||||
|
def set_status_led(self, color):
|
||||||
|
"""
|
||||||
|
Sets the state of the PSU status LED
|
||||||
|
|
||||||
|
Args:
|
||||||
|
color: A string representing the color with which to set the
|
||||||
|
PSU status LED
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if status LED state is set successfully, False if not
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_status_led(self):
|
||||||
|
"""
|
||||||
|
Gets the state of the PSU status LED
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A string, one of the predefined STATUS_LED_COLOR_* strings above
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,253 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Name: thermal.py, version: 1.0
|
||||||
|
#
|
||||||
|
# Description: Module contains the definitions of SONiC platform APIs
|
||||||
|
#
|
||||||
|
|
||||||
|
try:
|
||||||
|
import os
|
||||||
|
import logging
|
||||||
|
from sonic_platform_base.thermal_base import ThermalBase
|
||||||
|
from sonic_platform.inv_const import PsuConst, Common
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
|
PSU1_THERMAL_START=9
|
||||||
|
PSU2_THERMAL_START=12
|
||||||
|
|
||||||
|
class Thermal(ThermalBase):
|
||||||
|
|
||||||
|
__core_temp_path = Common.INFO_PREFIX+"/coretemp/temp{}_input"
|
||||||
|
__switch_thermal_path = Common.INFO_PREFIX+"/board_thermal_{}/temp1_input"
|
||||||
|
__psu_thermal_path = Common.INFO_PREFIX+"/psu{}/temp{}_input"
|
||||||
|
__max_temp_path = Common.INFO_PREFIX+"/coretemp/temp{}_max"
|
||||||
|
__name_of_thermal = [
|
||||||
|
"Core 0 Temperature",
|
||||||
|
"Core 1 Temperature",
|
||||||
|
"Core 2 Temperature",
|
||||||
|
"Core 3 Temperature",
|
||||||
|
"Core 4 Temperature",
|
||||||
|
"CPU Board Temperature",
|
||||||
|
"FrontSide Temperature",
|
||||||
|
"RearSide Temperature",
|
||||||
|
"NearASIC Temperature",
|
||||||
|
"PSU1 Temperature1",
|
||||||
|
"PSU1 Temperature2",
|
||||||
|
"PSU1 Temperature3",
|
||||||
|
"PSU2 Temperature1",
|
||||||
|
"PSU2 Temperature2",
|
||||||
|
"PSU2 Temperature3"
|
||||||
|
]
|
||||||
|
__thermal_path_list = [
|
||||||
|
__core_temp_path.format(1),
|
||||||
|
__core_temp_path.format(2),
|
||||||
|
__core_temp_path.format(3),
|
||||||
|
__core_temp_path.format(4),
|
||||||
|
__core_temp_path.format(5),
|
||||||
|
__switch_thermal_path.format(1),
|
||||||
|
__switch_thermal_path.format(2),
|
||||||
|
__switch_thermal_path.format(3),
|
||||||
|
__switch_thermal_path.format(4),
|
||||||
|
__psu_thermal_path.format(1,1),
|
||||||
|
__psu_thermal_path.format(1,2),
|
||||||
|
__psu_thermal_path.format(1,3),
|
||||||
|
__psu_thermal_path.format(2,1),
|
||||||
|
__psu_thermal_path.format(2,2),
|
||||||
|
__psu_thermal_path.format(2,3)
|
||||||
|
]
|
||||||
|
__max_temp_path_list = [
|
||||||
|
__max_temp_path.format(1),
|
||||||
|
__max_temp_path.format(2),
|
||||||
|
__max_temp_path.format(3),
|
||||||
|
__max_temp_path.format(4),
|
||||||
|
__max_temp_path.format(5),
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, index):
|
||||||
|
self.__index = index
|
||||||
|
|
||||||
|
self.__thermal_temp_attr = self.__thermal_path_list[self.__index]
|
||||||
|
self.__max_temp_attr = self.__max_temp_path_list[self.__index]
|
||||||
|
|
||||||
|
|
||||||
|
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 retval
|
||||||
|
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
# Device methods
|
||||||
|
##############################################
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
"""
|
||||||
|
Retrieves the name of the device
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string: The name of the device
|
||||||
|
"""
|
||||||
|
return self.__name_of_thermal[self.__index]
|
||||||
|
|
||||||
|
def get_presence(self):
|
||||||
|
"""
|
||||||
|
Retrieves the presence of the device
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if device is present, False if not
|
||||||
|
"""
|
||||||
|
presence=False
|
||||||
|
|
||||||
|
if (self.__index < PSU1_THERMAL_START):
|
||||||
|
attr_path = self.__thermal_temp_attr
|
||||||
|
presence=os.path.isfile(attr_path)
|
||||||
|
elif(self.__index < PSU2_THERMAL_START):
|
||||||
|
path="{}/i2c-inv_cpld/psu1".format(Common.I2C_PREFIX)
|
||||||
|
psu_state=self.__get_attr_value(path)
|
||||||
|
if (psu_state != 'ERR'):
|
||||||
|
if (psu_state == PsuConst.PSU_TYPE_LIST[0] or psu_state == PsuConst.PSU_TYPE_LIST[1]):
|
||||||
|
presence = True
|
||||||
|
else:
|
||||||
|
path="{}/i2c-inv_cpld/psu2".format(Common.I2C_PREFIX)
|
||||||
|
psu_state=self.__get_attr_value(path)
|
||||||
|
if (psu_state != 'ERR'):
|
||||||
|
if (psu_state == PsuConst.PSU_TYPE_LIST[0] or psu_state == PsuConst.PSU_TYPE_LIST[1]):
|
||||||
|
presence = True
|
||||||
|
|
||||||
|
return presence
|
||||||
|
|
||||||
|
def get_model(self):
|
||||||
|
"""
|
||||||
|
Retrieves the model number (or part number) of the device
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string: Model/part number of device
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_serial(self):
|
||||||
|
"""
|
||||||
|
Retrieves the serial number of the device
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string: Serial number of device
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_status(self):
|
||||||
|
"""
|
||||||
|
Retrieves the operational status of the device
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A boolean value, True if device is operating properly, False if not
|
||||||
|
"""
|
||||||
|
status = False
|
||||||
|
if self.get_presence():
|
||||||
|
status = True
|
||||||
|
|
||||||
|
return status
|
||||||
|
|
||||||
|
##############################################
|
||||||
|
# THERMAL methods
|
||||||
|
##############################################
|
||||||
|
|
||||||
|
def get_temperature(self):
|
||||||
|
"""
|
||||||
|
Retrieves current temperature reading from thermal
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A float number of current temperature in Celsius up to nearest thousandth
|
||||||
|
of one degree Celsius, e.g. 30.125
|
||||||
|
"""
|
||||||
|
temperature = 0.0
|
||||||
|
attr_path = self.__thermal_temp_attr
|
||||||
|
|
||||||
|
if(self.get_presence()):
|
||||||
|
attr_rv = self.__get_attr_value(attr_path)
|
||||||
|
if (attr_rv != 'ERR'):
|
||||||
|
temperature = float(attr_rv) / 1000
|
||||||
|
else:
|
||||||
|
raise SyntaxError
|
||||||
|
|
||||||
|
return temperature
|
||||||
|
|
||||||
|
def get_high_threshold(self):
|
||||||
|
"""
|
||||||
|
Retrieves the high threshold temperature of thermal
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A float number, the high threshold temperature of thermal in Celsius
|
||||||
|
up to nearest thousandth of one degree Celsius, e.g. 30.125
|
||||||
|
"""
|
||||||
|
attr_path = self.__max_temp_attr
|
||||||
|
|
||||||
|
if attr_path == '':
|
||||||
|
raise NotImplementedError
|
||||||
|
else:
|
||||||
|
attr_rv = self.__get_attr_value(attr_path)
|
||||||
|
if (attr_rv != 'ERR'):
|
||||||
|
high_threshold = float(attr_rv) / 1000
|
||||||
|
else:
|
||||||
|
raise SyntaxError
|
||||||
|
|
||||||
|
return high_threshold
|
||||||
|
|
||||||
|
def get_low_threshold(self):
|
||||||
|
"""
|
||||||
|
Retrieves the low threshold temperature of thermal
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A float number, the low threshold temperature of thermal in Celsius
|
||||||
|
up to nearest thousandth of one degree Celsius, e.g. 30.125
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def set_high_threshold(self, temperature):
|
||||||
|
"""
|
||||||
|
Sets the high threshold temperature of thermal
|
||||||
|
|
||||||
|
Args :
|
||||||
|
temperature: A float number up to nearest thousandth of one degree Celsius,
|
||||||
|
e.g. 30.125
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A boolean, True if threshold is set successfully, False if not
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def set_low_threshold(self, temperature):
|
||||||
|
"""
|
||||||
|
Sets the low threshold temperature of thermal
|
||||||
|
|
||||||
|
Args :
|
||||||
|
temperature: A float number up to nearest thousandth of one degree Celsius,
|
||||||
|
e.g. 30.125
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A boolean, True if threshold is set successfully, False if not
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
try:
|
||||||
|
from sonic_platform_base.watchdog_base import WatchdogBase
|
||||||
|
except ImportError as e:
|
||||||
|
raise ImportError(str(e) + "- required module not found")
|
||||||
|
|
||||||
|
class Watchdog(WatchdogBase):
|
||||||
|
def __init__(self):
|
||||||
|
print('init Watchdog()')
|
||||||
|
|
||||||
|
def arm(self, seconds):
|
||||||
|
"""
|
||||||
|
Arm the hardware watchdog with a timeout of <seconds> seconds.
|
||||||
|
If the watchdog is currently armed, calling this function will
|
||||||
|
simply reset the timer to the provided value. If the underlying
|
||||||
|
hardware does not support the value provided in <seconds>, this
|
||||||
|
method should arm the watchdog with the *next greater* available
|
||||||
|
value.
|
||||||
|
Returns:
|
||||||
|
An integer specifying the *actual* number of seconds the watchdog
|
||||||
|
was armed with. On failure returns -1.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def disarm(self):
|
||||||
|
"""
|
||||||
|
Disarm the hardware watchdog
|
||||||
|
Returns:
|
||||||
|
A boolean, True if watchdog is disarmed successfully, False if not
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def is_armed(self):
|
||||||
|
"""
|
||||||
|
Retrieves the armed state of the hardware watchdog.
|
||||||
|
Returns:
|
||||||
|
A boolean, True if watchdog is armed, False if not
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def get_remaining_time(self):
|
||||||
|
"""
|
||||||
|
If the watchdog is armed, retrieve the number of seconds remaining on
|
||||||
|
the watchdog timer
|
||||||
|
Returns:
|
||||||
|
An integer specifying the number of seconds remaining on thei
|
||||||
|
watchdog timer. If the watchdog is not armed, returns -1.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
@ -0,0 +1,325 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright (C) 2017 Inventec, Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Usage: %(scriptName)s [options] command object
|
||||||
|
|
||||||
|
options:
|
||||||
|
-h | --help : this help message
|
||||||
|
-d | --debug : run with debug mode
|
||||||
|
-f | --force : ignore error during installation or clean
|
||||||
|
command:
|
||||||
|
install : install drivers and generate related sysfs nodes
|
||||||
|
clean : uninstall drivers and remove related sysfs nodes
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import commands
|
||||||
|
import sys, getopt
|
||||||
|
import logging
|
||||||
|
import syslog
|
||||||
|
import time
|
||||||
|
|
||||||
|
DEBUG = False
|
||||||
|
args = []
|
||||||
|
FORCE = 0
|
||||||
|
FAN_VPD_CHANNEL= 1
|
||||||
|
FAN_VPD_ADDR_BASE=0x52
|
||||||
|
FAN_NUM=5
|
||||||
|
RETRY_LIMIT = 5
|
||||||
|
i2c_prefix = '/sys/bus/i2c/devices/'
|
||||||
|
|
||||||
|
|
||||||
|
if DEBUG == True:
|
||||||
|
print sys.argv[0]
|
||||||
|
print 'ARGV: ', sys.argv[1:]
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
global DEBUG
|
||||||
|
global args
|
||||||
|
global FORCE
|
||||||
|
|
||||||
|
|
||||||
|
if len(sys.argv)<2:
|
||||||
|
show_help()
|
||||||
|
|
||||||
|
options, args = getopt.getopt(sys.argv[1:], 'hdf', ['help',
|
||||||
|
'debug',
|
||||||
|
'force',
|
||||||
|
])
|
||||||
|
if DEBUG == True:
|
||||||
|
print options
|
||||||
|
print args
|
||||||
|
print len(sys.argv)
|
||||||
|
|
||||||
|
for opt, arg in options:
|
||||||
|
if opt in ('-h', '--help'):
|
||||||
|
show_help()
|
||||||
|
elif opt in ('-d', '--debug'):
|
||||||
|
DEBUG = True
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
elif opt in ('-f', '--force'):
|
||||||
|
FORCE = 1
|
||||||
|
else:
|
||||||
|
logging.info('no option')
|
||||||
|
for arg in args:
|
||||||
|
if arg == 'install':
|
||||||
|
install()
|
||||||
|
elif arg == 'clean':
|
||||||
|
uninstall()
|
||||||
|
else:
|
||||||
|
show_help()
|
||||||
|
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def show_help():
|
||||||
|
print __doc__ % {'scriptName' : sys.argv[0].split("/")[-1]}
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
def show_log(txt):
|
||||||
|
if DEBUG == True:
|
||||||
|
print "[D6332]"+txt
|
||||||
|
return
|
||||||
|
|
||||||
|
def exec_cmd(cmd, show):
|
||||||
|
logging.info('Run :'+cmd)
|
||||||
|
status, output = commands.getstatusoutput(cmd)
|
||||||
|
show_log (cmd +" with result:" + str(status))
|
||||||
|
show_log (" output:"+output)
|
||||||
|
if status:
|
||||||
|
logging.info('Failed :'+cmd)
|
||||||
|
if show:
|
||||||
|
print('Failed :'+cmd)
|
||||||
|
return status, output
|
||||||
|
|
||||||
|
def link_dir(prefix,dst):
|
||||||
|
retry=0
|
||||||
|
ret=False
|
||||||
|
while(ret==False and retry<RETRY_LIMIT):
|
||||||
|
ret=os.path.isdir(prefix)
|
||||||
|
if ret==True:
|
||||||
|
break
|
||||||
|
time.sleep(0.5)
|
||||||
|
retry+=1
|
||||||
|
|
||||||
|
if ret==True:
|
||||||
|
dirs=os.listdir(prefix)
|
||||||
|
ret=False
|
||||||
|
for i in dirs:
|
||||||
|
if i.startswith('hwmon'):
|
||||||
|
src=prefix+i
|
||||||
|
os.symlink(src,dst)
|
||||||
|
ret=True
|
||||||
|
break
|
||||||
|
if ret==False:
|
||||||
|
syslog.syslog(syslog.LOG_ERR, "Can't find proper dir to link under %s" % prefix)
|
||||||
|
else:
|
||||||
|
syslog.syslog(syslog.LOG_ERR,"Path %s is not a dir" % prefix)
|
||||||
|
|
||||||
|
_path_prefix_list=[
|
||||||
|
"/sys/bus/i2c/devices/i2c-pmbus-1/hwmon/",
|
||||||
|
"/sys/bus/i2c/devices/i2c-pmbus-2/hwmon/",
|
||||||
|
"/sys/devices/platform/coretemp.0/hwmon/",
|
||||||
|
"/sys/bus/i2c/devices/i2c-tmp75-1/hwmon/",
|
||||||
|
"/sys/bus/i2c/devices/i2c-tmp75-2/hwmon/",
|
||||||
|
"/sys/bus/i2c/devices/i2c-tmp75-3/hwmon/",
|
||||||
|
"/sys/bus/i2c/devices/i2c-tmp75-4/hwmon/"
|
||||||
|
]
|
||||||
|
|
||||||
|
_path_dst_list=[
|
||||||
|
"/usr/share/sonic/device/x86_64-inventec_d6332-r0/psu1",
|
||||||
|
"/usr/share/sonic/device/x86_64-inventec_d6332-r0/psu2",
|
||||||
|
"/usr/share/sonic/device/x86_64-inventec_d6332-r0/coretemp",
|
||||||
|
"/usr/share/sonic/device/x86_64-inventec_d6332-r0/board_thermal_1",
|
||||||
|
"/usr/share/sonic/device/x86_64-inventec_d6332-r0/board_thermal_2",
|
||||||
|
"/usr/share/sonic/device/x86_64-inventec_d6332-r0/board_thermal_3",
|
||||||
|
"/usr/share/sonic/device/x86_64-inventec_d6332-r0/board_thermal_4",
|
||||||
|
]
|
||||||
|
|
||||||
|
instantiate = [
|
||||||
|
'echo inv_eeprom 0x55 > /sys/bus/i2c/devices/i2c-0/new_device'
|
||||||
|
#'echo inv_cpld 0x33 > /sys/bus/i2c/devices/i2c-0/i2c-2/new_device',
|
||||||
|
#'echo inv_cpld 0x77 > /sys/bus/i2c/devices/i2c-0/i2c-2/new_device'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
drivers =[
|
||||||
|
#kernel-dirvers
|
||||||
|
'gpio_ich',
|
||||||
|
'lpc_ich',
|
||||||
|
'i2c-i801',
|
||||||
|
'i2c-mux',
|
||||||
|
'i2c-mux-pca954x',
|
||||||
|
'i2c-mux-pca9541',
|
||||||
|
'i2c-dev',
|
||||||
|
'ucd9000',
|
||||||
|
#inv-modules
|
||||||
|
'inv_eeprom',
|
||||||
|
'inv_cpld',
|
||||||
|
'lm75',
|
||||||
|
'inv_platform',
|
||||||
|
#'monitor',
|
||||||
|
'swps']
|
||||||
|
|
||||||
|
|
||||||
|
# Modify for fast-reboot
|
||||||
|
def system_install(boot_option):
|
||||||
|
global FORCE
|
||||||
|
|
||||||
|
#remove default drivers to avoid modprobe order conflicts
|
||||||
|
status, output = exec_cmd("rmmod i2c_ismt ", 1)
|
||||||
|
if status:
|
||||||
|
print output
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
|
||||||
|
status, output = exec_cmd("rmmod i2c-i801 ", 1)
|
||||||
|
if status:
|
||||||
|
print output
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
|
||||||
|
status, output = exec_cmd("rmmod gpio_ich ", 1)
|
||||||
|
if status:
|
||||||
|
print output
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
|
||||||
|
status, output = exec_cmd("rmmod lpc_ich ", 1)
|
||||||
|
if status:
|
||||||
|
print output
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
|
||||||
|
#insert extra module
|
||||||
|
#status, output = exec_cmd("insmod /lib/modules/4.9.0-9-2-amd64/kernel/drivers/gpio/gpio-ich.ko gpiobase=0",1)
|
||||||
|
|
||||||
|
#install drivers
|
||||||
|
''' boot_option: 0 - normal, 1 - fast-reboot'''
|
||||||
|
for i in range(0,len(drivers)):
|
||||||
|
if drivers[i] == "swps":
|
||||||
|
if boot_option == 1:
|
||||||
|
status, output = exec_cmd("modprobe swps io_no_init=1", 1)
|
||||||
|
else:
|
||||||
|
status, output = exec_cmd("modprobe "+drivers[i], 1)
|
||||||
|
else:
|
||||||
|
status, output = exec_cmd("modprobe "+drivers[i], 1)
|
||||||
|
|
||||||
|
if status:
|
||||||
|
print output
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
|
||||||
|
#instantiate devices
|
||||||
|
for i in range(0,len(instantiate)):
|
||||||
|
#time.sleep(1)
|
||||||
|
status, output = exec_cmd(instantiate[i], 1)
|
||||||
|
if status:
|
||||||
|
print output
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
for addr_offset in range (0,FAN_NUM):
|
||||||
|
addr=FAN_VPD_ADDR_BASE+addr_offset
|
||||||
|
cmd = "i2cdetect -y "+str(FAN_VPD_CHANNEL)+" "+str(addr)+" "+str(addr)+" | grep "+str(hex(addr)).replace('0x','')
|
||||||
|
result=os.system(cmd)
|
||||||
|
if( result==0 ):
|
||||||
|
cmd="echo inv_eeprom "+str(addr)+" > /sys/bus/i2c/devices/i2c-"+FAN_VPD_CHANNEL
|
||||||
|
status, output = exec_cmd(cmd,1)
|
||||||
|
if status:
|
||||||
|
print output
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
#
|
||||||
|
# INV_FIX-4037
|
||||||
|
# It replaces the original sff8436 driver with the optoe driver
|
||||||
|
#
|
||||||
|
#optoe map to i2c-bus\
|
||||||
|
for i in range(12,20):
|
||||||
|
cmd="echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-4/i2c-"+str(i)+"/new_device"
|
||||||
|
status, output =exec_cmd(cmd,1)
|
||||||
|
if status:
|
||||||
|
print output
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
for i in range(20,28):
|
||||||
|
status, output =exec_cmd("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-5/i2c-"+str(i)+"/new_device", 1)
|
||||||
|
if status:
|
||||||
|
print output
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
for i in range(28,36):
|
||||||
|
status, output =exec_cmd("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-6/i2c-"+str(i)+"/new_device", 1)
|
||||||
|
if status:
|
||||||
|
print output
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
for i in range(36,44):
|
||||||
|
status, output =exec_cmd("echo optoe1 0x50 > /sys/bus/i2c/devices/i2c-0/i2c-7/i2c-"+str(i)+"/new_device", 1)
|
||||||
|
if status:
|
||||||
|
print output
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
|
||||||
|
#make softlink for device info
|
||||||
|
for i in range(0,len(_path_prefix_list)):
|
||||||
|
if( os.path.islink(_path_dst_list[i]) ):
|
||||||
|
os.unlink(_path_dst_list[i])
|
||||||
|
syslog.syslog(syslog.LOG_WARNING, "Path %s exists, remove before link again" % _path_dst_list[i] )
|
||||||
|
link_dir(_path_prefix_list[i],_path_dst_list[i])
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def system_ready():
|
||||||
|
if not device_found():
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def install(boot_option=0):
|
||||||
|
''' boot_option: 0 - normal, 1 - fast-reboot '''
|
||||||
|
if not device_found():
|
||||||
|
print "No device, installing...."
|
||||||
|
status = system_install(boot_option)
|
||||||
|
if status:
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
else:
|
||||||
|
print "D6332 devices detected...."
|
||||||
|
return
|
||||||
|
|
||||||
|
def uninstall():
|
||||||
|
global FORCE
|
||||||
|
#uninstall drivers
|
||||||
|
for i in range(len(drivers)-1,-1,-1):
|
||||||
|
status, output = exec_cmd("rmmod "+drivers[i], 1)
|
||||||
|
if status:
|
||||||
|
print output
|
||||||
|
if FORCE == 0:
|
||||||
|
return status
|
||||||
|
return
|
||||||
|
|
||||||
|
def device_found():
|
||||||
|
ret1, log = exec_cmd("ls "+i2c_prefix+"*0072", 0)
|
||||||
|
ret2, log = exec_cmd("ls "+i2c_prefix+"i2c-5", 0)
|
||||||
|
return not(ret1 or ret2)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
@ -2,7 +2,7 @@ Source: sonic-inventec-platform-modules
|
|||||||
Section: main
|
Section: main
|
||||||
Priority: extra
|
Priority: extra
|
||||||
Maintainer: Inventec <swsp@inventec.com>
|
Maintainer: Inventec <swsp@inventec.com>
|
||||||
Build-Depends: debhelper (>= 8.0.0), bzip2
|
Build-Depends: debhelper (>= 8.0.0), bzip2, dh-python
|
||||||
Standards-Version: 3.9.3
|
Standards-Version: 3.9.3
|
||||||
|
|
||||||
Package: platform-modules-d7032q28b
|
Package: platform-modules-d7032q28b
|
||||||
@ -34,3 +34,8 @@ Package: platform-modules-d7264q28b
|
|||||||
Architecture: amd64
|
Architecture: amd64
|
||||||
Depends: linux-image-4.19.0-9-2-amd64-unsigned
|
Depends: linux-image-4.19.0-9-2-amd64-unsigned
|
||||||
Description: kernel modules for platform devices such as fan, led
|
Description: kernel modules for platform devices such as fan, led
|
||||||
|
|
||||||
|
Package: platform-modules-d6332
|
||||||
|
Architecture: amd64
|
||||||
|
Depends: linux-image-4.19.0-9-2-amd64-unsigned
|
||||||
|
Description: kernel modules for platform devices such as fan, led
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: setup-board
|
||||||
|
# Required-Start:
|
||||||
|
# Required-Stop:
|
||||||
|
# Should-Start:
|
||||||
|
# Should-Stop:
|
||||||
|
# Default-Start: S
|
||||||
|
# Default-Stop: 0 6
|
||||||
|
# Short-Description: Setup Inventec d6356j board.
|
||||||
|
### END INIT INFO
|
||||||
|
|
||||||
|
PLATFORM_DIR=/usr/share/sonic/device/x86_64-inventec_d6332-r0/plugins
|
||||||
|
PLUGIN_DIR=/usr/lib/python2.7/dist-packages/inventec_plugin
|
||||||
|
|
||||||
|
PLATFORM_DAEMON=$PLATFORM_DIR/platfmgr.py
|
||||||
|
PLATFORM_DAEMON_NAME=platfmgr
|
||||||
|
INVSYNCD_DAEMON=$PLUGIN_DIR/invSyncd.py
|
||||||
|
INVSYNCD_DAEMON_NAME=invSyncd
|
||||||
|
|
||||||
|
# The process ID of the script when it runs is stored here:
|
||||||
|
PLATFORM_PIDFILE=/var/run/$PLATFORM_DAEMON_NAME.pid
|
||||||
|
|
||||||
|
do_monitor_start() {
|
||||||
|
/sbin/start-stop-daemon --quiet --oknodo --pidfile $PLATFORM_PIDFILE --make-pidfile --startas $PLATFORM_DAEMON --start --background -- $DAEMON_OPTS
|
||||||
|
/sbin/start-stop-daemon --quiet --oknodo --pidfile $INVSYNCD_PIDFILE --make-pidfile --startas $INVSYNCD_DAEMON --start --background -- $DAEMON_OPTS
|
||||||
|
}
|
||||||
|
|
||||||
|
do_monitor_stop() {
|
||||||
|
/sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $PLATFORM_PIDFILE --retry 10
|
||||||
|
/sbin/start-stop-daemon --quiet --oknodo --stop --pidfile $INVSYNCD_PIDFILE --retry 10
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check Fast-Reboot cause
|
||||||
|
FAST_REBOOT='no'
|
||||||
|
case "$(cat /proc/cmdline)" in
|
||||||
|
*fast-reboot*|*warm*)
|
||||||
|
FAST_REBOOT='yes'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
FAST_REBOOT='no'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
echo -n "Setting up board... "
|
||||||
|
if [ "$FAST_REBOOT" = "yes" ] ; then
|
||||||
|
/usr/local/bin/inventec_d6332_util.py -f fast-reboot-install
|
||||||
|
else
|
||||||
|
/usr/local/bin/inventec_d6332_util.py -f install
|
||||||
|
fi
|
||||||
|
do_monitor_${1}
|
||||||
|
echo "done."
|
||||||
|
;;
|
||||||
|
|
||||||
|
stop)
|
||||||
|
/usr/local/bin/inventec_d6332_util.py -f clean
|
||||||
|
do_monitor_${1}
|
||||||
|
echo "done."
|
||||||
|
;;
|
||||||
|
|
||||||
|
force-reload|restart)
|
||||||
|
echo "Not supported"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Usage: /etc/init.d/platform-modules-d6332.init {start|stop}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
@ -0,0 +1,4 @@
|
|||||||
|
d6332/utils/inventec_d6332_util.py /usr/local/bin
|
||||||
|
systemd/platform-modules-d6332.service /lib/systemd/system
|
||||||
|
d6332/utils/sonic_platform-1.0-py2-none-any.whl /usr/share/sonic/device/x86_64-inventec_d6332-r0
|
||||||
|
d6332/utils/sonic_platform-1.0-py3-none-any.whl /usr/share/sonic/device/x86_64-inventec_d6332-r0
|
@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Automatically added by dh_systemd_enable
|
||||||
|
# This will only remove masks created by d-s-h on package removal.
|
||||||
|
deb-systemd-helper unmask platform-modules-d6356j.service >/dev/null || true
|
||||||
|
|
||||||
|
# was-enabled defaults to true, so new installations run enable.
|
||||||
|
if deb-systemd-helper --quiet was-enabled platform-modules-d6332.service; then
|
||||||
|
# Enables the unit on first installation, creates new
|
||||||
|
# symlinks on upgrades if the unit file has changed.
|
||||||
|
deb-systemd-helper enable platform-modules-d6332.service >/dev/null || true
|
||||||
|
else
|
||||||
|
# Update the statefile to add new symlinks (if any), which need to be
|
||||||
|
# cleaned up on purge. Also remove old symlinks.
|
||||||
|
deb-systemd-helper update-state platform-modules-d6332.service >/dev/null || true
|
||||||
|
fi
|
||||||
|
# End automatically added section
|
||||||
|
depmod -a
|
||||||
|
# Automatically added by dh_installinit
|
||||||
|
if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ]; then
|
||||||
|
if [ -x "/etc/init.d/platform-modules-d6332" ]; then
|
||||||
|
update-rc.d platform-modules-d6332 defaults >/dev/null
|
||||||
|
invoke-rc.d platform-modules-d6332 start || exit $?
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# End automatically added section
|
@ -14,7 +14,7 @@ export INSTALL_MOD_DIR:=extra
|
|||||||
KVERSION ?= $(shell uname -r)
|
KVERSION ?= $(shell uname -r)
|
||||||
KERNEL_SRC := /lib/modules/$(KVERSION)
|
KERNEL_SRC := /lib/modules/$(KVERSION)
|
||||||
MOD_SRC_DIR:= $(shell pwd)
|
MOD_SRC_DIR:= $(shell pwd)
|
||||||
MODULE_DIRS:= d7032q28b d7054q28b d6254qs d6556 d6356 d7264q28b
|
MODULE_DIRS:= d7032q28b d7054q28b d6254qs d6556 d6356 d7264q28b d6332
|
||||||
|
|
||||||
%:
|
%:
|
||||||
dh $@ --with python2,systemd
|
dh $@ --with python2,systemd
|
||||||
@ -22,11 +22,17 @@ MODULE_DIRS:= d7032q28b d7054q28b d6254qs d6556 d6356 d7264q28b
|
|||||||
override_dh_auto_build:
|
override_dh_auto_build:
|
||||||
(for mod in $(MODULE_DIRS); do \
|
(for mod in $(MODULE_DIRS); do \
|
||||||
make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \
|
make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \
|
||||||
if [ $$mod = "d7054q28b" ] || [ $$mod = "d6356" ]; then \
|
if [ $$mod = "d7054q28b" ] || [ $$mod = "d6356" ] || [ $$mod = "d6332" ]; then \
|
||||||
cd $(MOD_SRC_DIR)/$${mod}; \
|
cd $(MOD_SRC_DIR)/$${mod}; \
|
||||||
python2 setup.py build; \
|
python2 setup.py build; \
|
||||||
python2 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/utils; \
|
python2 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/utils; \
|
||||||
cd $(MOD_SRC_DIR); \
|
cd $(MOD_SRC_DIR); \
|
||||||
|
fi; \
|
||||||
|
if [ $$mod = "d6332" ]; then \
|
||||||
|
cd $(MOD_SRC_DIR)/$${mod}; \
|
||||||
|
python3 setup.py build; \
|
||||||
|
python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/utils; \
|
||||||
|
cd $(MOD_SRC_DIR); \
|
||||||
fi \
|
fi \
|
||||||
done)
|
done)
|
||||||
|
|
||||||
@ -36,10 +42,15 @@ override_dh_auto_install:
|
|||||||
$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
|
$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
|
||||||
cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \
|
cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \
|
||||||
debian/platform-modules-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
|
debian/platform-modules-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
|
||||||
if [ $$mod = "d7054q28b" ] || [ $$mod = "d6356" ]; then \
|
if [ $$mod = "d7054q28b" ] || [ $$mod = "d6356" ] || [ $$mod = "d6332" ]; then \
|
||||||
cd $(MOD_SRC_DIR)/$${mod}; \
|
cd $(MOD_SRC_DIR)/$${mod}; \
|
||||||
python2 setup.py install --root=$(MOD_SRC_DIR)/debian/platform-modules-$${mod} --install-layout=deb; \
|
python2 setup.py install --root=$(MOD_SRC_DIR)/debian/platform-modules-$${mod} --install-layout=deb; \
|
||||||
cd $(MOD_SRC_DIR); \
|
cd $(MOD_SRC_DIR); \
|
||||||
|
fi; \
|
||||||
|
if [ $$mod = "d6332" ]; then \
|
||||||
|
cd $(MOD_SRC_DIR)/$${mod}; \
|
||||||
|
python3 setup.py install --root=$(MOD_SRC_DIR)/debian/platform-modules-$${mod} --install-layout=deb; \
|
||||||
|
cd $(MOD_SRC_DIR); \
|
||||||
fi \
|
fi \
|
||||||
done)
|
done)
|
||||||
|
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Inventec d6332 Platform modules
|
||||||
|
After=local-fs.target
|
||||||
|
Before=pmon.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=-/etc/init.d/platform-modules-d6332 start
|
||||||
|
ExecStop=-/etc/init.d/platform-modules-d6332 stop
|
||||||
|
RemainAfterExit=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
Loading…
Reference in New Issue
Block a user