[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:
CynthiaINV 2020-10-21 02:37:16 +08:00 committed by GitHub
parent d19d1dd569
commit 38bd6be609
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
55 changed files with 26470 additions and 4 deletions

View File

@ -0,0 +1,2 @@
{%- set default_topo = 't1' %}
{%- include 'buffers_config.j2' %}

View File

@ -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 %}

View File

@ -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

View 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

View File

@ -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]"
}
}
}

View File

@ -0,0 +1,2 @@
SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td3-d6332-32x100G-SR4.config.bcm
SAI_NUM_ECMP_MEMBERS=32

View File

@ -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

View File

@ -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(":","")}}

View File

@ -0,0 +1 @@
INVENTEC-D6332 t1

View File

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

View File

@ -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

View 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)

View 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

View 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, {}

View File

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

View 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)"

View File

@ -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) \

View File

@ -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)))

View 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

View File

@ -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);

View File

@ -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", &reg))
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");

View File

@ -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

View File

@ -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");

View File

@ -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");

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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'],
)

View File

@ -0,0 +1,3 @@
__all__ = ["platform", "chassis"]
from sonic_platform import *

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"]

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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