DellEMC: Add support for new platform z9332f -32x400G (#3845)

* Switch Vendor: DellEMC
* Switch SKU: z9332F
* ASIC Vendor: Broadcom
* Swich ASIC: tomahawk3
* Port Configuration: 32x400G
* SONiC Image: sonic-broadcom.bin

* Changes Include ipmitool implementation for platform_sensors script is inclued in pmon startup
This commit is contained in:
srideepDell 2019-12-17 16:26:23 -07:00 committed by Joe LeVeque
parent 063deb9b5f
commit 4458efbd71
38 changed files with 5910 additions and 2 deletions

View File

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

View File

@ -0,0 +1,20 @@
{%- set default_cable = '40m' %}
{%- macro generate_buffer_pool_and_profiles() %}
"BUFFER_POOL": {
},
"BUFFER_PROFILE": {
},
{%- endmacro %}
{%- macro generate_pg_profils(port_names_active) %}
"BUFFER_PG": {
},
{%- endmacro %}
{% macro generate_queue_buffers(port_names_active) %}
"BUFFER_QUEUE": {
}
{% endmacro %}

View File

@ -0,0 +1,20 @@
{%- set default_cable = '40m' %}
{%- macro generate_buffer_pool_and_profiles() %}
"BUFFER_POOL": {
},
"BUFFER_PROFILE": {
},
{%- endmacro %}
{%- macro generate_pg_profils(port_names_active) %}
"BUFFER_PG": {
},
{%- endmacro %}
{% macro generate_queue_buffers(port_names_active) %}
"BUFFER_QUEUE": {
}
{% endmacro %}

View File

@ -0,0 +1,23 @@
# PG lossless profiles.
# speed cable size xon xoff threshold xon_offset
10000 5m 1270 0 190500 -2 2540
25000 5m 1270 0 190500 -2 2540
40000 5m 1270 0 190500 -2 2540
50000 5m 1270 0 190500 -2 2540
100000 5m 1270 0 190500 -2 2540
200000 5m 1270 0 190500 -2 2540
400000 5m 1270 0 190500 -2 2540
10000 40m 1270 0 190500 -2 2540
25000 40m 1270 0 190500 -2 2540
40000 40m 1270 0 190500 -2 2540
50000 40m 1270 0 190500 -2 2540
100000 40m 1270 0 190500 -2 2540
200000 40m 1270 0 190500 -2 2540
400000 40m 1270 0 190500 -2 2540
10000 300m 1270 0 190500 -2 2540
25000 300m 1270 0 190500 -2 2540
40000 300m 1270 0 190500 -2 2540
50000 300m 1270 0 190500 -2 2540
100000 300m 1270 0 190500 -2 2540
200000 300m 1270 0 190500 -2 2540
400000 300m 1270 0 190500 -2 2540

View File

@ -0,0 +1,35 @@
# name lanes alias index speed
Ethernet0 33,34,35,36,37,38,39,40 fourhundredGigE1/1 1 400000
Ethernet8 41,42,43,44,45,46,47,48 fourhundredGigE1/2 2 400000
Ethernet16 49,50,51,52,53,54,55,56 fourhundredGigE1/3 3 400000
Ethernet24 57,58,59,60,61,62,63,64 fourhundredGigE1/4 4 400000
Ethernet32 65,66,67,68,69,70,71,72 fourhundredGigE1/5 5 400000
Ethernet40 73,74,75,76,77,78,79,80 fourhundredGigE1/6 6 400000
Ethernet48 81,82,83,84,85,86,87,88 fourhundredGigE1/7 7 400000
Ethernet56 89,90,91,92,93,94,95,96 fourhundredGigE1/8 8 400000
Ethernet64 1,2,3,4,5,6,7,8 fourhundredGigE1/9 9 400000
Ethernet72 9,10,11,12,13,14,15,16 fourhundredGigE1/10 10 400000
Ethernet80 17,18,19,20,21,22,23,24 fourhundredGigE1/11 11 400000
Ethernet88 25,26,27,28,29,30,31,32 fourhundredGigE1/12 12 400000
Ethernet96 97,98,99,100,101,102,103,104 fourhundredGigE1/13 13 400000
Ethernet104 105,106,107,108,109,110,111,112 fourhundredGigE1/14 14 400000
Ethernet112 113,114,115,116,117,118,119,120 fourhundredGigE1/15 15 400000
Ethernet120 121,122,123,124,125,126,127,128 fourhundredGigE1/16 16 400000
Ethernet128 129,130,131,132,133,134,135,136 fourhundredGigE1/17 17 400000
Ethernet136 137,138,139,140,141,142,143,144 fourhundredGigE1/18 18 400000
Ethernet144 145,146,147,148,149,150,151,152 fourhundredGigE1/19 19 400000
Ethernet152 153,154,155,156,157,158,159,160 fourhundredGigE1/20 20 400000
Ethernet160 225,226,227,228,229,230,231,232 fourhundredGigE1/21 21 400000
Ethernet168 233,234,235,236,237,238,239,240 fourhundredGigE1/22 22 400000
Ethernet176 241,242,243,244,245,246,247,248 fourhundredGigE1/23 23 400000
Ethernet184 249,250,251,252,253,254,255,256 fourhundredGigE1/24 24 400000
Ethernet192 161,162,163,164,165,166,167,168 fourhundredGigE1/25 25 400000
Ethernet200 169,170,171,172,173,174,175,176 fourhundredGigE1/26 26 400000
Ethernet208 177,178,179,180,181,182,183,184 fourhundredGigE1/27 27 400000
Ethernet216 185,186,187,188,189,190,191,192 fourhundredGigE1/28 28 400000
Ethernet224 193,194,195,196,197,198,199,200 fourhundredGigE1/29 29 400000
Ethernet232 201,202,203,204,205,206,207,208 fourhundredGigE1/30 30 400000
Ethernet240 209,210,211,212,213,214,215,216 fourhundredGigE1/31 31 400000
Ethernet248 217,218,219,220,221,222,223,224 fourhundredGigE1/32 32 400000
Ethernet256 257 tenGigE1/33 33 10000
Ethernet257 258 tenGigE1/34 34 10000

View File

@ -0,0 +1,226 @@
{%- set PORT_ALL = [] %}
{%- for port in PORT %}
{%- if PORT_ALL.append(port) %}{% endif %}
{%- endfor %}
{%- if PORT_ALL | sort_by_port_index %}{% endif %}
{%- set port_names_list_all = [] %}
{%- for port in PORT_ALL %}
{%- if port_names_list_all.append(port) %}{% endif %}
{%- endfor %}
{%- set port_names_all = port_names_list_all | join(',') -%}
{%- set PORT_ACTIVE = [] %}
{%- if DEVICE_NEIGHBOR is not defined %}
{%- set PORT_ACTIVE = PORT_ALL %}
{%- else %}
{%- for port in DEVICE_NEIGHBOR.keys() %}
{%- if PORT_ACTIVE.append(port) %}{%- endif %}
{%- endfor %}
{%- endif %}
{%- if PORT_ACTIVE | sort_by_port_index %}{% endif %}
{%- set port_names_list_active = [] %}
{%- for port in PORT_ACTIVE %}
{%- if port_names_list_active.append(port) %}{%- endif %}
{%- endfor %}
{%- set port_names_active = port_names_list_active | join(',') -%}
{%- set pfc_to_pg_map_supported_asics = ['mellanox', 'barefoot', 'marvell'] -%}
{
{% if generate_tc_to_pg_map is defined %}
{{- generate_tc_to_pg_map() }}
{% else %}
"TC_TO_PRIORITY_GROUP_MAP": {
"DEFAULT": {
"0": "0",
"1": "0",
"2": "0",
"3": "3",
"4": "4",
"5": "0",
"6": "0",
"7": "7"
}
},
{% endif %}
"MAP_PFC_PRIORITY_TO_QUEUE": {
"DEFAULT": {
"0": "0",
"1": "1",
"2": "2",
"3": "3",
"4": "4",
"5": "5",
"6": "6",
"7": "7"
}
},
"TC_TO_QUEUE_MAP": {
"DEFAULT": {
"0": "0",
"1": "1",
"2": "2",
"3": "3",
"4": "4",
"5": "5",
"6": "6",
"7": "7"
}
},
"DSCP_TO_TC_MAP": {
"DEFAULT": {
"0" : "0",
"1" : "0",
"2" : "0",
"3" : "0",
"4" : "0",
"5" : "0",
"6" : "0",
"7" : "0",
"8" : "0",
"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": "1"
},
"scheduler.1": {
"type" : "DWRR",
"weight": "2"
},
"scheduler.2": {
"type" : "DWRR",
"weight": "3"
},
"scheduler.3": {
"type" : "DWRR",
"weight": "4"
},
"scheduler.4": {
"type" : "DWRR",
"weight": "5"
},
"scheduler.5": {
"type" : "DWRR",
"weight": "10"
},
"scheduler.6": {
"type" : "DWRR",
"weight": "25"
},
"scheduler.7": {
"type" : "STRICT"
}
},
"PORT_QOS_MAP": {
"{{ port_names_active }}": {
"dscp_to_tc_map" : "[DSCP_TO_TC_MAP|DEFAULT]",
"tc_to_queue_map" : "[TC_TO_QUEUE_MAP|DEFAULT]",
"pfc_enable" : "3,4",
"tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|DEFAULT]"
}
},
"QUEUE": {
{% for port in PORT_ACTIVE %}
"{{ port }}|0": {
"scheduler" : "[SCHEDULER|scheduler.0]"
},
{% endfor %}
{% for port in PORT_ACTIVE %}
"{{ port }}|1": {
"scheduler" : "[SCHEDULER|scheduler.1]"
},
{% endfor %}
{% for port in PORT_ACTIVE %}
"{{ port }}|2": {
"scheduler": "[SCHEDULER|scheduler.2]"
},
{% endfor %}
{% for port in PORT_ACTIVE %}
"{{ port }}|3": {
"scheduler": "[SCHEDULER|scheduler.3]"
},
{% endfor %}
{% for port in PORT_ACTIVE %}
"{{ port }}|4": {
"scheduler": "[SCHEDULER|scheduler.4]"
},
{% endfor %}
{% for port in PORT_ACTIVE %}
"{{ port }}|5": {
"scheduler": "[SCHEDULER|scheduler.5]"
},
{% endfor %}
{% for port in PORT_ACTIVE %}
"{{ port }}|6": {
"scheduler": "[SCHEDULER|scheduler.6]"
},
{% endfor %}
{% for port in PORT_ACTIVE %}
"{{ port }}|7": {
"scheduler": "[SCHEDULER|scheduler.7]"
}{% if not loop.last %},{% endif %}
{% endfor %}
}
}

View File

@ -0,0 +1 @@
SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/th3-z9332f-32x400G.config.bcm

View File

@ -0,0 +1,3 @@
#Not supported Until SAI 3.6
#m0 load 0 0x0 /usr/share/sonic/hwsku/linkscan_led_fw.bin
#m0 load 0 0x3800 /usr/share/sonic/hwsku/custom_led.bin

View File

@ -0,0 +1,519 @@
core_clock_frequency=1325
dpr_clock_frequency=1000
device_clock_frequency=1325
port_flex_enable=1
#firmware load method, use fast load
load_firmware=0x2
ccm_dma_enable=0
ccmdma_intr_enable=0
mem_cache_enable=0
phy_enable=0
phy_null=1
dport_map_enable=1
module_64ports.0=0
tdma_intr_enable.0=1
ipv6_lpm_128b_enable.0=1
stat_if_parity_enable.0=1
oversubscribe_mode=0
bcm_tunnel_term_compatible_mode.0=1
table_dma_enable.0=1
schan_intr_enable.0=0
parity_enable.0=1
tdma_timeout_usec=1000000
lls_num_l2uc.0=10
miim_intr_enable.0=0
table_dma_enable=1
max_vp_lags.0=0
tdma_intr_enable=1
tdma_timeout_usec.0=5000000
parity_correction.0=1
mmu_lossless.0=0
bcm_num_cos=8
default_cpu_tx_queue=7
pktdma_poll_mode_channel_bitmap=1
l3_max_ecmp_mode.0=1
l3_alpm_enable=2
l3_alpm_ipv6_128b_bkt_rsvd=1
l2_mem_entries=40960
l3_mem_entries=40960
l2xlrn_thread_interval=50000
l2xlrn_intr_en=0
pbmp_xport_xe=0xffffffFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE
phy_an_c73=3
portmap_1.0=1:400
portmap_5.0=9:400
portmap_10.0=17:400
portmap_14.0=25:400
portmap_20.0=33:400
portmap_24.0=41:400
portmap_29.0=49:400
portmap_33.0=57:400
portmap_40.0=65:400
portmap_44.0=73:400
portmap_49.0=81:400
portmap_53.0=89:400
portmap_60.0=97:400
portmap_64.0=105:400
portmap_69.0=113:400
portmap_73.0=121:400
portmap_80.0=129:400
portmap_84.0=137:400
portmap_89.0=145:400
portmap_93.0=153:400
portmap_100.0=161:400
portmap_104.0=169:400
portmap_109.0=177:400
portmap_113.0=185:400
portmap_120.0=193:400
portmap_124.0=201:400
portmap_129.0=209:400
portmap_133.0=217:400
portmap_140.0=225:400
portmap_144.0=233:400
portmap_149.0=241:400
portmap_153.0=249:400
portmap_38.0=257:10:1
portmap_118.0=258:10:1
dport_map_port_20=1
dport_map_port_21=2
dport_map_port_22=3
dport_map_port_23=4
dport_map_port_24=5
dport_map_port_25=6
dport_map_port_26=7
dport_map_port_27=8
dport_map_port_28=9
dport_map_port_29=10
dport_map_port_30=11
dport_map_port_31=12
dport_map_port_32=13
dport_map_port_33=14
dport_map_port_34=15
dport_map_port_35=16
dport_map_port_36=17
dport_map_port_37=18
dport_map_port_40=19
dport_map_port_41=20
dport_map_port_42=21
dport_map_port_43=22
dport_map_port_44=23
dport_map_port_45=24
dport_map_port_46=25
dport_map_port_47=26
dport_map_port_48=27
dport_map_port_49=28
dport_map_port_50=29
dport_map_port_51=30
dport_map_port_52=31
dport_map_port_53=32
dport_map_port_54=33
dport_map_port_55=34
dport_map_port_56=35
dport_map_port_57=36
dport_map_port_1=37
dport_map_port_2=38
dport_map_port_3=39
dport_map_port_4=40
dport_map_port_5=41
dport_map_port_6=42
dport_map_port_7=43
dport_map_port_8=44
dport_map_port_9=45
dport_map_port_10=46
dport_map_port_11=47
dport_map_port_12=48
dport_map_port_13=49
dport_map_port_14=50
dport_map_port_15=51
dport_map_port_16=52
dport_map_port_17=53
dport_map_port_18=54
dport_map_port_60=55
dport_map_port_61=56
dport_map_port_62=57
dport_map_port_63=58
dport_map_port_64=59
dport_map_port_65=60
dport_map_port_66=61
dport_map_port_67=62
dport_map_port_68=63
dport_map_port_69=64
dport_map_port_70=65
dport_map_port_71=66
dport_map_port_72=67
dport_map_port_73=68
dport_map_port_74=69
dport_map_port_75=70
dport_map_port_76=71
dport_map_port_77=72
dport_map_port_80=73
dport_map_port_81=74
dport_map_port_82=75
dport_map_port_83=76
dport_map_port_84=77
dport_map_port_85=78
dport_map_port_86=79
dport_map_port_87=80
dport_map_port_88=81
dport_map_port_89=82
dport_map_port_90=83
dport_map_port_91=84
dport_map_port_92=85
dport_map_port_93=86
dport_map_port_94=87
dport_map_port_95=88
dport_map_port_96=89
dport_map_port_97=90
dport_map_port_140=91
dport_map_port_141=92
dport_map_port_142=93
dport_map_port_143=94
dport_map_port_144=95
dport_map_port_145=96
dport_map_port_146=97
dport_map_port_147=98
dport_map_port_148=99
dport_map_port_149=100
dport_map_port_150=101
dport_map_port_151=102
dport_map_port_152=103
dport_map_port_153=104
dport_map_port_154=105
dport_map_port_155=106
dport_map_port_156=107
dport_map_port_157=108
dport_map_port_100=109
dport_map_port_101=110
dport_map_port_102=111
dport_map_port_103=112
dport_map_port_104=113
dport_map_port_105=114
dport_map_port_106=115
dport_map_port_107=116
dport_map_port_108=117
dport_map_port_109=118
dport_map_port_110=119
dport_map_port_111=120
dport_map_port_112=121
dport_map_port_113=122
dport_map_port_114=123
dport_map_port_115=124
dport_map_port_116=125
dport_map_port_117=126
dport_map_port_120=127
dport_map_port_121=128
dport_map_port_122=129
dport_map_port_123=130
dport_map_port_124=131
dport_map_port_125=132
dport_map_port_126=133
dport_map_port_127=134
dport_map_port_128=135
dport_map_port_129=136
dport_map_port_130=137
dport_map_port_131=138
dport_map_port_132=139
dport_map_port_133=140
dport_map_port_134=141
dport_map_port_135=142
dport_map_port_136=143
dport_map_port_137=144
dport_map_port_38=145
dport_map_port_118=146
phy_chain_rx_lane_map_physical{33.0}=0x65732041
phy_chain_tx_lane_map_physical{33.0}=0x47206531
phy_chain_rx_lane_map_physical{41.0}=0x07561243
phy_chain_tx_lane_map_physical{41.0}=0x36207514
phy_chain_rx_lane_map_physical{49.0}=0x54632071
phy_chain_tx_lane_map_physical{49.0}=0x06241735
phy_chain_rx_lane_map_physical{57.0}=0x07561243
phy_chain_tx_lane_map_physical{57.0}=0x35207614
phy_chain_rx_lane_map_physical{65.0}=0x45623170
phy_chain_tx_lane_map_physical{65.0}=0x51260734
phy_chain_rx_lane_map_physical{73.0}=0x07561243
phy_chain_tx_lane_map_physical{73.0}=0x37245610
phy_chain_rx_lane_map_physical{81.0}=0x45632071
phy_chain_tx_lane_map_physical{81.0}=0x51260734
phy_chain_rx_lane_map_physical{89.0}=0x07561243
phy_chain_tx_lane_map_physical{89.0}=0x26437510
phy_chain_rx_lane_map_physical{1.0}=0x30176524
phy_chain_tx_lane_map_physical{1.0}=0x20615374
phy_chain_rx_lane_map_physical{9.0}=0x37562041
phy_chain_tx_lane_map_physical{9.0}=0x05176432
phy_chain_rx_lane_map_physical{17.0}=0x43607251
phy_chain_tx_lane_map_physical{17.0}=0x70261435
phy_chain_rx_lane_map_physical{25.0}=0x60347125
phy_chain_tx_lane_map_physical{25.0}=0x46357120
phy_chain_rx_lane_map_physical{97.0}=0x47601352
phy_chain_tx_lane_map_physical{97.0}=0x04265137
phy_chain_rx_lane_map_physical{105.0}=0x73206415
phy_chain_tx_lane_map_physical{105.0}=0x26374150
phy_chain_rx_lane_map_physical{113.0}=0x47632051
phy_chain_tx_lane_map_physical{113.0}=0x03254617
phy_chain_rx_lane_map_physical{121.0}=0x63027415
phy_chain_tx_lane_map_physical{121.0}=0x63721045
phy_chain_rx_lane_map_physical{129.0}=0x30154627
phy_chain_tx_lane_map_physical{129.0}=0x04735261
phy_chain_rx_lane_map_physical{137.0}=0x24753061
phy_chain_tx_lane_map_physical{137.0}=0x37614520
phy_chain_rx_lane_map_physical{145.0}=0x47601352
phy_chain_tx_lane_map_physical{145.0}=0x63274510
phy_chain_rx_lane_map_physical{153.0}=0x07361524
phy_chain_tx_lane_map_physical{153.0}=0x36527104
phy_chain_rx_lane_map_physical{225.0}=0x56410273
phy_chain_tx_lane_map_physical{225.0}=0x10274635
phy_chain_rx_lane_map_physical{233.0}=0x15740263
phy_chain_tx_lane_map_physical{233.0}=0x24351607
phy_chain_rx_lane_map_physical{241.0}=0x74015263
phy_chain_tx_lane_map_physical{241.0}=0x04152637
phy_chain_rx_lane_map_physical{249.0}=0x62037514
phy_chain_tx_lane_map_physical{249.0}=0x72453160
phy_chain_rx_lane_map_physical{161.0}=0x46510273
phy_chain_tx_lane_map_physical{161.0}=0x01653724
phy_chain_rx_lane_map_physical{169.0}=0x25743160
phy_chain_tx_lane_map_physical{169.0}=0x07216435
phy_chain_rx_lane_map_physical{177.0}=0x46510273
phy_chain_tx_lane_map_physical{177.0}=0x01652734
phy_chain_rx_lane_map_physical{185.0}=0x25743160
phy_chain_tx_lane_map_physical{185.0}=0x37016425
phy_chain_rx_lane_map_physical{193.0}=0x46510372
phy_chain_tx_lane_map_physical{193.0}=0x06153724
phy_chain_rx_lane_map_physical{201.0}=0x25743160
phy_chain_tx_lane_map_physical{201.0}=0x36017524
phy_chain_rx_lane_map_physical{209.0}=0x47601352
phy_chain_tx_lane_map_physical{209.0}=0x04152736
phy_chain_rx_lane_map_physical{217.0}=0x26453170
phy_chain_tx_lane_map_physical{217.0}=0x36027415
serdes_core_rx_polarity_flip_physical{33}=0x29
serdes_core_tx_polarity_flip_physical{33}=0xfe
serdes_core_rx_polarity_flip_physical{41}=0xb1
serdes_core_tx_polarity_flip_physical{41}=0xe8
serdes_core_rx_polarity_flip_physical{49}=0xca
serdes_core_tx_polarity_flip_physical{49}=0xb6
serdes_core_rx_polarity_flip_physical{57}=0x9b
serdes_core_tx_polarity_flip_physical{57}=0xdc
serdes_core_rx_polarity_flip_physical{65}=0x17
serdes_core_tx_polarity_flip_physical{65}=0x86
serdes_core_rx_polarity_flip_physical{73}=0x9b
serdes_core_tx_polarity_flip_physical{73}=0x55
serdes_core_rx_polarity_flip_physical{81}=0xa
serdes_core_tx_polarity_flip_physical{81}=0x6
serdes_core_rx_polarity_flip_physical{89}=0x9b
serdes_core_tx_polarity_flip_physical{89}=0x48
serdes_core_rx_polarity_flip_physical{1}=0xec
serdes_core_tx_polarity_flip_physical{1}=0x56
serdes_core_rx_polarity_flip_physical{9}=0x13
serdes_core_tx_polarity_flip_physical{9}=0xa6
serdes_core_rx_polarity_flip_physical{17}=0x5a
serdes_core_tx_polarity_flip_physical{17}=0xc6
serdes_core_rx_polarity_flip_physical{25}=0xf
serdes_core_tx_polarity_flip_physical{25}=0x4e
serdes_core_rx_polarity_flip_physical{97}=0x17
serdes_core_tx_polarity_flip_physical{97}=0x2e
serdes_core_rx_polarity_flip_physical{105}=0xce
serdes_core_tx_polarity_flip_physical{105}=0x7c
serdes_core_rx_polarity_flip_physical{113}=0xa
serdes_core_tx_polarity_flip_physical{113}=0x35
serdes_core_rx_polarity_flip_physical{121}=0xb9
serdes_core_tx_polarity_flip_physical{121}=0xef
serdes_core_rx_polarity_flip_physical{129}=0xe8
serdes_core_tx_polarity_flip_physical{129}=0xac
serdes_core_rx_polarity_flip_physical{137}=0xcb
serdes_core_tx_polarity_flip_physical{137}=0x9c
serdes_core_rx_polarity_flip_physical{145}=0x17
serdes_core_tx_polarity_flip_physical{145}=0x32
serdes_core_rx_polarity_flip_physical{153}=0xb9
serdes_core_tx_polarity_flip_physical{153}=0xaf
serdes_core_rx_polarity_flip_physical{225}=0xaa
serdes_core_tx_polarity_flip_physical{225}=0x7
serdes_core_rx_polarity_flip_physical{233}=0x31
serdes_core_tx_polarity_flip_physical{233}=0x47
serdes_core_rx_polarity_flip_physical{241}=0xe8
serdes_core_tx_polarity_flip_physical{241}=0x9e
serdes_core_rx_polarity_flip_physical{249}=0xec
serdes_core_tx_polarity_flip_physical{249}=0x1f
serdes_core_rx_polarity_flip_physical{161}=0x6a
serdes_core_tx_polarity_flip_physical{161}=0xd4
serdes_core_rx_polarity_flip_physical{169}=0x9e
serdes_core_tx_polarity_flip_physical{169}=0x7b
serdes_core_rx_polarity_flip_physical{177}=0x6a
serdes_core_tx_polarity_flip_physical{177}=0xcc
serdes_core_rx_polarity_flip_physical{185}=0x9e
serdes_core_tx_polarity_flip_physical{185}=0x58
serdes_core_rx_polarity_flip_physical{193}=0x6f
serdes_core_tx_polarity_flip_physical{193}=0x24
serdes_core_rx_polarity_flip_physical{201}=0x9e
serdes_core_tx_polarity_flip_physical{201}=0xdf
serdes_core_rx_polarity_flip_physical{209}=0x17
serdes_core_tx_polarity_flip_physical{209}=0xe9
serdes_core_rx_polarity_flip_physical{217}=0xec
serdes_core_tx_polarity_flip_physical{217}=0x68
serdes_lane_config_media_type_49=copper
serdes_lane_config_media_type_50=copper
serdes_lane_config_media_type_51=copper
serdes_lane_config_media_type_52=copper
serdes_lane_config_media_type_54=copper
serdes_lane_config_media_type_55=copper
serdes_lane_config_media_type_56=copper
serdes_lane_config_media_type_57=copper
serdes_lane_config_media_type_53=copper
serdes_lane_config_media_type_60=copper
serdes_lane_config_media_type_61=copper
serdes_lane_config_media_type_62=copper
serdes_lane_config_media_type_63=copper
serdes_lane_config_media_type_65=copper
serdes_lane_config_media_type_66=copper
serdes_lane_config_media_type_67=copper
serdes_lane_config_media_type_68=copper
serdes_lane_config_media_type_64=copper
serdes_lane_config_media_type_80=copper
serdes_lane_config_media_type_81=copper
serdes_lane_config_media_type_82=copper
serdes_lane_config_media_type_83=copper
serdes_lane_config_media_type_85=copper
serdes_lane_config_media_type_86=copper
serdes_lane_config_media_type_87=copper
serdes_lane_config_media_type_88=copper
serdes_lane_config_media_type_84=copper
serdes_lane_config_media_type_100=copper
serdes_lane_config_media_type_101=copper
serdes_lane_config_media_type_102=copper
serdes_lane_config_media_type_103=copper
serdes_lane_config_media_type_105=copper
serdes_lane_config_media_type_106=copper
serdes_lane_config_media_type_107=copper
serdes_lane_config_media_type_108=copper
serdes_lane_config_media_type_104=copper
serdes_lane_config_media_type_120=copper
serdes_lane_config_media_type_121=copper
serdes_lane_config_media_type_122=copper
serdes_lane_config_media_type_123=copper
serdes_lane_config_media_type_125=copper
serdes_lane_config_media_type_126=copper
serdes_lane_config_media_type_127=copper
serdes_lane_config_media_type_128=copper
serdes_lane_config_media_type_124=copper
serdes_lane_config_media_type_140=copper
serdes_lane_config_media_type_141=copper
serdes_lane_config_media_type_142=copper
serdes_lane_config_media_type_143=copper
serdes_lane_config_media_type_145=copper
serdes_lane_config_media_type_146=copper
serdes_lane_config_media_type_147=copper
serdes_lane_config_media_type_148=copper
serdes_lane_config_media_type_144=copper
serdes_lane_config_media_type_40=copper
serdes_lane_config_media_type_41=copper
serdes_lane_config_media_type_42=copper
serdes_lane_config_media_type_43=copper
serdes_lane_config_media_type_45=copper
serdes_lane_config_media_type_46=copper
serdes_lane_config_media_type_47=copper
serdes_lane_config_media_type_48=copper
serdes_lane_config_media_type_44=copper
serdes_lane_config_media_type_69=copper
serdes_lane_config_media_type_70=copper
serdes_lane_config_media_type_71=copper
serdes_lane_config_media_type_72=copper
serdes_lane_config_media_type_74=copper
serdes_lane_config_media_type_75=copper
serdes_lane_config_media_type_76=copper
serdes_lane_config_media_type_77=copper
serdes_lane_config_media_type_73=copper
serdes_lane_config_media_type_1=copper
serdes_lane_config_media_type_2=copper
serdes_lane_config_media_type_3=copper
serdes_lane_config_media_type_4=copper
serdes_lane_config_media_type_6=copper
serdes_lane_config_media_type_7=copper
serdes_lane_config_media_type_8=copper
serdes_lane_config_media_type_9=copper
serdes_lane_config_media_type_5=copper
serdes_lane_config_media_type_29=copper
serdes_lane_config_media_type_30=copper
serdes_lane_config_media_type_31=copper
serdes_lane_config_media_type_32=copper
serdes_lane_config_media_type_34=copper
serdes_lane_config_media_type_35=copper
serdes_lane_config_media_type_36=copper
serdes_lane_config_media_type_37=copper
serdes_lane_config_media_type_33=copper
serdes_lane_config_media_type_89=copper
serdes_lane_config_media_type_90=copper
serdes_lane_config_media_type_91=copper
serdes_lane_config_media_type_92=copper
serdes_lane_config_media_type_94=copper
serdes_lane_config_media_type_95=copper
serdes_lane_config_media_type_96=copper
serdes_lane_config_media_type_97=copper
serdes_lane_config_media_type_93=copper
serdes_lane_config_media_type_109=copper
serdes_lane_config_media_type_110=copper
serdes_lane_config_media_type_111=copper
serdes_lane_config_media_type_112=copper
serdes_lane_config_media_type_114=copper
serdes_lane_config_media_type_115=copper
serdes_lane_config_media_type_116=copper
serdes_lane_config_media_type_117=copper
serdes_lane_config_media_type_113=copper
serdes_lane_config_media_type_129=copper
serdes_lane_config_media_type_130=copper
serdes_lane_config_media_type_131=copper
serdes_lane_config_media_type_132=copper
serdes_lane_config_media_type_134=copper
serdes_lane_config_media_type_135=copper
serdes_lane_config_media_type_136=copper
serdes_lane_config_media_type_137=copper
serdes_lane_config_media_type_133=copper
serdes_lane_config_media_type_149=copper
serdes_lane_config_media_type_150=copper
serdes_lane_config_media_type_151=copper
serdes_lane_config_media_type_152=copper
serdes_lane_config_media_type_154=copper
serdes_lane_config_media_type_155=copper
serdes_lane_config_media_type_156=copper
serdes_lane_config_media_type_157=copper
serdes_lane_config_media_type_153=copper
serdes_lane_config_media_type_10=copper
serdes_lane_config_media_type_11=copper
serdes_lane_config_media_type_12=copper
serdes_lane_config_media_type_13=copper
serdes_lane_config_media_type_15=copper
serdes_lane_config_media_type_16=copper
serdes_lane_config_media_type_17=copper
serdes_lane_config_media_type_18=copper
serdes_lane_config_media_type_14=copper
serdes_lane_config_media_type_20=copper
serdes_lane_config_media_type_21=copper
serdes_lane_config_media_type_22=copper
serdes_lane_config_media_type_23=copper
serdes_lane_config_media_type_25=copper
serdes_lane_config_media_type_26=copper
serdes_lane_config_media_type_27=copper
serdes_lane_config_media_type_28=copper
serdes_lane_config_media_type_24=copper
#sai_preinit_cmd_file=/usr/share/sonic/hwsku/sai_preinit_cmd.soc
sai_postinit_cmd_file=/usr/share/sonic/hwsku/sai_postinit_cmd.soc

View File

@ -0,0 +1 @@
DellEMC-Z9332f-O32 t1

View File

@ -0,0 +1,2 @@
CONSOLE_PORT=0x3f8
CONSOLE_DEV=0

View File

@ -0,0 +1,7 @@
# LED microprocessor initialization for Dell z9332f
#
#
#Led0
#Support only after SAI 3.6
#led auto on
#led start

View File

@ -0,0 +1,22 @@
#!/usr/bin/env python
#############################################################################
# DellEMC Z9332f
#
# 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/class/i2c-adapter/i2c-0/0-0056/eeprom"
super(board, self).__init__(self.eeprom_path, 0, '', True)

View File

@ -0,0 +1,126 @@
#
# psuutil.py
# Platform-specific PSU status interface for SONiC
#
import os.path
import logging
import commands
import sys
Z9332F_MAX_PSUS = 2
IPMI_PSU1_DATA = "docker exec -it pmon ipmitool raw 0x04 0x2d 0x2f | awk '{print substr($0,9,1)}'"
IPMI_PSU1_DATA_DOCKER = "ipmitool raw 0x04 0x2d 0x2f | awk '{print substr($0,9,1)}'"
IPMI_PSU2_DATA = "docker exec -it pmon ipmitool raw 0x04 0x2d 0x39 | awk '{print substr($0,9,1)}'"
IPMI_PSU2_DATA_DOCKER = "ipmitool raw 0x04 0x2d 0x39 | awk '{print substr($0,9,1)}'"
PSU_PRESENCE = "PSU{0}_Status"
# Use this for older firmware
# PSU_PRESENCE="PSU{0}_prsnt"
ipmi_sdr_list = ""
try:
from sonic_psu.psu_base import PsuBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
class PsuUtil(PsuBase):
"""Platform-specific PSUutil class"""
def __init__(self):
PsuBase.__init__(self)
def isDockerEnv(self):
num_docker = open('/proc/self/cgroup', 'r').read().count(":/docker")
if num_docker > 0:
return True
else:
return False
# Fetch a BMC register
def get_pmc_register(self, reg_name):
status = 1
global ipmi_sdr_list
ipmi_dev_node = "/dev/pmi0"
ipmi_cmd_1 = IPMI_PSU1_DATA
ipmi_cmd_2 = IPMI_PSU1_DATA
dockerenv = self.isDockerEnv()
if dockerenv == True:
if index == 1:
status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU1_DATA_DOCKER)
elif index == 2:
status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU2_DATA_DOCKER)
else:
if index == 1:
status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU1_DATA)
elif index == 2:
status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU2_DATA)
if status:
logging.error('Failed to execute ipmitool')
sys.exit(0)
output = ipmi_sdr_list
return output
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
"""
Z9332F_MAX_PSUS = 2
return Z9332F_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
"""
# Until psu_status is implemented this is hardcoded temporarily
status = 1
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
ret_status = 1
global ipmi_sdr_list
ipmi_dev_node = "/dev/pmi0"
dockerenv = self.isDockerEnv()
if dockerenv == True:
if index == 1:
status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU1_DATA_DOCKER)
elif index == 2:
status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU2_DATA_DOCKER)
else:
if index == 1:
status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU1_DATA)
elif index == 2:
ret_status, ipmi_sdr_list = commands.getstatusoutput(IPMI_PSU2_DATA)
#if ret_status:
# print ipmi_sdr_list
# logging.error('Failed to execute ipmitool')
# sys.exit(0)
psu_status = ipmi_sdr_list
if psu_status == '1':
status = 1
return status

