diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/buffers.json.j2 b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/buffers.json.j2 new file mode 100644 index 0000000000..0b1cb2c541 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/buffers_defaults_t0.j2 new file mode 100644 index 0000000000..77747f6403 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/buffers_defaults_t0.j2 @@ -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 %} + diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/buffers_defaults_t1.j2 new file mode 100644 index 0000000000..77747f6403 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/buffers_defaults_t1.j2 @@ -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 %} + diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/platform-def.json b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/platform-def.json new file mode 100644 index 0000000000..f39fd3021c --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/platform-def.json @@ -0,0 +1,49 @@ +{ + "fec-mode": { + "Ethernet0-255": { + "1": { + "10000": [ "none" ], + "25000": [ "none", "fc", "rs" ], + "50000": [ "rs" ] + }, + "2":{ + "50000": [ "none", "fc", "rs" ], + "100000": [ "rs" ] + }, + "4": { + "40000": [ "none" ], + "100000": [ "none", "rs" ], + "200000": [ "rs" ] + }, + "8": [ "rs" ] + } + }, + "default-fec-mode": { + "Ethernet0-255": { + "1": { + "10000": "none", + "25000": "none", + "50000": "rs" + }, + "2": { + "20000": "none", + "50000": "none", + "100000": "rs" + }, + "4": { + "40000": "none", + "100000": "none", + "200000": "rs" + }, + "8": "rs" + } + }, + "native-port-supported-speeds": { + "Ethernet0-255": { + "8": ["400000"] + }, + "Ethernet256-257": { + "1": ["10000","1000"] + } + } +} diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/port_config.ini b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/port_config.ini new file mode 100644 index 0000000000..c79d00e4ed --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/port_config.ini @@ -0,0 +1,35 @@ +# name lanes alias index speed +Ethernet0 17,18,19,20,21,22,23,24 fourhundredGigE1/1 1 400000 +Ethernet8 25,26,27,28,29,30,31,32 fourhundredGigE1/2 2 400000 +Ethernet16 1,2,3,4,5,6,7,8 fourhundredGigE1/3 3 400000 +Ethernet24 9,10,11,12,13,14,15,16 fourhundredGigE1/4 4 400000 +Ethernet32 49,50,51,52,53,54,55,56 fourhundredGigE1/5 5 400000 +Ethernet40 57,58,59,60,61,62,63,64 fourhundredGigE1/6 6 400000 +Ethernet48 33,34,35,36,37,38,39,40 fourhundredGigE1/7 7 400000 +Ethernet56 41,42,43,44,45,46,47,48 fourhundredGigE1/8 8 400000 +Ethernet64 81,82,83,84,85,86,87,88 fourhundredGigE1/9 9 400000 +Ethernet72 89,90,91,92,93,94,95,96 fourhundredGigE1/10 10 400000 +Ethernet80 65,66,67,68,69,70,71,72 fourhundredGigE1/11 11 400000 +Ethernet88 73,74,75,76,77,78,79,80 fourhundredGigE1/12 12 400000 +Ethernet96 113,114,115,116,117,118,119,120 fourhundredGigE1/13 13 400000 +Ethernet104 121,122,123,124,125,126,127,128 fourhundredGigE1/14 14 400000 +Ethernet112 97,98,99,100,101,102,103,104 fourhundredGigE1/15 15 400000 +Ethernet120 105,106,107,108,109,110,111,112 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 161,162,163,164,165,166,167,168 fourhundredGigE1/21 21 400000 +Ethernet168 169,170,171,172,173,174,175,176 fourhundredGigE1/22 22 400000 +Ethernet176 177,178,179,180,181,182,183,184 fourhundredGigE1/23 23 400000 +Ethernet184 185,186,187,188,189,190,191,192 fourhundredGigE1/24 24 400000 +Ethernet192 193,194,195,196,197,198,199,200 fourhundredGigE1/25 25 400000 +Ethernet200 201,202,203,204,205,206,207,208 fourhundredGigE1/26 26 400000 +Ethernet208 209,210,211,212,213,214,215,216 fourhundredGigE1/27 27 400000 +Ethernet216 217,218,219,220,221,222,223,224 fourhundredGigE1/28 28 400000 +Ethernet224 225,226,227,228,229,230,231,232 fourhundredGigE1/29 29 400000 +Ethernet232 233,234,235,236,237,238,239,240 fourhundredGigE1/30 30 400000 +Ethernet240 241,242,243,244,245,246,247,248 fourhundredGigE1/31 31 400000 +Ethernet248 249,250,251,252,253,254,255,256 fourhundredGigE1/32 32 400000 +Ethernet256 257 tenGigE1/33 33 10000 +Ethernet257 259 tenGigE1/34 34 10000 diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/qos.json.j2 b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/qos.json.j2 new file mode 100644 index 0000000000..f6b7ac977f --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/qos.json.j2 @@ -0,0 +1,225 @@ +{%- 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": "0", + "4": "0", + "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]", + "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 %} + } +} diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/sai.profile b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/sai.profile new file mode 100644 index 0000000000..26ae09b9df --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td4-z9432f-32x400G.config.yml diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/td4-z9432f-32x400G.config.yml b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/td4-z9432f-32x400G.config.yml new file mode 100644 index 0000000000..c93590a022 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-O32/td4-z9432f-32x400G.config.yml @@ -0,0 +1,700 @@ +--- +bcm_device: + 0: + global: + l2_table_default_view: 1 + pktio_mode: 1 + vlan_flooding_l2mc_num_reserved: 0 + shared_block_mask_section: uc_mc + ctr_evict_enable: 0 + uat_mode: 1 + uft_mode: 4 + sai_brcm_sonic_acl_enhancements: 1 + sai_tunnel_support: 1 + multi_network_groups: 1 + sai_field_group_auto_prioritize: 1 + sai_modify_hash_flexdigest: 1 + sai_fast_convergence_support: 1 +... +--- +device: + 0: + DEVICE_CONFIG: + # CORE CLOCK FREQUENCY + CORE_CLK_FREQ: CLK_1350MHZ + # PP CLOCK FREQUENCY + PP_CLK_FREQ: CLK_1350MHZ + VARIANT: DNA_4_9_5_0 +... +--- +device: + 0: + PC_PM_CORE: + ? + PC_PM_ID: 1 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x05471326 + TX_LANE_MAP: 0x53016724 + RX_POLARITY_FLIP: 0x44 + TX_POLARITY_FLIP: 0x56 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 2 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x20536741 + TX_LANE_MAP: 0x36104527 + RX_POLARITY_FLIP: 0xB3 + TX_POLARITY_FLIP: 0xA4 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 3 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x25173046 + TX_LANE_MAP: 0x71460352 + RX_POLARITY_FLIP: 0x35 + TX_POLARITY_FLIP: 0x10 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 4 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x34261507 + TX_LANE_MAP: 0x54027631 + RX_POLARITY_FLIP: 0x5 + TX_POLARITY_FLIP: 0xD5 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 5 + CORE_INDEX: 0 + : # Same as PM_ID_4 + RX_LANE_MAP: 0x06534217 + TX_LANE_MAP: 0x31746250 + RX_POLARITY_FLIP: 0xAF + TX_POLARITY_FLIP: 0x2D + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 6 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x27641305 + TX_LANE_MAP: 0x76130524 + RX_POLARITY_FLIP: 0xea + TX_POLARITY_FLIP: 0x0d + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 7 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x57134602 + TX_LANE_MAP: 0x61537240 + RX_POLARITY_FLIP: 0xFF + TX_POLARITY_FLIP: 0xA8 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 8 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x31607425 + TX_LANE_MAP: 0x74106523 + RX_POLARITY_FLIP: 0xFE + TX_POLARITY_FLIP: 0x1C + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 9 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x47612350 + TX_LANE_MAP: 0x17362504 + RX_POLARITY_FLIP: 0xBB + TX_POLARITY_FLIP: 0xAF + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 10 + CORE_INDEX: 0 + : # Same as PM_ID_4 + RX_LANE_MAP: 0x74523061 + TX_LANE_MAP: 0x10654372 + RX_POLARITY_FLIP: 0xB1 + TX_POLARITY_FLIP: 0x5B + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 11 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x53071246 + TX_LANE_MAP: 0x16240537 + RX_POLARITY_FLIP: 0x0 + TX_POLARITY_FLIP: 0x96 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 12 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x75243061 + TX_LANE_MAP: 0x02371564 + RX_POLARITY_FLIP: 0x1 + TX_POLARITY_FLIP: 0xA9 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 13 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x60317425 + TX_LANE_MAP: 0x54612703 + RX_POLARITY_FLIP: 0x44 + TX_POLARITY_FLIP: 0xBB + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 14 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x53704261 + TX_LANE_MAP: 0x13467052 + RX_POLARITY_FLIP: 0xBb + TX_POLARITY_FLIP: 0xC6 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 15 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x20573146 + TX_LANE_MAP: 0x07352416 + RX_POLARITY_FLIP: 0xaa + TX_POLARITY_FLIP: 0x4E + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 16 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x16570243 + TX_LANE_MAP: 0x57016423 + RX_POLARITY_FLIP: 0xfb + TX_POLARITY_FLIP: 0x44 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 17 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x40675132 + TX_LANE_MAP: 0x57360214 + RX_POLARITY_FLIP: 0xee + TX_POLARITY_FLIP: 0x95 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 18 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x73240516 + TX_LANE_MAP: 0x54307612 + RX_POLARITY_FLIP: 0xfa + TX_POLARITY_FLIP: 0x65 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 19 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x64751203 + TX_LANE_MAP: 0x01547263 + RX_POLARITY_FLIP: 0xd4 + TX_POLARITY_FLIP: 0xAD + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 20 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x13572046 + TX_LANE_MAP: 0x67230415 + RX_POLARITY_FLIP: 0x33 + TX_POLARITY_FLIP: 0x5C + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 21 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x23416750 + TX_LANE_MAP: 0x52346170 + RX_POLARITY_FLIP: 0x3F + TX_POLARITY_FLIP: 0x89 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 22 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x61043527 + TX_LANE_MAP: 0x76205413 + RX_POLARITY_FLIP: 0x7F + TX_POLARITY_FLIP: 0xFF + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 23 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x07352614 + TX_LANE_MAP: 0x21456073 + RX_POLARITY_FLIP: 0xEE + TX_POLARITY_FLIP: 0x9C + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 24 + CORE_INDEX: 0 + : # Same as PM_ID_21 + RX_LANE_MAP: 0x13604752 + TX_LANE_MAP: 0x57230614 + RX_POLARITY_FLIP: 0x11 + TX_POLARITY_FLIP: 0xCC + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 25 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x13475206 + TX_LANE_MAP: 0x25431607 + RX_POLARITY_FLIP: 0x01 + TX_POLARITY_FLIP: 0x5a + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 26 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x74502163 + TX_LANE_MAP: 0x24150736 + RX_POLARITY_FLIP: 0x9 + TX_POLARITY_FLIP: 0x14 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 27 + CORE_INDEX: 0 + : # Same as PM_ID_21 + RX_LANE_MAP: 0x73506241 + TX_LANE_MAP: 0x25341607 + RX_POLARITY_FLIP: 0x11 + TX_POLARITY_FLIP: 0x2F + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 28 + CORE_INDEX: 0 + : # Same as PM_ID_21 + RX_LANE_MAP: 0x37625041 + TX_LANE_MAP: 0x24170536 + RX_POLARITY_FLIP: 0x3B + TX_POLARITY_FLIP: 0x0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 29 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x24753160 + TX_LANE_MAP: 0x37051642 + RX_POLARITY_FLIP: 0x61 + TX_POLARITY_FLIP: 0x90 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 30 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x31657024 + TX_LANE_MAP: 0x25361704 + RX_POLARITY_FLIP: 0x7C + TX_POLARITY_FLIP: 0xC5 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 31 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x20563147 + TX_LANE_MAP: 0x26543710 + RX_POLARITY_FLIP: 0x37 + TX_POLARITY_FLIP: 0xE1 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 32 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x05471623 + TX_LANE_MAP: 0x24607351 + RX_POLARITY_FLIP: 0x44 + TX_POLARITY_FLIP: 0x33 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 +... +--- +device: + 0: + PC_PORT_PHYS_MAP: + ? + # CPU port + PORT_ID: 0 + : + PC_PHYS_PORT_ID: 0 + ? + PORT_ID: 1 + : + PC_PHYS_PORT_ID: 17 + ? + PORT_ID: 5 + : + PC_PHYS_PORT_ID: 25 + ? + PORT_ID: 10 + : + PC_PHYS_PORT_ID: 1 + ? + PORT_ID: 14 + : + PC_PHYS_PORT_ID: 9 + ? + PORT_ID: 20 + : + PC_PHYS_PORT_ID: 49 + ? + PORT_ID: 24 + : + PC_PHYS_PORT_ID: 57 + ? + PORT_ID: 29 + : + PC_PHYS_PORT_ID: 33 + ? + PORT_ID: 33 + : + PC_PHYS_PORT_ID: 41 + ? + PORT_ID: 40 + : + PC_PHYS_PORT_ID: 81 + ? + PORT_ID: 44 + : + PC_PHYS_PORT_ID: 89 + ? + PORT_ID: 49 + : + PC_PHYS_PORT_ID: 65 + ? + PORT_ID: 53 + : + PC_PHYS_PORT_ID: 73 + ? + PORT_ID: 60 + : + PC_PHYS_PORT_ID: 113 + ? + PORT_ID: 64 + : + PC_PHYS_PORT_ID: 121 + ? + PORT_ID: 69 + : + PC_PHYS_PORT_ID: 97 + ? + PORT_ID: 73 + : + PC_PHYS_PORT_ID: 105 + ? + PORT_ID: 80 + : + PC_PHYS_PORT_ID: 129 + ? + PORT_ID: 84 + : + PC_PHYS_PORT_ID: 137 + ? + PORT_ID: 89 + : + PC_PHYS_PORT_ID: 145 + ? + PORT_ID: 93 + : + PC_PHYS_PORT_ID: 153 + ? + PORT_ID: 100 + : + PC_PHYS_PORT_ID: 161 + ? + PORT_ID: 104 + : + PC_PHYS_PORT_ID: 169 + ? + PORT_ID: 109 + : + PC_PHYS_PORT_ID: 177 + ? + PORT_ID: 113 + : + PC_PHYS_PORT_ID: 185 + ? + PORT_ID: 120 + : + PC_PHYS_PORT_ID: 193 + ? + PORT_ID: 124 + : + PC_PHYS_PORT_ID: 201 + ? + PORT_ID: 129 + : + PC_PHYS_PORT_ID: 209 + ? + PORT_ID: 133 + : + PC_PHYS_PORT_ID: 217 + ? + PORT_ID: 140 + : + PC_PHYS_PORT_ID: 225 + ? + PORT_ID: 144 + : + PC_PHYS_PORT_ID: 233 + ? + PORT_ID: 149 + : + PC_PHYS_PORT_ID: 241 + ? + PORT_ID: 153 + : + PC_PHYS_PORT_ID: 249 + ? + # management port + PORT_ID: 38 + : + PC_PHYS_PORT_ID: 257 + ? + # management port + PORT_ID: 118 + : + PC_PHYS_PORT_ID: 259 + ? + # Loopback port 0 (Pipe 1) + PORT_ID: 39 + : + PC_PHYS_PORT_ID: 261 + ? + # Loopback port 1 (Pipe 3) + PORT_ID: 79 + : + PC_PHYS_PORT_ID: 262 + ? + # Loopback port 2 (Pipe 5) + PORT_ID: 119 + : + PC_PHYS_PORT_ID: 263 + ? + # Loopback port 3 (Pipe 7) + PORT_ID: 159 + : + PC_PHYS_PORT_ID: 264 +... +--- +device: + 0: + PC_PORT: + ? + PORT_ID: [0, + 39, # Loopback port 0 (Pipe 1) + 79, # Loopback port 1 (Pipe 3) + 119, # Loopback port 2 (Pipe 5) + 159] # Loopback port 3 (Pipe 7) + : + &port_mode_10g + ENABLE: 1 + SPEED: 10000 + NUM_LANES: 1 + ? + PORT_ID: [1, 5, 10, 14, + 20, 24, 29, 33, + 40, 44, 49, 53, + 60, 64, 69, 73, + 80, 84, 89, 93, + 100, 104, 109, 113, + 120, 124, 129, 133, + 140, 144, 149, 153] + : + &port_mode_400g + ENABLE: 0 + SPEED: 400000 + NUM_LANES: 8 + FEC_MODE: PC_FEC_RS544_2XN + MAX_FRAME_SIZE: 9416 + LINK_TRAINING: 0 + ? + PORT_ID: [38, # Management port 0 (Pipe 1) + 118] # Management port 2 (Pipe 5) + : + &port_mode_10g_xfi + ENABLE: 0 + SPEED: 10000 + NUM_LANES: 1 + MAX_FRAME_SIZE: 9416 + SER_CONFIG: + SER_ENABLE: 0 +... +--- +device: + 0: + PC_TX_TAPS: + PORT_ID: [1, 5, 10, 14, + 20, 24, 29, 33, + 40, 44, 49, 53, + 60, 64, 69, 73, + 80, 84, 89, 93, + 100, 104, 109, 113, + 120, 124, 129, 133, + 140, 144, 149, 153] + TX_SIG_MODE: PC_SIG_MODE_PAM4 + TXFIR_TAP_MODE: PC_TXFIR_PAM4_TAPS_6 + TX_DRV_MODE_SIGN: 0 + TX_DRV_MODE: 0 + TX_AMP_SIGN: 0 + TX_AMP: 0 + TX_RPARA_SIGN: 1 + TX_RPARA: 1 + TX_POST3_SIGN: 0 + TX_POST3: 0 + TX_POST2_SIGN: 0 + TX_POST2: 6 + TX_POST_SIGN: 0 + TX_POST: 0 + TX_MAIN_SIGN: 0 + TX_MAIN: 0x76 + TX_PRE2_SIGN: 0 + TX_PRE2: 8 + TX_PRE_SIGN: 1 + TX_PRE: 0x24 + LANE_INDEX: 0 + +... +--- +device: + 0: + # Per pipe flex counter configuration + CTR_EFLEX_CONFIG: + CTR_ING_EFLEX_OPERMODE_PIPEUNIQUE: 0 + CTR_EGR_EFLEX_OPERMODE_PIPEUNIQUE: 0 + +... +--- +device: + 0: + PC_PMD_FIRMWARE: + PORT_ID: [1, 5, 10, 14, + 20, 24, 29, 33, 38, + 40, 44, 49, 53, + 60, 64, 69, 73, 78, + 80, 84, 89, 93, + 100, 104, 109, 113 , 118, + 120, 124, 129, 133, + 140, 144, 149, 153, 158] + MEDIUM_TYPE: PC_PHY_MEDIUM_COPPER +... +--- +device: + 0: + FP_CONFIG: + FP_ING_OPERMODE: GLOBAL_PIPE_AWARE +... +--- +device: + 0: + CTR_CONTROL: + # Counter Collection Interval in Microseconds + INTERVAL: 2000000 +... diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/buffers.json.j2 b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/buffers.json.j2 new file mode 100644 index 0000000000..0b1cb2c541 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/buffers_defaults_t0.j2 b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/buffers_defaults_t0.j2 new file mode 100644 index 0000000000..77747f6403 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/buffers_defaults_t0.j2 @@ -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 %} + diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/buffers_defaults_t1.j2 b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/buffers_defaults_t1.j2 new file mode 100644 index 0000000000..77747f6403 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/buffers_defaults_t1.j2 @@ -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 %} + diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/platform-def.json b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/platform-def.json new file mode 100644 index 0000000000..5bc05ac684 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/platform-def.json @@ -0,0 +1,48 @@ +{ + "fec-mode": { + "Ethernet0-255": { + "1": { + "10000": [ "none" ], + "25000": [ "none", "fc", "rs" ], + "50000": [ "rs" ] + }, + "2":{ + "50000": [ "none", "fc", "rs" ], + "100000": [ "rs" ] + }, + "4": { + "40000": [ "none" ], + "100000": [ "none", "rs" ], + "200000": [ "rs" ] + }, + "8": [ "rs" ] + } + }, + "default-fec-mode": { + "Ethernet0-255": { + "1": { + "10000": "none", + "25000": "none", + "50000": "rs" + }, + "2": { + "20000": "none", + "50000": "none", + "100000": "rs" + }, + "4": { + "40000": "none", + "100000": "none", + "200000": "rs" + }, + "8": "rs" + } + }, + "native-port-supported-speeds": { + "Ethernet0-255": { + }, + "Ethernet256-257": { + "1": ["10000","1000"] + } + } +} diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/port_config.ini b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/port_config.ini new file mode 100644 index 0000000000..c79d00e4ed --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/port_config.ini @@ -0,0 +1,35 @@ +# name lanes alias index speed +Ethernet0 17,18,19,20,21,22,23,24 fourhundredGigE1/1 1 400000 +Ethernet8 25,26,27,28,29,30,31,32 fourhundredGigE1/2 2 400000 +Ethernet16 1,2,3,4,5,6,7,8 fourhundredGigE1/3 3 400000 +Ethernet24 9,10,11,12,13,14,15,16 fourhundredGigE1/4 4 400000 +Ethernet32 49,50,51,52,53,54,55,56 fourhundredGigE1/5 5 400000 +Ethernet40 57,58,59,60,61,62,63,64 fourhundredGigE1/6 6 400000 +Ethernet48 33,34,35,36,37,38,39,40 fourhundredGigE1/7 7 400000 +Ethernet56 41,42,43,44,45,46,47,48 fourhundredGigE1/8 8 400000 +Ethernet64 81,82,83,84,85,86,87,88 fourhundredGigE1/9 9 400000 +Ethernet72 89,90,91,92,93,94,95,96 fourhundredGigE1/10 10 400000 +Ethernet80 65,66,67,68,69,70,71,72 fourhundredGigE1/11 11 400000 +Ethernet88 73,74,75,76,77,78,79,80 fourhundredGigE1/12 12 400000 +Ethernet96 113,114,115,116,117,118,119,120 fourhundredGigE1/13 13 400000 +Ethernet104 121,122,123,124,125,126,127,128 fourhundredGigE1/14 14 400000 +Ethernet112 97,98,99,100,101,102,103,104 fourhundredGigE1/15 15 400000 +Ethernet120 105,106,107,108,109,110,111,112 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 161,162,163,164,165,166,167,168 fourhundredGigE1/21 21 400000 +Ethernet168 169,170,171,172,173,174,175,176 fourhundredGigE1/22 22 400000 +Ethernet176 177,178,179,180,181,182,183,184 fourhundredGigE1/23 23 400000 +Ethernet184 185,186,187,188,189,190,191,192 fourhundredGigE1/24 24 400000 +Ethernet192 193,194,195,196,197,198,199,200 fourhundredGigE1/25 25 400000 +Ethernet200 201,202,203,204,205,206,207,208 fourhundredGigE1/26 26 400000 +Ethernet208 209,210,211,212,213,214,215,216 fourhundredGigE1/27 27 400000 +Ethernet216 217,218,219,220,221,222,223,224 fourhundredGigE1/28 28 400000 +Ethernet224 225,226,227,228,229,230,231,232 fourhundredGigE1/29 29 400000 +Ethernet232 233,234,235,236,237,238,239,240 fourhundredGigE1/30 30 400000 +Ethernet240 241,242,243,244,245,246,247,248 fourhundredGigE1/31 31 400000 +Ethernet248 249,250,251,252,253,254,255,256 fourhundredGigE1/32 32 400000 +Ethernet256 257 tenGigE1/33 33 10000 +Ethernet257 259 tenGigE1/34 34 10000 diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/qos.json.j2 b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/qos.json.j2 new file mode 100644 index 0000000000..f6b7ac977f --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/qos.json.j2 @@ -0,0 +1,225 @@ +{%- 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": "0", + "4": "0", + "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]", + "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 %} + } +} diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/sai.profile b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/sai.profile new file mode 100644 index 0000000000..26ae09b9df --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/sai.profile @@ -0,0 +1 @@ +SAI_INIT_CONFIG_FILE=/usr/share/sonic/hwsku/td4-z9432f-32x400G.config.yml diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/td4-z9432f-32x400G.config.yml b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/td4-z9432f-32x400G.config.yml new file mode 100644 index 0000000000..245a45207f --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/DellEMC-Z9432f-T64C64O8-DPB/td4-z9432f-32x400G.config.yml @@ -0,0 +1,700 @@ +--- +bcm_device: + 0: + global: + l2_table_default_view: 1 + pktio_mode: 1 + vlan_flooding_l2mc_num_reserved: 0 + shared_block_mask_section: uc_mc + ctr_evict_enable: 0 + uat_mode: 1 + uft_mode: 4 + sai_brcm_sonic_acl_enhancements: 1 + sai_tunnel_support: 1 + multi_network_groups: 1 + sai_field_group_auto_prioritize: 1 + sai_modify_hash_flexdigest: 1 + sai_fast_convergence_support: 1 +... +--- +device: + 0: + DEVICE_CONFIG: + # CORE CLOCK FREQUENCY + CORE_CLK_FREQ: CLK_1350MHZ + # PP CLOCK FREQUENCY + PP_CLK_FREQ: CLK_1350MHZ + VARIANT: DNA_4_9_5_0 +... +--- +device: + 0: + PC_PM_CORE: + ? + PC_PM_ID: 1 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x05471326 + TX_LANE_MAP: 0x53016724 + RX_POLARITY_FLIP: 0x44 + TX_POLARITY_FLIP: 0x56 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 2 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x20536741 + TX_LANE_MAP: 0x36104527 + RX_POLARITY_FLIP: 0xB3 + TX_POLARITY_FLIP: 0xA4 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 3 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x25173046 + TX_LANE_MAP: 0x71460352 + RX_POLARITY_FLIP: 0x35 + TX_POLARITY_FLIP: 0x10 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 4 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x34261507 + TX_LANE_MAP: 0x54027631 + RX_POLARITY_FLIP: 0x5 + TX_POLARITY_FLIP: 0xD5 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 5 + CORE_INDEX: 0 + : # Same as PM_ID_4 + RX_LANE_MAP: 0x06534217 + TX_LANE_MAP: 0x31746250 + RX_POLARITY_FLIP: 0xAF + TX_POLARITY_FLIP: 0x2D + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 6 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x27641305 + TX_LANE_MAP: 0x76130524 + RX_POLARITY_FLIP: 0xea + TX_POLARITY_FLIP: 0x0d + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 7 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x57134602 + TX_LANE_MAP: 0x61537240 + RX_POLARITY_FLIP: 0xFF + TX_POLARITY_FLIP: 0xA8 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 8 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x31607425 + TX_LANE_MAP: 0x74106523 + RX_POLARITY_FLIP: 0xFE + TX_POLARITY_FLIP: 0x1C + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 9 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x47612350 + TX_LANE_MAP: 0x17362504 + RX_POLARITY_FLIP: 0xBB + TX_POLARITY_FLIP: 0xAF + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 10 + CORE_INDEX: 0 + : # Same as PM_ID_4 + RX_LANE_MAP: 0x74523061 + TX_LANE_MAP: 0x10654372 + RX_POLARITY_FLIP: 0xB1 + TX_POLARITY_FLIP: 0x5B + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 11 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x53071246 + TX_LANE_MAP: 0x16240537 + RX_POLARITY_FLIP: 0x0 + TX_POLARITY_FLIP: 0x96 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 12 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x75243061 + TX_LANE_MAP: 0x02371564 + RX_POLARITY_FLIP: 0x1 + TX_POLARITY_FLIP: 0xA9 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 13 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x60317425 + TX_LANE_MAP: 0x54612703 + RX_POLARITY_FLIP: 0x44 + TX_POLARITY_FLIP: 0xBB + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 14 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x53704261 + TX_LANE_MAP: 0x13467052 + RX_POLARITY_FLIP: 0xBb + TX_POLARITY_FLIP: 0xC6 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 15 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x20573146 + TX_LANE_MAP: 0x07352416 + RX_POLARITY_FLIP: 0xaa + TX_POLARITY_FLIP: 0x4E + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 16 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x16570243 + TX_LANE_MAP: 0x57016423 + RX_POLARITY_FLIP: 0xfb + TX_POLARITY_FLIP: 0x44 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 17 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x40675132 + TX_LANE_MAP: 0x57360214 + RX_POLARITY_FLIP: 0xee + TX_POLARITY_FLIP: 0x95 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 18 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x73240516 + TX_LANE_MAP: 0x54307612 + RX_POLARITY_FLIP: 0xfa + TX_POLARITY_FLIP: 0x65 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 19 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x64751203 + TX_LANE_MAP: 0x01547263 + RX_POLARITY_FLIP: 0xd4 + TX_POLARITY_FLIP: 0xAD + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 20 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x13572046 + TX_LANE_MAP: 0x67230415 + RX_POLARITY_FLIP: 0x33 + TX_POLARITY_FLIP: 0x5C + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 21 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x23416750 + TX_LANE_MAP: 0x52346170 + RX_POLARITY_FLIP: 0x3F + TX_POLARITY_FLIP: 0x89 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 22 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x61043527 + TX_LANE_MAP: 0x76205413 + RX_POLARITY_FLIP: 0x7F + TX_POLARITY_FLIP: 0xFF + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 23 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x07352614 + TX_LANE_MAP: 0x21456073 + RX_POLARITY_FLIP: 0xEE + TX_POLARITY_FLIP: 0x9C + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 24 + CORE_INDEX: 0 + : # Same as PM_ID_21 + RX_LANE_MAP: 0x13604752 + TX_LANE_MAP: 0x57230614 + RX_POLARITY_FLIP: 0x11 + TX_POLARITY_FLIP: 0xCC + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 25 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x13475206 + TX_LANE_MAP: 0x25431607 + RX_POLARITY_FLIP: 0x01 + TX_POLARITY_FLIP: 0x5a + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 26 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x74502163 + TX_LANE_MAP: 0x24150736 + RX_POLARITY_FLIP: 0x9 + TX_POLARITY_FLIP: 0x14 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 27 + CORE_INDEX: 0 + : # Same as PM_ID_21 + RX_LANE_MAP: 0x73506241 + TX_LANE_MAP: 0x25341607 + RX_POLARITY_FLIP: 0x11 + TX_POLARITY_FLIP: 0x2F + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 28 + CORE_INDEX: 0 + : # Same as PM_ID_21 + RX_LANE_MAP: 0x37625041 + TX_LANE_MAP: 0x24170536 + RX_POLARITY_FLIP: 0x3B + TX_POLARITY_FLIP: 0x0 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 29 + CORE_INDEX: 0 + : + RX_LANE_MAP: 0x24753160 + TX_LANE_MAP: 0x37051642 + RX_POLARITY_FLIP: 0x61 + TX_POLARITY_FLIP: 0x90 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 30 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x31657024 + TX_LANE_MAP: 0x25361704 + RX_POLARITY_FLIP: 0x7C + TX_POLARITY_FLIP: 0xC5 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 31 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x20563147 + TX_LANE_MAP: 0x26543710 + RX_POLARITY_FLIP: 0x37 + TX_POLARITY_FLIP: 0xE1 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 + ? + PC_PM_ID: 32 + CORE_INDEX: 0 + : # Same as PM_ID_0 + RX_LANE_MAP: 0x05471623 + TX_LANE_MAP: 0x24607351 + RX_POLARITY_FLIP: 0x44 + TX_POLARITY_FLIP: 0x33 + RX_POLARITY_FLIP_AUTO: 0 + TX_POLARITY_FLIP_AUTO: 0 + RX_LANE_MAP_AUTO: 0 + TX_LANE_MAP_AUTO: 0 +... +--- +device: + 0: + PC_PORT_PHYS_MAP: + ? + # CPU port + PORT_ID: 0 + : + PC_PHYS_PORT_ID: 0 + ? + PORT_ID: 1 + : + PC_PHYS_PORT_ID: 17 + ? + PORT_ID: 2 + : + PC_PHYS_PORT_ID: 25 + ? + PORT_ID: 10 + : + PC_PHYS_PORT_ID: 1 + ? + PORT_ID: 11 + : + PC_PHYS_PORT_ID: 9 + ? + PORT_ID: 20 + : + PC_PHYS_PORT_ID: 49 + ? + PORT_ID: 21 + : + PC_PHYS_PORT_ID: 57 + ? + PORT_ID: 29 + : + PC_PHYS_PORT_ID: 33 + ? + PORT_ID: 30 + : + PC_PHYS_PORT_ID: 41 + ? + PORT_ID: 40 + : + PC_PHYS_PORT_ID: 81 + ? + PORT_ID: 41 + : + PC_PHYS_PORT_ID: 89 + ? + PORT_ID: 49 + : + PC_PHYS_PORT_ID: 65 + ? + PORT_ID: 50 + : + PC_PHYS_PORT_ID: 73 + ? + PORT_ID: 60 + : + PC_PHYS_PORT_ID: 113 + ? + PORT_ID: 61 + : + PC_PHYS_PORT_ID: 121 + ? + PORT_ID: 69 + : + PC_PHYS_PORT_ID: 97 + ? + PORT_ID: 70 + : + PC_PHYS_PORT_ID: 105 + ? + PORT_ID: 80 + : + PC_PHYS_PORT_ID: 129 + ? + PORT_ID: 84 + : + PC_PHYS_PORT_ID: 137 + ? + PORT_ID: 89 + : + PC_PHYS_PORT_ID: 145 + ? + PORT_ID: 93 + : + PC_PHYS_PORT_ID: 153 + ? + PORT_ID: 100 + : + PC_PHYS_PORT_ID: 161 + ? + PORT_ID: 104 + : + PC_PHYS_PORT_ID: 169 + ? + PORT_ID: 109 + : + PC_PHYS_PORT_ID: 177 + ? + PORT_ID: 113 + : + PC_PHYS_PORT_ID: 185 + ? + PORT_ID: 120 + : + PC_PHYS_PORT_ID: 193 + ? + PORT_ID: 124 + : + PC_PHYS_PORT_ID: 201 + ? + PORT_ID: 129 + : + PC_PHYS_PORT_ID: 209 + ? + PORT_ID: 133 + : + PC_PHYS_PORT_ID: 217 + ? + PORT_ID: 140 + : + PC_PHYS_PORT_ID: 225 + ? + PORT_ID: 144 + : + PC_PHYS_PORT_ID: 233 + ? + PORT_ID: 149 + : + PC_PHYS_PORT_ID: 241 + ? + PORT_ID: 153 + : + PC_PHYS_PORT_ID: 249 + ? + # management port + PORT_ID: 38 + : + PC_PHYS_PORT_ID: 257 + ? + # management port + PORT_ID: 118 + : + PC_PHYS_PORT_ID: 259 + ? + # Loopback port 0 (Pipe 1) + PORT_ID: 39 + : + PC_PHYS_PORT_ID: 261 + ? + # Loopback port 1 (Pipe 3) + PORT_ID: 79 + : + PC_PHYS_PORT_ID: 262 + ? + # Loopback port 2 (Pipe 5) + PORT_ID: 119 + : + PC_PHYS_PORT_ID: 263 + ? + # Loopback port 3 (Pipe 7) + PORT_ID: 159 + : + PC_PHYS_PORT_ID: 264 +... +--- +device: + 0: + PC_PORT: + ? + PORT_ID: [0, + 39, # Loopback port 0 (Pipe 1) + 79, # Loopback port 1 (Pipe 3) + 119, # Loopback port 2 (Pipe 5) + 159] # Loopback port 3 (Pipe 7) + : + &port_mode_10g + ENABLE: 1 + SPEED: 10000 + NUM_LANES: 1 + ? + PORT_ID: [1, 2, 10, 11, + 20, 21, 29, 30, + 40, 41, 49, 50, + 60, 61, 69, 70, + 80, 84, 89, 93, + 100, 104, 109, 113, + 120, 124, 129, 133, + 140, 144, 149, 153] + : + &port_mode_400g + ENABLE: 0 + SPEED: 400000 + NUM_LANES: 8 + FEC_MODE: PC_FEC_RS544_2XN + MAX_FRAME_SIZE: 9416 + LINK_TRAINING: 0 + ? + PORT_ID: [38, # Management port 0 (Pipe 1) + 118] # Management port 2 (Pipe 5) + : + &port_mode_10g_xfi + ENABLE: 0 + SPEED: 10000 + NUM_LANES: 1 + MAX_FRAME_SIZE: 9416 + SER_CONFIG: + SER_ENABLE: 0 +... +--- +device: + 0: + PC_TX_TAPS: + PORT_ID: [1, 2, 10, 11, + 20, 21, 29, 30, + 40, 41, 49, 50, + 60, 61, 69, 70, + 80, 84, 89, 93, + 100, 104, 109, 113, + 120, 124, 129, 133, + 140, 144, 149, 153] + TX_SIG_MODE: PC_SIG_MODE_PAM4 + TXFIR_TAP_MODE: PC_TXFIR_PAM4_TAPS_6 + TX_DRV_MODE_SIGN: 0 + TX_DRV_MODE: 0 + TX_AMP_SIGN: 0 + TX_AMP: 0 + TX_RPARA_SIGN: 1 + TX_RPARA: 1 + TX_POST3_SIGN: 0 + TX_POST3: 0 + TX_POST2_SIGN: 0 + TX_POST2: 6 + TX_POST_SIGN: 0 + TX_POST: 0 + TX_MAIN_SIGN: 0 + TX_MAIN: 0x76 + TX_PRE2_SIGN: 0 + TX_PRE2: 8 + TX_PRE_SIGN: 1 + TX_PRE: 0x24 + LANE_INDEX: 0 + +... +--- +device: + 0: + # Per pipe flex counter configuration + CTR_EFLEX_CONFIG: + CTR_ING_EFLEX_OPERMODE_PIPEUNIQUE: 0 + CTR_EGR_EFLEX_OPERMODE_PIPEUNIQUE: 0 + +... +--- +device: + 0: + PC_PMD_FIRMWARE: + PORT_ID: [1, 2, 10, 11, + 20, 21, 29, 30, 38, + 40, 41, 49, 50, + 60, 61, 69, 70, 78, + 80, 84, 89, 93, + 100, 104, 109, 113 , 118, + 120, 124, 129, 133, + 140, 144, 149, 153, 158] + MEDIUM_TYPE: PC_PHY_MEDIUM_COPPER +... +--- +device: + 0: + FP_CONFIG: + FP_ING_OPERMODE: GLOBAL_PIPE_AWARE +... +--- +device: + 0: + CTR_CONTROL: + # Counter Collection Interval in Microseconds + INTERVAL: 2000000 +... diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/custom_led.bin b/device/dell/x86_64-dellemc_z9432f_c3758-r0/custom_led.bin new file mode 100644 index 0000000000..20efa33609 Binary files /dev/null and b/device/dell/x86_64-dellemc_z9432f_c3758-r0/custom_led.bin differ diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/default_sku b/device/dell/x86_64-dellemc_z9432f_c3758-r0/default_sku new file mode 100644 index 0000000000..0cb490cdcc --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/default_sku @@ -0,0 +1 @@ +DellEMC-Z9432f-O32 t1 diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/installer.conf b/device/dell/x86_64-dellemc_z9432f_c3758-r0/installer.conf new file mode 100644 index 0000000000..ff014aa8c2 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/installer.conf @@ -0,0 +1,3 @@ +CONSOLE_PORT=0x3f8 +CONSOLE_DEV=0 +ONIE_PLATFORM_EXTRA_CMDLINE_LINUX="intel_iommu=off" diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/led_proc_init.soc b/device/dell/x86_64-dellemc_z9432f_c3758-r0/led_proc_init.soc new file mode 100644 index 0000000000..c683151c04 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/led_proc_init.soc @@ -0,0 +1,7 @@ +# LED microprocessor initialization for Dell z9432 +# +# +led 0 stop +led 0 load /usr/share/sonic/platform/custom_led.bin +led start +led auto on diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/platform.json b/device/dell/x86_64-dellemc_z9432f_c3758-r0/platform.json new file mode 100644 index 0000000000..2b6c0d2069 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/platform.json @@ -0,0 +1,583 @@ +{ + "chassis": { + "name": "Z9432F-ON", + "thermal_manager":false, + "status_led": { + "controllable": true, + "colors": ["green", "blinking_green", "amber", "blinking_amber"] + }, + "components": [ + { + "name": "BIOS" + }, + { + "name": "FPGA" + }, + { + "name": "BMC" + }, + { + "name": "Baseboard CPLD" + }, + { + "name": "Switch CPLD 1" + }, + { + "name": "Switch CPLD 2" + } + ], + "fans": [ + { + "name": "FanTray1-Fan1", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray1-Fan2", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray2-Fan1", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray2-Fan2", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray3-Fan1", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray3-Fan2", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray4-Fan1", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray4-Fan2", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray5-Fan1", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray5-Fan2", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray6-Fan1", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray6-Fan2", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray7-Fan1", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray7-Fan2", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + } + ], + "fan_drawers":[ + { + "name": "FanTray1", + "status_led": { + "controllable": false + }, + "fans": [ + { + "name": "FanTray1-Fan1", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray1-Fan2", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + } + ] + }, + { + "name": "FanTray2", + "status_led": { + "controllable": false + }, + "fans": [ + { + "name": "FanTray2-Fan1", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray2-Fan2", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + } + ] + }, + { + "name": "FanTray3", + "status_led": { + "controllable": false + }, + "fans": [ + { + "name": "FanTray3-Fan1", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray3-Fan2", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + } + ] + }, + { + "name": "FanTray4", + "status_led": { + "controllable": false + }, + "fans": [ + { + "name": "FanTray4-Fan1", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray4-Fan2", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + } + ] + }, + { + "name": "FanTray5", + "status_led": { + "controllable": false + }, + "fans": [ + { + "name": "FanTray5-Fan1", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray5-Fan2", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + } + ] + }, + { + "name": "FanTray6", + "status_led": { + "controllable": false + }, + "fans": [ + { + "name": "FanTray6-Fan1", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray6-Fan2", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + } + ] + }, + { + "name": "FanTray7", + "status_led": { + "controllable": false + }, + "fans": [ + { + "name": "FanTray7-Fan1", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + }, + { + "name": "FanTray7-Fan2", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + } + ] + } + ], + "psus": [ + { + "name": "PSU1", + "status_led": { + "controllable": false + }, + "fans": [ + { + "name": "PSU1 Fan", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + } + ] + }, + { + "name": "PSU2", + "status_led": { + "controllable": false + }, + "fans": [ + { + "name": "PSU2 Fan", + "speed": { + "controllable": false + }, + "status_led": { + "available": false + } + } + ] + } + ], + "thermals": [ + { + "name": "CPU Temp", + "controllable": false, + "low-crit-threshold": false, + "minimum-recorded": false, + "maximum-recorded": false + }, + { + "name": "FAN Right Temp", + "controllable": false, + "low-crit-threshold": false, + "minimum-recorded": false, + "maximum-recorded": false + }, + { + "name": "NPU Front Temp", + "controllable": false, + "low-crit-threshold": false, + "minimum-recorded": false, + "maximum-recorded": false + }, + { + "name": "NPU Rear Temp", + "controllable": false, + "low-crit-threshold": false, + "minimum-recorded": false, + "maximum-recorded": false + }, + { + "name": "NPU Temp", + "controllable": false, + "low-crit-threshold": false, + "minimum-recorded": false, + "maximum-recorded": false + }, + { + "name": "PSU1 AF Temp", + "controllable": false, + "low-crit-threshold": false, + "high-threshold": false, + "minimum-recorded": false, + "maximum-recorded": false + }, + { + "name": "PSU1 Mid Temp", + "controllable": false, + "low-crit-threshold": false, + "high-threshold": false, + "minimum-recorded": false, + "maximum-recorded": false + }, + { + "name": "PSU1 Rear Temp", + "controllable": false, + "low-crit-threshold": false, + "high-threshold": false, + "minimum-recorded": false, + "maximum-recorded": false + }, + { + "name": "PSU2 AF Temp", + "controllable": false, + "low-crit-threshold": false, + "high-threshold": false, + "minimum-recorded": false, + "maximum-recorded": false + }, + { + "name": "PSU2 Mid Temp", + "controllable": false, + "low-crit-threshold": false, + "high-threshold": false, + "minimum-recorded": false, + "maximum-recorded": false + }, + { + "name": "PSU2 Rear Temp", + "controllable": false, + "low-crit-threshold": false, + "high-threshold": false, + "minimum-recorded": false, + "maximum-recorded": false + }, + { + "name": "PT Left Temp", + "controllable": false, + "low-crit-threshold": false, + "minimum-recorded": false, + "maximum-recorded": false + }, + { + "name": "PT Right Temp", + "controllable": false, + "low-crit-threshold": false, + "minimum-recorded": false, + "maximum-recorded": false + } + ], + "modules": [], + "sfps": [ + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "QSFP-DD Double Density 8X Pluggable Transceiver" + }, + { + "name": "SFP/SFP+/SFP28" + }, + { + "name": "SFP/SFP+/SFP28" + } + ] + }, + "interfaces": {} +} diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/platform_asic b/device/dell/x86_64-dellemc_z9432f_c3758-r0/platform_asic new file mode 100644 index 0000000000..9604676527 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/platform_asic @@ -0,0 +1 @@ +broadcom diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/plugins/eeprom.py b/device/dell/x86_64-dellemc_z9432f_c3758-r0/plugins/eeprom.py new file mode 100644 index 0000000000..261022b143 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/plugins/eeprom.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +############################################################################# +# DellEMC S5232f +# +# 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: + import os.path + from sonic_eeprom import eeprom_tlvinfo +except ImportError as 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 = None + for b in (0, 1): + f = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom'.format(b) + if os.path.exists(f): + self.eeprom_path = f + break + if self.eeprom_path is None: + return + + super(board, self).__init__(self.eeprom_path, 0, '', True) diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/plugins/fanutil.py b/device/dell/x86_64-dellemc_z9432f_c3758-r0/plugins/fanutil.py new file mode 100644 index 0000000000..5dabf2de10 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/plugins/fanutil.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python +############################################################################# +# Dell +# +# Module contains an implementation of SONiC FAN Base API and +# provides various info about the FANs which are available in the platform +# +############################################################################# +import logging +import commands + +try: + from sonic_fan.fan_base import FanBase +except ImportError as e: + raise ImportError (str(e) + "- required module not found") + +class FanUtil(FanBase): + """Platform-specific FANutil class""" + FANTRAY_NUM_ON_MAIN_BOARD = 7 + NUM_FANS_PERTRAY = 2 + FANTRAY_NUM_START_IDX = 1 + FRU_FAN_START_IDX = 1 + IPMI_FAN_PRESENCE = "ipmitool sensor get FAN{0}_prsnt" + IPMI_FAN_FRONT_SPEED = "ipmitool sdr get Fan{0}_Front_rpm" + IPMI_FAN_REAR_SPEED = "ipmitool sdr get Fan{0}_Rear_rpm" + IPMI_FRU_DATA = "ipmitool fru print {0}" + + def __init__(self, log_level=logging.DEBUG): + FanBase.__init__(self) + self.num_fans = (self.FANTRAY_NUM_ON_MAIN_BOARD*self.NUM_FANS_PERTRAY) + + def get_fan_status(self,fan_id): + try: + ret_status, ipmi_cmd_ret = commands.getstatusoutput(self.IPMI_FAN_PRESENCE.format(fan_id)) + if ret_status == 0: + return(ipmi_cmd_ret.splitlines()[5].strip(' ').strip('[]')) + except Exception: + logging.error('Failed to execute : %s'%self.IPMI_FAN_PRESENCE.format(fan_id)) + + def get_front_fan_speed(self,fan_id): + try: + ret_status, ipmi_cmd_ret = commands.getstatusoutput(self.IPMI_FAN_FRONT_SPEED.format(fan_id)) + if ret_status == 0: + rdata = ipmi_cmd_ret.splitlines()[3].split(':')[1].split(' ')[1] + return rdata + except Exception: + logging.error('Failed to execute : %s'%self.IPMI_FAN_FRONT_SPEED.format(fan_id)) + + def get_rear_fan_speed(self,fan_id): + try: + ret_status, ipmi_cmd_ret = commands.getstatusoutput(self.IPMI_FAN_REAR_SPEED.format(fan_id)) + if ret_status == 0: + rdata = ipmi_cmd_ret.splitlines()[3].split(':')[1].split(' ')[1] + return rdata + + except Exception: + logging.error('Failed to execute : %s'%self.IPMI_FAN_REAR_SPEED.format(fan_id)) + + + # Read FAN FRU info + def get_fan_direction_from_fru(self,fru_id,reg_name): + output = None + try: + status, ipmi_fru_list = commands.getstatusoutput(self.IPMI_FRU_DATA.format(fru_id)) + if status == 0: + for item in ipmi_fru_list.split("\n"): + if reg_name in item: + output = item.strip() + if output is None: + logging.error('\nFailed to fetch: ' + reg_name + ' sensor ') + output = output.split(':')[1].strip(' ') + if output == 'F2B' or output == 'B2F': + return output + except Exception: + logging.error('Failed to execute:' + ipmi_fru_list) + + def get_num_fans(self): + return self.num_fans + + def get_presence(self, index): + if index is None: + return False + + if index < self.FANTRAY_NUM_START_IDX or index > self.FANTRAY_NUM_START_IDX + self.num_fans - 1: + logging.error('Invalid FAN index:%d', index) + return False + + tray_index = ((index-1)/self.NUM_FANS_PERTRAY) + 1 + + if (self.get_fan_status(tray_index) == 'Device Present'): + return True + else: + return False + + def get_status(self, index): + if index is None: + return False + + if index < self.FANTRAY_NUM_START_IDX or index > self.FANTRAY_NUM_START_IDX + self.num_fans - 1: + logging.error('Invalid FAN index:%d', index) + return False + + tray_index = ((index-1)/self.NUM_FANS_PERTRAY) + 1 + fantray_front_speed=self.get_front_fan_speed(tray_index) + fantray_rear_speed=self.get_rear_fan_speed(tray_index) + + if (fantray_front_speed != '0' and fantray_rear_speed != '0'): + return True + else: + return False + + + def get_direction(self, index): + if index is None: + return None + + if index < self.FANTRAY_NUM_START_IDX or index > self.FANTRAY_NUM_START_IDX + self.num_fans - 1: + logging.error('Invalid FAN index:%d', index) + return None + + tray_index = ((index-1)/self.NUM_FANS_PERTRAY) + fru_id = self.FRU_FAN_START_IDX + tray_index + direction = self.get_fan_direction_from_fru(fru_id,'Board Extra') + + if direction == 'B2F': + return "INTAKE" + elif direction == 'F2B': + return "EXHAUST" + else: + return None + + + def get_speed(self, index): + if index is None: + return 0 + + if index < self.FANTRAY_NUM_START_IDX or index > self.FANTRAY_NUM_START_IDX + self.num_fans - 1: + logging.error('Invalid FAN index:%d', index) + return 0 + + tray_index = ((index-1)/self.NUM_FANS_PERTRAY) + 1 + + if (index % 2 != 0): + fantray_speed=self.get_front_fan_speed(tray_index) + else: + fantray_speed=self.get_rear_fan_speed(tray_index) + + if (self.get_presence(index) == True): + return int(fantray_speed.strip()) + else: + return 0 + + def set_speed(self, val): + logging.error("Not allowed to set fan speed!") + + return False diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/plugins/pcie.yaml b/device/dell/x86_64-dellemc_z9432f_c3758-r0/plugins/pcie.yaml new file mode 100644 index 0000000000..467db07c12 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/plugins/pcie.yaml @@ -0,0 +1,25 @@ +- bus: '03' + dev: '00' + fn: '0' + id: '1533' + name: 'Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev 03)' +- bus: '02' + dev: '00' + fn: '0' + id: b881 + name: 'Ethernet controller: Broadcom Limited Device b881 (rev 11)' +- bus: '04' + dev: '00' + fn: '0' + id: '7021' + name: 'Non-VGA unclassified device: Xilinx Corporation Device 7021' +- bus: '00' + dev: '13' + fn: '0' + id: 19b2 + name: 'SATA controller: Intel Corporation DNV SATA Controller 0 (rev 11)' +- bus: '00' + dev: '14' + fn: '0' + id: 19c2 + name: 'SATA controller: Intel Corporation DNV SATA Controller 1 (rev 11)' diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/plugins/psuutil.py b/device/dell/x86_64-dellemc_z9432f_c3758-r0/plugins/psuutil.py new file mode 100644 index 0000000000..aaf02fec0c --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/plugins/psuutil.py @@ -0,0 +1,236 @@ +# +# psuutil.py +# Platform-specific PSU status interface for SONiC +# +import logging +import commands + +Z9332F_MAX_PSUS = 2 +FRU_PSUL = 11 +FRU_PSUR = 12 + + +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""" + IPMI_PSU1_DATA = "ipmitool raw 0x04 0x2d 0x2f | awk '{print substr($0,9,1)}'" + IPMI_PSU2_DATA = "ipmitool raw 0x04 0x2d 0x39 | awk '{print substr($0,9,1)}'" + IPMI_PSU_VOUT = "ipmitool sdr get PSU{0}_VOut" + IPMI_PSU_POUT = "ipmitool sdr get PSU{0}_POut" + IPMI_PSU_COUT = "ipmitool sdr get PSU{0}_COut" + IPMI_PSU_FAN_SPEED = "ipmitool sdr get PSU{0}_Fan" + IPMI_FRU = "ipmitool fru" + IPMI_FRU_DATA = "ipmitool fru print {0}" + + 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 + + def get_psu_vout(self,index): + try: + ret_status, ipmi_cmd_ret = commands.getstatusoutput(self.IPMI_PSU_VOUT.format(index)) + if ret_status == 0: + rdata = ipmi_cmd_ret.splitlines()[3].split(':')[1].split(' ')[1] + return rdata + + except Exception: + logging.error('Failed to execute : %s'%self.IPMI_PSU_VOUT.format(index)) + + def get_psu_cout(self,index): + try: + ret_status, ipmi_cmd_ret = commands.getstatusoutput(self.IPMI_PSU_COUT.format(index)) + if ret_status == 0: + rdata = ipmi_cmd_ret.splitlines()[3].split(':')[1].split(' ')[1] + return rdata + + except Exception: + logging.error('Failed to execute : %s'%self.IPMI_PSU_COUT.format(index)) + + def get_psu_pout(self,index): + try: + ret_status, ipmi_cmd_ret = commands.getstatusoutput(self.IPMI_PSU_POUT.format(index)) + if ret_status == 0: + rdata = ipmi_cmd_ret.splitlines()[3].split(':')[1].split(' ')[1] + return rdata + + except Exception: + logging.error('Failed to execute : %s'%self.IPMI_PSU_POUT.format(index)) + + def get_psu_fan_speed(self,index): + try: + ret_status, ipmi_cmd_ret = commands.getstatusoutput(self.IPMI_PSU_FAN_SPEED.format(index)) + if ret_status == 0: + rdata = ipmi_cmd_ret.splitlines()[3].split(':')[1].split(' ')[1] + return rdata + + except Exception: + logging.error('Failed to execute : %s'%self.IPMI_PSU_FAN_SPEED.format(index)) + + + #Fetch FRU Data for given fruid + def get_psu_airflow(self, index): + if index == 1: + fru_id = 'FRU_PSUL' + else: + fru_id = 'FRU_PSUR' + + ret_status, ipmi_cmd_ret = commands.getstatusoutput(self.IPMI_FRU) + if ret_status: + logging.error('Failed to execute ipmitool: '+ self.IPMI_FRU) + + found_fru = False + for line in ipmi_cmd_ret.splitlines(): + if line.startswith('FRU Device Description') and fru_id in line.split(':')[1] : + found_fru = True + if found_fru and line.startswith(' Board Product '): + return ' B2F' if 'PS/IO' in line else ' F2B' + return '' + + # Read FRU info + def get_fru_info(self,fru_id,reg_name): + output = None + Found = False + try: + status, ipmi_fru_list = commands.getstatusoutput(self.IPMI_FRU_DATA.format(fru_id)) + if status == 0: + for item in ipmi_fru_list.split("\n"): + if reg_name == item.split(':')[0].strip(' '): + output = item.strip() + output = output.split(':')[1] + Found = True + break; + + if not Found: + logging.error('\nFailed to fetch: ' + reg_name + ' sensor ') + + return output + except Exception: + logging.error('Failed to execute:' + ipmi_fru_list) + + 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 + :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 + """ + psu_status = '0' + + if index == 1: + cmd_status, psu_status = commands.getstatusoutput(self.IPMI_PSU1_DATA) + elif index == 2: + cmd_status, psu_status = commands.getstatusoutput(self.IPMI_PSU2_DATA) + else: + logging.error("Invalid PSU number:" + index) + + if cmd_status: + logging.error('Failed to execute ipmitool') + + return (not int(psu_status, 16) > 1) + + def get_psu_presence(self, index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by index + :param index: An integer, index of the PSU of which to query status + :return: Boolean, True if PSU is plugged, False if not + """ + psu_status = '0' + + if index == 1: + cmd_status, psu_status = commands.getstatusoutput(self.IPMI_PSU1_DATA) + elif index == 2: + cmd_status, psu_status = commands.getstatusoutput(self.IPMI_PSU2_DATA) + else: + logging.error("Invalid PSU number:" + index) + + if cmd_status: + logging.error('Failed to execute ipmitool') + + return (int(psu_status, 16) & 1) + + def get_output_voltage(self, index): + if index is None: + return 0.0 + psuvoltage=self.get_psu_vout(index) + return float(psuvoltage.strip()) + + def get_output_current(self, index): + if index is None: + return 0.0 + psucurrent=self.get_psu_cout(index) + return float(psucurrent.strip()) + + def get_output_power(self, index): + if index is None: + return 0.0 + psupower=self.get_psu_pout(index) + return float(psupower.strip()) + + def get_fan_rpm(self, index, fan_idx): + if index is None: + return 0 + fanrpm=self.get_psu_fan_speed(index) + return int(fanrpm.strip()) + + def get_serial(self, index): + if index is None: + return None + if index == 1: + fru_id = FRU_PSUL + else: + fru_id = FRU_PSUR + + return self.get_fru_info(fru_id,'Board Serial') + + def get_model(self, index): + if index is None: + return None + if index == 1: + fru_id = FRU_PSUL + else: + fru_id = FRU_PSUR + + return self.get_fru_info(fru_id,'Board Part Number') + + def get_mfr_id(self, index): + if index is None: + return None + if index == 1: + fru_id = FRU_PSUL + else: + fru_id = FRU_PSUR + + return self.get_fru_info(fru_id,'Board Mfg') + + def get_direction(self, index): + if index is None: + return None + + direction=self.get_psu_airflow(index).strip() + if direction == 'B2F': + return "INTAKE" + elif direction == 'F2B': + return "EXHAUST" + else: + return None diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/plugins/sfputil.py b/device/dell/x86_64-dellemc_z9432f_c3758-r0/plugins/sfputil.py new file mode 100644 index 0000000000..5106e84e6e --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/plugins/sfputil.py @@ -0,0 +1,246 @@ +# sfputil.py +# +# Platform-specific SFP transceiver interface for SONiC +# + +try: + import struct + import time + import os + from sonic_sfp.sfputilbase import SfpUtilBase + 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 = 32 + + BASE_RES_PATH = "/sys/bus/pci/devices/0000:04:00.0/resource0" + + _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 = os.open(resource, os.O_RDWR) + mm = mmap(fd, 0) + val = self.pci_mem_write(mm, offset, val) + mm.close() + os.close(fd) + return val + + def pci_get_value(self, resource, offset): + fd = os.open(resource, os.O_RDWR) + mm = mmap(fd, 0) + val = self.pci_mem_read(mm, offset) + mm.close() + os.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(x+1) + 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 + 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 + 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 + self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + + return True + + 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) diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/pmon_daemon_control.json b/device/dell/x86_64-dellemc_z9432f_c3758-r0/pmon_daemon_control.json new file mode 100644 index 0000000000..0c42f485ac --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/pmon_daemon_control.json @@ -0,0 +1,4 @@ +{ + "skip_ledd": true, + "start_ipmievd": true +} diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/port-locator.soc b/device/dell/x86_64-dellemc_z9432f_c3758-r0/port-locator.soc new file mode 100644 index 0000000000..7419e6641b --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/port-locator.soc @@ -0,0 +1,308 @@ +# LED interface controls +config add sai_led_intf_enable_0=1 +config add sai_led_intf_head_0=0 +config add sai_led_intf_tail_0=15 +config add sai_led_intf_bits_0=1 + +config add sai_led_intf_enable_2=1 +config add sai_led_intf_head_2=16 +config add sai_led_intf_tail_2=33 +config add sai_led_intf_bits_2=1 + +# LED data patterns for ON/OFF +config add sai_led_patt_off_0=0x1 +config add sai_led_patt_on_0=0x0 + +# Physical Port --> LED Port (1-based indexing) +# QSFPDD [17-24] Ethernet0-7 Eth1/1/1-8 +config add sai_led_portmap_17=1 +config add sai_led_portmap_18=1 +config add sai_led_portmap_19=1 +config add sai_led_portmap_20=1 +config add sai_led_portmap_21=1 +config add sai_led_portmap_22=1 +config add sai_led_portmap_23=1 +config add sai_led_portmap_24=1 +# QSFPDD [25-32] Ethernet8-15 Eth1/2/1-8 +config add sai_led_portmap_25=2 +config add sai_led_portmap_26=2 +config add sai_led_portmap_27=2 +config add sai_led_portmap_28=2 +config add sai_led_portmap_29=2 +config add sai_led_portmap_30=2 +config add sai_led_portmap_31=2 +config add sai_led_portmap_32=2 +# QSFPDD [1-8] Ethernet16-23 Eth1/3/1-8 +config add sai_led_portmap_1=3 +config add sai_led_portmap_2=3 +config add sai_led_portmap_3=3 +config add sai_led_portmap_4=3 +config add sai_led_portmap_5=3 +config add sai_led_portmap_6=3 +config add sai_led_portmap_7=3 +config add sai_led_portmap_8=3 +# QSFPDD [9-16] Ethernet24-31 Eth1/4/1-8 +config add sai_led_portmap_9=4 +config add sai_led_portmap_10=4 +config add sai_led_portmap_11=4 +config add sai_led_portmap_12=4 +config add sai_led_portmap_13=4 +config add sai_led_portmap_14=4 +config add sai_led_portmap_15=4 +config add sai_led_portmap_16=4 +# QSFPDD [49-56] Ethernet32-39 Eth1/5/1-8 +config add sai_led_portmap_49=5 +config add sai_led_portmap_50=5 +config add sai_led_portmap_51=5 +config add sai_led_portmap_52=5 +config add sai_led_portmap_53=5 +config add sai_led_portmap_54=5 +config add sai_led_portmap_55=5 +config add sai_led_portmap_56=5 +# QSFPDD [57-64] Ethernet40-47 Eth1/6/1-8 +config add sai_led_portmap_57=6 +config add sai_led_portmap_58=6 +config add sai_led_portmap_59=6 +config add sai_led_portmap_60=6 +config add sai_led_portmap_61=6 +config add sai_led_portmap_62=6 +config add sai_led_portmap_63=6 +config add sai_led_portmap_64=6 +# QSFPDD [33-40] Ethernet48-55 Eth1/7/1-8 +config add sai_led_portmap_33=7 +config add sai_led_portmap_34=7 +config add sai_led_portmap_35=7 +config add sai_led_portmap_36=7 +config add sai_led_portmap_37=7 +config add sai_led_portmap_38=7 +config add sai_led_portmap_39=7 +config add sai_led_portmap_40=7 +# QSFPDD [41-48] Ethernet56-63 Eth1/8/1-8 +config add sai_led_portmap_41=8 +config add sai_led_portmap_42=8 +config add sai_led_portmap_43=8 +config add sai_led_portmap_44=8 +config add sai_led_portmap_45=8 +config add sai_led_portmap_46=8 +config add sai_led_portmap_47=8 +config add sai_led_portmap_48=8 +# QSFPDD [81-88] Ethernet64-71 Eth1/9/1-8 +config add sai_led_portmap_81=9 +config add sai_led_portmap_82=9 +config add sai_led_portmap_83=9 +config add sai_led_portmap_84=9 +config add sai_led_portmap_85=9 +config add sai_led_portmap_86=9 +config add sai_led_portmap_87=9 +config add sai_led_portmap_88=9 +# QSFPDD [89-96] Ethernet72-79 Eth1/10/1-8 +config add sai_led_portmap_89=10 +config add sai_led_portmap_90=10 +config add sai_led_portmap_91=10 +config add sai_led_portmap_92=10 +config add sai_led_portmap_93=10 +config add sai_led_portmap_94=10 +config add sai_led_portmap_95=10 +config add sai_led_portmap_96=10 +# QSFPDD [65-72] Ethernet80-87 Eth1/11/1-8 +config add sai_led_portmap_65=11 +config add sai_led_portmap_66=11 +config add sai_led_portmap_67=11 +config add sai_led_portmap_68=11 +config add sai_led_portmap_69=11 +config add sai_led_portmap_70=11 +config add sai_led_portmap_71=11 +config add sai_led_portmap_72=11 +# QSFPDD [73-80] Ethernet88-95 Eth1/12/1-8 +config add sai_led_portmap_73=12 +config add sai_led_portmap_74=12 +config add sai_led_portmap_75=12 +config add sai_led_portmap_76=12 +config add sai_led_portmap_77=12 +config add sai_led_portmap_78=12 +config add sai_led_portmap_79=12 +config add sai_led_portmap_80=12 +# QSFPDD [113-120] Ethernet96-103 Eth1/13/1-8 +config add sai_led_portmap_113=13 +config add sai_led_portmap_114=13 +config add sai_led_portmap_115=13 +config add sai_led_portmap_116=13 +config add sai_led_portmap_117=13 +config add sai_led_portmap_118=13 +config add sai_led_portmap_119=13 +config add sai_led_portmap_120=13 +# QSFPDD [121-128] Ethernet104-111 Eth1/14/1-8 +config add sai_led_portmap_121=14 +config add sai_led_portmap_122=14 +config add sai_led_portmap_123=14 +config add sai_led_portmap_124=14 +config add sai_led_portmap_125=14 +config add sai_led_portmap_126=14 +config add sai_led_portmap_127=14 +config add sai_led_portmap_128=14 +# QSFPDD [97-104] Ethernet112-119 Eth1/15/1-8 +config add sai_led_portmap_97=15 +config add sai_led_portmap_98=15 +config add sai_led_portmap_99=15 +config add sai_led_portmap_100=15 +config add sai_led_portmap_101=15 +config add sai_led_portmap_102=15 +config add sai_led_portmap_103=15 +config add sai_led_portmap_104=15 +# QSFPDD [105-112] Ethernet120-127 Eth1/16/1-8 +config add sai_led_portmap_105=16 +config add sai_led_portmap_106=16 +config add sai_led_portmap_107=16 +config add sai_led_portmap_108=16 +config add sai_led_portmap_109=16 +config add sai_led_portmap_110=16 +config add sai_led_portmap_111=16 +config add sai_led_portmap_112=16 +# QSFPDD [129-136] Ethernet128-135 Eth1/17/1-8 +config add sai_led_portmap_129=17 +config add sai_led_portmap_130=17 +config add sai_led_portmap_131=17 +config add sai_led_portmap_132=17 +config add sai_led_portmap_133=17 +config add sai_led_portmap_134=17 +config add sai_led_portmap_135=17 +config add sai_led_portmap_136=17 +# QSFPDD [137-144] Ethernet136-143 Eth1/18/1-8 +config add sai_led_portmap_137=18 +config add sai_led_portmap_138=18 +config add sai_led_portmap_139=18 +config add sai_led_portmap_140=18 +config add sai_led_portmap_141=18 +config add sai_led_portmap_142=18 +config add sai_led_portmap_143=18 +config add sai_led_portmap_144=18 +# QSFPDD [145-152] Ethernet144-151 Eth1/19/1-8 +config add sai_led_portmap_145=19 +config add sai_led_portmap_146=19 +config add sai_led_portmap_147=19 +config add sai_led_portmap_148=19 +config add sai_led_portmap_149=19 +config add sai_led_portmap_150=19 +config add sai_led_portmap_151=19 +config add sai_led_portmap_152=19 +# QSFPDD [153-160] Ethernet152-159 Eth1/20/1-8 +config add sai_led_portmap_153=20 +config add sai_led_portmap_154=20 +config add sai_led_portmap_155=20 +config add sai_led_portmap_156=20 +config add sai_led_portmap_157=20 +config add sai_led_portmap_158=20 +config add sai_led_portmap_159=20 +config add sai_led_portmap_160=20 +# QSFPDD [161-168] Ethernet160-167 Eth1/21/1-8 +config add sai_led_portmap_161=21 +config add sai_led_portmap_162=21 +config add sai_led_portmap_163=21 +config add sai_led_portmap_164=21 +config add sai_led_portmap_165=21 +config add sai_led_portmap_166=21 +config add sai_led_portmap_167=21 +config add sai_led_portmap_168=21 +# QSFPDD [169-176] Ethernet168-175 Eth1/22/1-8 +config add sai_led_portmap_169=22 +config add sai_led_portmap_170=22 +config add sai_led_portmap_171=22 +config add sai_led_portmap_172=22 +config add sai_led_portmap_173=22 +config add sai_led_portmap_174=22 +config add sai_led_portmap_175=22 +config add sai_led_portmap_176=22 +# QSFPDD [177-184] Ethernet176-183 Eth1/23/1-8 +config add sai_led_portmap_177=23 +config add sai_led_portmap_178=23 +config add sai_led_portmap_179=23 +config add sai_led_portmap_180=23 +config add sai_led_portmap_181=23 +config add sai_led_portmap_182=23 +config add sai_led_portmap_183=23 +config add sai_led_portmap_184=23 +# QSFPDD [185-192] Ethernet184-191 Eth1/24/1-8 +config add sai_led_portmap_185=24 +config add sai_led_portmap_186=24 +config add sai_led_portmap_187=24 +config add sai_led_portmap_188=24 +config add sai_led_portmap_189=24 +config add sai_led_portmap_190=24 +config add sai_led_portmap_191=24 +config add sai_led_portmap_192=24 +# QSFPDD [193-200] Ethernet192-199 Eth1/25/1-8 +config add sai_led_portmap_193=25 +config add sai_led_portmap_194=25 +config add sai_led_portmap_195=25 +config add sai_led_portmap_196=25 +config add sai_led_portmap_197=25 +config add sai_led_portmap_198=25 +config add sai_led_portmap_199=25 +config add sai_led_portmap_200=25 +# QSFPDD [201-208] Ethernet200-207 Eth1/26/1-8 +config add sai_led_portmap_201=26 +config add sai_led_portmap_202=26 +config add sai_led_portmap_203=26 +config add sai_led_portmap_204=26 +config add sai_led_portmap_205=26 +config add sai_led_portmap_206=26 +config add sai_led_portmap_207=26 +config add sai_led_portmap_208=26 +# QSFPDD [209-216] Ethernet208-215 Eth1/27/1-8 +config add sai_led_portmap_209=27 +config add sai_led_portmap_210=27 +config add sai_led_portmap_211=27 +config add sai_led_portmap_212=27 +config add sai_led_portmap_213=27 +config add sai_led_portmap_214=27 +config add sai_led_portmap_215=27 +config add sai_led_portmap_216=27 +# QSFPDD [217-224] Ethernet216-223 Eth1/28/1-8 +config add sai_led_portmap_217=28 +config add sai_led_portmap_218=28 +config add sai_led_portmap_219=28 +config add sai_led_portmap_220=28 +config add sai_led_portmap_221=28 +config add sai_led_portmap_222=28 +config add sai_led_portmap_223=28 +config add sai_led_portmap_224=28 +# QSFPDD [225-232] Ethernet224-231 Eth1/29/1-8 +config add sai_led_portmap_225=29 +config add sai_led_portmap_226=29 +config add sai_led_portmap_227=29 +config add sai_led_portmap_228=29 +config add sai_led_portmap_229=29 +config add sai_led_portmap_230=29 +config add sai_led_portmap_231=29 +config add sai_led_portmap_232=29 +# QSFPDD [233-240] Ethernet232-239 Eth1/30/1-8 +config add sai_led_portmap_233=30 +config add sai_led_portmap_234=30 +config add sai_led_portmap_235=30 +config add sai_led_portmap_236=30 +config add sai_led_portmap_237=30 +config add sai_led_portmap_238=30 +config add sai_led_portmap_239=30 +config add sai_led_portmap_240=30 +# QSFPDD [241-248] Ethernet240-247 Eth1/31/1-8 +config add sai_led_portmap_241=31 +config add sai_led_portmap_242=31 +config add sai_led_portmap_243=31 +config add sai_led_portmap_244=31 +config add sai_led_portmap_245=31 +config add sai_led_portmap_246=31 +config add sai_led_portmap_247=31 +config add sai_led_portmap_248=31 +# QSFPDD [249-256] Ethernet248-255 Eth1/32/1-8 +config add sai_led_portmap_249=32 +config add sai_led_portmap_250=32 +config add sai_led_portmap_251=32 +config add sai_led_portmap_252=32 +config add sai_led_portmap_253=32 +config add sai_led_portmap_254=32 +config add sai_led_portmap_255=32 +config add sai_led_portmap_256=32 +# 1-lane port [257-257] Ethernet256 Eth1/33 +config add sai_led_portmap_257=33 +# 1-lane port [259-259] Ethernet257 Eth1/34 +config add sai_led_portmap_259=34 diff --git a/device/dell/x86_64-dellemc_z9432f_c3758-r0/system_health_monitoring_config.json b/device/dell/x86_64-dellemc_z9432f_c3758-r0/system_health_monitoring_config.json new file mode 100644 index 0000000000..dc20d41214 --- /dev/null +++ b/device/dell/x86_64-dellemc_z9432f_c3758-r0/system_health_monitoring_config.json @@ -0,0 +1,11 @@ +{ + "services_to_ignore": [], + "devices_to_ignore": ["fan.speed","psu.temperature","psu.voltage","asic"], + "user_defined_checkers": [], + "polling_interval": 60, + "led_color": { + "fault" : "blink_yellow", + "normal" : "green", + "booting": "blink_green" + } +} diff --git a/platform/broadcom/one-image.mk b/platform/broadcom/one-image.mk index 00b3716c06..bde6b9da0e 100644 --- a/platform/broadcom/one-image.mk +++ b/platform/broadcom/one-image.mk @@ -14,6 +14,7 @@ $(SONIC_ONE_IMAGE)_LAZY_INSTALLS += $(DELL_S6000_PLATFORM_MODULE) \ $(DELL_S5232F_PLATFORM_MODULE) \ $(DELL_S5248F_PLATFORM_MODULE) \ $(DELL_Z9332F_PLATFORM_MODULE) \ + $(DELL_Z9432F_PLATFORM_MODULE) \ $(DELL_S5296F_PLATFORM_MODULE) \ $(DELL_Z9100_PLATFORM_MODULE) \ $(DELL_S6100_PLATFORM_MODULE) \ diff --git a/platform/broadcom/platform-modules-dell.mk b/platform/broadcom/platform-modules-dell.mk index 3f17b16fbc..a9d2a1880b 100644 --- a/platform/broadcom/platform-modules-dell.mk +++ b/platform/broadcom/platform-modules-dell.mk @@ -8,6 +8,7 @@ DELL_S5212F_PLATFORM_MODULE_VERSION = 1.1 DELL_S5224F_PLATFORM_MODULE_VERSION = 1.1 DELL_S5232F_PLATFORM_MODULE_VERSION = 1.1 DELL_Z9332F_PLATFORM_MODULE_VERSION = 1.1 +DELL_Z9432F_PLATFORM_MODULE_VERSION = 1.1 DELL_S5248F_PLATFORM_MODULE_VERSION = 1.1 DELL_S5296F_PLATFORM_MODULE_VERSION = 1.1 DELL_N3248PXE_PLATFORM_MODULE_VERSION = 1.1 @@ -21,6 +22,7 @@ export DELL_S5212F_PLATFORM_MODULE_VERSION export DELL_S5224F_PLATFORM_MODULE_VERSION export DELL_S5232F_PLATFORM_MODULE_VERSION export DELL_Z9332F_PLATFORM_MODULE_VERSION +export DELL_Z9432F_PLATFORM_MODULE_VERSION export DELL_S5248F_PLATFORM_MODULE_VERSION export DELL_S5296F_PLATFORM_MODULE_VERSION export DELL_N3248PXE_PLATFORM_MODULE_VERSION @@ -61,6 +63,10 @@ DELL_Z9332F_PLATFORM_MODULE = platform-modules-z9332f_$(DELL_Z9332F_PLATFORM_MOD $(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_Z9432F_PLATFORM_MODULE = platform-modules-z9432f_$(DELL_Z9432F_PLATFORM_MODULE_VERSION)_amd64.deb +$(DELL_Z9432F_PLATFORM_MODULE)_PLATFORM = x86_64-dellemc_z9432f_c3758-r0 +$(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_Z9432F_PLATFORM_MODULE))) + 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 $(eval $(call add_extra_package,$(DELL_Z9100_PLATFORM_MODULE),$(DELL_S5248F_PLATFORM_MODULE))) diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/control b/platform/broadcom/sonic-platform-modules-dell/debian/control index b16a3d7904..7821dbd4f2 100644 --- a/platform/broadcom/sonic-platform-modules-dell/debian/control +++ b/platform/broadcom/sonic-platform-modules-dell/debian/control @@ -55,6 +55,11 @@ Architecture: amd64 Depends: linux-image-5.10.0-12-2-amd64-unsigned Description: kernel modules for platform devices such as fan, led, sfp +Package: platform-modules-z9432f +Architecture: amd64 +Depends: linux-image-5.10.0-8-2-amd64-unsigned +Description: kernel modules for platform devices such as fan, led, sfp + Package: platform-modules-n3248pxe Architecture: amd64 Depends: linux-image-5.10.0-12-2-amd64-unsigned diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9432f.init b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9432f.init new file mode 100755 index 0000000000..26c44fca61 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9432f.init @@ -0,0 +1,40 @@ +#!/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 Z9432f board. +### END INIT INFO + +case "$1" in +start) + echo -n "Setting up board... " + + # /usr/local/bin/iom_power_on.sh + /usr/local/bin/z9432f_platform.sh init + + echo "done." + ;; + +stop) + /usr/local/bin/z9432f_platform.sh deinit + echo "done." + + ;; + +force-reload|restart) + echo "Not supported" + ;; + +*) + echo "Usage: /etc/init.d/platform-modules-z9432f.init {start|stop}" + exit 1 + ;; +esac + +exit 0 diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9432f.install b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9432f.install new file mode 100644 index 0000000000..b42c7f362a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9432f.install @@ -0,0 +1,12 @@ +z9432f/scripts/z9432f_platform.sh usr/local/bin +z9432f/scripts/check_qsfp.sh usr/local/bin +z9432f/scripts/platform_sensors.py usr/local/bin +z9432f/scripts/sensors usr/bin +z9432f/scripts/pcisysfs.py usr/bin +z9432f/scripts/qsfp_irq_enable.py usr/bin +z9432f/cfg/z9432f-modules.conf etc/modules-load.d +z9432f/systemd/platform-modules-z9432f.service etc/systemd/system +z9432f/modules/sonic_platform-1.0-py3-none-any.whl usr/share/sonic/device/x86_64-dellemc_z9432f_c3758-r0 +common/platform_reboot usr/share/sonic/device/x86_64-dellemc_z9432f_c3758-r0 +common/fw-updater usr/local/bin +common/onie_mode_set usr/local/bin diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9432f.postinst b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9432f.postinst new file mode 100644 index 0000000000..4f5bf4dc4d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/debian/platform-modules-z9432f.postinst @@ -0,0 +1,10 @@ +# postinst script for Z9432f + +# Enable Dell-Z9432f-platform-service +depmod -a +systemctl enable platform-modules-z9432f.service +systemctl start platform-modules-z9432f.service + + +#DEBHELPER# + diff --git a/platform/broadcom/sonic-platform-modules-dell/debian/rules b/platform/broadcom/sonic-platform-modules-dell/debian/rules index 8baafa1407..9904cce52b 100755 --- a/platform/broadcom/sonic-platform-modules-dell/debian/rules +++ b/platform/broadcom/sonic-platform-modules-dell/debian/rules @@ -5,7 +5,7 @@ export INSTALL_MOD_DIR:=extra KVERSION ?= $(shell uname -r) KERNEL_SRC := /lib/modules/$(KVERSION) MOD_SRC_DIR:= $(shell pwd) -MODULE_DIRS:= s6000 z9100 s6100 z9264f s5212f s5224f s5232f s5248f z9332f s5296f n3248pxe n3248te +MODULE_DIRS:= s6000 z9100 s6100 z9264f s5212f s5224f s5232f s5248f z9332f z9432f s5296f n3248pxe n3248te COMMON_DIR := common %: @@ -64,6 +64,11 @@ override_dh_auto_build: cd $(MOD_SRC_DIR)/$${mod}; \ python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ cd $(MOD_SRC_DIR); \ + elif [ $$mod = "z9432f" ]; then \ + cp $(COMMON_DIR)/ipmihelper.py $(MOD_SRC_DIR)/$${mod}/sonic_platform/ipmihelper.py; \ + cd $(MOD_SRC_DIR)/$${mod}; \ + python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ + cd $(MOD_SRC_DIR); \ elif [ $$mod = "n3248pxe" ]; then \ cd $(MOD_SRC_DIR)/$${mod}; \ python3 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/modules; \ @@ -140,6 +145,11 @@ override_dh_clean: rm -f $(MOD_SRC_DIR)/$${mod}/modules/*.whl; \ rm -rf $(MOD_SRC_DIR)/$${mod}/build; \ rm -rf $(MOD_SRC_DIR)/$${mod}/build/*.egg-info; \ + elif [ $$mod = "z9432f" ]; then \ + rm -f $(MOD_SRC_DIR)/$${mod}/sonic_platform/ipmihelper.py; \ + rm -f $(MOD_SRC_DIR)/$${mod}/modules/*.whl; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/build; \ + rm -rf $(MOD_SRC_DIR)/$${mod}/build/*.egg-info; \ elif [ $$mod = "n3248pxe" ]; then \ rm -f $(MOD_SRC_DIR)/$${mod}/sonic_platform/ipmihelper.py; \ rm -f $(MOD_SRC_DIR)/$${mod}/modules/*.whl; \ diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/cfg/z9432f-modules.conf b/platform/broadcom/sonic-platform-modules-dell/z9432f/cfg/z9432f-modules.conf new file mode 100644 index 0000000000..13746785c2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/cfg/z9432f-modules.conf @@ -0,0 +1,16 @@ +# /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-pca954x + +ipmi_devintf +ipmi_si diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/modules/Makefile b/platform/broadcom/sonic-platform-modules-dell/z9432f/modules/Makefile new file mode 100644 index 0000000000..0625bd0d57 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/modules/Makefile @@ -0,0 +1,2 @@ +obj-m := dell_z9432f_fpga_ocores.o mc24lc64t.o + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/modules/dell_z9432f_fpga_ocores.c b/platform/broadcom/sonic-platform-modules-dell/z9432f/modules/dell_z9432f_fpga_ocores.c new file mode 100644 index 0000000000..f86f10c071 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/modules/dell_z9432f_fpga_ocores.c @@ -0,0 +1,1485 @@ +/* +* Copyright (C) 2018 Dell Inc +* +* Licensed under the GNU General Public License Version 2 +* +* 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. +* +*/ + +/** +* @file fpga_i2ccore.c +* @brief This is a driver to interface with Linux Open Cores drivber for FPGA i2c access +* +************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include //siginfo +#include //rcu_read_lock +#include //kernel_version +#include +#include +#include +#include +#include + + +void __iomem * fpga_base_addr = NULL; +void __iomem * fpga_ctl_addr = NULL; + +#define DRIVER_NAME "fpgapci" +#define PCI_NUM_BARS 4 + +#ifdef DEBUG +# define PRINT(fmt, ...) printk(fmt, ##__VA_ARGS__) +#else +# define PRINT(fmt, ...) +#endif + +/* Maximum size of driver buffer (allocated with kalloc()). + * Needed to copy data from user to kernel space, among other + * things. */ +static const size_t BUF_SIZE = PAGE_SIZE; + +/* Device data used by this driver. */ +struct fpgapci_dev { + /* the kernel pci device data structure */ + struct pci_dev *pci_dev; + + /* upstream root node */ + struct pci_dev *upstream; + + /* kernels virtual addr. for the mapped BARs */ + void * __iomem bar[PCI_NUM_BARS]; + + /* length of each memory region. Used for error checking. */ + size_t bar_length[PCI_NUM_BARS]; + + /* Debug data */ + /* number of hw interrupts handled. */ + int num_handled_interrupts; + int num_undelivered_signals; + int pci_gen; + int pci_num_lanes; + + unsigned int irq_first; + unsigned int irq_length; + unsigned int irq_assigned; + +}; + +static int use_irq = 1; +module_param(use_irq, int, 0644); +MODULE_PARM_DESC(use_irq, "Get an use_irq value from user...\n"); + +static uint32_t num_bus = 0; +module_param(num_bus, int, 0); +MODULE_PARM_DESC(num_bus, + "Number of i2c busses supported by the FPGA on this platform."); + + +/* Xilinx FPGA PCIE info: */ +/* Non-VGA unclassified device: Xilinx Corporation Device 7021*/ +/* Subsystem: Xilinx Corporation Device 0007 */ +//#define VENDOR 0x10EE +#define DEVICE 0x7021 + +/* Altera FPGA PCIE info: + Unassigned class [ff00]: Altera Corporation Device 0004 (rev 01) + Subsystem: Altera Corporation Device 0004 */ +#define PCI_VENDOR_ID_ALTERA 0x1172 +#define PCI_DEVICE_ID_ALTERA 0x0004 + +static phys_addr_t fpga_phys_addr; + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +typedef unsigned long long u64; + + +/* struct to hold data related to the pcie device */ +struct pci_data_struct{ + struct pci_dev* dev; + unsigned long long phy_addr_bar0; + unsigned long long phy_len_bar0; + unsigned long long phy_flags_bar0; + unsigned int irq_first; + unsigned int irq_length; + unsigned int irq_assigned; + void * kvirt_addr_bar0; +}; + +/* global variable declarations */ + +/* Static function declarations */ +static int fpgapci_probe(struct pci_dev *dev, const struct pci_device_id *id); +static void fpgapci_remove(struct pci_dev *dev); + +static int scan_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev); +static int map_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev); +static void free_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev); + + +struct fpgalogic_i2c { + void __iomem *base; + u32 reg_shift; + u32 reg_io_width; + wait_queue_head_t wait; + struct i2c_msg *msg; + int pos; + int nmsgs; + int state; /* see STATE_ */ + int ip_clock_khz; + int bus_clock_khz; + void (*reg_set)(struct fpgalogic_i2c *i2c, int reg, u8 value); + u8 (*reg_get)(struct fpgalogic_i2c *i2c, int reg); + u32 timeout; + struct mutex lock; +}; +/* registers */ +#define FPGAI2C_REG_PRELOW 0 +#define FPGAI2C_REG_PREHIGH 1 +#define FPGAI2C_REG_CONTROL 2 +#define FPGAI2C_REG_DATA 3 +#define FPGAI2C_REG_CMD 4 /* write only */ +#define FPGAI2C_REG_STATUS 4 /* read only, same address as FPGAI2C_REG_CMD */ +#define FPGAI2C_REG_VER 5 + + + +#define FPGAI2C_REG_CTRL_IEN 0x40 +#define FPGAI2C_REG_CTRL_EN 0x80 + +#define FPGAI2C_REG_CMD_START 0x91 +#define FPGAI2C_REG_CMD_STOP 0x41 +#define FPGAI2C_REG_CMD_READ 0x21 +#define FPGAI2C_REG_CMD_WRITE 0x11 +#define FPGAI2C_REG_CMD_READ_ACK 0x21 +#define FPGAI2C_REG_CMD_READ_NACK 0x29 +#define FPGAI2C_REG_CMD_IACK 0x01 + +#define FPGAI2C_REG_STAT_IF 0x01 +#define FPGAI2C_REG_STAT_TIP 0x02 +#define FPGAI2C_REG_STAT_ARBLOST 0x20 +#define FPGAI2C_REG_STAT_BUSY 0x40 +#define FPGAI2C_REG_STAT_NACK 0x80 + +/* SR[7:0] - Status register */ +#define FPGAI2C_REG_SR_RXACK (1 << 7) /* Receive acknowledge from secondary �1� = No acknowledge received*/ +#define FPGAI2C_REG_SR_BUSY (1 << 6) /* Busy, I2C bus busy (as defined by start / stop bits) */ +#define FPGAI2C_REG_SR_AL (1 << 5) /* Arbitration lost - fpga i2c logic lost arbitration */ +#define FPGAI2C_REG_SR_TIP (1 << 1) /* Transfer in progress */ +#define FPGAI2C_REG_SR_IF (1 << 0) /* Interrupt flag */ + +enum { + STATE_DONE = 0, + STATE_INIT, + STATE_ADDR, + STATE_ADDR10, + STATE_START, + STATE_WRITE, + STATE_READ, + STATE_STOP, + STATE_ERROR, +}; + +#define TYPE_FPGALOGIC 0 +#define TYPE_GRLIB 1 + +/*I2C_CH1 Offset address from PCIE BAR 0*/ +#define FPGALOGIC_I2C_BASE 0x00006000 +#define FPGALOGIC_CH_OFFSET 0x10 + +#define i2c_bus_controller_numb 1 +#define I2C_PCI_MAX_BUS (16) +#define I2C_PCI_MAX_BUS_REV00 (7) +#define DELL_I2C_CLOCK_LEGACY 0 +#define DELL_I2C_CLOCK_PRESERVE (~0U) +#define I2C_PCI_BUS_NUM_5 5 +#define I2C_PCI_BUS_NUM_7 7 +#define I2C_PCI_BUS_NUM_8 8 +#define I2C_PCI_BUS_NUM_10 10 +#define I2C_PCI_BUS_NUM_12 12 +#define I2C_PCI_BUS_NUM_16 16 + +#define MB_BRD_REV_TYPE 0x0008 +#define MB_BRD_REV_MASK 0x00f0 +#define MB_BRD_REV_00 0x0000 +#define MB_BRD_REV_01 0x0010 +#define MB_BRD_REV_02 0x0020 +#define MB_BRD_REV_03 0x0030 +#define MB_BRD_TYPE_MASK 0x000f +#define BRD_TYPE_Z9232_NON_NEBS 0x0 +#define BRD_TYPE_Z9232_NEBS 0x1 +#define BRD_TYPE_Z9264_NON_NEBS 0x2 +#define BRD_TYPE_Z9264_NEBS 0x3 +#define BRD_TYPE_S5212_NON_NEBS 0x4 +#define BRD_TYPE_S5212_NEBS 0x5 +#define BRD_TYPE_S5224_NON_NEBS 0x6 +#define BRD_TYPE_S5224_NEBS 0x7 +#define BRD_TYPE_S5248_NON_NEBS 0x8 +#define BRD_TYPE_S5248_NEBS 0x9 +#define BRD_TYPE_S5296_NON_NEBS 0xa +#define BRD_TYPE_S5296_NEBS 0xb +#define BRD_TYPE_S5232_NON_NEBS 0xc +#define BRD_TYPE_S5232_NEBS 0xd + +#define FPGA_CTL_REG_SIZE 0x60 +#define MSI_VECTOR_MAP_MASK 0x1f +#define MSI_VECTOR_MAP1 0x58 +#define I2C_CH1_MSI_MAP_VECT_8 0x00000008 +#define I2C_CH2_MSI_MAP_VECT_9 0x00000120 +#define I2C_CH3_MSI_MAP_VECT_10 0x00002800 +#define I2C_CH4_MSI_MAP_VECT_11 0x00058000 +#define I2C_CH5_MSI_MAP_VECT_12 0x00c00000 +#define I2C_CH6_MSI_MAP_VECT_13 0x15000000 +#define MSI_VECTOR_MAP2 0x5c +#define I2C_CH7_MSI_MAP_VECT_14 0x0000000e +#define MSI_VECTOR_MAP3 0x9c +#define I2C_CH8_MSI_MAP_VECT_8 0x00800000 +#define I2C_CH8_MSI_MAP_VECT_16 0x01100000 +#define I2C_CH9_MSI_MAP_VECT_9 0x12000000 +#define I2C_CH9_MSI_MAP_VECT_17 0x24000000 +#define MSI_VECTOR_MAP4 0xa0 +#define I2C_CH10_MSI_MAP_VECT_10 0x0000000a +#define I2C_CH10_MSI_MAP_VECT_18 0x00000012 +#define I2C_CH11_MSI_MAP_VECT_11 0x00000120 +#define I2C_CH11_MSI_MAP_VECT_19 0x00000260 +#define I2C_CH12_MSI_MAP_VECT_12 0x00002800 +#define I2C_CH12_MSI_MAP_VECT_20 0x00005000 +#define I2C_CH13_MSI_MAP_VECT_13 0x00058000 +#define I2C_CH13_MSI_MAP_VECT_21 0x000a8000 +#define I2C_CH14_MSI_MAP_VECT_14 0x00c00000 +#define I2C_CH14_MSI_MAP_VECT_22 0x01600000 +#define I2C_CH15_MSI_MAP_VECT_8 0x10000000 +#define I2C_CH15_MSI_MAP_VECT_23 0x2e000000 +#define MSI_VECTOR_MAP5 0xa4 +#define I2C_CH16_MSI_MAP_VECT_9 0x00000009 +#define I2C_CH16_MSI_MAP_VECT_24 0x00000018 + +#define MSI_VECTOR_REV_00 16 +#define MSI_VECTOR_REV_01 32 + +#define FPGA_MSI_VECTOR_ID_8 8 +#define FPGA_MSI_VECTOR_ID_9 9 +#define FPGA_MSI_VECTOR_ID_10 10 +#define FPGA_MSI_VECTOR_ID_11 11 +#define FPGA_MSI_VECTOR_ID_12 12 +#define FPGA_MSI_VECTOR_ID_13 13 +#define FPGA_MSI_VECTOR_ID_14 14 +#define FPGA_MSI_VECTOR_ID_15 15 /*Note: this is external MSI vector id */ +#define FPGA_MSI_VECTOR_ID_16 16 +#define FPGA_MSI_VECTOR_ID_17 17 +#define FPGA_MSI_VECTOR_ID_18 18 +#define FPGA_MSI_VECTOR_ID_19 19 +#define FPGA_MSI_VECTOR_ID_20 20 +#define FPGA_MSI_VECTOR_ID_21 21 +#define FPGA_MSI_VECTOR_ID_22 22 +#define FPGA_MSI_VECTOR_ID_23 23 +#define FPGA_MSI_VECTOR_ID_24 24 + +#define MAX_WAIT_LOOP 10 + +static int total_i2c_pci_bus = 0; +static uint32_t board_rev_type = 0; +static struct fpgalogic_i2c fpgalogic_i2c[I2C_PCI_MAX_BUS]; +static struct i2c_adapter i2c_pci_adap[I2C_PCI_MAX_BUS]; +static struct mutex i2c_xfer_lock[I2C_PCI_MAX_BUS]; + +static void fpgai2c_reg_set_8(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + iowrite8(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void fpgai2c_reg_set_16(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + iowrite16(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void fpgai2c_reg_set_32(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + iowrite32(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void fpgai2c_reg_set_16be(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + iowrite16be(value, i2c->base + (reg << i2c->reg_shift)); +} + +static void fpgai2c_reg_set_32be(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + iowrite32be(value, i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 fpgai2c_reg_get_8(struct fpgalogic_i2c *i2c, int reg) +{ + return ioread8(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 fpgai2c_reg_get_16(struct fpgalogic_i2c *i2c, int reg) +{ + return ioread16(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 fpgai2c_reg_get_32(struct fpgalogic_i2c *i2c, int reg) +{ + return ioread32(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 fpgai2c_reg_get_16be(struct fpgalogic_i2c *i2c, int reg) +{ + return ioread16be(i2c->base + (reg << i2c->reg_shift)); +} + +static inline u8 fpgai2c_reg_get_32be(struct fpgalogic_i2c *i2c, int reg) +{ + return ioread32be(i2c->base + (reg << i2c->reg_shift)); +} + +static inline void fpgai2c_reg_set(struct fpgalogic_i2c *i2c, int reg, u8 value) +{ + i2c->reg_set(i2c, reg, value); + udelay(100); +} + +static inline u8 fpgai2c_reg_get(struct fpgalogic_i2c *i2c, int reg) +{ + udelay(100); + return i2c->reg_get(i2c, reg); +} + +static void fpgai2c_dump(struct fpgalogic_i2c *i2c) +{ + u8 tmp; + + PRINT("Logic register dump:\n"); + + tmp = fpgai2c_reg_get(i2c, FPGAI2C_REG_PRELOW); + PRINT("FPGAI2C_REG_PRELOW (%d) = 0x%x\n",FPGAI2C_REG_PRELOW,tmp); + + tmp = fpgai2c_reg_get(i2c, FPGAI2C_REG_PREHIGH); + PRINT("FPGAI2C_REG_PREHIGH(%d) = 0x%x\n",FPGAI2C_REG_PREHIGH,tmp); + + tmp = fpgai2c_reg_get(i2c, FPGAI2C_REG_CONTROL); + PRINT("FPGAI2C_REG_CONTROL(%d) = 0x%x\n",FPGAI2C_REG_CONTROL,tmp); + + tmp = fpgai2c_reg_get(i2c, FPGAI2C_REG_DATA); + PRINT("FPGAI2C_REG_DATA (%d) = 0x%x\n",FPGAI2C_REG_DATA,tmp); + + tmp = fpgai2c_reg_get(i2c, FPGAI2C_REG_CMD); + PRINT("FPGAI2C_REG_CMD (%d) = 0x%x\n",FPGAI2C_REG_CMD,tmp); +} + +static void fpgai2c_stop(struct fpgalogic_i2c *i2c) +{ + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_STOP); +} + +/* + * dell_get_mutex must be called prior to calling this function. + */ +static int fpgai2c_poll(struct fpgalogic_i2c *i2c) +{ + u8 stat = fpgai2c_reg_get(i2c, FPGAI2C_REG_STATUS); + struct i2c_msg *msg = i2c->msg; + u8 addr; + + /* Ready? */ + if (stat & FPGAI2C_REG_STAT_TIP) + return -EBUSY; + + if (i2c->state == STATE_DONE || i2c->state == STATE_ERROR) { + /* Stop has been sent */ + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_IACK); + if (i2c->state == STATE_ERROR) + return -EIO; + return 0; + } + + /* Error? */ + if ((stat & FPGAI2C_REG_STAT_ARBLOST) || ( i2c->msg == NULL) || ( i2c->msg->buf == NULL)) { + i2c->state = STATE_ERROR; + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_STOP); + return -EAGAIN; + } + + if (i2c->state == STATE_INIT) { + if (stat & FPGAI2C_REG_STAT_BUSY) + return -EBUSY; + + i2c->state = STATE_ADDR; + } + + if (i2c->state == STATE_ADDR) { + /* 10 bit address? */ + if (i2c->msg->flags & I2C_M_TEN) { + addr = 0xf0 | ((i2c->msg->addr >> 7) & 0x6); + i2c->state = STATE_ADDR10; + } else { + addr = (i2c->msg->addr << 1); + i2c->state = STATE_START; + } + + /* Set read bit if necessary */ + addr |= (i2c->msg->flags & I2C_M_RD) ? 1 : 0; + + fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, addr); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_START); + + return 0; + } + + /* Second part of 10 bit addressing */ + if (i2c->state == STATE_ADDR10) { + fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, i2c->msg->addr & 0xff); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_WRITE); + + i2c->state = STATE_START; + return 0; + } + + if (i2c->state == STATE_START || i2c->state == STATE_WRITE) { + i2c->state = (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE; + + if (stat & FPGAI2C_REG_STAT_NACK) { + i2c->state = STATE_ERROR; + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_STOP); + return -ENXIO; + } + } else { + msg->buf[i2c->pos++] = fpgai2c_reg_get(i2c, FPGAI2C_REG_DATA); + } + + if (i2c->pos >= msg->len) { + i2c->nmsgs--; + i2c->msg++; + i2c->pos = 0; + msg = i2c->msg; + + if (i2c->nmsgs) { + if (!(msg->flags & I2C_M_NOSTART)) { + i2c->state = STATE_ADDR; + return 0; + } else { + i2c->state = (msg->flags & I2C_M_RD) + ? STATE_READ : STATE_WRITE; + } + } else { + i2c->state = STATE_DONE; + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_STOP); + return 0; + } + } + + if (i2c->state == STATE_READ) { + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, i2c->pos == (msg->len - 1) ? + FPGAI2C_REG_CMD_READ_NACK : FPGAI2C_REG_CMD_READ_ACK); + } else { + fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, msg->buf[i2c->pos++]); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_WRITE); + } + + return 0; +} + +static void fpgai2c_process(struct fpgalogic_i2c *i2c) +{ + struct i2c_msg *msg = i2c->msg; + u8 stat = fpgai2c_reg_get(i2c, FPGAI2C_REG_STATUS); + + PRINT("fpgai2c_process in. status reg :0x%x\n", stat); + + if ((i2c->state == STATE_STOP) || (i2c->state == STATE_ERROR)) { + /* stop has been sent */ + PRINT("fpgai2c_process FPGAI2C_REG_CMD_IACK stat = 0x%x Set FPGAI2C_REG_CMD(0%x) FPGAI2C_REG_CMD_IACK = 0x%x\n" \ + ,stat, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_IACK); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_IACK); + if(i2c->state == STATE_STOP) { + i2c->state = STATE_DONE; + } + wake_up(&i2c->wait); + return; + } + + + /* error? */ + if (stat & FPGAI2C_REG_STAT_ARBLOST) { + i2c->state = STATE_ERROR; + PRINT("fpgai2c_process FPGAI2C_REG_STAT_ARBLOST FPGAI2C_REG_CMD_STOP\n"); + fpgai2c_stop(i2c); + return; + } + + /* Spurious IRQs would lead to invocation of handler with msg being NULL. + * Skip handling them. + */ + if (msg == NULL) + return; + + if ((i2c->state == STATE_START) || (i2c->state == STATE_WRITE)) { + i2c->state = + (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE; + + if (stat & FPGAI2C_REG_STAT_NACK) { + i2c->state = STATE_ERROR; + fpgai2c_stop(i2c); + return; + } + } else + { + if(( i2c->msg == NULL) || ( i2c->msg->buf == NULL) || (i2c->pos >= i2c->msg->len) ) { + printk("crash debug..1 fpgai2c_process MSG and MAS->BUFF is NULL or pos > len "); + return; + } + + msg->buf[i2c->pos++] = fpgai2c_reg_get(i2c, FPGAI2C_REG_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 = (msg->addr << 1); + + if (msg->flags & I2C_M_RD) + addr |= 1; + + i2c->state = STATE_START; + fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, addr); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_START); + return; + } else + { + i2c->state = (msg->flags & I2C_M_RD) + ? STATE_READ : STATE_WRITE; + } + } else { + i2c->state = STATE_STOP; + fpgai2c_stop(i2c); + return; + } + } + + if (i2c->state == STATE_READ) { + + if(( i2c->msg == NULL) || ( i2c->msg->buf == NULL) || (i2c->pos >= i2c->msg->len) ) { + printk("crash debug..2 fpgai2c_process MSG and MAS->BUFF is NULL or pos > len "); + return; + } + + + PRINT("fpgai2c_poll STATE_READ i2c->pos=%d msg->len-1 = 0x%x set FPGAI2C_REG_CMD = 0x%x\n",i2c->pos, msg->len-1, + i2c->pos == (msg->len-1) ? FPGAI2C_REG_CMD_READ_NACK : FPGAI2C_REG_CMD_READ_ACK); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, i2c->pos == (msg->len-1) ? + FPGAI2C_REG_CMD_READ_NACK : FPGAI2C_REG_CMD_READ_ACK); + } else { + PRINT("fpgai2c_process set FPGAI2C_REG_DATA(0x%x)\n",FPGAI2C_REG_DATA); + + if(( i2c->msg == NULL) || ( i2c->msg->buf == NULL) || (i2c->pos >= i2c->msg->len) ) { + printk("crash debug..3 fpgai2c_process MSG and MAS->BUFF is NULL or pos > len "); + return; + } + + fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, msg->buf[i2c->pos++]); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_WRITE); + } +} + +static irqreturn_t fpgai2c_isr(int irq, void *dev_id) +{ + struct fpgalogic_i2c *i2c = dev_id; + fpgai2c_process(i2c); + + return IRQ_HANDLED; +} +void dell_get_mutex(struct fpgalogic_i2c *i2c) +{ + mutex_lock(&i2c->lock); +} + +/** + * dell_release_mutex - release mutex + */ +void dell_release_mutex(struct fpgalogic_i2c *i2c) +{ + mutex_unlock(&i2c->lock); +} + +static int fpgai2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +{ + struct fpgalogic_i2c *i2c = i2c_get_adapdata(adap); + int ret; + unsigned long timeout = jiffies + msecs_to_jiffies(1000); + + i2c->msg = msgs; + i2c->pos = 0; + i2c->nmsgs = num; + i2c->state = (use_irq == 1) ? STATE_START : STATE_INIT; + + PRINT("i2c->msg->addr = 0x%x i2c->msg->flags = 0x%x\n",i2c->msg->addr,i2c->msg->flags); + PRINT("I2C_M_RD = 0x%x i2c->msg->addr << 1 = 0x%x\n",I2C_M_RD,i2c->msg->addr << 1); + + if (!use_irq) { + /* Handle the transfer */ + while (time_before(jiffies, timeout)) { + dell_get_mutex(i2c); + ret = fpgai2c_poll(i2c); + dell_release_mutex(i2c); + + if (i2c->state == STATE_DONE || i2c->state == STATE_ERROR) + return (i2c->state == STATE_DONE) ? num : ret; + + if (ret == 0) + timeout = jiffies + HZ; + + usleep_range(5, 15); + } + + i2c->state = STATE_ERROR; + + return -ETIMEDOUT; + + + } else { + ret = -ETIMEDOUT; + PRINT("Set FPGAI2C_REG_DATA(0%x) val = 0x%x\n",FPGAI2C_REG_DATA, + (i2c->msg->addr << 1) | ((i2c->msg->flags & I2C_M_RD) ? 1:0)); + + fpgai2c_reg_set(i2c, FPGAI2C_REG_DATA, + (i2c->msg->addr << 1) | + ((i2c->msg->flags & I2C_M_RD) ? 1:0)); + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_START); + + /* Interrupt mode */ + if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || + (i2c->state == STATE_DONE), HZ)) + ret = (i2c->state == STATE_DONE) ? num : -EIO; + return ret; + } +} + +static int fpgai2c_init(struct fpgalogic_i2c *i2c) +{ + int prescale; + int diff; + u8 ctrl = 0, stat, loop = 0; + + if (i2c->reg_io_width == 0) + i2c->reg_io_width = 1; /* Set to default value */ + + if (!i2c->reg_set || !i2c->reg_get) { + bool be = 0; //1:big_endian 0:little_endian + + switch (i2c->reg_io_width) { + case 1: + i2c->reg_set = fpgai2c_reg_set_8; + i2c->reg_get = fpgai2c_reg_get_8; + break; + + case 2: + i2c->reg_set = be ? fpgai2c_reg_set_16be : fpgai2c_reg_set_16; + i2c->reg_get = be ? fpgai2c_reg_get_16be : fpgai2c_reg_get_16; + break; + + case 4: + i2c->reg_set = be ? fpgai2c_reg_set_32be : fpgai2c_reg_set_32; + i2c->reg_get = be ? fpgai2c_reg_get_32be : fpgai2c_reg_get_32; + break; + + default: + PRINT("Unsupported I/O width (%d)\n", + i2c->reg_io_width); + return -EINVAL; + } + } + + PRINT("%s(), line:%d\n", __func__, __LINE__); + PRINT("i2c->base = 0x%p\n",i2c->base); + + PRINT("ctrl = 0x%x\n",ctrl); + PRINT("set ctrl = 0x%x\n",ctrl & ~(FPGAI2C_REG_CTRL_EN|FPGAI2C_REG_CTRL_IEN)); + + /* make sure the device is disabled */ + fpgai2c_reg_set(i2c, FPGAI2C_REG_CONTROL, ctrl & ~(FPGAI2C_REG_CTRL_EN|FPGAI2C_REG_CTRL_IEN)); + + /* + * I2C Frequency depends on host clock + * input clock of 100MHz + * prescale to 100MHz / ( 5*100kHz) -1 = 199 = 0x4F 100000/(5*100)-1=199=0xc7 + */ + prescale = (i2c->ip_clock_khz / (5 * i2c->bus_clock_khz)) - 1; + prescale = clamp(prescale, 0, 0xffff); + + diff = i2c->ip_clock_khz / (5 * (prescale + 1)) - i2c->bus_clock_khz; + if (abs(diff) > i2c->bus_clock_khz / 10) { + PRINT("Unsupported clock settings: core: %d KHz, bus: %d KHz\n", + i2c->ip_clock_khz, i2c->bus_clock_khz); + return -EINVAL; + } + + fpgai2c_reg_set(i2c, FPGAI2C_REG_PRELOW, prescale & 0xff); + fpgai2c_reg_set(i2c, FPGAI2C_REG_PREHIGH, prescale >> 8); + + /* Init the device */ + fpgai2c_reg_set(i2c, FPGAI2C_REG_CONTROL, ctrl | FPGAI2C_REG_CTRL_EN); + if (use_irq) { + /* Clear any pending interrupts */ + fpgai2c_reg_set(i2c, FPGAI2C_REG_CMD, FPGAI2C_REG_CMD_IACK); + while (loop < MAX_WAIT_LOOP) { + stat = fpgai2c_reg_get(i2c, FPGAI2C_REG_STATUS); + if (stat & FPGAI2C_REG_STAT_IF) { + udelay(100); + loop++; + } else { + break; + } + } + if (loop >=10) { + printk("interrupts can't be cleared: loop %d\n", loop); + } + } + fpgai2c_dump(i2c); + + /* Initialize interrupt handlers if not already done */ + init_waitqueue_head(&i2c->wait); + + return 0; +} + +static int fpgai2c_interrupt_enable(struct fpgapci_dev *fpgapci) +{ + int i; + u8 ctrl = 0; + + /* Enable Interrupts */ + for (i = 0 ; i < total_i2c_pci_bus; i ++) { + fpgai2c_reg_set(&fpgalogic_i2c[i], FPGAI2C_REG_CONTROL, ctrl | FPGAI2C_REG_CTRL_IEN | FPGAI2C_REG_CTRL_EN); + } + return 0; +} + +static u32 fpgai2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm fpgai2c_algorithm = { + .master_xfer = fpgai2c_xfer, + .functionality = fpgai2c_func, +}; + +static int i2c_pci_add_bus (struct i2c_adapter *adap) +{ + int ret = 0; + /* Register new adapter */ + adap->algo = &fpgai2c_algorithm; + ret = i2c_add_numbered_adapter(adap); + return ret; +} + +static int i2c_init_internal_data(void) +{ + int i; + PRINT("%s(), line:%d\n", __func__, __LINE__); + + for( i = 0; i < total_i2c_pci_bus; i++ ) + { + fpgalogic_i2c[i].reg_shift = 0; /* 8 bit registers */ + fpgalogic_i2c[i].reg_io_width = 1; /* 8 bit read/write */ + fpgalogic_i2c[i].timeout = 500;//1000;//1ms + fpgalogic_i2c[i].ip_clock_khz = 100000;//100000;/* input clock of 100MHz */ + fpgalogic_i2c[i].bus_clock_khz = 100; + fpgalogic_i2c[i].base = fpga_base_addr + i*FPGALOGIC_CH_OFFSET; + mutex_init(&fpgalogic_i2c[i].lock); + fpgai2c_init(&fpgalogic_i2c[i]); + } + + return 0; +} + + +static int i2c_pci_init (struct fpgapci_dev *fpgapci) +{ + int i; + + if ((fpgapci != NULL) && (fpgapci->pci_dev->vendor == PCI_VENDOR_ID_ALTERA)) { + num_bus = I2C_PCI_BUS_NUM_10; + } else { + num_bus = I2C_PCI_MAX_BUS; + } + + printk("vendor 0x%x, num_bus 0x%x\n", fpgapci->pci_dev->vendor, num_bus); + total_i2c_pci_bus = num_bus; + + memset (&i2c_pci_adap, 0, sizeof(i2c_pci_adap)); + memset (&fpgalogic_i2c, 0, sizeof(fpgalogic_i2c)); + for(i=0; i < i2c_bus_controller_numb; i++) + mutex_init(&i2c_xfer_lock[i]); + + /* Initialize driver's itnernal data structures */ + i2c_init_internal_data(); + + for (i = 0 ; i < total_i2c_pci_bus; i ++) { + + i2c_pci_adap[i].owner = THIS_MODULE; + i2c_pci_adap[i].class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + + i2c_pci_adap[i].algo_data = &fpgalogic_i2c[i]; + /* /dev/i2c-600 ~ /dev/i2c-615 for FPGA LOGIC I2C channel controller 1-7 */ + i2c_pci_adap[i].nr = i+600; + sprintf( i2c_pci_adap[ i ].name, "i2c-pci-%d", i ); + /* Add the bus via the algorithm code */ + if( i2c_pci_add_bus( &i2c_pci_adap[ i ] ) != 0 ) + { + PRINT("Cannot add bus %d to algorithm layer\n", i ); + return( -ENODEV ); + } + i2c_set_adapdata(&i2c_pci_adap[i], &fpgalogic_i2c[i]); + + PRINT( "Registered bus id: %s\n", kobject_name(&i2c_pci_adap[ i ].dev.kobj)); + } + + return 0; +} + +static void i2c_pci_deinit(void) +{ + int i; + for( i = 0; i < total_i2c_pci_bus; i++ ){ + i2c_del_adapter(&i2c_pci_adap[i]); + } + +} + +/* Find upstream PCIe root node. + * Used for re-training and disabling AER. */ +static struct pci_dev* find_upstream_dev (struct pci_dev *dev) +{ + struct pci_bus *bus = 0; + struct pci_dev *bridge = 0; + struct pci_dev *cur = 0; + int found_dev = 0; + + bus = dev->bus; + if (bus == 0) { + PRINT ( "Device doesn't have an associated bus!\n"); + return 0; + } + + bridge = bus->self; + if (bridge == 0) { + PRINT ( "Can't get the bridge for the bus!\n"); + return 0; + } + + PRINT ( "Upstream device %x/%x, bus:slot.func %02x:%02x.%02x\n", + bridge->vendor, bridge->device, + bridge->bus->number, PCI_SLOT(bridge->devfn), PCI_FUNC(bridge->devfn)); + + PRINT ( "List of downstream devices:"); + list_for_each_entry (cur, &bus->devices, bus_list) { + if (cur != 0) { + PRINT ( " %x/%x", cur->vendor, cur->device); + if (cur == dev) { + found_dev = 1; + } + } + } + PRINT ( "\n"); + if (found_dev) { + return bridge; + } else { + PRINT ( "Couldn't find upstream device!\n"); + return 0; + } +} + + +static int scan_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev) +{ + int i; + + for (i = 0; i < PCI_NUM_BARS; i++) { + //unsigned long bar_start = pci_resource_start(dev, i); + //if (bar_start) { + //unsigned long bar_end = pci_resource_end(dev, i); + //unsigned long bar_flags = pci_resource_flags(dev, i); + //PRINT ( "BAR[%d] 0x%08lx-0x%08lx flags 0x%08lx", + //i, bar_start, bar_end, bar_flags); + //} + } + + return 0; +} + + +/** + * Map the device memory regions into kernel virtual address space + * after verifying their sizes respect the minimum sizes needed, given + * by the bar_min_len[] array. + */ +static int map_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev) +{ + int i; + + for (i = 0; i < PCI_NUM_BARS; i++){ + phys_addr_t bar_start = pci_resource_start(dev, i); + phys_addr_t bar_end = pci_resource_end(dev, i); + unsigned long bar_length = bar_end - bar_start + 1; + fpgapci->bar_length[i] = bar_length; + + + if (!bar_start || !bar_end) { + fpgapci->bar_length[i] = 0; + continue; + } + + if (bar_length < 1) { + PRINT ( "BAR #%d length is less than 1 byte\n", i); + continue; + } + + PRINT ( "bar_start=%llx, bar_end=%llx, bar_length=%lx, flag=%lx\n", bar_start, + bar_end, bar_length, pci_resource_flags(dev, i)); + + /* map the device memory or IO region into kernel virtual + * address space */ + fpgapci->bar[i] = ioremap_cache (bar_start + FPGALOGIC_I2C_BASE, I2C_PCI_MAX_BUS * FPGALOGIC_CH_OFFSET); + + if (!fpgapci->bar[i]) { + PRINT ( "Could not map BAR #%d.\n", i); + return -1; + } + + PRINT ( "BAR[%d] mapped at 0x%p with length %lu.", i, + fpgapci->bar[i], bar_length); + + if(i == 0) //FPGA register is in the BAR[0] + { + + fpga_phys_addr = bar_start; + fpga_ctl_addr = ioremap_cache (bar_start, FPGA_CTL_REG_SIZE); + fpga_base_addr = fpgapci->bar[i]; + } + + PRINT ( "BAR[%d] mapped at 0x%p with length %lu.\n", i, + fpgapci->bar[i], bar_length); + } + return 0; +} + +static void free_bars(struct fpgapci_dev *fpgapci, struct pci_dev *dev) +{ + int i; + + for (i = 0; i < PCI_NUM_BARS; i++) { + if (fpgapci->bar[i]) { + pci_iounmap(dev, fpgapci->bar[i]); + fpgapci->bar[i] = NULL; + } + } +} + +#define FPGA_PCI_NAME "FPGA_PCI" + +/** + * @brief Register specific function with msi interrupt line + * @param dev Pointer to pci-device, which should be allocated + * @param int interrupt number relative to global interrupt number + * @return Returns error code or zero if success + * */ +static int register_intr_handler(struct pci_dev *dev, int irq_num_id) +{ + int err = 0; + struct fpgapci_dev *fpgapci = 0; + + fpgapci = (struct fpgapci_dev*) dev_get_drvdata(&dev->dev); + if (fpgapci == 0) { + PRINT ( ": fpgapci_dev is 0\n"); + return err; + } + /* FPGA SPEC 4.3.1.34, First i2c channel mapped to vector 8 */ + switch (irq_num_id) { + case FPGA_MSI_VECTOR_ID_8: + err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME, + FPGA_PCI_NAME, &fpgalogic_i2c[0]); + fpgapci->irq_assigned++; + break; + case FPGA_MSI_VECTOR_ID_9: + err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME, + FPGA_PCI_NAME, &fpgalogic_i2c[1]); + fpgapci->irq_assigned++; + break; + case FPGA_MSI_VECTOR_ID_10: + err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME, + FPGA_PCI_NAME, &fpgalogic_i2c[2]); + fpgapci->irq_assigned++; + break; + case FPGA_MSI_VECTOR_ID_11: + err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME, + FPGA_PCI_NAME, &fpgalogic_i2c[3]); + fpgapci->irq_assigned++; + break; + case FPGA_MSI_VECTOR_ID_12: + err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, IRQF_EARLY_RESUME, + FPGA_PCI_NAME, &fpgalogic_i2c[4]); + fpgapci->irq_assigned++; + break; + case FPGA_MSI_VECTOR_ID_13: + if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_5) { + err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, + IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[5]); + fpgapci->irq_assigned++; + } + break; + case FPGA_MSI_VECTOR_ID_14: + if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_5) { + err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, + IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[6]); + fpgapci->irq_assigned++; + } + break; + case FPGA_MSI_VECTOR_ID_15: + /*it is an external interrupt number. Ignore this case */ + break; + case FPGA_MSI_VECTOR_ID_16: + if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_7) { + err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, + IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[7]); + fpgapci->irq_assigned++; + } + break; + case FPGA_MSI_VECTOR_ID_17: + if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_8) { + err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, + IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[8]); + fpgapci->irq_assigned++; + } + break; + case FPGA_MSI_VECTOR_ID_18: + if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_8) { + err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, + IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[9]); + fpgapci->irq_assigned++; + } + break; + case FPGA_MSI_VECTOR_ID_19: + if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_10) { + err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, + IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[10]); + fpgapci->irq_assigned++; + } + break; + case FPGA_MSI_VECTOR_ID_20: + if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_10) { + err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, + IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[11]); + fpgapci->irq_assigned++; + } + break; + case FPGA_MSI_VECTOR_ID_21: + if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_12) { + err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, + IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[12]); + fpgapci->irq_assigned++; + } + break; + case FPGA_MSI_VECTOR_ID_22: + if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_12) { + err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, + IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[13]); + fpgapci->irq_assigned++; + } + break; + case FPGA_MSI_VECTOR_ID_23: + if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_12) { + err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, + IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[14]); + fpgapci->irq_assigned++; + } + break; + case FPGA_MSI_VECTOR_ID_24: + if (total_i2c_pci_bus > I2C_PCI_BUS_NUM_12) { + err = request_irq(dev->irq + irq_num_id, fpgai2c_isr, + IRQF_EARLY_RESUME, FPGA_PCI_NAME, &fpgalogic_i2c[15]); + fpgapci->irq_assigned++; + } + break; + + default: + PRINT("No more interrupt handler for number (%d)\n", + dev->irq + irq_num_id); + break; + } + + return err; +} +/* Mask for MSI Multi message enable bits */ +#define MSI_MME 0x70 +/** + * These enums define the type of interrupt scheme that the overall + * system uses. + */ +enum fpga_irq_type { + INT_MSI_SINGLE, + INT_MSI_MULTI, + INT_MSIX, + INT_NONE, + INT_FENCE /* Last item to guard from loop run-overs */ +}; +/** + * @def PCI_DEVICE_STATUS + * define the offset for STS register + * from the start of PCI config space as specified in the + * NVME_Comliance 1.0b. offset 06h:STS - Device status. + * This register has error status for NVME PCI Exress + * Card. After reading data from this reagister, the driver + * will identify if any error is set during the operation and + * report as kernel alert message. + */ +#define PCI_DEVICE_STATUS 0x6 +/** + * @def NEXT_MASK + * This indicates the location of the next capability item + * in the list. + */ +#define NEXT_MASK 0xFF00 +/** + * @def MSIXCAP_ID + * This bit indicates if the pointer leading to this position + * is a capability. + */ +#define MSIXCAP_ID 0x11 +/** + * @def MSICAP_ID + * This bit indicates if the pointer leading to this position + * is a capability. + */ +#define MSICAP_ID 0x5 + +/** + * @def CL_MASK + * This bit position indicates Capabilities List of the controller + * The controller should support the PCI Power Management cap as a + * minimum. + */ +#define CL_MASK 0x0010 + +/** + * @def CAP_REG + * Set to offset defined in NVME Spec 1.0b. + */ +#define CAP_REG 0x34 +static void msi_set_enable(struct pci_dev *dev, int enable) +{ + int pos,maxvec; + u16 control; + int request_private_bits = 4; + + pos = pci_find_capability(dev, PCI_CAP_ID_MSI); + + if (pos) { + pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); + maxvec = 1 << ((control & PCI_MSI_FLAGS_QMASK) >> 1); + PRINT("control = 0x%x maxvec = 0x%x\n", control, maxvec); + control &= ~PCI_MSI_FLAGS_ENABLE; + + + /* + * The PCI 2.3 spec mandates that there are at most 32 + * interrupts. If this device asks for more, only give it one. + */ + if (request_private_bits > 5) { + request_private_bits = 0; + } + + /* Update the number of IRQs the device has available to it */ + control &= ~PCI_MSI_FLAGS_QSIZE; + control |= (request_private_bits << 4); + + pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); + } +} +/** + * @brief Enables pcie-device and claims/remaps neccessary bar resources + * @param dev Pointer to pci-device, which should be allocated + * @return Returns error code or zero if success + * */ +static int fpgapci_setup_device(struct fpgapci_dev *fpgapci,struct pci_dev *dev) +{ + int err = 0; + + /* wake up the pci device */ + err = pci_enable_device(dev); + if(err) { + PRINT("failed to enable pci device %d\n", err); + goto error_pci_en; + } + + /* on platforms with buggy ACPI, pdev->msi_enabled may be set to + * allow pci_enable_device to work. This indicates INTx was not routed + * and only MSI should be used + */ + + pci_set_master(dev); + + /* Setup the BAR memory regions */ + err = pci_request_regions(dev, DRIVER_NAME); + if (err) { + PRINT("failed to enable pci device %d\n", err); + goto error_pci_req; + } + + scan_bars(fpgapci, dev); + + if (map_bars(fpgapci, dev)) { + goto fail_map_bars; + } + + i2c_pci_init(fpgapci); + + return 0; + /* ERROR HANDLING */ +fail_map_bars: + pci_release_regions(dev); +error_pci_req: + pci_disable_device(dev); +error_pci_en: + return -ENODEV; +} + +static int fpgapci_configure_msi(struct fpgapci_dev *fpgapci,struct pci_dev *dev) +{ + int err = 0, i; + int request_vec; + + msi_set_enable(dev,1); + PRINT("Check MSI capability after msi_set_enable\n"); + + + /*Above 4.1.12*/ + request_vec = total_i2c_pci_bus; + err = pci_alloc_irq_vectors(dev, request_vec, pci_msi_vec_count(dev), + PCI_IRQ_MSI);//PCI_IRQ_AFFINITY | PCI_IRQ_MSI); + + if (err <= 0) { + PRINT("Cannot set MSI vector (%d)\n", err); + goto error_no_msi; + } else { + PRINT("Got %d MSI vectors starting at %d\n", err, dev->irq); + if ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_00) { + if (err < MSI_VECTOR_REV_00) { + goto error_disable_msi; + } + } else if (((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_01) || + ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_02) || + ((board_rev_type & MB_BRD_REV_MASK) == MB_BRD_REV_03)) { + if (err < MSI_VECTOR_REV_01) { + goto error_disable_msi; + } + } + } + fpgapci->irq_first = dev->irq; + fpgapci->irq_length = err; + fpgapci->irq_assigned = 0; + + + for(i = 0; i < fpgapci->irq_length; i++) { + err = register_intr_handler(dev, i); + if (err) { + PRINT("Cannot request Interrupt number %d\n", i); + goto error_pci_req_irq; + } + } + + return 0; + +error_pci_req_irq: + for(i = 0; i < fpgapci->irq_assigned; i++) + { + PRINT("free_irq %d i =%d\n",fpgapci->irq_first + i,i); + if (i < 7) + free_irq(fpgapci->irq_first + 8 + i, &fpgalogic_i2c[i]); + else + free_irq(fpgapci->irq_first + 8 + i + 1, &fpgalogic_i2c[i]); + } +error_disable_msi: + pci_disable_msi(fpgapci->pci_dev); +error_no_msi: + return -ENOSPC; +} + +static int fpgapci_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct fpgapci_dev *fpgapci = 0; + +#ifdef TEST + PRINT ( " vendor = 0x%x, device = 0x%x, class = 0x%x, bus:slot.func = %02x:%02x.%02x\n", + dev->vendor, dev->device, dev->class, + dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); +#endif + fpgapci = kzalloc(sizeof(struct fpgapci_dev), GFP_KERNEL); + + if (!fpgapci) { + PRINT( "Couldn't allocate memory!\n"); + goto fail_kzalloc; + } + + fpgapci->pci_dev = dev; + dev_set_drvdata(&dev->dev, (void*)fpgapci); + + fpgapci->upstream = find_upstream_dev (dev); + + if(fpgapci_setup_device(fpgapci,dev)) { + goto error_no_device; + } + + if (use_irq) { + if(fpgapci_configure_msi(fpgapci,dev)) { + goto error_cannot_configure; + } + /* Enable interrupt after config msi */ + fpgai2c_interrupt_enable(fpgapci); + + } + + + return 0; + /* ERROR HANDLING */ +error_cannot_configure: + printk("error_cannot_configure\n"); + free_bars (fpgapci, dev); + pci_release_regions(dev); + pci_disable_device(dev); +error_no_device: + i2c_pci_deinit(); + printk("error_no_device\n"); +fail_kzalloc: + return -1; + + +} + +static void fpgapci_remove(struct pci_dev *dev) +{ + struct fpgapci_dev *fpgapci = 0; + int i; + PRINT (": dev is %p\n", dev); + + if (dev == 0) { + PRINT ( ": dev is 0\n"); + return; + } + + fpgapci = (struct fpgapci_dev*) dev_get_drvdata(&dev->dev); + if (fpgapci == 0) { + PRINT ( ": fpgapci_dev is 0\n"); + return; + } + i2c_pci_deinit(); + // + if (use_irq) + { + for(i = 0; i < fpgapci->irq_assigned; i++) + { + PRINT("free_irq %d i =%d\n",fpgapci->irq_first + i,i); + if (i < 7) + free_irq(fpgapci->irq_first + 8 + i, &fpgalogic_i2c[i]); + else + free_irq(fpgapci->irq_first + 8 + i + 1, &fpgalogic_i2c[i]); + } + } + pci_disable_msi(fpgapci->pci_dev); + free_bars (fpgapci, dev); + pci_disable_device(dev); + pci_release_regions(dev); + + kfree (fpgapci); +} + +static const struct pci_device_id fpgapci_ids[] = { + {PCI_DEVICE(PCI_VENDOR_ID_XILINX, DEVICE)}, + {PCI_DEVICE(PCI_VENDOR_ID_ALTERA, PCI_DEVICE_ID_ALTERA)}, + {0, }, +}; + +MODULE_DEVICE_TABLE(pci, fpgapci_ids); + +static struct pci_driver fpgapci_driver = { + .name = DRIVER_NAME, + .id_table = fpgapci_ids, + .probe = fpgapci_probe, + .remove = fpgapci_remove, + /* resume, suspend are optional */ +}; + +/* Initialize the driver module (but not any device) and register + * the module with the kernel PCI subsystem. */ +static int __init fpgapci_init(void) +{ + + if (pci_register_driver(&fpgapci_driver)) { + PRINT("pci_unregister_driver\n"); + pci_unregister_driver(&fpgapci_driver); + return -ENODEV; + } + + return 0; +} + +static void __exit fpgapci_exit(void) +{ + PRINT ("fpgapci_exit"); + + /* unregister this driver from the PCI bus driver */ + pci_unregister_driver(&fpgapci_driver); + +} + + +module_init (fpgapci_init); +module_exit (fpgapci_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("joyce_yu@dell.com"); +MODULE_DESCRIPTION ("Driver for FPGA Logic I2C bus"); +MODULE_SUPPORTED_DEVICE ("FPGA Logic I2C bus"); +MODULE_VERSION ("01.01"); diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/modules/mc24lc64t.c b/platform/broadcom/sonic-platform-modules-dell/z9432f/modules/mc24lc64t.c new file mode 100644 index 0000000000..002172f587 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/modules/mc24lc64t.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +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_device(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 "); +MODULE_DESCRIPTION("Microchip 24LC64T Driver"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/check_qsfp.sh b/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/check_qsfp.sh new file mode 100755 index 0000000000..4bde690b72 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/check_qsfp.sh @@ -0,0 +1,3 @@ +# Temporary dummy file for Z9432F. +# Will be updated soon. + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/pcisysfs.py b/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/pcisysfs.py new file mode 100755 index 0000000000..047618e057 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/pcisysfs.py @@ -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 --res ' + print '\t\t pcisysfs.py --set --val --offset --res ' + 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:]) + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/platform_sensors.py b/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/platform_sensors.py new file mode 100755 index 0000000000..3446a09321 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/platform_sensors.py @@ -0,0 +1,254 @@ +#!/usr/bin/python +""" +# Module on Z9432F, 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. +# This provies support for the following objects: +# * Onboard temperature sensors +# * FAN trays +# * PSU +""" + +import sys +import logging +import commands + +Z9432F_MAX_FAN_TRAYS = 7 +Z9432F_MAX_PSUS = 2 +IPMI_SENSOR_DATA = "ipmitool sdr elist" + +IPMI_RAW_STORAGE_READ = "ipmitool raw 0x0a 0x11 {0} {1} 0 1" + +# Dump sensor registers +class SdrStatus(object): + """ Contains IPMI SDR List """ + def __init__(self): + ipmi_cmd = IPMI_SENSOR_DATA + status, resp = commands.getstatusoutput(ipmi_cmd) + if status: + logging.error('Failed to execute: ' + ipmi_cmd) + sys.exit(0) + self.ipmi_sdr_dict = {} + for sdr_status in resp.split('\n'): + sdr_status_l = sdr_status.split('|') + sensor = sdr_status_l[0].strip() + value = sdr_status_l[4].strip() + self.ipmi_sdr_dict[sensor] = value + + + def get(self): + """ Returns SDR List """ + return self.ipmi_sdr_dict + +# Fetch a Fan Status +SDR_STATUS = SdrStatus() +def get_fan_status(fan_id): + """ Get Fan Status of give Id """ + status, cmd_ret = commands.getstatusoutput(IPMI_FAN_PRESENCE.format(fan_id)) + if status: + logging.error('Failed to execute : %s', IPMI_FAN_PRESENCE.format(fan_id)) + sys.exit(0) + return ' ' + cmd_ret.splitlines()[5].strip(' ').strip('[]') + +# Fetch a BMC register + + +def get_pmc_register(reg_name): + """ Returns the value of BMC Regster """ + + output = None + sdr_status = SDR_STATUS.get() + if reg_name in sdr_status: + output = sdr_status[reg_name] + else: + print '\nFailed to fetch: ' + reg_name + ' sensor ' + sys.exit(0) + + logging.basicConfig(level=logging.DEBUG) + return output + +# Fetch FRU on given offset +def fetch_raw_fru(dev_id, offset): + """ Fetch RAW value from FRU (dev_id) @ given offset """ + status, cmd_ret = commands.getstatusoutput(IPMI_RAW_STORAGE_READ.format(dev_id, offset)) + if status: + logging.error('Failed to execute ipmitool :' + IPMI_RAW_STORAGE_READ.format(dev_id, offset)) + return -1 + return int(cmd_ret.strip().split(' ')[1]) + + + + +def get_fan_airflow(fan_id): + """ Return Airflow of direction of FANTRAY(fan_id) """ + airflow_direction = ['Exhaust', 'Intake'] + dir_idx = fetch_raw_fru(fan_id+2, 0x45) + if dir_idx == -1: + return 'N/A' + return airflow_direction[dir_idx] + +#Fetch FRU Data for given fruid +def get_psu_airflow(psu_id): + """ Return Airflow Direction of psu_id """ + airflow_direction = ['Exhaust', 'Intake'] + dir_idx = fetch_raw_fru(psu_id, 0x2F) + if dir_idx == -1: + return 'N/A' + return airflow_direction[dir_idx] + +# Print the information for temperature sensors + + +def print_temperature_sensors(): + """ Prints Temperature Sensor """ + + print "\nOnboard Temperature Sensors:" + + print ' PT Left Temp: ',\ + (get_pmc_register('PT_Left_temp')) + print ' NPU Rear Temp: ',\ + (get_pmc_register('NPU_Rear_temp')) + print ' PT Right Temp: ',\ + (get_pmc_register('PT_Right_temp')) + print ' NPU Front Temp: ',\ + (get_pmc_register('NPU_Front_temp')) + print ' FAN Right Temp: ',\ + (get_pmc_register('FAN_Right_temp')) + print ' NPU Temp: ',\ + (get_pmc_register('NPU_temp')) + print ' CPU Temp: ',\ + (get_pmc_register('CPU_temp')) + print ' PSU1 AF Temp: ',\ + (get_pmc_register('PSU1_AF_temp')) + print ' PSU1 Mid Temp: ',\ + (get_pmc_register('PSU1_Mid_temp')) + print ' PSU1 Rear Temp: ',\ + (get_pmc_register('PSU1_Rear_temp')) + print ' PSU2 AF Temp: ',\ + (get_pmc_register('PSU2_AF_temp')) + print ' PSU2 Mid Temp: ',\ + (get_pmc_register('PSU2_Mid_temp')) + print ' PSU2 Rear Temp: ',\ + (get_pmc_register('PSU2_Rear_temp')) + + + commands.getstatusoutput('echo 0 > /sys/module/ipmi_si/parameters/kipmid_max_busy_us') + +print_temperature_sensors() + +# Print the information for 1 Fan Tray + + +def print_fan_tray(fan_tray): + """ Prints given Fan Tray information """ + fan_status = ['Abnormal', 'Normal'] + + print ' Fan Tray ' + str(fan_tray) + ':' + + fan_front_status = (get_pmc_register('Fan{0}_Front_state'.format(str(fan_tray))) == '') + fan_rear_status = (get_pmc_register('Fan{0}_Rear_state'.format(str(fan_tray))) == '') + print ' Fan1 Speed: ', \ + get_pmc_register('FAN{0}_Front_rpm'.format(str(fan_tray))) + print ' Fan2 Speed: ',\ + get_pmc_register('FAN{0}_Rear_rpm'.format(str(fan_tray))) + print ' Fan1 State: ', fan_status[fan_front_status] + print ' Fan2 State: ', fan_status[fan_rear_status] + print ' Airflow: ', get_fan_airflow(fan_tray) + + +print '\nFan Trays:' + +for tray in range(1, Z9432F_MAX_FAN_TRAYS + 1): + if get_pmc_register('FAN{0}_prsnt'.format(str(tray))) == 'Present': + print_fan_tray(tray) + else: + print ' Fan Tray {}: NOT PRESENT'.format(str(tray)) + +def get_psu_status(index): + """ + Retrieves the presence status of power supply unit (PSU) defined + by 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 = get_pmc_register('PSU{0}_state'.format(str(index))) + if len(status.split(',')) > 1: + return 'NOT OK' + elif 'Presence' not in status: + return 'NOT PRESENT' + return None + + +# Print the information for PSU1, PSU2 +def print_psu(psu_id): + """ Print PSU information od psu_id """ + + + # PSU FAN details + if psu_id == 1: + print ' PSU1:' + print ' AF Temperature: ',\ + get_pmc_register('PSU1_AF_temp') + print ' Mid Temperature: ',\ + get_pmc_register('PSU1_Mid_temp') + print ' Rear Temperature: ',\ + get_pmc_register('PSU1_Rear_temp') + print ' FAN RPM: ',\ + get_pmc_register('PSU1_rpm') + + # PSU input & output monitors + print ' Input Voltage: ',\ + get_pmc_register('PSU1_In_volt') + print ' Output Voltage: ',\ + get_pmc_register('PSU1_Out_volt') + print ' Input Power: ',\ + get_pmc_register('PSU1_In_watt') + print ' Output Power: ',\ + get_pmc_register('PSU1_Out_watt') + print ' Input Current: ',\ + get_pmc_register('PSU1_In_amp') + print ' Output Current: ',\ + get_pmc_register('PSU1_Out_amp') + + else: + + print ' PSU2:' + print ' AF Temperature: ',\ + get_pmc_register('PSU2_AF_temp') + print ' Mid Temperature: ',\ + get_pmc_register('PSU2_Mid_temp') + print ' Rear Temperature: ',\ + get_pmc_register('PSU2_Rear_temp') + print ' FAN RPM: ',\ + get_pmc_register('PSU2_rpm') + + # PSU input & output monitors + print ' Input Voltage: ',\ + get_pmc_register('PSU2_In_volt') + print ' Output Voltage: ',\ + get_pmc_register('PSU2_Out_volt') + print ' Input Power: ',\ + get_pmc_register('PSU2_In_watt') + print ' Output Power: ',\ + get_pmc_register('PSU2_Out_watt') + print ' Input Current: ',\ + get_pmc_register('PSU2_In_amp') + print ' Output Current: ',\ + get_pmc_register('PSU2_Out_amp') + print ' Airflow: ',\ + get_psu_airflow(psu_id) + + +print '\nPSUs:' +for psu in range(1, Z9432F_MAX_PSUS + 1): + psu_status = get_psu_status(psu) + if psu_status is not None: + print ' PSU{0}: {1}'.format(psu, psu_status) + else: + print_psu(psu) + +print '\n Total Power: ',\ + get_pmc_register('PSU_Total_watt') + commands.getstatusoutput('echo 1000 > /sys/module/ipmi_si/parameters/kipmid_max_busy_us') diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/qsfp_irq_enable.py b/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/qsfp_irq_enable.py new file mode 100755 index 0000000000..77eac10ec3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/qsfp_irq_enable.py @@ -0,0 +1,30 @@ +#!/usr/bin/python + +try: + import struct + from os import * + from mmap import * + +except ImportError as e: + raise ImportError("%s - required module no found" % str(e)) + +BASE_RES_PATH = "/sys/bus/pci/devices/0000:04:00.0/resource0" +PORT_START = 0 +PORT_END = 32 + + +def pci_mem_write(mm, offset, data): + mm.seek(offset) + 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) + mm.close() + close(fd) + +for port_num in range(PORT_START, PORT_END+1): + port_offset = 0x400c + ((port_num) * 16) + pci_set_value(BASE_RES_PATH, 0x30, port_offset) diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/sensors b/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/sensors new file mode 100755 index 0000000000..ee53f2b0f3 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/sensors @@ -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 diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/z9432f_platform.sh b/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/z9432f_platform.sh new file mode 100755 index 0000000000..99cf5371b7 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/scripts/z9432f_platform.sh @@ -0,0 +1,212 @@ +#!/bin/bash + +init_devnum() { + found=0 + for devnum in 0 1; do + devname=`cat /sys/bus/i2c/devices/i2c-${devnum}/name` + # iSMT adapter can be at either dffd0000 or dfff0000 + if [[ $devname == 'SMBus iSMT adapter at '* ]]; then + found=1 + break + fi + done + + [ $found -eq 0 ] && echo "cannot find iSMT" && exit 1 +} + +# Attach/Detach syseeprom on CPU board +sys_eeprom() { + case $1 in + "new_device") echo 24c16 0x50 > /sys/bus/i2c/devices/i2c-${devnum}/$1 + ;; + "delete_device") echo 0x50 > /sys/bus/i2c/devices/i2c-${devnum}/$1 + ;; + *) echo "z9432f_platform: sys_eeprom : invalid command !" + ;; + esac +} + +#Attach/Detach the MUX connecting all QSFPs +switch_board_qsfp_sfp_mux() { + case $1 in + "new_device") + for ((j=0x70,i=603;i<=607;i++,j++)); + do + sleep 0.1 + echo "Attaching PCA9548 @ $j" + echo pca9548 $j > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + "delete_device") + for ((j=0x70,i=603;i<=607;i++,j++)); + do + echo "Detaching PCA9548 @ $j" + echo $j > /sys/bus/i2c/devices/i2c-$i/$1 + done + + ;; + *) echo "z9432f_platform: switch_board_qsfp_sfp_mux: invalid command !" + ;; + esac + sleep 2 +} + +#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=34;i<=35;i++)); + do + echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + "delete_device") + for ((i=34;i<=35;i++)); + do + echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + *) echo "z9332f_platform: switch_board_qsfp: invalid command !" + ;; + esac +} + +#Attach/Detach 32 instances of EEPROM driver QSFP ports +#eeprom can dump data using below command +switch_board_qsfp() { + case $1 in + "new_device") + for ((i=2;i<=33;i++)); + do + echo optoe3 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + "delete_device") + for ((i=2;i<=33;i++)); + do + echo 0x50 > /sys/bus/i2c/devices/i2c-$i/$1 + done + ;; + + *) echo "z9432f_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:04:00.0/resource0" + for ((i=1;i<=34;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 +} + +platform_firmware_versions() { + FIRMWARE_VERSION_FILE=/var/log/firmware_versions + rm -rf ${FIRMWARE_VERSION_FILE} + echo "BIOS: `dmidecode -s system-version `" > $FIRMWARE_VERSION_FILE + ## Get FPGA version + r=`/usr/bin/pcisysfs.py --get --offset 0x00 --res /sys/bus/pci/devices/0000\:04\: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=`cat /sys/class/ipmi/ipmi0/device/bmc/firmware_revision` + echo "BMC: $r" >> $FIRMWARE_VERSION_FILE + + #System CPLD 0x31 on i2c bus 601 ( physical FPGA I2C-2) + r_min=`/usr/sbin/i2cget -y 601 0x31 0x0 | sed ' s/.*\(0x..\)$/\1/'` + r_maj=`/usr/sbin/i2cget -y 601 0x31 0x1 | sed ' s/.*\(0x..\)$/\1/'` + echo "System CPLD: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE + + #Slave CPLD 1 0x30 on i2c bus 600 ( physical FPGA I2C-1) + r_min=`/usr/sbin/i2cget -y 600 0x30 0x0 | sed ' s/.*\(0x..\)$/\1/'` + r_maj=`/usr/sbin/i2cget -y 600 0x30 0x1 | sed ' s/.*\(0x..\)$/\1/'` + echo "Slave CPLD 1: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE + + #Slave CPLD 2 0x31 on i2c bus 600 ( physical FPGA I2C-1) + r_min=`/usr/sbin/i2cget -y 600 0x31 0x0 | sed ' s/.*\(0x..\)$/\1/'` + r_maj=`/usr/sbin/i2cget -y 600 0x31 0x1 | sed ' s/.*\(0x..\)$/\1/'` + echo "Slave CPLD 2: $((r_maj)).$((r_min))" >> $FIRMWARE_VERSION_FILE +} + +#This enables the led control for CPU and default states +switch_board_led_default() { + resource="/sys/bus/pci/devices/0000:04:00.0/resource0" + python /usr/bin/pcisysfs.py --set --offset 0x24 --val 0x194 --res $resource > /dev/null 2>&1 +} + +install_python_api_package() { + device="/usr/share/sonic/device" + platform=$(/usr/local/bin/sonic-cfggen -H -v DEVICE_METADATA.localhost.platform) + + pip3 install $device/$platform/sonic_platform-1.0-py3-none-any.whl +} + +remove_python_api_package() { + rv=$(pip3 show sonic-platform > /dev/null 2>/dev/null) + if [ $? -eq 0 ]; then + rv=$(pip3 uninstall -y sonic-platform > /dev/null 2>/dev/null) + fi +} + +get_reboot_cause() { + REBOOT_REASON_FILE="/host/reboot-cause/platform/reboot_reason" + resource="/sys/bus/pci/devices/0000:04:00.0/resource0" + + mkdir -p $(dirname $REBOOT_REASON_FILE) + + # Handle First Boot into software version with reboot cause determination support + if [[ ! -e $REBOOT_REASON_FILE ]]; then + echo "0" > $REBOOT_REASON_FILE + else + /usr/bin/pcisysfs.py --get --offset 0x18 --res $resource | sed '1d; s/.*:\(.*\)$/\1/;' > $REBOOT_REASON_FILE + fi + /usr/bin/pcisysfs.py --set --val 0x0 --offset 0x18 --res $resource +} + +init_devnum + +if [ "$1" == "init" ]; then + modprobe i2c-dev + modprobe i2c-mux-pca954x force_deselect_on_exit=1 + modprobe ipmi_devintf + modprobe ipmi_si kipmid_max_busy_us=1000 + modprobe i2c_ocores + modprobe dell_z9432f_fpga_ocores + modprobe mc24lc64t + sys_eeprom "new_device" + switch_board_qsfp_sfp_mux "new_device" + switch_board_qsfp "new_device" + switch_board_sfp "new_device" + switch_board_modsel + switch_board_led_default + install_python_api_package + #python /usr/bin/qsfp_irq_enable.py + platform_firmware_versions + get_reboot_cause + echo 1000 > /sys/module/ipmi_si/parameters/kipmid_max_busy_us + +elif [ "$1" == "deinit" ]; then + sys_eeprom "delete_device" + switch_board_sfp "delete_device" + switch_board_qsfp "delete_device" + switch_board_qsfp_sfp_mux "delete_device" + + modprobe -r mc24lc64t + modprobe -r i2c-mux-pca954x + modprobe -r i2c-dev + remove_python_api_package +else + echo "z9432f_platform : Invalid option !" +fi + diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/setup.py b/platform/broadcom/sonic-platform-modules-dell/z9432f/setup.py new file mode 120000 index 0000000000..4f6de9941d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/setup.py @@ -0,0 +1 @@ +../s6100/setup.py \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/__init__.py new file mode 100644 index 0000000000..4f5d4f6e47 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/__init__.py @@ -0,0 +1,2 @@ +__all__ = ["platform", "chassis", "sfp", "eeprom", "component", "psu", "thermal", "fan", "fan_drawer"] +from sonic_platform import * diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/chassis.py new file mode 100644 index 0000000000..bb2446445f --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/chassis.py @@ -0,0 +1,425 @@ +#!/usr/bin/env python +""" +############################################################################# +# DELLEMC Z9432F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# +""" +try: + import time + import sys + import os + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.sfp import Sfp + from sonic_platform.eeprom import Eeprom + from sonic_platform.component import Component + from sonic_platform.psu import Psu + from sonic_platform.thermal import Thermal + from sonic_platform.watchdog import Watchdog + from sonic_platform.fan_drawer import FanDrawer + import sonic_platform.hwaccess as hwaccess +except ImportError as err: + raise ImportError(str(err) + "- required module not found") + +MAX_Z9432F_COMPONENT = 6 # BIOS,BMC,FPGA,SYSTEM CPLD,2 SLAVE CPLDs +MAX_Z9432F_FANTRAY = 7 +MAX_Z9432F_FAN = 2 +MAX_Z9432F_PSU = 2 +MAX_Z9432F_THERMAL = 13 +SYSTEM_LED_REG = 0x24 +SYSTEM_BEACON_LED_SET = 0x8 +SYSTEM_BEACON_LED_CLEAR = 0xFFFFFFF7 + +MEDIA_PART_NUM_LIST = set([ \ +"8T47V", "XTY28", "MHVPK", "GF76J", "J6FGD", "F1KMV", "9DN5J", "H4DHD", "6MCNV", "0WRX0", "X7F70", +"5R2PT", "WTRD1", "WTRD1", "WTRD1", "WTRD1", "5250G", "WTRD1", "C5RNH", "C5RNH", "FTLX8571D3BCL-FC", +"C5RNH", "5250G", "N8TDR", "7D64H", "7D64H", "RN84N", "RN84N", "HMTNW", "6K3Y6", "6K3Y6", "TY5FM", +"50M0R", "PGYJT", "WP2PP", "85Y13", "1HCGH", "FP9R1", "FYD0M", "C6Y7M", "C6Y7M", "V250M", "V250M", +"5CWK6", "5CWK6", "53HVN", "53HVN", "358VV", "358VV", "MV799", "MV799", "YJF03", "P9GND", "T1KCN", +"1DXKP", "MT7R2", "K0T7R", "W5G04", "7TCDN", "7TCDN", "7TCDN", "7TCDN", "7TCDN", "V3XJK", "0MV31", +"5FVP7", "N6KM9", "C41MF", "77KC3", "XW7J0", "V4NJV", "2XJHY", "H93DH", "H93DH", "F8CG0", "F8CG0", +"F8CG0", "119N6", "WFMF5", "794RX", "288F6", "1M31V", "1M31V", "5NP8R", "5NP8R", "4TC09", "4TC09", +"FC6KV", "FC6KV", "J90VN", "J90VN", "05RH0", "05RH0", "YDN52", "0C2YV", "YDN52", "0C2YV", "9JT65", +"D7M6H", "6GW14", "FYVFW", "0VF5H", "P4YPY", "P4YPY", "TCPM2", "TCPM2", "JNPF8", "JNPF8", "27GG5", +"27GG5", "P8T4W", "P8T4W", "JR54Y", "M6N0J", "XJYD0", "K44H9", "035KG", "P7C7N", "76V43", "3CC35", +"FN4FC", "26FN3", "YFNDD", "YFNDD", "7R9N9", "035KG", "P7C7N", "76V43", "3CC35", "PLRXPLSCS43811", +"FN4FC", "26FN3", "YFNDD", "YFNDD", "7R9N9", "G86YJ", "V407F", "V407F", "9KH6T", "G86YJ", "V407F", +"9KH6T", "2JVDD", "D0R73", "VXFJY", "9X8JP", "2JVDD", "D0R73", "VXFJY", "9X8JP", "2JVDD", "D0R73", +"VXFJY", "9X8JP", "GMFC5", "GMFC5", "GMFC5", "D7P80", "3MFXG", "3MFXG", "0GWXJ", "THPF3", "PJ62G", +"3XCX1", "JJYKG", "RRRTK", "16K56", "86JM2", "K5R6C", "7MG2C", "WTPPN", "9HTT2", "NKM4F", "VXGGG", +"JC9W6", "6MR8M", "RP3GV", "M5PPJ", "XKY55", "TKCXT", "05J8P", "5WGKD", "XFDRT", "NW8DM", "YPKH3", +"5WGKD", "XFDRT", "NW8DM", "YPKH3", "71XXK", "MVCX6", "0XYP6", "HPPVW", "3GHRT", "71XXK", "MVCX6", +"0XYP6", "HPPVW", "3GHRT", "2X5T6", "135V2", "KD5MV", "2X5T6", "KD5MV", "HHFK0", "3YWG7", "5CMT2", +"RCVP5", "X5DH4", "HHFK0", "3YWG7", "5CMT2", "RCVP5", "X5DH4", "3YWG7", "5CMT2", "RCVP5", "X5DH4", +"4WJ41", "4WJ41", "14NV5", "14NV5", "14NV5", "4WGYD", "YKMH7", "X7CCC", "X7CCC", "0X9CT", "0CY8V", +"P7D7R", "W4GPP", "W4GPP", "W4GPP", "HHHCHC", "07RN7", "07RN7", "0YR96", "0YR96", "JCYM9", +"FTLX8571D3BCL", "DDW0X", "VPFDJ", "229KM", "9FC7D", "DDW0X", "VPFDJ", "6FMR5", "J7K20", "N3K9W", +"6FMR5", "8R4VM", "7VN5T", "D9YM8", "8R4VM", "VYXPW", "87TPX", "WY6FK", "VYXPW", "87TPX", "WY6FK", +"WG8C4", "N8K82", "2DV6Y", "77C3C", "RC0HM", "77C3C", "RC0HM", "JHXTN", "3P3PG", "92YVM", "4VX5M", +"4VX5M", "6RRGD", "W4JWV", "22V6R", "XR11M", "9GMDY", "JMCWK", "TP2F0", "6MGDY", "78RHK", "C0TP5", +"0WDNV", "FCLF8522P2BTL"]) + +PORT_START = 1 +PORT_END = 34 +PORTS_IN_BLOCK = (PORT_END + 1) +REBOOT_CAUSE_PATH = "/host/reboot-cause/platform/reboot_reason" +PCI_RES = "/sys/bus/pci/devices/0000:04:00.0/resource0" + +class Chassis(ChassisBase): + """ + DELLEMC Platform-specific Chassis class + """ + + + sysled_offset = 0x0024 + + SYSLED_COLOR_TO_REG = { + "blinking_green": 0x0, + "green" : 0x10, + "amber" : 0x20, + "blinking_amber": 0x30 + } + + REG_TO_SYSLED_COLOR = { + 0x0 : "blinking_green", + 0x10 : "green", + 0x20 : "amber", + 0x30 : "blinking_amber" + } + + _global_port_pres_dict = {} + + def __init__(self): + ChassisBase.__init__(self) + # sfp.py will read eeprom contents and retrive the eeprom data. + # We pass the eeprom path from chassis.py + _sfp_port = list(range(33, PORTS_IN_BLOCK)) + i2c_bus_for_port = 2 + i2c_mux_to_populate = 603 + i2c_mux_address = 70 + i2c_mux_is_good = False + eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" + mux_channel = "/sys/class/i2c-adapter/i2c-{0}/{0}-00{1}/channel-0" + for index in range(PORT_START, PORTS_IN_BLOCK): + eeprom_path = "" + if index%8 == 1: # 8 buses per i2c mux + i2c_mux_is_good = True if os.path.exists(mux_channel.format(i2c_mux_to_populate, i2c_mux_address)) else False + i2c_mux_to_populate += 1 + i2c_mux_address += 1 + if i2c_mux_is_good: + eeprom_path = eeprom_base.format(i2c_bus_for_port) + i2c_bus_for_port += 1 + port_type = 'QSFP_DD' if index not in _sfp_port else 'SFP' + sfp_node = Sfp(index, port_type, eeprom_path) + self._sfp_list.append(sfp_node) + + self._eeprom = Eeprom() + self._watchdog = Watchdog() + self._num_sfps = PORT_END + self._num_fans = MAX_Z9432F_FANTRAY * MAX_Z9432F_FAN + + for i in range(MAX_Z9432F_FANTRAY): + fandrawer = FanDrawer(i) + self._fan_drawer_list.append(fandrawer) + self._fan_list.extend(fandrawer._fan_list) + + self._psu_list = [Psu(i) for i in range(MAX_Z9432F_PSU)] + self._thermal_list = [Thermal(i) for i in range(MAX_Z9432F_THERMAL)] + self._component_list = [Component(i) for i in range(MAX_Z9432F_COMPONENT)] + for port_num in range(PORT_START, PORTS_IN_BLOCK): + presence = self.get_sfp(port_num).get_presence() + self._global_port_pres_dict[port_num] = '1' if presence else '0' + + self._watchdog = Watchdog() + #self.LOCATOR_LED_ON = self.STATUS_LED_COLOR_BLUE_BLINK + #self.LOCATOR_LED_OFF = self.STATUS_LED_COLOR_OFF + #ext_media_override() + +# check for this event change for sfp / do we need to handle timeout/sleep + + def get_change_event(self, timeout=0): + """ + Returns a nested dictionary containing all devices which have + experienced a change at chassis level + """ + start_ms = time.time() * 1000 + port_dict = {} + change_dict = {} + change_dict['sfp'] = port_dict + while True: + time.sleep(0.5) + for port_num in range(PORT_START, (PORT_END + 1)): + presence = self.get_sfp(port_num).get_presence() + 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, change_dict + + if timeout: + now_ms = time.time() * 1000 + if now_ms - start_ms >= timeout: + return True, change_dict + + + def get_status_led(self): + """ + Gets the state of the system LED + Returns: + A string, one of the valid LED color strings which could be + vendor specified. + """ + val = hwaccess.pci_get_value(PCI_RES, self.sysled_offset) + if val != -1: + val = val & 0x30 + return self.REG_TO_SYSLED_COLOR.get(val) + return self.sys_ledcolor + + def initizalize_system_led(self): + self.sys_ledcolor = "green" + + def set_status_led(self, color): + """ + Sets the state of the system LED + Args: + color: A string representing the color with which to set the + system LED + Returns: + bool: True if system LED state is set successfully, False if not + """ + if color not in list(self.SYSLED_COLOR_TO_REG.keys()): + return False + + val = hwaccess.pci_get_value(PCI_RES, self.sysled_offset) + val = (val & 0xFFCF) | self.SYSLED_COLOR_TO_REG[color] + + hwaccess.pci_set_value(PCI_RES, val, self.sysled_offset) + self.sys_ledcolor = color + return True + + def get_sfp(self, index): + """ + Retrieves sfp represented by (0-based) index + + Args: + index: An integer, the index (0-based) of the sfp to retrieve. + The index should be the sequence of a physical port in a chassis, + starting from 0. + For example, 0 for Ethernet0, 1 for Ethernet4 and so on. + + Returns: + An object dervied from SfpBase representing the specified sfp + """ + sfp = None + + try: + # The 'index' is 1-based + sfp = self._sfp_list[index-1] + except IndexError: + sys.stderr.write("SFP index {} out of range (1-{})\n".format( + index, len(self._sfp_list))) + return sfp + + def get_name(self): + """ + Retrieves the name of the chassis + Returns: + string: The name of the chassis + """ + return self._eeprom.modelstr() + + 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 (Service tag) + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_str() + + 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 + + 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() + + 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() + + def get_revision(self): + """ + Retrieves the hardware revision of the device + + Returns: + string: Revision value of device + """ + return self._eeprom.revision_str() + + 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. + """ + return self._eeprom.system_eeprom_info() + + def get_eeprom(self): + """ + Retrieves the Sys Eeprom instance for the chassis. + Returns : + The instance of the Sys Eeprom + """ + return self._eeprom + + def get_num_fans(self): + """ + Retrives the number of Fans on the chassis. + Returns : + An integer represents the number of Fans on the chassis. + """ + return self._num_fans + + def get_num_sfps(self): + """ + Retrives the numnber of Media on the chassis. + Returns: + An integer represences the number of SFPs on the chassis. + """ + return self._num_sfps + + 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. + """ + try: + with open(REBOOT_CAUSE_PATH) as filed: + reboot_cause = int(filed.read(), 16) + except EnvironmentError: + return (self.REBOOT_CAUSE_NON_HARDWARE, None) + + if reboot_cause & 0x1: + retval = (self.REBOOT_CAUSE_POWER_LOSS, None) + elif reboot_cause & 0x2: + retval = (self.REBOOT_CAUSE_NON_HARDWARE, None) + elif reboot_cause & 0x4: + retval = (self.REBOOT_CAUSE_HARDWARE_OTHER, "PSU Shutdown") + elif reboot_cause & 0x8: + retval = (self.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU, None) + elif reboot_cause & 0x10: + retval = (self.REBOOT_CAUSE_WATCHDOG, None) + elif reboot_cause & 0x20: + retval = (self.REBOOT_CAUSE_HARDWARE_OTHER, "BMC Shutdown") + elif reboot_cause & 0x40: + retval = (self.REBOOT_CAUSE_HARDWARE_OTHER, "Hot-Swap Shutdown") + elif reboot_cause & 0x80: + retval = (self.REBOOT_CAUSE_HARDWARE_OTHER, "Reset Button Shutdown") + elif reboot_cause & 0x100: + retval = (self.REBOOT_CAUSE_HARDWARE_OTHER, "Reset Button Cold Reboot") + else: + retval = (self.REBOOT_CAUSE_NON_HARDWARE, None) + return retval + + @staticmethod + def get_qualified_media_list(): + """ Returns Dell Qualified Media List """ + return MEDIA_PART_NUM_LIST + + def set_locator_led(self, color): + """ + Sets the state of the Chassis Locator LED + + Args: + color: A string representing the color with which to set the Chassis Locator LED + + Returns: + bool: True if the Chassis Locator LED state is set successfully, False if not + + """ + val = hwaccess.pci_get_value(PCI_RES, SYSTEM_LED_REG) + if self.LOCATOR_LED_ON == color: + val = int(val) | SYSTEM_BEACON_LED_SET + elif self.LOCATOR_LED_OFF == color: + val = int(val) & SYSTEM_BEACON_LED_CLEAR + else: + return False + hwaccess.pci_set_value(PCI_RES, val, SYSTEM_LED_REG) + return True + + def get_locator_led(self): + """ + Gets the state of the Chassis Locator LED + + Returns: + LOCATOR_LED_ON or LOCATOR_LED_OFF + """ + val = hwaccess.pci_get_value(PCI_RES, SYSTEM_LED_REG) + val = int(val) & SYSTEM_BEACON_LED_SET + if not val: + return self.LOCATOR_LED_OFF + else: + return self.LOCATOR_LED_ON + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether Chassis is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/component.py b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/component.py new file mode 100644 index 0000000000..763db39f5e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/component.py @@ -0,0 +1,428 @@ +#!/usr/bin/env python + +######################################################################## +# DELLEMC Z9432F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Components' (e.g., BIOS, CPLD, FPGA, BMC etc.) available in +# the platform +# +######################################################################## + +try: + import json + import os + import re + import subprocess + import tarfile + import tempfile + from sonic_platform_base.component_base import ComponentBase + import sonic_platform.hwaccess as hwaccess +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +def get_bios_version(): + return subprocess.check_output( + ['dmidecode', '-s', 'bios-version']).decode('utf-8').strip() + +def get_fpga_version(): + val = hwaccess.pci_get_value('/sys/bus/pci/devices/0000:04:00.0/resource0', 0) + return '{}.{}'.format((val >> 8) & 0xff, val & 0xff) + +def get_bmc_version(): + return subprocess.check_output( + ['cat', '/sys/class/ipmi/ipmi0/device/bmc/firmware_revision'] + ).decode('utf-8').strip() + +def get_cpld_version(bus, i2caddr): + return '{}.{}'.format(hwaccess.i2c_get(bus, i2caddr, 1), + hwaccess.i2c_get(bus, i2caddr, 0)) + +def get_cpld0_version(): + return get_cpld_version(601, 0x31) + +def get_cpld1_version(): + return get_cpld_version(600, 0x30) + +def get_cpld2_version(): + return get_cpld_version(600, 0x31) + +def get_ssd_version(): + val = 'NA' + try: + ssd_ver = subprocess.check_output(['ssdutil', '-v'], + stderr=subprocess.STDOUT, text=True) + except (FileNotFoundError, subprocess.CalledProcessError): + pass + else: + version = re.search(r'Firmware\s*:(.*)',ssd_ver) + if version: + val = version.group(1).strip() + + return val + +def get_pciephy_version(): + val = 'NA' + try: + pcie_ver = subprocess.check_output(['bcmcmd', 'pciephy fw version'], + stderr=subprocess.STDOUT, text=True) + except (FileNotFoundError, subprocess.CalledProcessError): + pass + else: + version = re.search(r'PCIe FW loader version:\s(.*)', pcie_ver) + if version: + val = version.group(1).strip() + + return val + + +class Component(ComponentBase): + """DellEMC Platform-specific Component class""" + + CHASSIS_COMPONENTS = [ + ['BIOS', + 'Performs initialization of hardware components during booting', + get_bios_version + ], + + ['FPGA', + 'Used for managing the system LEDs', + get_fpga_version + ], + + ['BMC', + 'Platform management controller for on-board temperature monitoring,in-chassis power, Fan and LED control', + get_bmc_version + ], + + ['Baseboard CPLD', + 'Used for managing the CPU power sequence and CPU states', + get_cpld0_version + ], + + ['Switch CPLD 1', + 'Used for managing QSFP-DD/QSFP28/SFP port transceivers ', + get_cpld1_version + ], + + ['Switch CPLD 2', + 'Used for managing QSFP-DD/QSFP28/SFP port transceivers', + get_cpld2_version + ], + + ['SSD', + 'Solid State Drive that stores data persistently', + get_ssd_version + ], + + ['PCIe', + 'ASIC PCIe firmware', + get_pciephy_version + ] + ] + + def __init__(self, component_index=0): + ComponentBase.__init__(self) + self.index = component_index + self.name = self.CHASSIS_COMPONENTS[self.index][0] + self.description = self.CHASSIS_COMPONENTS[self.index][1] + self.version = self.CHASSIS_COMPONENTS[self.index][2]() + + @staticmethod + def _get_available_firmware_version(image_path): + if not os.path.isfile(image_path): + return False, "ERROR: File not found" + + with tempfile.TemporaryDirectory() as tmpdir: + cmd = "sed -e '1,/^exit_marker$/d' {} | tar -x -C {} installer/onie-update.tar.xz".format(image_path, tmpdir) + try: + subprocess.check_call(cmd, stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, shell=True) + except subprocess.CalledProcessError: + return False, "ERROR: Unable to extract firmware updater" + + try: + updater = tarfile.open(os.path.join(tmpdir, "installer/onie-update.tar.xz"), "r") + except tarfile.ReadError: + return False, "ERROR: Unable to extract firmware updater" + + try: + ver_info_fd = updater.extractfile("firmware/fw-component-version") + except KeyError: + updater.close() + return False, "ERROR: Version info not available" + + ver_info = json.load(ver_info_fd) + ver_info_fd.close() + updater.close() + + ver_info = ver_info.get("x86_64-dellemc_z9432f_c3758-r0") + if ver_info: + return True, ver_info + else: + return False, "ERROR: Version info not available" + + @staticmethod + def _stage_firmware_package(image_path): + stage_msg = None + cmd = "onie_stage_fwpkg -a {}".format(image_path) + try: + subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT, text=True) + except subprocess.CalledProcessError as e: + if e.returncode != 2: + return False, e.output.strip() + else: + stage_msg = e.output.strip() + + cmd = "onie_mode_set -o update" + try: + subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT, text=True) + except subprocess.CalledProcessError as e: + return False, e.output.strip() + + if stage_msg: + return True, stage_msg + else: + return True, "INFO: Firmware upgrade staged" + + def get_name(self): + """ + Retrieves the name of the component + Returns: + A string containing the name of the component + """ + return self.name + + def get_description(self): + """ + Retrieves the description of the component + Returns: + A string containing the description of the component + """ + return self.description + + def get_firmware_version(self): + """ + Retrieves the firmware version of the component + Returns: + A string containing the firmware version of the component + """ + return self.version + + def get_presence(self): + """ + Retrieves the presence of the component + Returns: + bool: True if present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the part number of the component + Returns: + string: Part number of component + """ + return 'NA' + + def get_serial(self): + """ + Retrieves the serial number of the component + Returns: + string: Serial number of component + """ + return 'NA' + + def get_status(self): + """ + Retrieves the operational status of the component + Returns: + bool: True if component is operating properly, False if not + """ + return True + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return -1 + + def is_replaceable(self): + """ + Indicate whether component is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + + def get_available_firmware_version(self, image_path): + """ + Retrieves the available firmware version of the component + + Note: the firmware version will be read from image + + Args: + image_path: A string, path to firmware image + + Returns: + A string containing the available firmware version of the component + """ + avail_ver = None + valid, version = self._get_available_firmware_version(image_path) + if valid: + avail_ver = version.get(self.name) + if avail_ver: + avail_ver = avail_ver.get("version") + else: + print(version) + + return avail_ver if avail_ver else "NA" + + def get_firmware_update_notification(self, image_path): + """ + Retrieves a notification on what should be done in order to complete + the component firmware update + + Args: + image_path: A string, path to firmware image + + Returns: + A string containing the component firmware update notification if required. + By default 'None' value will be used, which indicates that no actions are required + """ + valid, version = self._get_available_firmware_version(image_path) + if valid: + avail_ver = version.get(self.name) + if avail_ver: + avail_ver = avail_ver.get("version") + if avail_ver and avail_ver != self.get_firmware_version(): + return "Cold reboot is required to perform firmware upgrade" + else: + print(version) + + return None + + def install_firmware(self, image_path): + """ + Installs firmware to the component + + This API performs firmware installation only: this may/may not be the same as firmware update. + In case platform component requires some extra steps (apart from calling Low Level Utility) + to load the installed firmware (e.g, reboot, power cycle, etc.) - this must be done manually by user + + Note: in case immediate actions are required to complete the component firmware update + (e.g., reboot, power cycle, etc.) - will be done automatically by API and no return value provided + + Args: + image_path: A string, path to firmware image + + Returns: + A boolean, True if install was successful, False if not + """ + valid, version = self._get_available_firmware_version(image_path) + if valid: + avail_ver = version.get(self.name) + if avail_ver: + avail_ver = avail_ver.get("version") + if avail_ver and avail_ver != self.get_firmware_version(): + status, msg = self._stage_firmware_package(image_path) + print(msg) + if status: + return True + else: + return False + + print("INFO: Firmware version up-to-date") + return True + else: + print(version) + + return False + + def update_firmware(self, image_path): + """ + Updates firmware of the component + + This API performs firmware update: it assumes firmware installation and loading in a single call. + In case platform component requires some extra steps (apart from calling Low Level Utility) + to load the installed firmware (e.g, reboot, power cycle, etc.) - this will be done automatically by API + + Args: + image_path: A string, path to firmware image + + Raises: + RuntimeError: update failed + """ + valid, version = self._get_available_firmware_version(image_path) + if valid: + avail_ver = version.get(self.name) + if avail_ver: + avail_ver = avail_ver.get("version") + if avail_ver and avail_ver != self.get_firmware_version(): + status, msg = self._stage_firmware_package(image_path) + if status: + print(msg) + subprocess.call("reboot") + else: + raise RuntimeError(msg) + + print("INFO: Firmware version up-to-date") + return None + else: + raise RuntimeError(version) + + def auto_update_firmware(self, image_path, boot_type): + """ + Updates firmware of the component + + This API performs firmware update automatically based on boot_type: it assumes firmware installation + and/or creating a loading task during the reboot, if needed, in a single call. + In case platform component requires some extra steps (apart from calling Low Level Utility) + to load the installed firmware (e.g, reboot, power cycle, etc.) - this will be done automatically during the reboot. + The loading task will be created by API. + + Args: + image_path: A string, path to firmware image + boot_type: A string, reboot type following the upgrade + - none/fast/warm/cold + + Returns: + Output: A return code + return_code: An integer number, status of component firmware auto-update + - return code of a positive number indicates successful auto-update + - status_installed = 1 + - status_updated = 2 + - status_scheduled = 3 + - return_code of a negative number indicates failed auto-update + - status_err_boot_type = -1 + - status_err_image = -2 + - status_err_unknown = -3 + + Raises: + RuntimeError: auto-update failure cause + """ + valid, version = self._get_available_firmware_version(image_path) + if valid: + avail_ver = version.get(self.name) + if avail_ver: + avail_ver = avail_ver.get("version") + if avail_ver and avail_ver != self.get_firmware_version(): + if boot_type != "cold": + return -1 + + status, msg = self._stage_firmware_package(image_path) + if status: + print(msg) + return 3 + else: + raise RuntimeError(msg) + + print("INFO: Firmware version up-to-date") + return 1 + else: + print(version) + return -2 diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/eeprom.py new file mode 100644 index 0000000000..2f9c501666 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/eeprom.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python + +############################################################################# +# DellEmc Z9432F +# +# 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: + import os.path + from sonic_eeprom import eeprom_tlvinfo +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self): + self.eeprom_path = None + for b in (0, 1): + f = '/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom'.format(b) + if os.path.exists(f): + self.eeprom_path = f + break + if self.eeprom_path is None: + return + 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 = (eeprom[9] << 8) | eeprom[10] + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + eeprom[tlv_index + 1]] + code = "0x%02X" % tlv[0] + name, value = self.decoder(None, tlv) + + self.eeprom_tlv_dict[code] = value + if eeprom[tlv_index] == self._TLV_CODE_CRC_32: + break + + tlv_index += eeprom[tlv_index+1] + 2 + + def serial_number_str(self): + """ + Returns the serial number + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + return results[2].decode('ascii') + + def base_mac_addr(self): + """ + Returns the base mac address found in the system EEPROM + """ + (is_valid, t) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(TlvInfoDecoder, self).switchaddrstr(e) + + return ":".join(["{:02x}".format(T) for T in t[2]]).upper() + + def modelstr(self): + """ + Returns the Model name + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def part_number_str(self): + """ + Returns the part number + """ + (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].decode('ascii') + + def serial_str(self): + """ + Returns the servicetag number + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + def revision_str(self): + """ + Returns the device revision + """ + (is_valid, results) = self.get_tlv_field( + self.eeprom_data, self._TLV_CODE_LABEL_REVISION) + if not is_valid: + return "N/A" + + return results[2].decode('ascii') + + 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 diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/fan.py new file mode 100644 index 0000000000..b95b4d070a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/fan.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9432F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fans' information which are available in the platform. +# +######################################################################## +try: + from sonic_platform_base.fan_base import FanBase + from sonic_platform.ipmihelper import IpmiSensor, IpmiFru +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +FAN1_MAX_SPEED_OFFSET = 71 +FAN2_MAX_SPEED_OFFSET = 73 +PSU_FAN_MAX_SPEED_OFFSET = 50 +FAN_DIRECTION_OFFSET = 69 +PSU_FAN_DIRECTION_OFFSET = 47 + +class Fan(FanBase): + """DellEMC Platform-specific Fan class""" + # { FAN-ID: { Sensor-Name: Sensor-ID } } + FAN_SENSOR_MAPPING = {1: {"Prsnt": 0x57, "State": 0x20, "Speed": 0x1c}, + 2: {"Prsnt": 0x57, "State": 0x21, "Speed": 0x1d}, + 3: {"Prsnt": 0x56, "State": 0x22, "Speed": 0x1a}, + 4: {"Prsnt": 0x56, "State": 0x23, "Speed": 0x1b}, + 5: {"Prsnt": 0x55, "State": 0x24, "Speed": 0x18}, + 6: {"Prsnt": 0x55, "State": 0x25, "Speed": 0x19}, + 7: {"Prsnt": 0x54, "State": 0x26, "Speed": 0x16}, + 8: {"Prsnt": 0x54, "State": 0x27, "Speed": 0x17}, + 9: {"Prsnt": 0x53, "State": 0x28, "Speed": 0x14}, + 10: {"Prsnt": 0x53, "State": 0x29, "Speed": 0x15}, + 11: {"Prsnt": 0x52, "State": 0x2a, "Speed": 0x12}, + 12: {"Prsnt": 0x52, "State": 0x2b, "Speed": 0x13}, + 13: {"Prsnt": 0x51, "State": 0x2c, "Speed": 0x10}, + 14: {"Prsnt": 0x51, "State": 0x2d, "Speed": 0x11}} + PSU_FAN_SENSOR_MAPPING = {1: {"State": 0x40, "Speed": 0x45}, + 2: {"State": 0x30, "Speed": 0x35}} + + # { FANTRAY-ID: FRU-ID } + FAN_FRU_MAPPING = {1: 3, 2: 4, 3: 5, 4: 6, 5: 7, 6: 8, 7: 9} + PSU_FRU_MAPPING = {1: 1, 2: 2} + + def __init__(self, fantray_index=1, fan_index=1, psu_fan=False, dependency=None): + FanBase.__init__(self) + self.is_psu_fan = psu_fan + if not self.is_psu_fan: + # API index is starting from 0, DellEMC platform index is + # starting from 1 + self.fantrayindex = fantray_index + 1 + self.fanindex = fan_index + 1 + self.index = (self.fantrayindex - 1) * 2 + self.fanindex + self.prsnt_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["Prsnt"], + is_discrete=True) + self.state_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["State"], + is_discrete=True) + self.speed_sensor = IpmiSensor(self.FAN_SENSOR_MAPPING[self.index]["Speed"]) + self.fru = IpmiFru(self.FAN_FRU_MAPPING[self.fantrayindex]) + if self.fanindex == 1: + self.max_speed_offset = FAN1_MAX_SPEED_OFFSET + else: + self.max_speed_offset = FAN2_MAX_SPEED_OFFSET + self.fan_direction_offset = FAN_DIRECTION_OFFSET + else: + self.dependency = dependency + self.fanindex = fan_index + self.state_sensor = IpmiSensor(self.PSU_FAN_SENSOR_MAPPING[self.fanindex]["State"], + is_discrete=True) + self.speed_sensor = IpmiSensor(self.PSU_FAN_SENSOR_MAPPING[self.fanindex]["Speed"]) + self.fru = IpmiFru(self.PSU_FRU_MAPPING[self.fanindex]) + self.max_speed_offset = PSU_FAN_MAX_SPEED_OFFSET + self.fan_direction_offset = PSU_FAN_DIRECTION_OFFSET + #self.fan_dir_raw_cmd = "0x3a 0x0a {}".format(7+(fan_index-1)) + self.max_speed = 18000 + + def get_name(self): + """ + Retrieves the name of the device + Returns: + String: The name of the device + """ + if self.is_psu_fan: + return "PSU{} Fan".format(self.fanindex) + else: + return "FanTray{}-Fan{}".format(self.fantrayindex, self.fanindex) + + def get_model(self): + """ + Retrieves the part number of the FAN + Returns: + String: Part number of FAN + """ + if self.is_psu_fan: + return 'NA' + else: + return self.fru.get_board_part_number() + + def get_serial(self): + """ + Retrieves the serial number of the FAN + Returns: + String: Serial number of FAN + """ + if self.is_psu_fan: + return 'NA' + else: + return self.fru.get_board_serial() + + def get_presence(self): + """ + Retrieves the presence of the FAN + Returns: + bool: True if fan is present, False if not + """ + presence = False + if self.is_psu_fan: + return self.dependency.get_presence() + else: + is_valid, state = self.prsnt_sensor.get_reading() + if is_valid: + if state & 0b1: + presence = True + return presence + + def get_status(self): + """ + Retrieves the operational status of the FAN + Returns: + bool: True if FAN is operating properly, False if not + """ + status = False + is_valid, state = self.state_sensor.get_reading() + if is_valid: + if state <= 1: + status = True + return status + + def get_direction(self): + """ + Retrieves the fan airfow direction + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + + Notes: + In DellEMC platforms, + - Forward/Exhaust : Air flows from Port side to Fan side. + - Reverse/Intake : Air flows from Fan side to Port side. + """ + direction = [self.FAN_DIRECTION_EXHAUST, self.FAN_DIRECTION_INTAKE] + fan_status = self.get_status() + if not fan_status: + return None + is_valid, fan_direction = self.fru.get_fru_data(self.fan_direction_offset) + if is_valid: + return direction[fan_direction[0]] + return None + + def get_speed(self): + """ + Retrieves the speed of the fan + Returns: + int: percentage of the max fan speed + """ + if self.max_speed == 0: + self.max_speed = self.fru.get_fru_data(self.max_speed_offset, 2)[1] + self.max_speed = self.max_speed[1] << 8 | self.max_speed[0] + is_valid, fan_speed = self.speed_sensor.get_reading() + if not is_valid or self.max_speed == 0: + return None + else: + speed = (100 * fan_speed)//self.max_speed + return speed + + def get_speed_rpm(self): + """ + Retrieves the speed of the fan + Returns: + int: percentage of the max fan speed + """ + is_valid, fan_speed = self.speed_sensor.get_reading() + return fan_speed if is_valid else None + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.fanindex + + def is_replaceable(self): + """ + Indicate whether Fan is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False + + 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 + """ + if self.get_presence(): + # The tolerance value is fixed as 20% for all the DellEMC platforms + tolerance = 20 + else: + tolerance = 0 + + return tolerance + + def set_status_led(self, color): + """ + Set led to expected color + Args: + color: A string representing the color with which to set the + fan status LED + Returns: + bool: True if set success, False if fail. + """ + # Fan tray status LED controlled by HW + # Return True to avoid thermalctld alarm + return True diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/fan_drawer.py b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/fan_drawer.py new file mode 100644 index 0000000000..970c49f700 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/fan_drawer.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9432F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Fan-Drawers' information available in the platform. +# +######################################################################## + +try: + from sonic_platform_base.fan_drawer_base import FanDrawerBase + from sonic_platform.fan import Fan + from sonic_platform.ipmihelper import IpmiFru +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +Z9432F_FANS_PER_FANTRAY = 2 + + +class FanDrawer(FanDrawerBase): + """DellEMC Platform-specific Fan class""" + + FAN_FRU_MAPPING = { 1: 6, 2: 7, 3: 8, 4: 9, 5: 10, 6: 11, 7: 12 } + def __init__(self, fantray_index): + + FanDrawerBase.__init__(self) + # FanTray is 1-based in DellEMC platforms + self.fantrayindex = fantray_index + 1 + for i in range(Z9432F_FANS_PER_FANTRAY): + self._fan_list.append(Fan(fantray_index, i)) + self.fru = IpmiFru(self.FAN_FRU_MAPPING[self.fantrayindex]) + + def get_name(self): + """ + Retrieves the fan drawer name + Returns: + string: The name of the device + """ + return "FanTray{}".format(self.fantrayindex) + + def get_presence(self): + """ + Retrieves the presence of the fan drawer + Returns: + bool: True if fan_tray is present, False if not + """ + return self.get_fan(0).get_presence() + + def get_model(self): + """ + Retrieves the part number of the fan drawer + Returns: + string: Part number of fan drawer + """ + return self.fru.get_board_part_number() + + def get_serial(self): + """ + Retrieves the serial number of the fan drawer + Returns: + string: Serial number of the fan drawer + """ + return self.fru.get_board_serial() + + def get_status(self): + """ + Retrieves the operational status of the fan drawer + Returns: + bool: True if fan drawer is operating properly, False if not + """ + status = True + for fan in self.get_all_fans(): + status &= fan.get_status() + return status + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.fantrayindex + + def is_replaceable(self): + """ + Indicate whether this fan drawer is replaceable. + Returns: + bool: True if it is replaceable, False if not + """ + return True + + def set_status_led(self, color): + """ + Set led to expected color + Args: + color: A string representing the color with which to set the + fan module status LED + Returns: + bool: True if set success, False if fail. + """ + # Fan tray status LED controlled by BMC + # Return True to avoid thermalctld alarm + return True + + def get_maximum_consumed_power(self): + """ + Retrives the maximum power drawn by Fan Drawer + + Returns: + A float, with value of the maximum consumable power of the + component. + """ + return 36.0 diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/hwaccess.py b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/hwaccess.py new file mode 120000 index 0000000000..e8fa340a44 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/hwaccess.py @@ -0,0 +1 @@ +../../common/sonic_platform/hwaccess.py \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/platform.py new file mode 100644 index 0000000000..996d94cf5a --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/platform.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +############################################################################# +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# + +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): + """ + DELLEMC Platform-specific class + """ + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/psu.py new file mode 100644 index 0000000000..613e5b3610 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/psu.py @@ -0,0 +1,282 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9432F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the PSUs' information which are available in the platform +# +######################################################################## + +try: + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.ipmihelper import IpmiSensor, IpmiFru + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +PSU_TYPE_OFFSET = 48 + +class Psu(PsuBase): + """DellEMC Platform-specific PSU class""" + + # { PSU-ID: { Sensor-Name: Sensor-ID } } + SENSOR_MAPPING = {1: {"State": 0x40, "Current": 0x4a, + "Power": 0x4b, "Voltage": 0x49, + "InCurrent": 0x43, "InPower": 0x44, + "InVoltage": 0x42, "Temperature": 0x48 }, + 2: {"State": 0x30, "Current": 0x3a, + "Power": 0x3b, "Voltage": 0x39, + "InCurrent": 0x33, "InPower": 0x34, + "InVoltage": 0x32, "Temperature": 0x38 } } + # ( PSU-ID: FRU-ID } + FRU_MAPPING = {1: 1, 2: 2} + + def __init__(self, psu_index): + PsuBase.__init__(self) + # PSU is 1-based in DellEMC platforms + self.index = psu_index + 1 + self.state_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["State"], + is_discrete=True) + self.voltage_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Voltage"]) + self.current_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Current"]) + self.power_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Power"]) + self.input_voltage_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["InVoltage"]) + self.input_current_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["InCurrent"]) + self.input_power_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["InPower"]) + self.temp_sensor = IpmiSensor(self.SENSOR_MAPPING[self.index]["Temperature"]) + self.psu_type_offset = PSU_TYPE_OFFSET + self.fru = IpmiFru(self.FRU_MAPPING[self.index]) + + self._fan_list.append(Fan(fan_index=self.index, psu_fan=True, + dependency=self)) + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return "PSU{}".format(self.index) + + def get_presence(self): + """ + Retrieves the presence of the Power Supply Unit (PSU) + + Returns: + bool: True if PSU is present, False if not + """ + presence = False + is_valid, state = self.state_sensor.get_reading() + if is_valid: + if state & 0b1: + presence = True + + return presence + + def get_model(self): + """ + Retrieves the part number of the PSU + + Returns: + string: Part number of PSU + """ + return self.fru.get_board_part_number() + + def get_serial(self): + """ + Retrieves the serial number of the PSU + + Returns: + string: Serial number of PSU + """ + return self.fru.get_board_serial() + + def get_revision(self): + """ + Retrieves the hardware revision of the device + + Returns: + string: Revision value of device + """ + serial = self.fru.get_board_serial() + if serial != "NA" and len(serial) == 23: + return serial[-3:] + else: + return "NA" + + def get_status(self): + """ + Retrieves the operational status of the PSU + + Returns: + bool: True if PSU is operating properly, False if not + """ + status = False + is_valid, state = self.state_sensor.get_reading() + if is_valid: + if state <= 0x01: + status = True + + return status + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + is_valid, voltage = self.voltage_sensor.get_reading() + if not is_valid: + return None + + return float(voltage) + + def get_voltage_low_threshold(self): + """ + Returns PSU low threshold in Volts + """ + is_valid, low_threshold = self.voltage_sensor.get_threshold("LowerCritical") + if not is_valid: + low_threshold = 11.4 + low_threshold = "{:.2f}".format(low_threshold) + + return float(low_threshold) + + + def get_voltage_high_threshold(self): + """ + Returns PSU high threshold in Volts + """ + is_valid, high_threshold = self.voltage_sensor.get_threshold("UpperCritical") + if not is_valid: + high_threshold = 12.6 + high_threshold = "{:.2f}".format(high_threshold) + + return float(high_threshold) + + 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 + """ + is_valid, temperature = self.temp_sensor.get_reading() + if not is_valid: + temperature = 0 + + return float(temperature) + + def get_temperature_high_threshold(self): + """ + Returns the high temperature threshold for PSU in Celsius + """ + is_valid, high_threshold = self.temp_sensor.get_threshold("UpperCritical") + if not is_valid: + high_threshold = 113 + high_threshold = "{:.2f}".format(high_threshold) + + return float(high_threshold) + + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, electric current in amperes, + e.g. 15.4 + """ + is_valid, current = self.current_sensor.get_reading() + if not is_valid: + return None + + return float(current) + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, + e.g. 302.6 + """ + is_valid, power = self.power_sensor.get_reading() + if not is_valid: + return None + + return float(power) + + def get_maximum_supplied_power(self): + """ + Retrieves the maximum supplied power by PSU + + Returns: + A float number, the maximum power output in Watts. + e.g. 1200.1 + """ + is_valid, power = self.power_sensor.get_threshold("UpperCritical") + if not is_valid: + return None + + return float(power) + + 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. + """ + status = False + is_valid, state = self.state_sensor.get_reading() + if is_valid: + if state == 0x01: + status = True + + return status + + def get_mfr_id(self): + """ + Retrives the Manufacturer Id of PSU + + Returns: + A string, the manunfacturer id. + """ + return self.fru.get_board_mfr_id() + + def get_type(self): + """ + Retrives the Power Type of PSU + + Returns : + A string, PSU power type + """ + psu_type = ['AC', 'DC'] + is_valid , ct_psu_type = self.fru.get_fru_data(self.psu_type_offset) + if is_valid: + return psu_type[ct_psu_type[0]] + return None + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this PSU is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/sfp.py new file mode 100644 index 0000000000..eaff8e9b1d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/sfp.py @@ -0,0 +1,390 @@ +#!/usr/bin/env python +""" +############################################################################# +# DELLEMC Z9432F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the platform information +# +############################################################################# +""" + +try: + import os + import time + import subprocess + import mmap + from sonic_platform_base.sonic_xcvr.sfp_optoe_base import SfpOptoeBase + +except ImportError as err: + raise ImportError(str(err) + "- required module not found") + +QSFP_INFO_OFFSET = 128 +SFP_INFO_OFFSET = 0 +QSFP_DD_PAGE0 = 0 + +SFP_TYPE_LIST = [ + '0x3' # SFP/SFP+/SFP28 and later +] +QSFP_TYPE_LIST = [ + '0x0c', # QSFP + '0x0d', # QSFP+ or later + '0x11' # QSFP28 or later +] +QSFP_DD_TYPE_LIST = [ + '0x18' #QSFP_DD Type +] + +OSFP_TYPE_LIST = [ + '0x19' # OSFP 8X Type +] + +class Sfp(SfpOptoeBase): + """ + DELLEMC Platform-specific Sfp class + """ + BASE_RES_PATH = "/sys/bus/pci/devices/0000:04:00.0/resource0" + + def __init__(self, index, sfp_type, eeprom_path): + """ + SFP Dunder init + """ + SfpOptoeBase.__init__(self) + self.index = index + self.eeprom_path = eeprom_path + self.sfp_eeprom_path = eeprom_path + #port_type is the native port type and sfp_type is the transceiver type + #sfp_type will be detected in get_transceiver_info + self.port_type = sfp_type + self.sfp_type = self.port_type + self._initialize_media(delay=False) + + def get_eeprom_path(self): + """ + Returns SFP eeprom path + """ + return self.eeprom_path + + def get_name(self): + """ + Returns native transceiver type + """ + return "QSFP-DD Double Density 8X Pluggable Transceiver" if self.index < 33 else "SFP/SFP+/SFP28" + + @staticmethod + def pci_mem_read(mem, offset): + """ + Returns the desired byte in PCI memory space + """ + mem.seek(offset) + return mem.read_byte() + + @staticmethod + def pci_mem_write(mem, offset, data): + """ + Writes the desired byte in PCI memory space + """ + mem.seek(offset) + # print "data to write:%x"%data + mem.write_byte(data) + + def pci_set_value(self, resource, val, offset): + """ + Sets the value in PCI memory space + """ + filed = os.open(resource, os.O_RDWR) + mem = mmap.mmap(filed, 0) + self.pci_mem_write(mem, offset, val) + mem.close() + os.close(filed) + return val + + def pci_get_value(self, resource, offset): + """ + Retrieves the value from PCI memory space + """ + filed = os.open(resource, os.O_RDWR) + mem = mmap.mmap(filed, 0) + val = self.pci_mem_read(mem, offset) + mem.close() + os.close(filed) + return val + + def _initialize_media(self, delay=False): + """ + Initialize the media type and eeprom driver for SFP + """ + if delay: + time.sleep(1) + self._xcvr_api = None + self.get_xcvr_api() + + self.set_media_type() + self.reinit_sfp_driver() + + def get_presence(self): + """ + Retrieves the presence of the sfp + Returns : True if sfp is present and false if it is absent + """ + # Check for invalid port_num + mask = {'QSFP_DD' : (1 << 4), 'SFP' : (1 << 0)} + # Port offset starts with 0x4004 + port_offset = 16388 + ((self.index-1) * 16) + + try: + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + # ModPrsL is active low + if reg_value & mask[self.port_type] == 0: + return True + except ValueError: + pass + + return False + + def get_reset_status(self): + """ + Retrives the reset status of SFP + """ + reset_status = False + try: + if self.port_type == 'QSFP_DD': + # Port offset starts with 0x4000 + port_offset = 16384 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Mask off 4th bit for reset status + mask = (1 << 4) + reset_status = not (reg_value & mask) + except ValueError: + pass + + return reset_status + + def get_lpmode(self): + """ + Retrieves the lpmode(low power mode) of this SFP + """ + lpmode_state = False + try: + if self.sfp_type == 'QSFP_DD': + return SfpOptoeBase.get_lpmode(self) + else: + # Port offset starts with 0x4000 + port_offset = 16384 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Mask off 6th bit for lpmode + mask = (1 << 6) + + lpmode_state = (reg_value & mask) + except ValueError: + pass + return bool(lpmode_state) + + def reset(self): + """ + Reset the SFP and returns all user settings to their default state + """ + try: + if self.port_type == 'QSFP_DD': + # Port offset starts with 0x4000 + port_offset = 16384 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Mask off 4th bit for reset + mask = (1 << 4) + + # ResetL is active low + reg_value = reg_value & ~mask + + # Convert our register value back to a hex string and write back + 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 + self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + else: + return False + except ValueError: + return False + return True + + def set_lpmode(self, lpmode): + """ + Sets the lpmode(low power mode) of this SFP + """ + try: + if self.sfp_type == 'QSFP_DD': + return SfpOptoeBase.set_lpmode(self, lpmode) + else: + # Port offset starts with 0x4000 + port_offset = 16384 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Mask off 6th bit for lowpower mode + 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 + self.pci_set_value(self.BASE_RES_PATH, reg_value, port_offset) + except ValueError: + return False + return True + + def get_intl_state(self): + """ + Sets the intL (interrupt; active low) pin of this SFP + """ + intl_state = True + try: + if self.port_type == 'QSFP_DD': + # Port offset starts with 0x4004 + port_offset = 16388 + ((self.index-1) * 16) + + status = self.pci_get_value(self.BASE_RES_PATH, port_offset) + reg_value = int(status) + + # Mask off 4th bit for intL + mask = (1 << 4) + + intl_state = (reg_value & mask) + except ValueError: + pass + return intl_state + + def set_media_type(self): + """ + Reads optic eeprom byte to determine media type inserted + """ + eeprom_raw = [] + eeprom_raw = self._xcvr_api_factory._get_id() + if eeprom_raw is not None: + eeprom_raw = hex(eeprom_raw) + if eeprom_raw in SFP_TYPE_LIST: + self.sfp_type = 'SFP' + elif eeprom_raw in QSFP_TYPE_LIST: + self.sfp_type = 'QSFP' + elif eeprom_raw in QSFP_DD_TYPE_LIST: + self.sfp_type = 'QSFP_DD' + else: + #Set native port type if EEPROM type is not recognized/readable + self.sfp_type = self.port_type + else: + self.sfp_type = self.port_type + + return self.sfp_type + + def reinit_sfp_driver(self): + """ + Changes the driver based on media type detected + """ + + i2c_bus = self.sfp_eeprom_path[27:].split('/')[0] + del_sfp_path = "/sys/class/i2c-adapter/i2c-{0}/delete_device".format(i2c_bus) + new_sfp_path = "/sys/class/i2c-adapter/i2c-{0}/new_device".format(i2c_bus) + driver_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/name".format(i2c_bus) + delete_device = "echo 0x50 >" + del_sfp_path + + if not os.path.isfile(driver_path): + print(driver_path, "does not exist") + return False + + try: + with os.fdopen(os.open(driver_path, os.O_RDONLY)) as filed: + driver_name = filed.read() + driver_name = driver_name.rstrip('\r\n') + driver_name = driver_name.lstrip(" ") + + #Avoid re-initialization of the QSFP/SFP optic on QSFP/SFP port. + if self.sfp_type == 'SFP' and driver_name in ['optoe1', 'optoe3']: + subprocess.Popen(delete_device, shell=True, stdout=subprocess.PIPE) + time.sleep(0.2) + new_device = "echo optoe2 0x50 >" + new_sfp_path + subprocess.Popen(new_device, shell=True, stdout=subprocess.PIPE) + time.sleep(2) + elif self.sfp_type == 'QSFP' and driver_name in ['optoe2', 'optoe3']: + subprocess.Popen(delete_device, shell=True, stdout=subprocess.PIPE) + time.sleep(0.2) + new_device = "echo optoe1 0x50 >" + new_sfp_path + subprocess.Popen(new_device, shell=True, stdout=subprocess.PIPE) + time.sleep(2) + elif self.sfp_type == 'QSFP_DD' and driver_name in ['optoe1', 'optoe2']: + subprocess.Popen(delete_device, shell=True, stdout=subprocess.PIPE) + time.sleep(0.2) + new_device = "echo optoe3 0x50 >" + new_sfp_path + subprocess.Popen(new_device, shell=True, stdout=subprocess.PIPE) + time.sleep(2) + + except IOError as err: + print("Error: Unable to open file: %s" %str(err)) + return False + + return True + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + @staticmethod + def is_replaceable(): + """ + Indicate whether this device is replaceable. + Returns: + bool: True if it is replaceable. + """ + return True + + def get_error_description(self): + """ + Retrives the error descriptions of the SFP module + + Returns: + String that represents the current error descriptions of vendor specific errors + In case there are multiple errors, they should be joined by '|', + like: "Bad EEPROM|Unsupported cable" + """ + if not self.get_presence(): + return self.SFP_STATUS_UNPLUGGED + else: + if not os.path.isfile(self.eeprom_path): + return "EEPROM driver is not attached" + + if self.sfp_type == 'SFP': + offset = SFP_INFO_OFFSET + elif self.sfp_type == 'QSFP': + offset = QSFP_INFO_OFFSET + elif self.sfp_type == 'QSFP_DD': + offset = QSFP_DD_PAGE0 + + try: + with open(self.eeprom_path, mode="rb", buffering=0) as eeprom: + eeprom.seek(offset) + eeprom.read(1) + except OSError as e: + return "EEPROM read failed ({})".format(e.strerror) + + return self.SFP_STATUS_OK diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/thermal.py new file mode 100644 index 0000000000..6503787af8 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/thermal.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python + +######################################################################## +# DellEMC Z9432F +# +# Module contains an implementation of SONiC Platform Base API and +# provides the Thermals' information which are available in the platform +# +######################################################################## + + +try: + from sonic_platform_base.thermal_base import ThermalBase + from sonic_platform.ipmihelper import IpmiSensor +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Thermal(ThermalBase): + """DellEMC Platform-specific Thermal class""" + + # [ Sensor-Name, Sensor-ID, high threshold, high critical_threshold ] + # TBD : + # high thershold/hich crit threshold + # need to be modified as True in case if it is supported + # + SENSOR_MAPPING = [ + ['CPU Temp', 0xd, True, True], + ['FAN Right Temp', 0x0, True, True], + ['NPU Front Temp', 0x1, True, True], + ['NPU Rear Temp', 0x3, True, True], + ['NPU Temp', 0x8, True, True], + ['PSU1 AF Temp', 0x46, False, True], + ['PSU1 Mid Temp', 0x47, False, True], + ['PSU1 Rear Temp', 0x48, False, True], + ['PSU2 AF Temp', 0x36, False, True], + ['PSU2 Mid Temp', 0x37, False, True], + ['PSU2 Rear Temp', 0x38, False, True], + ['PT Left Temp', 0x2, True, True], + ['PT Right Temp', 0x4, True, True] + ] + + def __init__(self, thermal_index=0): + ThermalBase.__init__(self) + self.index = thermal_index + 1 + self.sensor = IpmiSensor(self.SENSOR_MAPPING[self.index - 1][1]) + self.has_high_threshold = self.SENSOR_MAPPING[self.index - 1][2] + self.has_high_crit_threshold = self.SENSOR_MAPPING[self.index - 1][3] + + def get_name(self): + """ + Retrieves the name of the thermal + + Returns: + string: The name of the thermal + """ + return self.SENSOR_MAPPING[self.index - 1][0] + + def get_presence(self): + """ + Retrieves the presence of the thermal + + Returns: + bool: True if thermal is present, False if not + """ + return True + + def get_model(self): + """ + Retrieves the model number (or part number) of the Thermal + + Returns: + string: Model/part number of Thermal + """ + return 'NA' + + def get_serial(self): + """ + Retrieves the serial number of the Thermal + + Returns: + string: Serial number of Thermal + """ + return 'NA' + + def get_status(self): + """ + Retrieves the operational status of the thermal + + Returns: + A boolean value, True if thermal is operating properly, + False if not + """ + return True + + 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 + """ + is_valid, temperature = self.sensor.get_reading() + if not is_valid: + temperature = 0 + + return float(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 + """ + if self.has_high_threshold: + is_valid, high_threshold = self.sensor.get_threshold("UpperNonCritical") + if is_valid: + return float(high_threshold) + + return super(Thermal, self).get_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 + """ + return 0.0 + + def get_high_critical_threshold(self): + """ + Retrieves the high critical threshold temperature of thermal + Returns: + A float number, the high critical threshold temperature of + thermal in Celsius up to nearest thousandth of one degree + Celsius, e.g. 30.125 + """ + if self.has_high_crit_threshold: + is_valid, high_crit_threshold = self.sensor.get_threshold("UpperCritical") + if is_valid: + return float(high_crit_threshold) + + return super(Thermal, self).get_high_critical_threshold() + + 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 + """ + # Thermal threshold values are pre-defined based on HW. + return False + + 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 + """ + # Thermal threshold values are pre-defined based on HW. + return False + + def get_position_in_parent(self): + """ + Retrieves 1-based relative physical position in parent device. + Returns: + integer: The 1-based relative physical position in parent + device or -1 if cannot determine the position + """ + return self.index + + def is_replaceable(self): + """ + Indicate whether this Thermal is replaceable. + Returns: + bool: True if it is replaceable. + """ + return False diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/watchdog.py b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/watchdog.py new file mode 100644 index 0000000000..0efc925a92 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/sonic_platform/watchdog.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python + +######################################################################## +# +# DELLEMC Z9432F +# +# Abstract base class for implementing a platform-specific class with +# which to interact with a hardware watchdog module in SONiC +# +######################################################################## + +try: + import ctypes + import subprocess + import syslog + import sonic_platform.component as Component + from sonic_platform_base.watchdog_base import WatchdogBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class _timespec(ctypes.Structure): + _fields_ = [ + ('tv_sec', ctypes.c_long), + ('tv_nsec', ctypes.c_long) + ] + + +class Watchdog(WatchdogBase): + """ + Abstract base class for interfacing with a hardware watchdog module + """ + + TIMERS = [15,20,30,40,50,60,65,70,80,100,120,140,160,180,210,240] + + armed_time = 0 + timeout = 0 + CLOCK_MONOTONIC = 1 + + def __init__(self): + self._librt = ctypes.CDLL('librt.so.1', use_errno=True) + self._clock_gettime = self._librt.clock_gettime + self._clock_gettime.argtypes=[ctypes.c_int, ctypes.POINTER(_timespec)] + + def _get_command_result(self, cmdline): + try: + proc = subprocess.Popen(cmdline.split(), stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + stdout = proc.communicate()[0] + proc.wait() + result = stdout.rstrip('\n'.encode()) + except OSError: + result = None + + return result + + def _get_reg_val(self): + # 0x31 = CPLD I2C Base Address + # 0x07 = Watchdog Function Register + value = self._get_command_result("/usr/sbin/i2cget -y 601 0x31 0x07") + if not value: + return None + else: + return int(value, 16) + + def _set_reg_val(self,val): + # 0x31 = CPLD I2C Base Address + # 0x07 = Watchdog Function Register + value = self._get_command_result("/usr/sbin/i2cset -y 601 0x31 0x07 %s" + % (val)) + return value + + def _get_time(self): + """ + To get clock monotonic time + """ + ts = _timespec() + if self._clock_gettime(self.CLOCK_MONOTONIC, ctypes.pointer(ts)) != 0: + self._errno = ctypes.get_errno() + return 0 + return ts.tv_sec + ts.tv_nsec * 1e-9 + + def arm(self, seconds): + """ + Arm the hardware watchdog with a timeout of 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 , 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. + """ + timer_offset = -1 + for key,timer_seconds in enumerate(self.TIMERS): + if seconds > 0 and seconds <= timer_seconds: + timer_offset = key + seconds = timer_seconds + break + + if timer_offset == -1: + return -1 + + cpld_version = Component.get_cpld0_version() + wd_enabled_version = "0.8" + + if cpld_version < wd_enabled_version: + syslog.syslog(syslog.LOG_ERR, + 'Older System CPLD ver, Update to 0.8 to support watchdog ') + return -1 + + # Extracting 5th to 8th bits for WD timer values + reg_val = self._get_reg_val() + wd_timer_offset = (reg_val >> 4) & 0xf + + if wd_timer_offset != timer_offset: + # Setting 5th to 7th bits + # value from timer_offset + self.disarm() + self._set_reg_val((reg_val & 0x07) | (timer_offset << 4)) + + if self.is_armed(): + # Setting last bit to WD Timer punch + # Last bit = WD Timer punch + self._set_reg_val(reg_val & 0xFE) + + self.armed_time = self._get_time() + self.timeout = seconds + return seconds + else: + # Setting 4th bit to enable WD + # 4th bit = Enable WD + reg_val = self._get_reg_val() + self._set_reg_val(reg_val | 0x8) + + self.armed_time = self._get_time() + self.timeout = seconds + return seconds + + def disarm(self): + """ + Disarm the hardware watchdog + + Returns: + A boolean, True if watchdog is disarmed successfully, False + if not + """ + if self.is_armed(): + # Setting 4th bit to disable WD + # 4th bit = Disable WD + reg_val = self._get_reg_val() + self._set_reg_val(reg_val & 0xF7) + + self.armed_time = 0 + self.timeout = 0 + return True + + return False + + def is_armed(self): + """ + Retrieves the armed state of the hardware watchdog. + + Returns: + A boolean, True if watchdog is armed, False if not + """ + + # Extracting 4th bit to get WD Enable/Disable status + # 0 - Disabled WD + # 1 - Enabled WD + reg_val = self._get_reg_val() + wd_offset = (reg_val >> 3) & 1 + + return bool(wd_offset) + + 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 + their watchdog timer. If the watchdog is not armed, returns + -1. + + Z9432F doesnot have hardware support to show remaining time. + Due to this limitation, this API is implemented in software. + This API would return correct software time difference if it + is called from the process which armed the watchdog timer. + If this API called from any other process, it would return + 0. If the watchdog is not armed, this API would return -1. + """ + if not self.is_armed(): + return -1 + + if self.armed_time > 0 and self.timeout != 0: + cur_time = self._get_time() + + if cur_time <= 0: + return 0 + + diff_time = int(cur_time - self.armed_time) + + if diff_time > self.timeout: + return self.timeout + else: + return self.timeout - diff_time + + return 0 diff --git a/platform/broadcom/sonic-platform-modules-dell/z9432f/systemd/platform-modules-z9432f.service b/platform/broadcom/sonic-platform-modules-dell/z9432f/systemd/platform-modules-z9432f.service new file mode 100644 index 0000000000..8ae1d65264 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-dell/z9432f/systemd/platform-modules-z9432f.service @@ -0,0 +1,14 @@ +[Unit] +Description=Dell Z9432F Platform modules +Before=pmon.service +After=platform-init.service +DefaultDependencies=no + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/z9432f_platform.sh init +ExecStop=/usr/local/bin/z9432f_platform.sh deinit +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target