View File

@ -0,0 +1,307 @@
# sfputil.py
#
# Platform-specific SFP transceiver interface for SONiC
#
try:
import struct
import sys
import getopt
import time
import select
from sonic_sfp.sfputilbase import SfpUtilBase
from os import *
from mmap import *
except ImportError as e:
raise ImportError("%s - required module not found" % str(e))
#from xcvrd
SFP_STATUS_REMOVED = '0'
SFP_STATUS_INSERTED = '1'
class SfpUtil(SfpUtilBase):
"""Platform-specific SfpUtil class"""
PORT_START = 1
PORT_END = 34
PORTS_IN_BLOCK = 34
BASE_RES_PATH = "/sys/bus/pci/devices/0000:09:00.0/resource0"
_port_to_i2c_mapping = {
1: 10,
2: 11,
3: 12,
4: 13,
5: 14,
6: 15,
7: 16,
8: 17,
9: 18,
10: 19,
11: 20,
12: 21,
13: 22,
14: 23,
15: 24,
16: 25,
17: 26,
18: 27,
19: 28,
20: 29,
21: 30,
22: 31,
23: 32,
24: 33,
25: 34,
26: 35,
27: 36,
28: 37,
29: 38,
30: 39,
31: 40,
32: 41,
33: 1,
34: 2,
}
_port_to_eeprom_mapping = {}
_global_port_pres_dict = {}
@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(self.PORT_START, self.PORTS_IN_BLOCK + 1)
@property
def port_to_eeprom_mapping(self):
return self._port_to_eeprom_mapping
def pci_mem_read(self, mm, offset):
mm.seek(offset)
read_data_stream = mm.read(4)
reg_val = struct.unpack('I', read_data_stream)
mem_val = str(reg_val)[1:-2]
# print "reg_val read:%x"%reg_val
return mem_val
def pci_mem_write(self, mm, offset, data):
mm.seek(offset)
# print "data to write:%x"%data
mm.write(struct.pack('I', data))
def pci_set_value(self, resource, val, offset):
fd = open(resource, O_RDWR)
mm = mmap(fd, 0)
val = self.pci_mem_write(mm, offset, val)
mm.close()
close(fd)
return val
def pci_get_value(self, resource, offset):
fd = open(resource, O_RDWR)
mm = mmap(fd, 0)
val = self.pci_mem_read(mm, offset)
mm.close()
close(fd)
return val
def init_global_port_presence(self):
for port_num in range(self.port_start, (self.port_end + 1)):
presence = self.get_presence(port_num)
if(presence):
self._global_port_pres_dict[port_num] = '1'
else:
self._global_port_pres_dict[port_num] = '0'
def mod_pres(self):
port_pres_mask =0
for port_num in range(self.port_start, (self.port_end + 1)):
presence = self.get_presence(port_num)
if(presence):
self._global_port_pres_dict[port_num] = '1'
port_val = (1 << (port_num -1))
port_pres_mask = (port_pres_mask | port_val)
else:
self._global_port_pres_dict[port_num] = '0'
port_val = ~(1 << (port_num -1))
port_pres_mask = (port_pres_mask & port_val)
return port_pres_mask
def __init__(self):
eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"
for x in range(self.port_start, self.port_end + 1):
self.port_to_eeprom_mapping[x] = eeprom_path.format(
self._port_to_i2c_mapping[x])
self.init_global_port_presence()
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
# Port offset starts with 0x4004
port_offset = 16388 + ((port_num-1) * 16)
status = self.pci_get_value(self.BASE_RES_PATH, port_offset)
reg_value = int(status)
# Absence of status throws error
if (reg_value == ""):
return False
# Mask off 4th bit for presence
mask = (1 << 4)
# Mask off 1st bit for presence 33,34
if (port_num > 32):
mask = (1 << 0)
# ModPrsL is active low
if reg_value & mask == 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
# Port offset starts with 0x4000
port_offset = 16384 + ((port_num-1) * 16)
status = self.pci_get_value(self.BASE_RES_PATH, port_offset)
reg_value = int(status)
# Absence of status throws error
if (reg_value == ""):
return False
# Mask off 4th bit for presence
mask = (1 << 6)
# LPMode is active high
if reg_value & mask == 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
# Port offset starts with 0x4000
port_offset = 16384 + ((port_num-1) * 16)
status = self.pci_get_value(self.BASE_RES_PATH, port_offset)
reg_value = int(status)
# Absence of status throws error
if (reg_value == ""):
return False
# Mask off 4th bit for presence
mask = (1 << 6)
# LPMode is active high; set or clear the bit accordingly
if lpmode is True:
reg_value = reg_value | mask
else:
reg_value = reg_value & ~mask
# Convert our register value back to a hex string and write back
status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset)
return True
def reset(self, port_num):
# Check for invalid port_num
if port_num < self.port_start or port_num > self.port_end:
return False
# Port offset starts with 0x4000
port_offset = 16384 + ((port_num-1) * 16)
status = self.pci_get_value(self.BASE_RES_PATH, port_offset)
reg_value = int(status)
# Absence of status throws error
if (reg_value == ""):
return False
# Mask off 4th bit for presence
mask = (1 << 6)
# ResetL is active low
reg_value = reg_value & ~mask
# Convert our register value back to a hex string and write back
status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset)
# Sleep 1 second to allow it to settle
time.sleep(1)
reg_value = reg_value | mask
# Convert our register value back to a hex string and write back
status = self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset)
return True
def get_register(self, reg_file):
retval = 'ERR'
if (not path.isfile(reg_file)):
print reg_file, 'not found !'
return retval
try:
with fdopen(open(reg_file, O_RDONLY)) as fd:
retval = fd.read()
except Exception as error:
logging.error("Unable to open ", reg_file, "file !")
retval = retval.rstrip('\r\n')
retval = retval.lstrip(" ")
return retval
def get_transceiver_change_event(self):
port_dict = {}
while True:
for port_num in range(self.port_start, (self.port_end + 1)):
presence = self.get_presence(port_num)
if(presence and self._global_port_pres_dict[port_num] == '0'):
self._global_port_pres_dict[port_num] = '1'
port_dict[port_num] = '1'
elif(not presence and
self._global_port_pres_dict[port_num] == '1'):
self._global_port_pres_dict[port_num] = '0'
port_dict[port_num] = '0'
if(len(port_dict) > 0):
return True, port_dict
time.sleep(0.5)

View File

@ -9,6 +9,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \
$(DELL_Z9264F_PLATFORM_MODULE) \ $(DELL_Z9264F_PLATFORM_MODULE) \
$(DELL_S5232F_PLATFORM_MODULE) \ $(DELL_S5232F_PLATFORM_MODULE) \
$(DELL_S5248F_PLATFORM_MODULE) \ $(DELL_S5248F_PLATFORM_MODULE) \
$(DELL_Z9332F_PLATFORM_MODULE) \
$(DELL_Z9100_PLATFORM_MODULE) \ $(DELL_Z9100_PLATFORM_MODULE) \
$(DELL_S6100_PLATFORM_MODULE) \ $(DELL_S6100_PLATFORM_MODULE) \
$(INGRASYS_S8900_54XC_PLATFORM_MODULE) \ $(INGRASYS_S8900_54XC_PLATFORM_MODULE) \

View File

@ -1,10 +1,11 @@
# Dell S6000,Z9100, S6100, Z9264F , S5232 Platform modules # Dell S6000,Z9100, S6100, Z9264F , S5232F,Z9332F Platform modules
DELL_S6000_PLATFORM_MODULE_VERSION = 1.1 DELL_S6000_PLATFORM_MODULE_VERSION = 1.1
DELL_Z9100_PLATFORM_MODULE_VERSION = 1.1 DELL_Z9100_PLATFORM_MODULE_VERSION = 1.1
DELL_S6100_PLATFORM_MODULE_VERSION = 1.1 DELL_S6100_PLATFORM_MODULE_VERSION = 1.1
DELL_Z9264F_PLATFORM_MODULE_VERSION = 1.1 DELL_Z9264F_PLATFORM_MODULE_VERSION = 1.1
DELL_S5232F_PLATFORM_MODULE_VERSION = 1.1 DELL_S5232F_PLATFORM_MODULE_VERSION = 1.1
DELL_Z9332F_PLATFORM_MODULE_VERSION = 1.1
DELL_S5248F_PLATFORM_MODULE_VERSION = 1.1 DELL_S5248F_PLATFORM_MODULE_VERSION = 1.1
export DELL_S6000_PLATFORM_MODULE_VERSION export DELL_S6000_PLATFORM_MODULE_VERSION
@ -12,6 +13,7 @@ export DELL_Z9100_PLATFORM_MODULE_VERSION
export DELL_S6100_PLATFORM_MODULE_VERSION export DELL_S6100_PLATFORM_MODULE_VERSION
export DELL_Z9264F_PLATFORM_MODULE_VERSION export DELL_Z9264F_PLATFORM_MODULE_VERSION
export DELL_S5232F_PLATFORM_MODULE_VERSION export DELL_S5232F_PLATFORM_MODULE_VERSION
export DELL_Z9332F_PLATFORM_MODULE_VERSION
export DELL_S5248F_PLATFORM_MODULE_VERSION export DELL_S5248F_PLATFORM_MODULE_VERSION
DELL_Z9100_PLATFORM_MODULE = platform-modules-z9100_$(DELL_Z9100_PLATFORM_MODULE_VERSION)_amd64.deb DELL_Z9100_PLATFORM_MODULE = platform-modules-z9100_$(DELL_Z9100_PLATFORM_MODULE_VERSION)_amd64.deb
@ -37,6 +39,10 @@ DELL_S5232F_PLATFORM_MODULE = platform-modules-s5232f_$(DELL_S5232F_PLATFORM_MOD
$(DELL_S5232F_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_s5232f_c3538-r0 $(DELL_S5232F_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_s5232f_c3538-r0
$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_S5232F_PLATFORM_MODULE))) $(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_S5232F_PLATFORM_MODULE)))
DELL_Z9332F_PLATFORM_MODULE = platform-modules-z9332f_$(DELL_Z9332F_PLATFORM_MODULE_VERSION)_amd64.deb
$(DELL_Z9332F_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_z9332f_d1508-r0
$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_Z9332F_PLATFORM_MODULE)))
DELL_S5248F_PLATFORM_MODULE = platform-modules-s5248f_$(DELL_S5248F_PLATFORM_MODULE_VERSION)_amd64.deb DELL_S5248F_PLATFORM_MODULE = platform-modules-s5248f_$(DELL_S5248F_PLATFORM_MODULE_VERSION)_amd64.deb
$(DELL_S5248F_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_s5248f_c3538-r0 $(DELL_S5248F_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_s5248f_c3538-r0
$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_S5248F_PLATFORM_MODULE))) $(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_S5248F_PLATFORM_MODULE)))

View File

@ -34,3 +34,8 @@ Package: platform-modules-s5248f
Architecture: amd64 Architecture: amd64
Depends: linux-image-4.9.0-9-2-amd64 Depends: linux-image-4.9.0-9-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp Description: kernel modules for platform devices such as fan, led, sfp
Package: platform-modules-z9332f
Architecture: amd64
Depends: linux-image-4.9.0-9-2-amd64
Description: kernel modules for platform devices such as fan, led, sfp

View File

@ -0,0 +1,39 @@
#!/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 Z9332f board.
### END INIT INFO
case "$1" in
start)
echo -n "Setting up board... "
/usr/local/bin/z9332f_platform.sh init
echo "done."
;;
stop)
/usr/local/bin/z9332f_platform.sh deinit
echo "done."
;;
force-reload|restart)
echo "Not supported"
;;
*)
echo "Usage: /etc/init.d/platform-modules-z9332f.init {start|stop}"
exit 1
;;
esac
exit 0

View File

@ -0,0 +1,7 @@
z9332f/scripts/z9332f_platform.sh usr/local/bin
z9332f/scripts/platform_sensors.py usr/local/bin
z9332f/scripts/sensors usr/bin
z9332f/scripts/pcisysfs.py usr/bin
z9332f/cfg/z9332f-modules.conf etc/modules-load.d
z9332f/systemd/platform-modules-z9332f.service etc/systemd/system
common/platform_reboot usr/share/sonic/device/x86_64-dellemc_z9332f_d1508-r0

View File

@ -0,0 +1,10 @@
# postinst script for Z9332f
# Enable Dell-Z9332f-platform-service
depmod -a
systemctl enable platform-modules-z9332f.service
systemctl start platform-modules-z9332f.service
#DEBHELPER#

View File

@ -5,7 +5,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:= s6000 z9100 s6100 z9264f s5232f s5248f MODULE_DIRS:= s6000 z9100 s6100 z9264f s5232f s5248f z9332f
COMMON_DIR := common COMMON_DIR := common
%: %:

View File

@ -0,0 +1,17 @@
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
i2c-i801
i2c-isch
i2c-ismt
i2c-dev
i2c-mux
i2c-smbus
i2c-mux-gpio
i2c-mux-pca954x
ipmi_devintf
ipmi_si

View File

@ -0,0 +1,4 @@
obj-m += cls-switchboard.o
obj-m += cls-i2c-ocore.o
obj-m += mc24lc64t.o

View File

@ -0,0 +1,845 @@
// SPDX-License-Identifier: GPL-2.0
/*
* cls-i2c-ocores.c: I2C bus driver for OpenCores I2C controller
* (https://opencores.org/project/i2c/overview)
*
* Peter Korsgaard <peter@korsgaard.com>
*
* Support for the GRLIB port of the controller by
* Andreas Larsson <andreas@gaisler.com>
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
// #include <linux/platform_data/i2c-ocores.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/log2.h>
#include <linux/spinlock.h>
#include <linux/jiffies.h>
#include "cls-i2c-ocore.h"
#define OCORES_FLAG_POLL BIT(0)
/*
* 'process_lock' exists because ocores_process() and ocores_process_timeout()
* can't run in parallel.
*/
struct ocores_i2c {
void __iomem *base;
int iobase;
u32 reg_shift;
u32 reg_io_width;
unsigned long flags;
wait_queue_head_t wait;
struct i2c_adapter adap;
struct i2c_msg *msg;
int pos;
int nmsgs;
int state; /* see STATE_ */
int nack_retry;
spinlock_t process_lock;
struct clk *clk;
int ip_clock_khz;
int bus_clock_khz;
void (*setreg)(struct ocores_i2c *i2c, int reg, u8 value);
u8 (*getreg)(struct ocores_i2c *i2c, int reg);
};
/* registers */
#define OCI2C_PRELOW 0
#define OCI2C_PREHIGH 1
#define OCI2C_CONTROL 2
#define OCI2C_DATA 3
#define OCI2C_CMD 4 /* write only */
#define OCI2C_STATUS 4 /* read only, same address as OCI2C_CMD */
#define OCI2C_CTRL_IEN 0x40
#define OCI2C_CTRL_EN 0x80
#define OCI2C_CMD_START 0x91
#define OCI2C_CMD_STOP 0x41
#define OCI2C_CMD_READ 0x21
#define OCI2C_CMD_WRITE 0x11
#define OCI2C_CMD_READ_ACK 0x21
#define OCI2C_CMD_READ_NACK 0x29
#define OCI2C_CMD_IACK 0x01
#define OCI2C_STAT_IF 0x01
#define OCI2C_STAT_TIP 0x02
#define OCI2C_STAT_ARBLOST 0x20
#define OCI2C_STAT_BUSY 0x40
#define OCI2C_STAT_NACK 0x80
#define STATE_DONE 0
#define STATE_START 1
#define STATE_WRITE 2
#define STATE_READ 3
#define STATE_ERROR 4
#define TYPE_OCORES 0
#define TYPE_GRLIB 1
static void oc_setreg_8(struct ocores_i2c *i2c, int reg, u8 value)
{
iowrite8(value, i2c->base + (reg << i2c->reg_shift));
}
static void oc_setreg_16(struct ocores_i2c *i2c, int reg, u8 value)
{
iowrite16(value, i2c->base + (reg << i2c->reg_shift));
}
static void oc_setreg_32(struct ocores_i2c *i2c, int reg, u8 value)
{
iowrite32(value, i2c->base + (reg << i2c->reg_shift));
}
static void oc_setreg_16be(struct ocores_i2c *i2c, int reg, u8 value)
{
iowrite16be(value, i2c->base + (reg << i2c->reg_shift));
}
static void oc_setreg_32be(struct ocores_i2c *i2c, int reg, u8 value)
{
iowrite32be(value, i2c->base + (reg << i2c->reg_shift));
}
static inline u8 oc_getreg_8(struct ocores_i2c *i2c, int reg)
{
return ioread8(i2c->base + (reg << i2c->reg_shift));
}
static inline u8 oc_getreg_16(struct ocores_i2c *i2c, int reg)
{
return ioread16(i2c->base + (reg << i2c->reg_shift));
}
static inline u8 oc_getreg_32(struct ocores_i2c *i2c, int reg)
{
return ioread32(i2c->base + (reg << i2c->reg_shift));
}
static inline u8 oc_getreg_16be(struct ocores_i2c *i2c, int reg)
{
return ioread16be(i2c->base + (reg << i2c->reg_shift));
}
static inline u8 oc_getreg_32be(struct ocores_i2c *i2c, int reg)
{
return ioread32be(i2c->base + (reg << i2c->reg_shift));
}
static void oc_setreg_io_8(struct ocores_i2c *i2c, int reg, u8 value)
{
outb(value, i2c->iobase + reg);
}
static inline u8 oc_getreg_io_8(struct ocores_i2c *i2c, int reg)
{
return inb(i2c->iobase + reg);
}
static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value)
{
i2c->setreg(i2c, reg, value);
}
static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg)
{
return i2c->getreg(i2c, reg);
}
static void ocores_process(struct ocores_i2c *i2c, u8 stat)
{
struct i2c_msg *msg = i2c->msg;
unsigned long flags;
/*
* If we spin here is because we are in timeout, so we are going
* to be in STATE_ERROR. See ocores_process_timeout()
*/
spin_lock_irqsave(&i2c->process_lock, flags);
dev_dbg(&i2c->adap.dev, "STATE: %d\n", i2c->state);
if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) {
/* stop has been sent */
oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
wake_up(&i2c->wait);
goto out;
}
/* error? */
if (stat & OCI2C_STAT_ARBLOST) {
// i2c->state = STATE_ERROR;
i2c->state = STATE_START;
// i2c->nack_retry = 1;
oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START);
dev_dbg(&i2c->adap.dev, "ERR: AL\n");
goto out;
}
if ((i2c->state == STATE_START) || (i2c->state == STATE_WRITE)) {
i2c->state =
(msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE;
if (stat & OCI2C_STAT_NACK) {
dev_dbg(&i2c->adap.dev, "ERR: NACK\n");
// printk(KERN_INFO "ERR: NACK\n");
i2c->state = STATE_ERROR;
if(!(msg->flags & I2C_M_RD))
i2c->nack_retry = 1;
oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
goto out;
}
} else {
msg->buf[i2c->pos++] = oc_getreg(i2c, OCI2C_DATA);
}
/* end of msg? */
if (i2c->pos == msg->len) {
i2c->nmsgs--;
i2c->msg++;
i2c->pos = 0;
msg = i2c->msg;
if (i2c->nmsgs) { /* end? */
/* send start? */
if (!(msg->flags & I2C_M_NOSTART)) {
u8 addr = i2c_8bit_addr_from_msg(msg);
i2c->state = STATE_START;
oc_setreg(i2c, OCI2C_DATA, addr);
oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START);
goto out;
}
i2c->state = (msg->flags & I2C_M_RD)
? STATE_READ : STATE_WRITE;
} else {
i2c->state = STATE_DONE;
oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
goto out;
}
}
if (i2c->state == STATE_READ) {
oc_setreg(i2c, OCI2C_CMD, i2c->pos == (msg->len-1) ?
OCI2C_CMD_READ_NACK : OCI2C_CMD_READ_ACK);
} else {
oc_setreg(i2c, OCI2C_DATA, msg->buf[i2c->pos++]);
oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_WRITE);
}
out:
spin_unlock_irqrestore(&i2c->process_lock, flags);
}
static irqreturn_t ocores_isr(int irq, void *dev_id)
{
struct ocores_i2c *i2c = dev_id;
u8 stat = oc_getreg(i2c, OCI2C_STATUS);
dev_dbg(&i2c->adap.dev, "STATUS: 0x%x\n", stat);
// printk(KERN_INFO "STATUS: 0x%x\n", stat);
if (!(stat & OCI2C_STAT_IF))
return IRQ_NONE;
ocores_process(i2c, stat);
return IRQ_HANDLED;
}
/**
* Process timeout event
* @i2c: ocores I2C device instance
*/
static void ocores_process_timeout(struct ocores_i2c *i2c)
{
unsigned long flags;
spin_lock_irqsave(&i2c->process_lock, flags);
i2c->state = STATE_ERROR;
oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
spin_unlock_irqrestore(&i2c->process_lock, flags);
}
/**
* Wait until something change in a given register
* @i2c: ocores I2C device instance
* @reg: register to query
* @mask: bitmask to apply on register value
* @val: expected result
* @timeout: timeout in jiffies
*
* Timeout is necessary to avoid to stay here forever when the chip
* does not answer correctly.
*
* Return: 0 on success, -ETIMEDOUT on timeout
*/
static int ocores_wait(struct ocores_i2c *i2c,
int reg, u8 mask, u8 val,
const unsigned long timeout)
{
unsigned long j;
j = jiffies + timeout;
while (1) {
u8 status = oc_getreg(i2c, reg);
if ((status & mask) == val)
break;
if (time_after(jiffies, j))
return -ETIMEDOUT;
cpu_relax();
cond_resched();
}
return 0;
}
/**
* Wait until is possible to process some data
* @i2c: ocores I2C device instance
*
* Used when the device is in polling mode (interrupts disabled).
*
* Return: 0 on success, -ETIMEDOUT on timeout
*/
static int ocores_poll_wait(struct ocores_i2c *i2c)
{
u8 mask;
int err;
if (i2c->state == STATE_DONE || i2c->state == STATE_ERROR) {
/* transfer is over */
mask = OCI2C_STAT_BUSY;
} else {
/* on going transfer */
mask = OCI2C_STAT_TIP;
/*
* We wait for the data to be transferred (8bit),
* then we start polling on the ACK/NACK bit
*/
udelay((8 * 1000) / i2c->bus_clock_khz);
}
dev_dbg(&i2c->adap.dev, "Wait for: 0x%x\n", mask);
// printk(KERN_INFO "Wait for: 0x%x\n", mask);
/*
* once we are here we expect to get the expected result immediately
* so if after 1ms we timeout then something is broken.
*/
err = ocores_wait(i2c, OCI2C_STATUS, mask, 0, msecs_to_jiffies(30));
if (err)
dev_warn(i2c->adap.dev.parent,
"%s: STATUS timeout, bit 0x%x did not clear in 1ms\n",
__func__, mask);
return err;
}
/**
* It handles an IRQ-less transfer
* @i2c: ocores I2C device instance
*
* Even if IRQ are disabled, the I2C OpenCore IP behavior is exactly the same
* (only that IRQ are not produced). This means that we can re-use entirely
* ocores_isr(), we just add our polling code around it.
*
* It can run in atomic context
*/
static void ocores_process_polling(struct ocores_i2c *i2c)
{
while (1) {
irqreturn_t ret;
int err;
err = ocores_poll_wait(i2c);
if (err) {
i2c->state = STATE_ERROR;
break; /* timeout */
}
ret = ocores_isr(-1, i2c);
if (ret == IRQ_NONE)
break; /* all messages have been transferred */
}
}
static int ocores_xfer_core(struct ocores_i2c *i2c,
struct i2c_msg *msgs, int num,
bool polling)
{
int ret;
u8 ctrl;
ctrl = oc_getreg(i2c, OCI2C_CONTROL);
if (polling)
oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~OCI2C_CTRL_IEN);
else
oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN);
i2c->msg = msgs;
i2c->pos = 0;
i2c->nmsgs = num;
i2c->state = STATE_START;
dev_dbg(&i2c->adap.dev, "STATE: %d\n", i2c->state);
// printk(KERN_INFO "STATE: %d\n", i2c->state);
oc_setreg(i2c, OCI2C_DATA, i2c_8bit_addr_from_msg(i2c->msg));
oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START);
if (polling) {
ocores_process_polling(i2c);
} else {
ret = wait_event_timeout(i2c->wait,
(i2c->state == STATE_ERROR) ||
(i2c->state == STATE_DONE), HZ);
if (ret == 0) {
ocores_process_timeout(i2c);
return -ETIMEDOUT;
}
}
return (i2c->state == STATE_DONE) ? num : -EIO;
}
static int ocores_xfer_polling(struct i2c_adapter *adap,
struct i2c_msg *msgs, int num)
{
return ocores_xfer_core(i2c_get_adapdata(adap), msgs, num, true);
}
static int ocores_xfer(struct i2c_adapter *adap,
struct i2c_msg *msgs, int num)
{
int ret;
int retry=0;
int max_retry = 0;
struct ocores_i2c *i2c = i2c_get_adapdata(adap);
i2c->nack_retry = 0;
if (i2c->flags & OCORES_FLAG_POLL)
{
//return ocores_xfer_polling(adap, msgs, num);
ret = ocores_xfer_polling(adap, msgs, num);
// Fix i2cdetect issue
if(num == 1)
max_retry = 5;
else
max_retry = 5;
while((i2c->nack_retry == 1)&&(retry < max_retry))
{
retry++;
i2c->nack_retry = 0;
ret = ocores_xfer_polling(adap, msgs, num);
// printk("nack retry polling = %d\n",retry);
}
// if(i2c->nack_retry!=0){
// printk("nack retry = %d, ret=%d\n",retry, ret);
// }
i2c->nack_retry = 0;
return ret;
}
return ocores_xfer_core(i2c, msgs, num, false);
}
static int ocores_init(struct device *dev, struct ocores_i2c *i2c)
{
int prescale;
int diff;
u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
/* make sure the device is disabled */
ctrl &= ~(OCI2C_CTRL_EN | OCI2C_CTRL_IEN);
oc_setreg(i2c, OCI2C_CONTROL, ctrl);
prescale = (i2c->ip_clock_khz / (5 * i2c->bus_clock_khz)) - 1;
prescale = clamp(prescale, 0, 0xffff);
dev_info(dev, "Prescale: %d\n", prescale);
diff = i2c->ip_clock_khz / (5 * (prescale + 1)) - i2c->bus_clock_khz;
if (abs(diff) > i2c->bus_clock_khz / 10) {
dev_err(dev,
"Unsupported clock settings: core: %d KHz, bus: %d KHz\n",
i2c->ip_clock_khz, i2c->bus_clock_khz);
return -EINVAL;
}
oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff);
oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8);
/* Init the device */
oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_EN);
return 0;
}
static u32 ocores_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static const struct i2c_algorithm ocores_algorithm = {
.master_xfer = ocores_xfer,
.functionality = ocores_func,
};
static const struct i2c_adapter ocores_adapter = {
.owner = THIS_MODULE,
.name = "i2c-goodcores",
.class = I2C_CLASS_DEPRECATED,
.algo = &ocores_algorithm,
};
static const struct of_device_id ocores_i2c_match[] = {
{
.compatible = "opencores,i2c-ocores",
.data = (void *)TYPE_OCORES,
},
{
.compatible = "aeroflexgaisler,i2cmst",
.data = (void *)TYPE_GRLIB,
},
{},
};
MODULE_DEVICE_TABLE(of, ocores_i2c_match);
#ifdef CONFIG_OF
/*
* Read and write functions for the GRLIB port of the controller. Registers are
* 32-bit big endian and the PRELOW and PREHIGH registers are merged into one
* register. The subsequent registers have their offsets decreased accordingly.
*/
static u8 oc_getreg_grlib(struct ocores_i2c *i2c, int reg)
{
u32 rd;
int rreg = reg;
if (reg != OCI2C_PRELOW)
rreg--;
rd = ioread32be(i2c->base + (rreg << i2c->reg_shift));
if (reg == OCI2C_PREHIGH)
return (u8)(rd >> 8);
else
return (u8)rd;
}
static void oc_setreg_grlib(struct ocores_i2c *i2c, int reg, u8 value)
{
u32 curr, wr;
int rreg = reg;
if (reg != OCI2C_PRELOW)
rreg--;
if (reg == OCI2C_PRELOW || reg == OCI2C_PREHIGH) {
curr = ioread32be(i2c->base + (rreg << i2c->reg_shift));
if (reg == OCI2C_PRELOW)
wr = (curr & 0xff00) | value;
else
wr = (((u32)value) << 8) | (curr & 0xff);
} else {
wr = value;
}
iowrite32be(wr, i2c->base + (rreg << i2c->reg_shift));
}
static int ocores_i2c_of_probe(struct platform_device *pdev,
struct ocores_i2c *i2c)
{
struct device_node *np = pdev->dev.of_node;
const struct of_device_id *match;
u32 val;
u32 clock_frequency;
bool clock_frequency_present;
if (of_property_read_u32(np, "reg-shift", &i2c->reg_shift)) {
/* no 'reg-shift', check for deprecated 'regstep' */
if (!of_property_read_u32(np, "regstep", &val)) {
if (!is_power_of_2(val)) {
dev_err(&pdev->dev, "invalid regstep %d\n",
val);
return -EINVAL;
}
i2c->reg_shift = ilog2(val);
dev_warn(&pdev->dev,
"regstep property deprecated, use reg-shift\n");
}
}
clock_frequency_present = !of_property_read_u32(np, "clock-frequency",
&clock_frequency);
i2c->bus_clock_khz = 100;
i2c->clk = devm_clk_get(&pdev->dev, NULL);
if (!IS_ERR(i2c->clk)) {
int ret = clk_prepare_enable(i2c->clk);
if (ret) {
dev_err(&pdev->dev,
"clk_prepare_enable failed: %d\n", ret);
return ret;
}
i2c->ip_clock_khz = clk_get_rate(i2c->clk) / 1000;
if (clock_frequency_present)
i2c->bus_clock_khz = clock_frequency / 1000;
}
if (i2c->ip_clock_khz == 0) {
if (of_property_read_u32(np, "opencores,ip-clock-frequency",
&val)) {
if (!clock_frequency_present) {
dev_err(&pdev->dev,
"Missing required parameter 'opencores,ip-clock-frequency'\n");
clk_disable_unprepare(i2c->clk);
return -ENODEV;
}
i2c->ip_clock_khz = clock_frequency / 1000;
dev_warn(&pdev->dev,
"Deprecated usage of the 'clock-frequency' property, please update to 'opencores,ip-clock-frequency'\n");
} else {
i2c->ip_clock_khz = val / 1000;
if (clock_frequency_present)
i2c->bus_clock_khz = clock_frequency / 1000;
}
}
of_property_read_u32(pdev->dev.of_node, "reg-io-width",
&i2c->reg_io_width);
match = of_match_node(ocores_i2c_match, pdev->dev.of_node);
if (match && (long)match->data == TYPE_GRLIB) {
dev_dbg(&pdev->dev, "GRLIB variant of i2c-ocores\n");
// printk(KERN_INFO "GRLIB variant of i2c-ocores\n");
i2c->setreg = oc_setreg_grlib;
i2c->getreg = oc_getreg_grlib;
}
return 0;
}
#else
#define ocores_i2c_of_probe(pdev, i2c) -ENODEV
#endif
static int ocores_i2c_probe(struct platform_device *pdev)
{
struct ocores_i2c *i2c;
struct ocores_i2c_platform_data *pdata;
struct resource *res;
int irq;
int ret;
int i;
i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
if (!i2c)
return -ENOMEM;
spin_lock_init(&i2c->process_lock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res) {
i2c->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(i2c->base))
return PTR_ERR(i2c->base);
} else {
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!res)
return -EINVAL;
i2c->iobase = res->start;
if (!devm_request_region(&pdev->dev, res->start,
resource_size(res),
pdev->name)) {
dev_err(&pdev->dev, "Can't get I/O resource.\n");
return -EBUSY;
}
i2c->setreg = oc_setreg_io_8;
i2c->getreg = oc_getreg_io_8;
}
pdata = dev_get_platdata(&pdev->dev);
if (pdata) {
i2c->reg_shift = pdata->reg_shift;
i2c->reg_io_width = pdata->reg_io_width;
i2c->ip_clock_khz = pdata->clock_khz;
if (pdata->bus_khz)
i2c->bus_clock_khz = pdata->bus_khz;
else
i2c->bus_clock_khz = 100;
} else {
ret = ocores_i2c_of_probe(pdev, i2c);
if (ret)
return ret;
}
if (i2c->reg_io_width == 0)
i2c->reg_io_width = 1; /* Set to default value */
if (!i2c->setreg || !i2c->getreg) {
bool be = pdata ? pdata->big_endian :
of_device_is_big_endian(pdev->dev.of_node);
switch (i2c->reg_io_width) {
case 1:
i2c->setreg = oc_setreg_8;
i2c->getreg = oc_getreg_8;
break;
case 2:
i2c->setreg = be ? oc_setreg_16be : oc_setreg_16;
i2c->getreg = be ? oc_getreg_16be : oc_getreg_16;
break;
case 4:
i2c->setreg = be ? oc_setreg_32be : oc_setreg_32;
i2c->getreg = be ? oc_getreg_32be : oc_getreg_32;
break;
default:
dev_err(&pdev->dev, "Unsupported I/O width (%d)\n",
i2c->reg_io_width);
ret = -EINVAL;
goto err_clk;
}
}
init_waitqueue_head(&i2c->wait);
irq = platform_get_irq(pdev, 0);
if (irq == -ENXIO) {
i2c->flags |= OCORES_FLAG_POLL;
} else {
if (irq < 0)
return irq;
}
if (!(i2c->flags & OCORES_FLAG_POLL)) {
ret = devm_request_irq(&pdev->dev, irq, ocores_isr, 0,
pdev->name, i2c);
if (ret) {
dev_err(&pdev->dev, "Cannot claim IRQ\n");
goto err_clk;
}
}
ret = ocores_init(&pdev->dev, i2c);
if (ret)
goto err_clk;
/* hook up driver to tree */
platform_set_drvdata(pdev, i2c);
i2c->adap = ocores_adapter;
i2c_set_adapdata(&i2c->adap, i2c);
i2c->adap.dev.parent = &pdev->dev;
i2c->adap.dev.of_node = pdev->dev.of_node;
/* add i2c adapter to i2c tree */
ret = i2c_add_adapter(&i2c->adap);
if (ret)
goto err_clk;
/* add in known devices to the bus */
if (pdata) {
for (i = 0; i < pdata->num_devices; i++)
i2c_new_device(&i2c->adap, pdata->devices + i);
}
return 0;
err_clk:
clk_disable_unprepare(i2c->clk);
return ret;
}
static int ocores_i2c_remove(struct platform_device *pdev)
{
struct ocores_i2c *i2c = platform_get_drvdata(pdev);
u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
/* disable i2c logic */
ctrl &= ~(OCI2C_CTRL_EN | OCI2C_CTRL_IEN);
oc_setreg(i2c, OCI2C_CONTROL, ctrl);
/* remove adapter & data */
i2c_del_adapter(&i2c->adap);
if (!IS_ERR(i2c->clk))
clk_disable_unprepare(i2c->clk);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int ocores_i2c_suspend(struct device *dev)
{
struct ocores_i2c *i2c = dev_get_drvdata(dev);
u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
/* make sure the device is disabled */
ctrl &= ~(OCI2C_CTRL_EN | OCI2C_CTRL_IEN);
oc_setreg(i2c, OCI2C_CONTROL, ctrl);
if (!IS_ERR(i2c->clk))
clk_disable_unprepare(i2c->clk);
return 0;
}
static int ocores_i2c_resume(struct device *dev)
{
struct ocores_i2c *i2c = dev_get_drvdata(dev);
if (!IS_ERR(i2c->clk)) {
unsigned long rate;
int ret = clk_prepare_enable(i2c->clk);
if (ret) {
dev_err(dev,
"clk_prepare_enable failed: %d\n", ret);
return ret;
}
rate = clk_get_rate(i2c->clk) / 1000;
if (rate)
i2c->ip_clock_khz = rate;
}
return ocores_init(dev, i2c);
}
static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume);
#define OCORES_I2C_PM (&ocores_i2c_pm)
#else
#define OCORES_I2C_PM NULL
#endif
static struct platform_driver ocores_i2c_driver = {
.probe = ocores_i2c_probe,
.remove = ocores_i2c_remove,
.driver = {
.name = "goodcores-i2c",
.of_match_table = ocores_i2c_match,
.pm = OCORES_I2C_PM,
},
};
module_platform_driver(ocores_i2c_driver);
MODULE_AUTHOR("Peter Korsgaard <peter@korsgaard.com>");
MODULE_DESCRIPTION("OpenCores I2C bus driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:ocores-i2c");

View File

@ -0,0 +1,22 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cls-i2c-ocores.h - definitions for the i2c-ocores interface
*
* Peter Korsgaard <peter@korsgaard.com>
*/
#ifndef _LINUX_I2C_OCORES_H
#define _LINUX_I2C_OCORES_H
struct ocores_i2c_platform_data {
u32 reg_shift; /* register offset shift value */
u32 reg_io_width; /* register io read/write width */
u32 clock_khz; /* input clock in kHz */
u32 bus_khz; /* bus clock in kHz */
bool big_endian; /* registers are big endian */
u8 num_devices; /* number of devices in the devices list */
struct i2c_board_info const *devices; /* devices connected to the bus */
};
#endif /* _LINUX_I2C_OCORES_H */

View File

@ -0,0 +1,447 @@
/*
* cls_switchboard.c - PCI device driver for Silverstone Switch board FPGA.
*
* Author: Pradchaya Phucharoen
*
* Copyright (C) 2019 Celestica Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*
*/
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/stddef.h>
#include <linux/acpi.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/i2c/pca954x.h>
#include "cls-i2c-ocore.h"
#define MOD_VERSION "2.1.0-1"
#define DRV_NAME "cls-switchboard"
#define I2C_MUX_CHANNEL(_ch, _adap_id, _deselect) \
[_ch] = { .adap_id = _adap_id, .deselect_on_exit = _deselect }
#define FPGA_PCIE_DEVICE_ID 0x7021
#define MMIO_BAR 0
#define I2C_BUS_OFS 9
/* I2C ocore configurations */
#define OCORE_REGSHIFT 2
#define OCORE_IP_CLK_khz 62500 //TODO: check fpga's `wb_clk_i`
#define OCORE_BUS_CLK_khz 100
#define OCORE_REG_IO_WIDTH 1
/* Optical port xcvr configuration */
#define XCVR_REG_SHIFT 2
#define XCVR_NUM_PORT 34
#define XCVR_PORT_REG_SIZE 0x10
/* i2c_bus_config - an i2c-core resource and platform data
* @id - I2C bus device ID, for identification.
* @res - resources for an i2c-core device.
* @num_res - size of the resources.
* @pdata - a platform data of an i2c-core device.
*/
struct i2c_bus_config {
int id;
struct resource *res;
ssize_t num_res;
struct ocores_i2c_platform_data pdata;
};
/* switchbrd_priv - switchboard private data */
struct switchbrd_priv {
unsigned long base;
int num_i2c_bus;
struct platform_device **i2cbuses_pdev;
struct platform_device *regio_pdev;
struct platform_device *spiflash_pdev;
//struct platform_device *xcvr_pdev;
};
// NOTE: Silverstone i2c channel mapping is very wierd!!!
/* PCA9548 channel config on MASTER BUS 3 */
static struct pca954x_platform_mode i2c_mux_70_modes[] = {
I2C_MUX_CHANNEL(5, I2C_BUS_OFS + 23, true),
I2C_MUX_CHANNEL(6, I2C_BUS_OFS + 26, true),
I2C_MUX_CHANNEL(0, I2C_BUS_OFS + 27, true),
I2C_MUX_CHANNEL(7, I2C_BUS_OFS + 28, true),
I2C_MUX_CHANNEL(2, I2C_BUS_OFS + 29, true),
I2C_MUX_CHANNEL(4, I2C_BUS_OFS + 30, true),
I2C_MUX_CHANNEL(3, I2C_BUS_OFS + 31, true),
I2C_MUX_CHANNEL(1, I2C_BUS_OFS + 32, true),
};
static struct pca954x_platform_mode i2c_mux_71_modes[] = {
I2C_MUX_CHANNEL(2, I2C_BUS_OFS + 1, true),
I2C_MUX_CHANNEL(3, I2C_BUS_OFS + 2, true),
I2C_MUX_CHANNEL(0, I2C_BUS_OFS + 3, true),
I2C_MUX_CHANNEL(1, I2C_BUS_OFS + 4, true),
I2C_MUX_CHANNEL(6, I2C_BUS_OFS + 5, true),
I2C_MUX_CHANNEL(5, I2C_BUS_OFS + 6, true),
I2C_MUX_CHANNEL(7, I2C_BUS_OFS + 15, true),
I2C_MUX_CHANNEL(4, I2C_BUS_OFS + 8, true),
};
static struct pca954x_platform_mode i2c_mux_72_modes[] = {
I2C_MUX_CHANNEL(1, I2C_BUS_OFS + 17, true),
I2C_MUX_CHANNEL(7, I2C_BUS_OFS + 18, true),
I2C_MUX_CHANNEL(4, I2C_BUS_OFS + 19, true),
I2C_MUX_CHANNEL(0, I2C_BUS_OFS + 20, true),
I2C_MUX_CHANNEL(5, I2C_BUS_OFS + 21, true),
I2C_MUX_CHANNEL(2, I2C_BUS_OFS + 22, true),
I2C_MUX_CHANNEL(3, I2C_BUS_OFS + 25, true),
I2C_MUX_CHANNEL(6, I2C_BUS_OFS + 24, true),
};
static struct pca954x_platform_mode i2c_mux_73_modes[] = {
I2C_MUX_CHANNEL(4, I2C_BUS_OFS + 9, true),
I2C_MUX_CHANNEL(3, I2C_BUS_OFS + 10, true),
I2C_MUX_CHANNEL(6, I2C_BUS_OFS + 11, true),
I2C_MUX_CHANNEL(2, I2C_BUS_OFS + 12, true),
I2C_MUX_CHANNEL(1, I2C_BUS_OFS + 13, true),
I2C_MUX_CHANNEL(5, I2C_BUS_OFS + 14, true),
I2C_MUX_CHANNEL(7, I2C_BUS_OFS + 7, true),
I2C_MUX_CHANNEL(0, I2C_BUS_OFS + 16, true),
};
static struct pca954x_platform_data om_muxes[] = {
{
.modes = i2c_mux_70_modes,
.num_modes = ARRAY_SIZE(i2c_mux_70_modes),
},
{
.modes = i2c_mux_71_modes,
.num_modes = ARRAY_SIZE(i2c_mux_71_modes),
},
{
.modes = i2c_mux_72_modes,
.num_modes = ARRAY_SIZE(i2c_mux_72_modes),
},
{
.modes = i2c_mux_73_modes,
.num_modes = ARRAY_SIZE(i2c_mux_73_modes),
},
};
/* Optical Module bus 3 i2c muxes info */
static struct i2c_board_info i2c_info_3[] = {
{
I2C_BOARD_INFO("pca9548", 0x70),
.platform_data = &om_muxes[0],
},
{
I2C_BOARD_INFO("pca9548", 0x71),
.platform_data = &om_muxes[1],
},
{
I2C_BOARD_INFO("pca9548", 0x72),
.platform_data = &om_muxes[2],
},
{
I2C_BOARD_INFO("pca9548", 0x73),
.platform_data = &om_muxes[3],
},
};
/* RESOURCE SEPERATES BY FUNCTION */
/* Resource IOMEM for i2c bus 1 */
static struct resource cls_i2c_res_1[] = {
{
.start = 0x800, .end = 0x81F,
.flags = IORESOURCE_MEM,},
};
/* Resource IOMEM for i2c bus 2 */
static struct resource cls_i2c_res_2[] = {
{
.start = 0x820, .end = 0x83F,
.flags = IORESOURCE_MEM,},
};
/* Resource IOMEM for i2c bus 3 */
static struct resource cls_i2c_res_3[] = {
{
.start = 0x840, .end = 0x85F,
.flags = IORESOURCE_MEM,},
};
/* Resource IOMEM for i2c bus 4 */
static struct resource cls_i2c_res_4[] = {
{
.start = 0x860, .end = 0x87F,
.flags = IORESOURCE_MEM,},
};
/* Resource IOMEM for i2c bus 5 */
static struct resource cls_i2c_res_5[] = {
{
.start = 0x880, .end = 0x89F,
.flags = IORESOURCE_MEM,},
};
/* Resource IOMEM for reg access */
static struct resource reg_io_res[] = {
{
.start = 0x00, .end = 0xFF,
.flags = IORESOURCE_MEM,},
};
/* Resource IOMEM for spi flash firmware upgrade */
static struct resource spi_flash_res[] = {
{
.start = 0x1200, .end = 0x121F,
.flags = IORESOURCE_MEM,},
};
/* Resource IOMEM for front panel XCVR */
// static struct resource xcvr_res[] = {
// {
// .start = 0x4000, .end = 0x421F,
// .flags = IORESOURCE_MEM,},
// };
static struct i2c_bus_config i2c_bus_configs[] = {
{
.id = 1,
.res = cls_i2c_res_1,
.num_res = ARRAY_SIZE(cls_i2c_res_1),
.pdata = {
.reg_shift = OCORE_REGSHIFT,
.reg_io_width = OCORE_REG_IO_WIDTH,
.clock_khz = OCORE_IP_CLK_khz,
.bus_khz = OCORE_BUS_CLK_khz,
.big_endian = false,
.num_devices = 0,
.devices = NULL,
},
},
{
.id = 2,
.res = cls_i2c_res_2,
.num_res = ARRAY_SIZE(cls_i2c_res_2),
.pdata = {
.reg_shift = OCORE_REGSHIFT,
.reg_io_width = OCORE_REG_IO_WIDTH,
.clock_khz = OCORE_IP_CLK_khz,
.bus_khz = OCORE_BUS_CLK_khz,
.big_endian = false,
.num_devices = 0,
.devices = NULL,
},
},
{
.id = 3,
.res = cls_i2c_res_3,
.num_res = ARRAY_SIZE(cls_i2c_res_3),
.pdata = {
.reg_shift = OCORE_REGSHIFT,
.reg_io_width = OCORE_REG_IO_WIDTH,
.clock_khz = OCORE_IP_CLK_khz,
.bus_khz = OCORE_BUS_CLK_khz,
.big_endian = false,
.num_devices = ARRAY_SIZE(i2c_info_3),
.devices = i2c_info_3,
},
},
{
.id = 4,
.res = cls_i2c_res_4,
.num_res = ARRAY_SIZE(cls_i2c_res_4),
.pdata = {
.reg_shift = OCORE_REGSHIFT,
.reg_io_width = OCORE_REG_IO_WIDTH,
.clock_khz = OCORE_IP_CLK_khz,
.bus_khz = OCORE_BUS_CLK_khz,
.big_endian = false,
.num_devices = 0,
.devices = NULL,
},
},
{
.id = 5,
.res = cls_i2c_res_5,
.num_res = ARRAY_SIZE(cls_i2c_res_5),
.pdata = {
.reg_shift = OCORE_REGSHIFT,
.reg_io_width = OCORE_REG_IO_WIDTH,
.clock_khz = OCORE_IP_CLK_khz,
.bus_khz = OCORE_BUS_CLK_khz,
.big_endian = false,
.num_devices = 0,
.devices = NULL,
},
},
};
// TODO: Add a platform configuration struct, and use probe as a factory,
// so xcvr, fwupgrade device can configured as options.
static int cls_fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct switchbrd_priv *priv;
struct platform_device **i2cbuses_pdev;
struct platform_device *regio_pdev;
struct platform_device *spiflash_pdev;
//struct platform_device *xcvr_pdev;
unsigned long rstart;
int num_i2c_bus, i;
int err;
err = pci_enable_device(dev);
if (err){
dev_err(&dev->dev, "Failed to enable PCI device\n");
goto err_exit;
}
/* Check for valid MMIO address */
rstart = pci_resource_start(dev, MMIO_BAR);
if (!rstart) {
dev_err(&dev->dev, "Switchboard base address uninitialized, "
"check FPGA\n");
err = -ENODEV;
goto err_disable_device;
}
dev_dbg(&dev->dev, "BAR%d res: 0x%lx-0x%llx\n", MMIO_BAR,
rstart, pci_resource_end(dev, MMIO_BAR));
priv = devm_kzalloc(&dev->dev,
sizeof(struct switchbrd_priv), GFP_KERNEL);
if (!priv){
err = -ENOMEM;
goto err_disable_device;
}
pci_set_drvdata(dev, priv);
num_i2c_bus = ARRAY_SIZE(i2c_bus_configs);
i2cbuses_pdev = devm_kzalloc(
&dev->dev,
num_i2c_bus * sizeof(struct platform_device*),
GFP_KERNEL);
reg_io_res[0].start += rstart;
reg_io_res[0].end += rstart;
spi_flash_res[0].start += rstart;
spi_flash_res[0].end += rstart;
regio_pdev = platform_device_register_resndata(
&dev->dev, "cls-swbrd-io",
-1,
reg_io_res, ARRAY_SIZE(reg_io_res),
NULL, 0);
if (IS_ERR(regio_pdev)) {
dev_err(&dev->dev, "Failed to register cls-swbrd-io\n");
err = PTR_ERR(regio_pdev);
goto err_disable_device;
}
spiflash_pdev = platform_device_register_resndata(
&dev->dev, "cls-swbrd-fwug",
-1,
spi_flash_res, ARRAY_SIZE(spi_flash_res),
NULL, 0);
if (IS_ERR(spiflash_pdev)) {
dev_err(&dev->dev, "Failed to register firmware upgrade node\n");
err = PTR_ERR(spiflash_pdev);
goto err_unregister_regio;
}
for(i = 0; i < num_i2c_bus; i++){
i2c_bus_configs[i].res[0].start += rstart;
i2c_bus_configs[i].res[0].end += rstart;
dev_dbg(&dev->dev, "i2c-bus.%d: 0x%llx - 0x%llx\n",
i2c_bus_configs[i].id,
i2c_bus_configs[i].res[0].start,
i2c_bus_configs[i].res[0].end);
i2cbuses_pdev[i] = platform_device_register_resndata(
&dev->dev, "goodcores-i2c",
i2c_bus_configs[i].id,
i2c_bus_configs[i].res,
i2c_bus_configs[i].num_res,
&i2c_bus_configs[i].pdata,
sizeof(i2c_bus_configs[i].pdata));
if (IS_ERR(i2cbuses_pdev[i])) {
dev_err(&dev->dev, "Failed to register goodcores-i2c.%d\n",
i2c_bus_configs[i].id);
err = PTR_ERR(i2cbuses_pdev[i]);
goto err_unregister_ocore;
}
}
priv->base = rstart;
priv->num_i2c_bus = num_i2c_bus;
priv->i2cbuses_pdev = i2cbuses_pdev;
priv->regio_pdev = regio_pdev;
priv->spiflash_pdev = spiflash_pdev;
return 0;
err_unregister_ocore:
for(i = 0; i < num_i2c_bus; i++){
if(priv->i2cbuses_pdev[i]){
platform_device_unregister(priv->i2cbuses_pdev[i]);
}
}
// err_unregister_spiflash:
// platform_device_unregister(spiflash_pdev);
err_unregister_regio:
platform_device_unregister(regio_pdev);
err_disable_device:
pci_disable_device(dev);
err_exit:
return err;
}
static void cls_fpga_remove(struct pci_dev *dev)
{
int i;
struct switchbrd_priv *priv = pci_get_drvdata(dev);
for(i = 0; i < priv->num_i2c_bus; i++){
if(priv->i2cbuses_pdev[i])
platform_device_unregister(priv->i2cbuses_pdev[i]);
}
platform_device_unregister(priv->spiflash_pdev);
platform_device_unregister(priv->regio_pdev);
pci_disable_device(dev);
return;
};
static const struct pci_device_id pci_clsswbrd[] = {
{ PCI_VDEVICE(XILINX, FPGA_PCIE_DEVICE_ID) },
{0, }
};
MODULE_DEVICE_TABLE(pci, pci_clsswbrd);
static struct pci_driver clsswbrd_pci_driver = {
.name = DRV_NAME,
.id_table = pci_clsswbrd,
.probe = cls_fpga_probe,
.remove = cls_fpga_remove,
};
module_pci_driver(clsswbrd_pci_driver);
MODULE_AUTHOR("Pradchaya P.<pphuchar@celestica.com>");
MODULE_DESCRIPTION("Celestica Silverstone switchboard driver");
MODULE_VERSION(MOD_VERSION);
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,142 @@
/*
* mc24lc64t.c - driver for Microchip 24LC64T
*
* Copyright (C) 2017 Celestica Corp.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
struct mc24lc64t_data {
struct i2c_client *fake_client;
struct mutex update_lock;
};
static ssize_t mc24lc64t_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct i2c_client *client = kobj_to_i2c_client(kobj);
struct mc24lc64t_data *drvdata = i2c_get_clientdata(client);
unsigned long timeout, read_time, i = 0;
int status;
mutex_lock(&drvdata->update_lock);
if (i2c_smbus_write_byte_data(client, off>>8, off))
{
status = -EIO;
goto exit;
}
msleep(1);
begin:
if (i < count)
{
timeout = jiffies + msecs_to_jiffies(25); /* 25 mS timeout*/
do {
read_time = jiffies;
status = i2c_smbus_read_byte(client);
if (status >= 0)
{
buf[i++] = status;
goto begin;
}
} while (time_before(read_time, timeout));
status = -ETIMEDOUT;
goto exit;
}
status = count;
exit:
mutex_unlock(&drvdata->update_lock);
return status;
}
static struct bin_attribute mc24lc64t_bit_attr = {
.attr = {
.name = "eeprom",
.mode = S_IRUGO,
},
.size = 65536,
.read = mc24lc64t_read,
};
static int mc24lc64t_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct i2c_adapter *adapter = client->adapter;
struct mc24lc64t_data *drvdata;
int err;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
| I2C_FUNC_SMBUS_READ_BYTE))
return -EPFNOSUPPORT;
if (!(drvdata = devm_kzalloc(&client->dev,
sizeof(struct mc24lc64t_data), GFP_KERNEL)))
return -ENOMEM;
drvdata->fake_client = i2c_new_dummy(client->adapter, client->addr + 1);
if (!drvdata->fake_client)
return -ENOMEM;
i2c_set_clientdata(client, drvdata);
mutex_init(&drvdata->update_lock);
err = sysfs_create_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr);
if (err)
i2c_unregister_device(drvdata->fake_client);
return err;
}
static int mc24lc64t_remove(struct i2c_client *client)
{
struct mc24lc64t_data *drvdata = i2c_get_clientdata(client);
i2c_unregister_device(drvdata->fake_client);
sysfs_remove_bin_file(&client->dev.kobj, &mc24lc64t_bit_attr);
return 0;
}
static const struct i2c_device_id mc24lc64t_id[] = {
{ "24lc64t", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, mc24lc64t_id);
static struct i2c_driver mc24lc64t_driver = {
.driver = {
.name = "mc24lc64t",
.owner = THIS_MODULE,
},
.probe = mc24lc64t_probe,
.remove = mc24lc64t_remove,
.id_table = mc24lc64t_id,
};
module_i2c_driver(mc24lc64t_driver);
MODULE_AUTHOR("Abhisit Sangjan <asang@celestica.com>");
MODULE_DESCRIPTION("Microchip 24LC64T Driver");
MODULE_LICENSE("GPL");

View File

@ -0,0 +1,17 @@
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
i2c-i801
i2c-isch
i2c-ismt
i2c-dev
i2c-mux
i2c-smbus
i2c-mux-gpio
i2c-mux-pca954x
ipmi_devintf
ipmi_si

View File

@ -0,0 +1,102 @@
#!/usr/bin/python
# Copyright (c) 2015 Dell Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
# LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS
# FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT.
#
# See the Apache Version 2.0 License for specific language governing
# permissions and limitations under the License.
import struct
import sys
import getopt
from os import *
from mmap import *
def usage():
''' This is the Usage Method '''
print '\t\t pcisysfs.py --get --offset <offset> --res <resource>'
print '\t\t pcisysfs.py --set --val <val> --offset <offset> --res <resource>'
sys.exit(1)
def pci_mem_read(mm,offset):
mm.seek(offset)
read_data_stream=mm.read(4)
print ""
reg_val=struct.unpack('I',read_data_stream)
print "reg_val read:%x"%reg_val
return reg_val
def pci_mem_write(mm,offset,data):
mm.seek(offset)
print "data to write:%x"%data
mm.write(struct.pack('I',data))
def pci_set_value(resource,val,offset):
fd=open(resource,O_RDWR)
mm=mmap(fd,0)
pci_mem_write(mm,offset,val)
def pci_get_value(resource,offset):
fd=open(resource,O_RDWR)
mm=mmap(fd,0)
pci_mem_read(mm,offset)
def main(argv):
''' The main function will read the user input from the
command line argument and process the request '''
opts = ''
val = ''
choice = ''
resource = ''
offset = ''
try:
opts, args = getopt.getopt(argv, "hgsv:" , \
["val=","res=","offset=","help", "get", "set"])
except getopt.GetoptError:
usage()
for opt,arg in opts:
if opt in ('-h','--help'):
choice = 'help'
elif opt in ('-g', '--get'):
choice = 'get'
elif opt in ('-s', '--set'):
choice = 'set'
elif opt == '--res':
resource = arg
elif opt == '--val':
val = int(arg,16)
elif opt == '--offset':
offset = int(arg,16)
if choice == 'set' and val != '' and offset !='' and resource !='':
pci_set_value(resource,val,offset)
elif choice == 'get' and offset != '' and resource !='':
pci_get_value(resource,offset)
else:
usage()
#Calling the main method
if __name__ == "__main__":
main(sys.argv[1:])

View File

@ -0,0 +1,198 @@
#!/usr/bin/python
# On Z9332F, the BaseBoard Management Controller is an
# autonomous subsystem provides monitoring and management
# facility independent of the host CPU. IPMI standard
# protocol is used with ipmitool to fetch sensor details.
# Current script support X00 board only. X01 support will
# be added soon. This provies support for the
# following objects:
# * Onboard temperature sensors
# * FAN trays
# * PSU
import os
import sys
import logging
import subprocess
import commands
Z9332F_MAX_FAN_TRAYS = 7
Z9332F_MAX_PSUS = 2
IPMI_SENSOR_DATA = "ipmitool sdr list"
IPMI_SENSOR_DUMP = "/tmp/sdr"
FAN_PRESENCE = "Fan{0}_Status"
PSU_PRESENCE = "PSU{0}_Status"
# Use this for older firmware
# PSU_PRESENCE="PSU{0}_prsnt"
IPMI_PSU1_DATA_DOCKER = "ipmitool raw 0x04 0x2d 0x2f | awk '{print substr($0,9,1)}'"
IPMI_PSU2_DATA_DOCKER = "ipmitool raw 0x04 0x2d 0x39 | awk '{print substr($0,9,1)}'"
ipmi_sdr_list = ""
# Dump sensor registers
def ipmi_sensor_dump():
status = 1
global ipmi_sdr_list
ipmi_cmd = IPMI_SENSOR_DATA
status, ipmi_sdr_list = commands.getstatusoutput(ipmi_cmd)
if status:
logging.error('Failed to execute:' + ipmi_sdr_list)
sys.exit(0)
# Fetch a BMC register
def get_pmc_register(reg_name):
output = None
for item in ipmi_sdr_list.split("\n"):
if reg_name in item:
output = item.strip()
if output is None:
print('\nFailed to fetch: ' + reg_name + ' sensor ')
sys.exit(0)
output = output.split('|')[1]
logging.basicConfig(level=logging.DEBUG)
return output
# Print the information for temperature sensors
def print_temperature_sensors():
print("\nOnboard Temperature Sensors:")
for x in (('TEMP_FAN_U52', 'Fan U52'),
('TEMP_FAN_U17', 'Fan U17'),
('TEMP_SW_U52', 'SW U52'),
('TEMP_SW_U16', 'SW U16'),
('TEMP_BB_U3', 'Baseboard U3'),
('TEMP_CPU', 'Near CPU'),
('TEMP_SW_Internal', 'SW interal'),
('PSU1_Temp1', 'PSU1 inlet'),
('PSU1_Temp2', 'PSU1 hotspot'),
('PSU2_Temp1', 'PSU2 inlet'),
('PSU2_Temp2', 'PSU2 hotspot'),
('SW_U04_Temp', 'SW U04'),
('SW_U14_Temp', 'SW U14'),
('SW_U4403_Temp', 'SW U4403')
):
print ' {0:32}{1}'.format(x[1] + ':', get_pmc_register(x[0]))
ipmi_sensor_dump()
print_temperature_sensors()
# Print the information for 1 Fan Tray
def print_fan_tray(tray):
Fan_Status = [' Normal', ' Abnormal']
Airflow_Direction = ['B2F', 'F2B']
print ' Fan Tray ' + str(tray) + ':'
print ' Fan1 Speed: ',\
get_pmc_register('Fan{}_Front'.format(tray))
print ' Fan2 Speed: ',\
get_pmc_register('Fan{}_Rear'.format(tray))
print ' Fan State: ',\
Fan_Status[int(get_pmc_register('Fan{}_Status'.format(tray)), 16)]
print('\nFan Trays:')
for tray in range(1, Z9332F_MAX_FAN_TRAYS + 1):
fan_presence = FAN_PRESENCE.format(tray)
if (get_pmc_register(fan_presence)):
print_fan_tray(tray)
else:
print '\n Fan Tray ' + str(tray + 1) + ': Not present'
def get_psu_presence(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
ret_status = 1
if index == 1:
status, ipmi_cmd_ret = commands.getstatusoutput(IPMI_PSU1_DATA_DOCKER)
elif index == 2:
ret_status, ipmi_cmd_ret = commands.getstatusoutput(IPMI_PSU2_DATA_DOCKER)
#if ret_status:
# print ipmi_cmd_ret
# logging.error('Failed to execute ipmitool')
# sys.exit(0)
psu_status = ipmi_cmd_ret
if psu_status == '1':
status = 1
return status
# Print the information for PSU1, PSU2
def print_psu(psu):
Psu_Type = ['Normal', 'Mismatch']
Psu_Input_Type = ['AC', 'DC']
PSU_STATUS_TYPE_BIT = 4
PSU_STATUS_INPUT_TYPE_BIT = 1
PSU_FAN_PRESENT_BIT = 2
PSU_FAN_STATUS_BIT = 1
PSU_FAN_AIR_FLOW_BIT = 0
Psu_Fan_Presence = ['Present', 'Absent']
Psu_Fan_Status = ['Normal', 'Abnormal']
Psu_Fan_Airflow = ['B2F', 'F2B']
# print ' Input: ', Psu_Input_Type[psu_input_type]
# print ' Type: ', Psu_Type[psu_type]
print ' PSU{}:'.format(psu)
print ' Inlet Temperature: ',\
get_pmc_register('PSU{}_Temp1'.format(psu))
print ' Hotspot Temperature: ',\
get_pmc_register('PSU{}_Temp2'.format(psu))
print ' FAN RPM: ',\
get_pmc_register('PSU{}_Fan'.format(psu))
# print ' FAN Status: ', Psu_Fan_Status[psu1_fan_status]
# PSU input & output monitors
print ' Input Voltage: ',\
get_pmc_register('PSU{}_VIn'.format(psu))
print ' Output Voltage: ',\
get_pmc_register('PSU{}_VOut'.format(psu))
print ' Input Power: ',\
get_pmc_register('PSU{}_PIn'.format(psu))
print ' Output Power: ',\
get_pmc_register('PSU{}_POut'.format(psu))
print ' Input Current: ',\
get_pmc_register('PSU{}_CIn'.format(psu))
print ' Output Current: ',\
get_pmc_register('PSU{}_COut'.format(psu))
print('\nPSUs:')
for psu in range(1, Z9332F_MAX_PSUS + 1):
#psu_presence = PSU_PRESENCE.format(psu)
if (get_psu_presence(psu)):
print_psu(psu)
else:
print '\n PSU ', psu, 'Not present'

View File

@ -0,0 +1,8 @@
#!/bin/bash
docker exec -i pmon sensors "$@"
docker exec -i pmon /usr/bin/platform_sensors.py "$@"
#To probe sensors not part of lm-sensors
#if [ -r /usr/local/bin/platform_sensors.py ]; then
# python /usr/local/bin/platform_sensors.py
#fi

View File

@ -0,0 +1,180 @@
#!/bin/bash
init_devnum() {
found=0
for devnum in 0; do
devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name`
# I801 adapter f000
if [[ $devname == 'SMBus I801 adapter at '* ]]; then
found=1
break
fi
done
[ $found -eq 0 ] && echo "cannot find I801" && exit 1
}
# Attach/Detach syseeprom on CPU board
sys_eeprom() {
case $1 in
"new_device") echo 24lc64t 0x56 > /sys/bus/i2c/devices/i2c-0/$1
;;
"delete_device") echo 0x56 > /sys/bus/i2c/devices/i2c-0/$1
;;
*) echo "z9332f_platform: sys_eeprom : invalid command !"
;;
esac
}
#Attach/Detach the MUX connecting all QSFPs
switch_board_qsfp_mux() {
case $1 in
"new_device")
for ((i=603;i<=607;i++));
do
echo "Attaching PCA9548 @ 0x74"
echo pca9548 0x74 > /sys/bus/i2c/devices/i2c-$i/$1
done
;;
"delete_device")
for ((i=603;i<=607;i++));
do
echo "Detaching PCA9548 @ 0x74"
echo 0x74 > /sys/bus/i2c/devices/i2c-$i/$1
done
;;
*) echo "z9332f_platform: switch_board_qsfp_mux: invalid command !"
;;
esac
sleep 2
}
#Attach/Detach 64 instances of EEPROM driver QSFP ports
#eeprom can dump data using below command
switch_board_qsfp() {
case $1 in
"new_device")
for ((i=10;i<=41;i++));
do
echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-$i/$1
done
;;
"delete_device")
for ((i=10;i<=41;i++));
do
echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1
done
;;
*) echo "z9332f_platform: switch_board_qsfp: invalid command !"
;;
esac
}
#Attach/Detach 2 instances of EEPROM driver SFP+ ports
#eeprom can dump data using below command
switch_board_sfp() {
case $1 in
"new_device")
for ((i=1;i<=2;i++));
do
echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-$i/$1
done
;;
"delete_device")
for ((i=1;i<=2;i++));
do
echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1
done
;;
*) echo "z9332f_platform: switch_board_qsfp: invalid command !"
;;
esac
}
#Modsel 64 ports to applicable QSFP type modules
#This enables the adapter to respond for i2c commands
switch_board_modsel() {
resource="/sys/bus/pci/devices/0000:09:00.0/resource0"
for ((i=1;i<=32;i++));
do
port_addr=$(( 16384 + ((i - 1) * 16)))
hex=$( printf "0x%x" $port_addr )
python /usr/bin/pcisysfs.py --set --offset $hex --val 0x10 --res $resource > /dev/null 2>&1
done
}
#This enables the led control for CPU and default states
switch_board_led_default() {
/usr/sbin/i2cset -y 5 0x0d 0x62 0xd0
}
# Readout firmware version of the system and
# store in /var/log/firmware_versions
platform_firmware_versions() {
FIRMWARE_VERSION_FILE=/var/log/firmware_versions
rm -rf ${FIRMWARE_VERSION_FILE}
echo "BIOS:`dmidecode -t bios | grep Version | awk -F":" '{print $2}'`" > $FIRMWARE_VERSION_FILE
# Get FPGA version
r=`/usr/bin/pcisysfs.py --get --offset 0x00 --res /sys/bus/pci/devices/0000\:09\:00.0/resource0 | sed '1d; s/.*\(....\)$/\1/; s/\(..\{1\}\)/\1./'`
r_min=$(echo $r | sed 's/.*\(..\)$/0x\1/')
r_maj=$(echo $r | sed 's/^\(..\).*/0x\1/')
echo "FPGA: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE
## Get BMC Firmware Revision
#r=`docker exec -it pmon ipmitool mc info | awk '/Firmware Revision/ { print $NF }'`
r=`cat /sys/class/ipmi/ipmi0/device/bmc/firmware_revision`
echo "BMC: $r" >> $FIRMWARE_VERSION_FILE
#BaseBoard CPLD 0x0d on i2c bus 5 ( physical FPGA I2C-5)
ver=`/usr/sbin/i2cget -y 5 0x0d 0x0`
echo "Baseboard CPLD: $((ver))" >> $FIRMWARE_VERSION_FILE
#Switch CPLD 1 0x30 on i2c bus 4 ( physical FPGA I2C-4)
ver=`/usr/sbin/i2cget -y 4 0x30 0x0`
echo "Switch CPLD 1: $((ver))" >> $FIRMWARE_VERSION_FILE
#Switch CPLD 1 0x30 on i2c bus 4 ( physical FPGA I2C-4)
ver=`/usr/sbin/i2cget -y 4 0x31 0x0`
echo "Switch CPLD 2: $((ver))" >> $FIRMWARE_VERSION_FILE
}
init_devnum
if [ "$1" == "init" ]; then
modprobe i2c-dev
modprobe i2c-mux-pca954x force_deselect_on_exit=1
modprobe ipmi_devintf
modprobe ipmi_si
modprobe cls-i2c-ocore
modprobe cls-switchboard
modprobe mc24lc64t
#insmod /lib/modules/`uname -r`/extra/mc24lc64t.ko
sys_eeprom "new_device"
switch_board_qsfp "new_device"
switch_board_sfp "new_device"
switch_board_led_default
# python /usr/bin/qsfp_irq_enable.py
platform_firmware_versions
elif [ "$1" == "deinit" ]; then
sys_eeprom "delete_device"
switch_board_qsfp "delete_device"
switch_board_sfp "delete_device"
modprobe -r i2c-mux-pca954x
modprobe -r i2c-dev
modprobe -r ipmi_devintf
modprobe -r ipmi_si
modprobe -r cls-i2c-ocore
modprobe -r cls-switchboard
modprobe -r mc24lc64t
else
echo "z9332f_platform : Invalid option !"
fi

View File

@ -0,0 +1,13 @@
[Unit]
Description=Dell Z9332f Platform modules
Before=pmon.service
DefaultDependencies=no
[Service]
Type=oneshot
ExecStart=/usr/local/bin/z9332f_platform.sh init
ExecStop=/usr/local/bin/z9332f_platform.sh deinit
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

View File

@ -2,6 +2,7 @@ arl_clean_timeout_usec
asf_mem_profile asf_mem_profile
bcm_linkscan_interval bcm_linkscan_interval
bcm_num_cos bcm_num_cos
default_cpu_tx_queue
bcm_stat_flags bcm_stat_flags
bcm_stat_interval bcm_stat_interval
bcm_stat_jumbo bcm_stat_jumbo