From 110bff9b47f5bcfa76638ac52f862dd83ba113b7 Mon Sep 17 00:00:00 2001 From: David Xiao <53024022+david-xk@users.noreply.github.com> Date: Wed, 9 Oct 2019 16:16:05 -0700 Subject: [PATCH] [Inventec][D6356] Update driver and Add new platform API implementation (#3521) * Update driver and Add new platform API implementation for Inventec D6356 * Update Platform API (SFP) * Update Platform API (QSFP) * Update Platform API (FAN, THERMAL) Signed-off-by: David Xiao --- .../INVENTEC-D6356/buffers.json.j2 | 2 + .../INVENTEC-D6356/buffers_defaults_t0.j2 | 50 + .../INVENTEC-D6356/buffers_defaults_t1.j2 | 50 + .../INVENTEC-D6356/pg_profile_lookup.ini | 17 + .../INVENTEC-D6356/port_config.ini | 114 +- .../INVENTEC-D6356/qos.json.j2 | 155 +++ .../td3-d6356-48x25G-8x100G.config.bcm | 248 ++-- .../x86_64-inventec_d6356-r0/custom_led.bin | Bin 0 -> 552 bytes .../led_proc_init.soc | 4 +- .../linkscan_led_fw.bin | Bin 0 -> 4744 bytes .../plugins/psuutil.py | 12 +- .../plugins/sfputil.py | 170 ++- .../x86_64-inventec_d6356-r0/sensors.conf | 7 +- .../d6356/modules/Makefile | 4 + .../d6356/modules/gpio-ich.c | 513 ++++++++ .../d6356/modules/i2c-mux-pca9541.c | 573 +++++++++ .../d6356/modules/inv_cpld.c | 165 ++- .../d6356/modules/inv_mux.c | 366 +++++- .../d6356/modules/inv_mux.h | 46 +- .../d6356/modules/inv_platform.c | 92 +- .../d6356/modules/inv_swps.c | 331 ++++- .../d6356/modules/inv_swps.h | 621 +++++++-- .../d6356/modules/io_expander.c | 634 ++++++++- .../d6356/modules/io_expander.h | 52 +- .../d6356/modules/lpc_ich.c | 1131 +++++++++++++++++ .../d6356/modules/pmbus.h | 425 +++++++ .../d6356/modules/transceiver.c | 35 +- .../d6356/modules/transceiver.h | 8 +- .../d6356/modules/ucd9000.c | 247 ++++ .../d6356/setup.py | 15 + .../d6356/sonic_platform/__init__.py | 3 + .../d6356/sonic_platform/chassis.py | 149 +++ .../d6356/sonic_platform/eeprom.py | 110 ++ .../d6356/sonic_platform/fan.py | 204 +++ .../d6356/sonic_platform/platform.py | 20 + .../d6356/sonic_platform/psu.py | 202 +++ .../d6356/sonic_platform/qsfp.py | 925 ++++++++++++++ .../d6356/sonic_platform/sfp.py | 739 +++++++++++ .../d6356/sonic_platform/thermal.py | 170 +++ .../d6356/utils/inventec_d6356_util.py | 33 +- .../debian/control | 2 +- .../debian/platform-modules-d6356.install | 4 +- .../debian/rules | 18 +- .../systemd/platform-modules-d6356.service | 13 + 44 files changed, 8077 insertions(+), 602 deletions(-) create mode 100644 device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers.json.j2 create mode 100644 device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers_defaults_t0.j2 create mode 100644 device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers_defaults_t1.j2 create mode 100644 device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/pg_profile_lookup.ini create mode 100644 device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/qos.json.j2 create mode 100644 device/inventec/x86_64-inventec_d6356-r0/custom_led.bin create mode 100644 device/inventec/x86_64-inventec_d6356-r0/linkscan_led_fw.bin create mode 100644 platform/broadcom/sonic-platform-modules-inventec/d6356/modules/gpio-ich.c create mode 100644 platform/broadcom/sonic-platform-modules-inventec/d6356/modules/i2c-mux-pca9541.c create mode 100644 platform/broadcom/sonic-platform-modules-inventec/d6356/modules/lpc_ich.c create mode 100644 platform/broadcom/sonic-platform-modules-inventec/d6356/modules/pmbus.h create mode 100644 platform/broadcom/sonic-platform-modules-inventec/d6356/modules/ucd9000.c create mode 100644 platform/broadcom/sonic-platform-modules-inventec/d6356/setup.py create mode 100644 platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/__init__.py create mode 100644 platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/chassis.py create mode 100644 platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/eeprom.py create mode 100644 platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/fan.py create mode 100644 platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/platform.py create mode 100644 platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/psu.py create mode 100644 platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/qsfp.py create mode 100644 platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/sfp.py create mode 100644 platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/thermal.py create mode 100644 platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6356.service diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers.json.j2 b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers.json.j2 new file mode 100644 index 0000000000..0b1cb2c541 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers.json.j2 @@ -0,0 +1,2 @@ +{%- set default_topo = 't1' %} +{%- include 'buffers_config.j2' %} diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers_defaults_t0.j2 b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers_defaults_t0.j2 new file mode 100644 index 0000000000..1587625a29 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers_defaults_t0.j2 @@ -0,0 +1,50 @@ +{%- set default_cable = '40m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,47) %} + {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %} + {% endfor %} + {% for port_idx in range(12,19) %} + {% if PORT.append("Ethernet%d" % (port_idx*4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10443264", + "type": "ingress", + "mode": "dynamic", + "xoff": "7335744" + }, + "egress_lossy_pool": { + "size": "8877440", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"3995680" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} + diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers_defaults_t1.j2 b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers_defaults_t1.j2 new file mode 100644 index 0000000000..1587625a29 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/buffers_defaults_t1.j2 @@ -0,0 +1,50 @@ +{%- set default_cable = '40m' %} + +{%- macro generate_port_lists(PORT_ALL) %} + {# Generate list of ports #} + {% for port_idx in range(0,47) %} + {% if PORT.append("Ethernet%d" % (port_idx)) %}{% endif %} + {% endfor %} + {% for port_idx in range(12,19) %} + {% if PORT.append("Ethernet%d" % (port_idx*4)) %}{% endif %} + {% endfor %} +{%- endmacro %} + +{%- macro generate_buffer_pool_and_profiles() %} + "BUFFER_POOL": { + "ingress_lossless_pool": { + "size": "10443264", + "type": "ingress", + "mode": "dynamic", + "xoff": "7335744" + }, + "egress_lossy_pool": { + "size": "8877440", + "type": "egress", + "mode": "dynamic" + }, + "egress_lossless_pool": { + "size": "15982720", + "type": "egress", + "mode": "static" + } + }, + "BUFFER_PROFILE": { + "ingress_lossy_profile": { + "pool":"[BUFFER_POOL|ingress_lossless_pool]", + "size":"0", + "dynamic_th":"3" + }, + "egress_lossless_profile": { + "pool":"[BUFFER_POOL|egress_lossless_pool]", + "size":"1518", + "static_th":"3995680" + }, + "egress_lossy_profile": { + "pool":"[BUFFER_POOL|egress_lossy_pool]", + "size":"1518", + "dynamic_th":"3" + } + }, +{%- endmacro %} + diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/pg_profile_lookup.ini b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/pg_profile_lookup.ini new file mode 100644 index 0000000000..7222f80149 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/pg_profile_lookup.ini @@ -0,0 +1,17 @@ +# PG lossless profiles. +# speed cable size xon xoff threshold xon_offset + 10000 5m 1248 2288 35776 -4 2288 + 25000 5m 1248 2288 53248 -4 2288 + 40000 5m 1248 2288 66560 -4 2288 + 50000 5m 1248 2288 79872 -4 2288 + 100000 5m 1248 2288 165568 -4 2288 + 10000 40m 1248 2288 37024 -4 2288 + 25000 40m 1248 2288 56160 -4 2288 + 40000 40m 1248 2288 71552 -4 2288 + 50000 40m 1248 2288 85696 -4 2288 + 100000 40m 1248 2288 177632 -4 2288 + 10000 300m 1248 2288 46176 -4 2288 + 25000 300m 1248 2288 79040 -4 2288 + 40000 300m 1248 2288 108160 -4 2288 + 50000 300m 1248 2288 131456 -4 2288 + 100000 300m 1248 2288 268736 -4 2288 diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/port_config.ini b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/port_config.ini index ba13dd5743..aaac478ab8 100755 --- a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/port_config.ini +++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/port_config.ini @@ -1,57 +1,57 @@ -# name lanes alias index -Ethernet0 1 Ethernet0 0 -Ethernet1 2 Ethernet1 1 -Ethernet2 3 Ethernet2 2 -Ethernet3 4 Ethernet3 3 -Ethernet4 5 Ethernet4 4 -Ethernet5 6 Ethernet5 5 -Ethernet6 7 Ethernet6 6 -Ethernet7 8 Ethernet7 7 -Ethernet8 13 Ethernet8 8 -Ethernet9 14 Ethernet9 9 -Ethernet10 15 Ethernet10 10 -Ethernet11 16 Ethernet11 11 -Ethernet12 21 Ethernet12 12 -Ethernet13 22 Ethernet13 13 -Ethernet14 23 Ethernet14 14 -Ethernet15 24 Ethernet15 15 -Ethernet16 29 Ethernet16 16 -Ethernet17 30 Ethernet17 17 -Ethernet18 31 Ethernet18 18 -Ethernet19 32 Ethernet19 19 -Ethernet20 33 Ethernet20 20 -Ethernet21 34 Ethernet21 21 -Ethernet22 35 Ethernet22 22 -Ethernet23 36 Ethernet23 23 -Ethernet24 41 Ethernet24 24 -Ethernet25 42 Ethernet25 25 -Ethernet26 43 Ethernet26 26 -Ethernet27 44 Ethernet27 27 -Ethernet28 49 Ethernet28 28 -Ethernet29 50 Ethernet29 29 -Ethernet30 51 Ethernet30 30 -Ethernet31 52 Ethernet31 31 -Ethernet32 57 Ethernet32 32 -Ethernet33 58 Ethernet33 33 -Ethernet34 59 Ethernet34 34 -Ethernet35 60 Ethernet35 35 -Ethernet36 61 Ethernet36 36 -Ethernet37 62 Ethernet37 37 -Ethernet38 63 Ethernet38 38 -Ethernet39 64 Ethernet39 39 -Ethernet40 65 Ethernet40 40 -Ethernet41 66 Ethernet41 41 -Ethernet42 67 Ethernet42 42 -Ethernet43 68 Ethernet43 43 -Ethernet44 69 Ethernet44 44 -Ethernet45 70 Ethernet45 45 -Ethernet46 71 Ethernet46 46 -Ethernet47 72 Ethernet47 47 -Ethernet48 85,86,87,88 Ethernet48 48 -Ethernet52 77,78,79,80 Ethernet52 49 -Ethernet56 93,94,95,96 Ethernet56 50 -Ethernet60 97,98,99,100 Ethernet60 51 -Ethernet64 113,114,115,116 Ethernet64 52 -Ethernet68 105,106,107,108 Ethernet68 53 -Ethernet72 121,122,123,124 Ethernet72 54 -Ethernet76 125,126,127,128 Ethernet76 55 +# name lanes alias index speed +Ethernet0 1 Ethernet0 0 25000 +Ethernet1 2 Ethernet1 1 25000 +Ethernet2 3 Ethernet2 2 25000 +Ethernet3 4 Ethernet3 3 25000 +Ethernet4 5 Ethernet4 4 25000 +Ethernet5 6 Ethernet5 5 25000 +Ethernet6 7 Ethernet6 6 25000 +Ethernet7 8 Ethernet7 7 25000 +Ethernet8 13 Ethernet8 8 25000 +Ethernet9 14 Ethernet9 9 25000 +Ethernet10 15 Ethernet10 10 25000 +Ethernet11 16 Ethernet11 11 25000 +Ethernet12 21 Ethernet12 12 25000 +Ethernet13 22 Ethernet13 13 25000 +Ethernet14 23 Ethernet14 14 25000 +Ethernet15 24 Ethernet15 15 25000 +Ethernet16 29 Ethernet16 16 25000 +Ethernet17 30 Ethernet17 17 25000 +Ethernet18 31 Ethernet18 18 25000 +Ethernet19 32 Ethernet19 19 25000 +Ethernet20 33 Ethernet20 20 25000 +Ethernet21 34 Ethernet21 21 25000 +Ethernet22 35 Ethernet22 22 25000 +Ethernet23 36 Ethernet23 23 25000 +Ethernet24 41 Ethernet24 24 25000 +Ethernet25 42 Ethernet25 25 25000 +Ethernet26 43 Ethernet26 26 25000 +Ethernet27 44 Ethernet27 27 25000 +Ethernet28 49 Ethernet28 28 25000 +Ethernet29 50 Ethernet29 29 25000 +Ethernet30 51 Ethernet30 30 25000 +Ethernet31 52 Ethernet31 31 25000 +Ethernet32 57 Ethernet32 32 25000 +Ethernet33 58 Ethernet33 33 25000 +Ethernet34 59 Ethernet34 34 25000 +Ethernet35 60 Ethernet35 35 25000 +Ethernet36 61 Ethernet36 36 25000 +Ethernet37 62 Ethernet37 37 25000 +Ethernet38 63 Ethernet38 38 25000 +Ethernet39 64 Ethernet39 39 25000 +Ethernet40 65 Ethernet40 40 25000 +Ethernet41 66 Ethernet41 41 25000 +Ethernet42 67 Ethernet42 42 25000 +Ethernet43 68 Ethernet43 43 25000 +Ethernet44 69 Ethernet44 44 25000 +Ethernet45 70 Ethernet45 45 25000 +Ethernet46 71 Ethernet46 46 25000 +Ethernet47 72 Ethernet47 47 25000 +Ethernet48 85,86,87,88 Ethernet48 48 100000 +Ethernet52 77,78,79,80 Ethernet52 49 100000 +Ethernet56 93,94,95,96 Ethernet56 50 100000 +Ethernet60 97,98,99,100 Ethernet60 51 100000 +Ethernet64 113,114,115,116 Ethernet64 52 100000 +Ethernet68 105,106,107,108 Ethernet68 53 100000 +Ethernet72 121,122,123,124 Ethernet72 54 100000 +Ethernet76 125,126,127,128 Ethernet76 55 100000 diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/qos.json.j2 b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/qos.json.j2 new file mode 100644 index 0000000000..d3cac04f66 --- /dev/null +++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/qos.json.j2 @@ -0,0 +1,155 @@ +{ + "TC_TO_PRIORITY_GROUP_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "MAP_PFC_PRIORITY_TO_QUEUE": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "TC_TO_QUEUE_MAP": { + "AZURE": { + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7" + } + }, + "DSCP_TO_TC_MAP": { + "AZURE": { + "0":"0", + "1":"0", + "2":"0", + "3":"3", + "4":"4", + "5":"0", + "6":"0", + "7":"0", + "8":"1", + "9":"0", + "10":"0", + "11":"0", + "12":"0", + "13":"0", + "14":"0", + "15":"0", + "16":"0", + "17":"0", + "18":"0", + "19":"0", + "20":"0", + "21":"0", + "22":"0", + "23":"0", + "24":"0", + "25":"0", + "26":"0", + "27":"0", + "28":"0", + "29":"0", + "30":"0", + "31":"0", + "32":"0", + "33":"0", + "34":"0", + "35":"0", + "36":"0", + "37":"0", + "38":"0", + "39":"0", + "40":"0", + "41":"0", + "42":"0", + "43":"0", + "44":"0", + "45":"0", + "46":"0", + "47":"0", + "48":"0", + "49":"0", + "50":"0", + "51":"0", + "52":"0", + "53":"0", + "54":"0", + "55":"0", + "56":"0", + "57":"0", + "58":"0", + "59":"0", + "60":"0", + "61":"0", + "62":"0", + "63":"0" + } + }, + "SCHEDULER": { + "scheduler.0" : { + "type":"DWRR", + "weight": "25" + }, + "scheduler.1" : { + "type":"DWRR", + "weight": "30" + }, + "scheduler.2" : { + "type":"DWRR", + "weight": "20" + } + }, + "PORT_QOS_MAP": { + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76": { + "dscp_to_tc_map" : "[DSCP_TO_TC_MAP|AZURE]", + "tc_to_queue_map" : "[TC_TO_QUEUE_MAP|AZURE]", + "tc_to_pg_map" : "[TC_TO_PRIORITY_GROUP_MAP|AZURE]", + "pfc_to_queue_map": "[MAP_PFC_PRIORITY_TO_QUEUE|AZURE]", + "pfc_enable": "3,4" + } + }, + "WRED_PROFILE": { + "AZURE_LOSSLESS" : { + "wred_green_enable":"true", + "wred_yellow_enable":"true", + "wred_red_enable":"true", + "ecn":"ecn_all", + "red_max_threshold":"312000", + "red_min_threshold":"104000", + "yellow_max_threshold":"312000", + "yellow_min_threshold":"104000", + "green_max_threshold": "312000", + "green_min_threshold": "104000" + } + }, + "QUEUE": { + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76|3-4" : { + "scheduler" : "[SCHEDULER|scheduler.0]", + "wred_profile" : "[WRED_PROFILE|AZURE_LOSSLESS]" + }, + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76|0" : { + "scheduler" : "[SCHEDULER|scheduler.1]" + }, + "Ethernet0,Ethernet1,Ethernet2,Ethernet3,Ethernet4,Ethernet5,Ethernet6,Ethernet7,Ethernet8,Ethernet9,Ethernet10,Ethernet11,Ethernet12,Ethernet13,Ethernet14,Ethernet15,Ethernet16,Ethernet17,Ethernet18,Ethernet19,Ethernet20,Ethernet21,Ethernet22,Ethernet23,Ethernet24,Ethernet25,Ethernet26,Ethernet27,Ethernet28,Ethernet29,Ethernet30,Ethernet31,Ethernet32,Ethernet33,Ethernet34,Ethernet35,Ethernet36,Ethernet37,Ethernet38,Ethernet39,Ethernet40,Ethernet41,Ethernet42,Ethernet43,Ethernet44,Ethernet45,Ethernet46,Ethernet47,Ethernet48,Ethernet52,Ethernet56,Ethernet60,Ethernet64,Ethernet68,Ethernet72,Ethernet76|1" : { + "scheduler" : "[SCHEDULER|scheduler.2]" + } + } +} diff --git a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/td3-d6356-48x25G-8x100G.config.bcm b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/td3-d6356-48x25G-8x100G.config.bcm index f6fc4f02f1..57fd5cd571 100644 --- a/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/td3-d6356-48x25G-8x100G.config.bcm +++ b/device/inventec/x86_64-inventec_d6356-r0/INVENTEC-D6356/td3-d6356-48x25G-8x100G.config.bcm @@ -2,8 +2,10 @@ ptp_ts_pll_fref=50000000 ptp_bs_fref_0=50000000 ptp_bs_fref_1=50000000 +ifp_inports_support_enable=1 ### end fix +stable_size=0x5500000 core_clock_frequency=1525 dpp_clock_ratio=2:3 @@ -12,7 +14,7 @@ oversubscribe_mode=1 pbmp_xport_xe=0x488787878808787fdfe1e1e1fe1e1e1fe -portmap_65=130:10 +#portmap_65=130:10 ### Pipeline0, halfpipe 0 (12x25G + 2x100G) portmap_1=1:25 @@ -60,11 +62,11 @@ portmap_64=64:25 ### Pipeline 1 ### First management port -portmap_66=129:10:m +#portmap_66=129:10:m ### Second management port -portmap_130=128:10:m +#portmap_130=128:10:m ### Loopback port -portmap_131=131:10 +#portmap_131=131:10 ### Pipeline 1, halfpipe 0 (12x25G + 2x100G) portmap_67=65:25 @@ -92,6 +94,11 @@ fpem_mem_entries=16384 l2xmsg_mode=1 + +pdma_descriptor_prefetch_enable=1 + +port_flex_enable=1 + #dport part dport_map_port_79=87 dport_map_port_87=79 @@ -281,118 +288,125 @@ phy_chain_tx_polarity_flip_physical{132.0}=0x0 phy_chain_rx_polarity_flip_physical{132.0}=0x0 # EQ/IDriver -serdes_preemphasis_1=0x13460B -serdes_preemphasis_2=0x13460B -serdes_preemphasis_3=0x14450B -serdes_preemphasis_4=0x13460B -serdes_preemphasis_5=0x11480B -serdes_preemphasis_6=0x13470A -serdes_preemphasis_7=0x14460A -serdes_preemphasis_8=0x11490A -serdes_preemphasis_13=0x10490B -serdes_preemphasis_14=0x104A0A -serdes_preemphasis_15=0x0F4B0A -serdes_preemphasis_16=0x0F4B0A -serdes_preemphasis_21=0x0D4D0A -serdes_preemphasis_22=0x0D4D0A -serdes_preemphasis_23=0x0D4D0A -serdes_preemphasis_24=0x0D4D0A -serdes_preemphasis_29=0x0B4F0A -serdes_preemphasis_30=0x0D4E09 -serdes_preemphasis_31=0x0B4F0A -serdes_preemphasis_32=0x0C4F09 -serdes_preemphasis_33=0x0B4F0A -serdes_preemphasis_34=0x0A5109 -serdes_preemphasis_35=0x09510A -serdes_preemphasis_36=0x0B5009 -serdes_preemphasis_41=0x09510A -serdes_preemphasis_42=0x0B5009 -serdes_preemphasis_43=0x09510A -serdes_preemphasis_44=0x0A5109 -serdes_preemphasis_49=0x0A500A -serdes_preemphasis_50=0x0B4F0A -serdes_preemphasis_51=0x09510A -serdes_preemphasis_52=0x0E4C0A -serdes_preemphasis_57=0x0D4D0A -serdes_preemphasis_58=0x0E4D09 -serdes_preemphasis_59=0x0C4E0A -serdes_preemphasis_60=0x0E4D09 -serdes_preemphasis_61=0x0B4F0A -serdes_preemphasis_62=0x0D4E09 -serdes_preemphasis_63=0x0D4D0A -serdes_preemphasis_64=0x0D4D0A -serdes_preemphasis_67=0x0B4F0A -serdes_preemphasis_68=0x0C4E0A -serdes_preemphasis_69=0x0B4F0A -serdes_preemphasis_70=0x0B4F0A -serdes_preemphasis_71=0x0B4F0A -serdes_preemphasis_72=0x0F4B0A -serdes_preemphasis_73=0x0E4C0A -serdes_preemphasis_74=0x0F4B0A -serdes_preemphasis_87=0x0E4C0A -serdes_preemphasis_79=0x0F4B0A -serdes_preemphasis_95=0x0F4B0A -serdes_preemphasis_99=0x0F4B0A -serdes_preemphasis_115=0x13470A -serdes_preemphasis_107=0x12480A -serdes_preemphasis_123=0x154609 -serdes_preemphasis_127=0x13470A +# 25G +serdes_preemphasis_1=0x0F4B0A +serdes_preemphasis_2=0x104A0A +serdes_preemphasis_3=0x0E4C0A +serdes_preemphasis_4=0x0E4C0A +serdes_preemphasis_5=0x0D4D0A +serdes_preemphasis_6=0x0D4D0A +serdes_preemphasis_7=0x0D4D0A +serdes_preemphasis_8=0x0D4D0A +serdes_preemphasis_13=0x0C4E0A +serdes_preemphasis_14=0x0D4D0A +serdes_preemphasis_15=0x0B4F0A +serdes_preemphasis_16=0x0C4E0A +serdes_preemphasis_21=0x0A500A +serdes_preemphasis_22=0x0A500A +serdes_preemphasis_23=0x09510A +serdes_preemphasis_24=0x09510A +serdes_preemphasis_29=0x08520A +serdes_preemphasis_30=0x08520A +serdes_preemphasis_31=0x07530A +serdes_preemphasis_32=0x07530A +serdes_preemphasis_33=0x06540A +serdes_preemphasis_34=0x07530A +serdes_preemphasis_35=0x05550A +serdes_preemphasis_36=0x06540A +serdes_preemphasis_41=0x05550A +serdes_preemphasis_42=0x06540A +serdes_preemphasis_43=0x05550A +serdes_preemphasis_44=0x05550A +serdes_preemphasis_49=0x04560A +serdes_preemphasis_50=0x05550A +serdes_preemphasis_51=0x05550A +serdes_preemphasis_52=0x06540A +serdes_preemphasis_57=0x06540A +serdes_preemphasis_58=0x07530A +serdes_preemphasis_59=0x06540A +serdes_preemphasis_60=0x07530A +serdes_preemphasis_61=0x06540A +serdes_preemphasis_62=0x08520A +serdes_preemphasis_63=0x08520A +serdes_preemphasis_64=0x09510A +serdes_preemphasis_67=0x06540A +serdes_preemphasis_68=0x06540A +serdes_preemphasis_69=0x06540A +serdes_preemphasis_70=0x08520A +serdes_preemphasis_71=0x09510A +serdes_preemphasis_72=0x09510A +serdes_preemphasis_73=0x09510A +serdes_preemphasis_74=0x0A500A +serdes_preemphasis_lane0_87=0x07530A +serdes_preemphasis_lane1_87=0x05550A +serdes_preemphasis_lane2_87=0x07530A +serdes_preemphasis_lane3_87=0x05550A +serdes_preemphasis_79=0x05550A +serdes_preemphasis_95=0x07530A +serdes_preemphasis_lane0_99=0x085309 +serdes_preemphasis_lane1_99=0x0B4F0A +serdes_preemphasis_lane2_99=0x085309 +serdes_preemphasis_lane3_99=0x0B4F0A +serdes_preemphasis_115=0x0B4F0A +serdes_preemphasis_107=0x0B4F0A +serdes_preemphasis_123=0x0B4F0A +serdes_preemphasis_127=0x0D4E09 +# 10G # interface type -serdes_if_type_1=13 -serdes_if_type_2=13 -serdes_if_type_3=13 -serdes_if_type_4=13 -serdes_if_type_5=13 -serdes_if_type_6=13 -serdes_if_type_7=13 -serdes_if_type_8=13 -serdes_if_type_13=13 -serdes_if_type_14=13 -serdes_if_type_15=13 -serdes_if_type_16=13 -serdes_if_type_21=13 -serdes_if_type_22=13 -serdes_if_type_23=13 -serdes_if_type_24=13 -serdes_if_type_29=13 -serdes_if_type_30=13 -serdes_if_type_31=13 -serdes_if_type_32=13 -serdes_if_type_33=13 -serdes_if_type_34=13 -serdes_if_type_35=13 -serdes_if_type_36=13 -serdes_if_type_41=13 -serdes_if_type_42=13 -serdes_if_type_43=13 -serdes_if_type_44=13 -serdes_if_type_49=13 -serdes_if_type_50=13 -serdes_if_type_51=13 -serdes_if_type_52=13 -serdes_if_type_57=13 -serdes_if_type_58=13 -serdes_if_type_59=13 -serdes_if_type_60=13 -serdes_if_type_61=13 -serdes_if_type_62=13 -serdes_if_type_63=13 -serdes_if_type_64=13 -serdes_if_type_67=13 -serdes_if_type_68=13 -serdes_if_type_69=13 -serdes_if_type_70=13 -serdes_if_type_71=13 -serdes_if_type_72=13 -serdes_if_type_73=13 -serdes_if_type_74=13 -serdes_if_type_87=14 -serdes_if_type_79=14 -serdes_if_type_95=14 -serdes_if_type_99=14 -serdes_if_type_115=14 -serdes_if_type_107=14 -serdes_if_type_123=14 -serdes_if_type_127=14 - +serdes_if_type_1=16 +serdes_if_type_2=16 +serdes_if_type_3=16 +serdes_if_type_4=16 +serdes_if_type_5=16 +serdes_if_type_6=16 +serdes_if_type_7=16 +serdes_if_type_8=16 +serdes_if_type_13=16 +serdes_if_type_14=16 +serdes_if_type_15=16 +serdes_if_type_16=16 +serdes_if_type_21=16 +serdes_if_type_22=16 +serdes_if_type_23=16 +serdes_if_type_24=16 +serdes_if_type_29=16 +serdes_if_type_30=16 +serdes_if_type_31=16 +serdes_if_type_32=16 +serdes_if_type_33=16 +serdes_if_type_34=16 +serdes_if_type_35=16 +serdes_if_type_36=16 +serdes_if_type_41=16 +serdes_if_type_42=16 +serdes_if_type_43=16 +serdes_if_type_44=16 +serdes_if_type_49=16 +serdes_if_type_50=16 +serdes_if_type_51=16 +serdes_if_type_52=16 +serdes_if_type_57=16 +serdes_if_type_58=16 +serdes_if_type_59=16 +serdes_if_type_60=16 +serdes_if_type_61=16 +serdes_if_type_62=16 +serdes_if_type_63=16 +serdes_if_type_64=16 +serdes_if_type_67=16 +serdes_if_type_68=16 +serdes_if_type_69=16 +serdes_if_type_70=16 +serdes_if_type_71=16 +serdes_if_type_72=16 +serdes_if_type_73=16 +serdes_if_type_74=16 +serdes_if_type_87=28 +serdes_if_type_79=28 +serdes_if_type_95=28 +serdes_if_type_99=28 +serdes_if_type_115=28 +serdes_if_type_107=28 +serdes_if_type_123=28 +serdes_if_type_127=28 diff --git a/device/inventec/x86_64-inventec_d6356-r0/custom_led.bin b/device/inventec/x86_64-inventec_d6356-r0/custom_led.bin new file mode 100644 index 0000000000000000000000000000000000000000..237c2a1a4c32e9774997a42e36661528a0b42a79 GIT binary patch literal 552 zcmeycHQp`E&DYJv?ZXxZWp*XUj8j1@#uD1UF5Ut1TrwU3d0&9MS|0|*T7O0*X4RE$ zY-$_an3QL^F{-X{>vm&*z^=o1gUNcK zaUjbC%o4iU%fObgKDt5G)`{Ul_k&oswv6%^R(+<6>29{pYd5hPO=57%m>N7wX3{2i z&4m|z6dP2T)pxkDDbI0ZQd#K6sK%ha%dLA;6i{A9#>ZyKCT1O`8&WdjK=;VVgn;>s zH&np97$6VicL*;7MXmtKGXSfsfU1P>0>E+_H)UiZz$|4TD+SDw1F~|!EXkWC*0VP; zYm46OW?;{_6Rql`b1~ShJ)y|**U2xi9z{r(&6O8DLfBc-Td6_fFYFsJk%}sd9s_k jo4V8ai{5T$pWE!2;5O53k=tsw4|@-|{ru0s@B@eeGVH;d literal 0 HcmV?d00001 diff --git a/device/inventec/x86_64-inventec_d6356-r0/led_proc_init.soc b/device/inventec/x86_64-inventec_d6356-r0/led_proc_init.soc index d4c2fde64f..01b49772c0 100644 --- a/device/inventec/x86_64-inventec_d6356-r0/led_proc_init.soc +++ b/device/inventec/x86_64-inventec_d6356-r0/led_proc_init.soc @@ -1,5 +1,5 @@ -led auto off -led stop +#led auto off +#led stop m0 load 0 0x0 /usr/share/sonic/platform/linkscan_led_fw.bin m0 load 0 0x3800 /usr/share/sonic/platform/custom_led.bin led auto on diff --git a/device/inventec/x86_64-inventec_d6356-r0/linkscan_led_fw.bin b/device/inventec/x86_64-inventec_d6356-r0/linkscan_led_fw.bin new file mode 100644 index 0000000000000000000000000000000000000000..e9d763ad98b22a06834cb2d6874287d36b122931 GIT binary patch literal 4744 zcmaJ_4|o&Dm4CY{$t(Yrjg!bmHY?fKD~BX9arv7jYb}f=V>`m-%PD`jZ)KdYGLR~5 z;?nCMY)HWlNn;W&C)1>DDBp!ENzQOlueqW_CRdKoTyJeRUjyph>8`zqYf@Nhf`lw< z@2%vJw3n;=&CJ`G`Mr5F@6Wt3gaEn$Ab@2HmOu4-_)~*hksihp{8V8)-y)RiOM?eG zHd8o&ymQHq{{U8cz&(jTquhB6|nr< z4uAwCJV#aUc5_#+7HeJT{?ZvWJe#&i7hPQ*0QexXjI{IyvWgo_`dWK{zwNuk2xDvV2 zy?cU}fu|JUa#5q*On=}3Rn|WA0w?&p9nTpqN*f16I4_JAjaCFDi<3HUu?M9XRQsXM z;)esEIy7joCx+RliLr?uk9V)29}~N4e0Ff$FFtCmBz*H%#m9Zk*2k>(O7u(5NI#Pv zCS?Iw`b?m#ueGvhzS*0Fr;B7Az0Q-8W zJ)os(wWZQ4Nt&?45}EXRQUCOe0kvSs%ik&f#M^82+1tf0Snm&llU9uRF>p|gynUm1 zzqQxa6`)(vaZA(^Io{bTANT~{*hov_u`X~xjju5vE+T?e$Fw76LmmU1jsj;z{BT#l z{Ia`b+L*_Dx2u27(Bm$=;9?q{(I&ExNO#8*>H-IB%^)=it3fA5Ir~54= z)S=G}br>C0v`^gMIb`)YHsa{VJ^OC-@UBqDY{Ue6CiZ%$u?pp*pdoyRyj^BpFm}>i zISuMx<)B8W`?1?NLvezg?>{e&~CkbIt z|0363X9%~DCkb%Hi9N8D%=uq|nT>Y_`)z{l2X2_68%Nx~pOIz3+8Wf)9Mq+`5t}Sg zVag6ND^laE1l*bAY-Hbr5m@C?uuTrhPr6N06s~MWIdpk4Nn>*m*DxJC3@7}1;GC}| zDA@XKhx04^*gZQ#hlilr1?snR>^SOQGAq>%M5u-w8>SCYvXT2`O=*HgUcX5Ge>_~W zGZ?EWNI5+}VslBRa5R~Y6hSpHD{zn{WrTI*f}rN++v|WU&7V~|x+cHdf-Jk?hyEYH z?|maE6NH`e5VZP$OGi_Y=APZS!z$%+kQx8Fyh>(Usj(;BaDXMc4&I%I8fsjq8*v*@ z3rwE#+N7?7vb+vHhdOv`o*EC->RRCQTDZKRg}R^lsug>d%I#`_84O_?|ltVu! zT@wY_;Lw=+%FI{glEfyA8>LvX_W(SDF?8&fMrLFYz=+kkpru~i|4!7B;m{B;iPe5@ z5%Y_|dbs`ilpz7P(+b$BaN#^JzP|_N{7=K8jkgB9xYizBCmeid9Q6*|`S;a`fs9V9 zLjR1-8)1z?)ftiAI`1SFY`0*`wz5e5`8;qGd6eu1!FJro@|id%-$^Db1fU!+HU`c9 zUfV9H5SREk|6~Q*^3e=5ejnOvs#{%tQ16-Vx3SBv#sACWB!IDMZ_Yq?)c-^C9MP>v z_vcK~5{YjB&PHg$wGG1qKEc+9D_uvgo{hXb!8F>#zY&2qC{PD#={&{L3P&0cZ4aZj zsLVXa)8}=2yo#FHK}=*AWqmX+D}#LQ;m{&2M?w9E zEPD*S{q82|AuFI$6lGYkVbqafp}J;1%%&8--Q zVxld7V)+mKTX1ZV@MT>8Y8)EEaHP{fz^=7D(RP#n2zj}yj~wxTuk#MVEwA!73pbP7 zg@44@eyC@Yz^yneF86tD%bg#@U+`LA<66!B2W?Itduu#SaRHnpV}sDq#kKYOZDND)xKH%4EtlfZ_%hDH*+=zx#Q!3>XM;rQ z{4x>!F0zEI6nJ5un^86kUnIxGulagy%UgaImxTQjNGg z&f(=jJHBM4|a|h2bj|17EEy>eA!< zn}|wB?ZkzMfm~UlK$$gmfojp11!_IYHl_RqbB#ufFPqi_2A5WfLz>5u)iiAxwxLL) z7n(wT{iX)H&UJa#P;a=Pdub?2**{8B`L)Kfi@WWFm-HFWXBi?(*3QD(f0i}Y8!r^- z6G=uXw49cDbxupYgR)djaTr_n%$dEwk4VLe*=xpJjm>8U?E%K#E@`P! z+?^$=$3k7^17-jlwrjBsMe@}$>I^oW*TK$auc zinISZqvJq5j2wnftkG9jr_zYQ_V5B~6j32uui90Hkqy+RaRpG%rVCO%n{lEHT53?! zcWEL;MBgDa>O1^OhO&>+57)!kh#O{>5q*z4GD2s&cTeq@`wpe#SH=7irJv`NZ#br5 zsFqXKVs=tGwIs2oGi-GzL)Hf6bDh2JA*5I0h(lRMTJt;Jv~U)fy+-jC2vZ3N(+>Bh z%Si^mGD!p0siYC>t4R~qSCU0oUrMrAe~>g|eGwxP*x^7BW&f8sLw!Y@X@ZxoiEx`) z;Ze?-30qc@H4G}GM zNgFkoON9p@s(&T(U+!Lr+B~o`)KTkYLwX%6GRx=WUbYuv6|{Ix3U%Cs9v+ipMX`!d zN0m2bGRsc|d(FL6teh5~!dFn4ryp}J*rw0G?0w2xKQ|TXD9ZN=f7FZb3JqZ0!amf< zOPx!Wo{`5l9O`<_ctD2RYn1zTQq6aZ_l1grBzSG{pzRIv^WZ6Cy|An7ZgDHwWo!~o z72hrXJg_hLx~Q3UnRWV1uz;is$N@4?K$Z{uUu1dTzJZUC<$Y%c3P?i%xs7ZqAbUOo z+0(ag+sDYBzBAhjNH&k`*lyZ>YVj`HN%HK#kBm!%!LpU&BV^FnEc~c=rTA>$-tB)Y zUNa4vb^6Tq0@6}ga|hXRl3ZK-uLFa&wZc|%%DAg+tseJ{M~WN7pY;vxI3~tSf|)_O zccgd2S@}7mRj4Ynh-W1=n!~8n)dOSHn1Q%LS}L3C?B*p3BULIVOCHZr$O3a@~M&6X~#)I&_^Qx#)!4+&L+)7Au7>jXY

u_quO?Wpl+sVg~YruZ;-_w%+>d)1i*(6I6o6FZ2xj z0>?GX7!CMltkg3`^#045E*;b{cA=ixSw+{1-umnB>aQ_|Fb+24wLx)jedb*&_L%T3 zYU(j2IPz<`=5}MhUq%8W%GmZYpd&| zwF6^E1o#G}Y6C0*M~%!RhTY72#l$Ov^ZFFD6f2A5Cu?7H8>T?ES}l@=&jCPo@b_3Exh>EsHxNBu}G%Qs@iFG8rH=qZk6=Qq!0P) zYZ!cx|DOz0Gf9BxVKePAKo&O7828b;H literal 0 HcmV?d00001 diff --git a/device/inventec/x86_64-inventec_d6356-r0/plugins/psuutil.py b/device/inventec/x86_64-inventec_d6356-r0/plugins/psuutil.py index 8ed0bce729..732650ffe6 100755 --- a/device/inventec/x86_64-inventec_d6356-r0/plugins/psuutil.py +++ b/device/inventec/x86_64-inventec_d6356-r0/plugins/psuutil.py @@ -15,7 +15,7 @@ except ImportError as e: class PsuUtil(PsuBase): """Platform-specific PSUutil class""" - PSU_DIR = "/sys/class/hwmon/hwmon1" + PSU_DIR = "/sys/class/hwmon/hwmon2/device/" def __init__(self): PsuBase.__init__(self) @@ -53,9 +53,12 @@ class PsuUtil(PsuBase): faulty """ status = 0 - attr_file = 'psoc_psu'+ str(index) + '_iout' - attr_path = self.PSU_DIR +'/' + attr_file + if index == 1 : + attr_path = "/sys/class/hwmon/hwmon7/in1_input" + else : + attr_path = "/sys/class/hwmon/hwmon8/in1_input" + attr_value = self.get_attr_value(attr_path) if (attr_value != 'ERR'): # Check for PSU status @@ -75,10 +78,11 @@ class PsuUtil(PsuBase): ind = index attr_file ='psu'+ str(ind) attr_path = self.PSU_DIR +'/' + attr_file - normal_attr_value = '0 : normal' + normal_attr_value = '1:normal' attr_value = self.get_attr_value(attr_path) if (attr_value != 'ERR'): # Check for PSU presence if (attr_value == normal_attr_value): status = 1 return status + diff --git a/device/inventec/x86_64-inventec_d6356-r0/plugins/sfputil.py b/device/inventec/x86_64-inventec_d6356-r0/plugins/sfputil.py index 5ea81ffcfc..116a3d9acb 100755 --- a/device/inventec/x86_64-inventec_d6356-r0/plugins/sfputil.py +++ b/device/inventec/x86_64-inventec_d6356-r0/plugins/sfputil.py @@ -3,12 +3,78 @@ # Platform-specific SFP transceiver interface for SONiC # +# +# INV_FIX-4037 +# (1) Support get_transceiver_change_event. +# Create the SWPSEventMonitor class to handle any kobject event from the SWPS driver. +# (2) Integrated with the optoe driver +# Due to installing the optoe driver to create the i2c topology, +# it needs to overwrite the followings functions which are declared in the sfputilbase.py. +# First, it needs to impore some SFP-related class object +# try: import time + import socket, re,os + from collections import OrderedDict from sonic_sfp.sfputilbase import SfpUtilBase + from sonic_sfp.sff8472 import sff8472Dom except ImportError as e: raise ImportError("%s - required module not found" % str(e)) +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VLOT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 + +NETLINK_KOBJECT_UEVENT = 15 +monitor = None + +class SWPSEventMonitor(object): + + def __init__(self): + self.recieved_events = OrderedDict() + self.socket = socket.socket( + socket.AF_NETLINK, socket.SOCK_DGRAM, NETLINK_KOBJECT_UEVENT) + + def start(self): + self.socket.bind((os.getpid(), -1)) + + def stop(self): + self.socket.close() + + def __enter__(self): + self.start() + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.stop() + + def __iter__(self): + global monitor + while True: + for item in monitor.next_events(): + yield item + + def next_events(self): + data = self.socket.recv(16384) + event = {} + for item in data.split(b'\x00'): + if not item: + # check if we have an event and if we already received it + if event and event['SEQNUM'] not in self.recieved_events: + self.recieved_events[event['SEQNUM']] = None + if (len(self.recieved_events) > 100): + self.recieved_events.popitem(last=False) + yield event + event = {} + else: + try: + k, v = item.split(b'=', 1) + event[k.decode('ascii')] = v.decode('ascii') + except ValueError: + pass class SfpUtil(SfpUtilBase): """Platform-specific SfpUtil class""" @@ -210,8 +276,104 @@ class SfpUtil(SfpUtilBase): return True +# +# INV_FIX-4037 +# (1) Support get_transceiver_change_event. +# Modify get_transceiver_change_event() to listen the SWPS kobject event. +# (2) Integrated with the optoe driver +# Due to installing the optoe driver to create the i2c topology, +# it needs to overwrite the followings functions which are declared in the sfputilbase.py. +# It modified the get_eeprom_dom_raw() and get_transceiver_dom_info_dict(). +# def get_transceiver_change_event(self): - """ - TODO: This function need to be implemented - """ - raise NotImplementedError + global monitor + port_dict = {} + with SWPSEventMonitor() as monitor: + for event in monitor: + if event['SUBSYSTEM'] == 'swps': + #print('SWPS event. From %s, ACTION %s, IF_TYPE %s, IF_LANE %s' % (event['DEVPATH'], event['ACTION'], event['IF_TYPE'], event['IF_LANE'])) + portname = event['DEVPATH'].split("/")[-1] + rc = re.match(r"port(?P\d+)",portname) + if rc is not None: + if event['ACTION'] == "remove": + remove_num = int(rc.group("num")) + port_dict[remove_num] = "0" + #port_dict[rc.group("num")] = "0" + if event['ACTION'] == "add": + add_num = int(rc.group("num")) + port_dict[add_num] = "1" + #port_dict[rc.group("num")] = "1" + return True, port_dict + return False, {} + + def get_eeprom_dom_raw(self, port_num): + if port_num in self.qsfp_ports: + # QSFP DOM EEPROM is also at addr 0x50 and thus also stored in eeprom_ifraw + return None + else: + # Read dom eeprom at addr 0x51 + return self._read_eeprom_devid(port_num, self.DOM_EEPROM_ADDR, 256) + + def get_transceiver_dom_info_dict(self, port_num): + if port_num in self.qsfp_ports: + return SfpUtilBase.get_transceiver_dom_info_dict(self, port_num) + else: + transceiver_dom_info_dict = {} + + offset = 256 + file_path = self._get_port_eeprom_path(port_num, self.DOM_EEPROM_ADDR) + if not self._sfp_eeprom_present(file_path, 0): + return None + + try: + sysfsfile_eeprom = open(file_path, "rb") + except IOError: + print("Error: reading sysfs file %s" % file_path) + return None + + sfpd_obj = sff8472Dom(None, 1) + if sfpd_obj is None: + return None + + dom_temperature_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_TEMPE_OFFSET), SFP_TEMPE_WIDTH) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + else: + return None + + dom_voltage_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_VLOT_OFFSET), SFP_VOLT_WIDTH) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + else: + return None + + dom_channel_monitor_raw = self._read_eeprom_specific_bytes(sysfsfile_eeprom, (offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + else: + return None + + try: + sysfsfile_eeprom.close() + except IOError: + print("Error: closing sysfs file %s" % file_path) + return None + + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RXPower']['value'] + transceiver_dom_info_dict['rx2power'] = 'N/A' + transceiver_dom_info_dict['rx3power'] = 'N/A' + transceiver_dom_info_dict['rx4power'] = 'N/A' + transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TXBias']['value'] + transceiver_dom_info_dict['tx2bias'] = 'N/A' + transceiver_dom_info_dict['tx3bias'] = 'N/A' + transceiver_dom_info_dict['tx4bias'] = 'N/A' + transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TXPower']['value'] + transceiver_dom_info_dict['tx2power'] = 'N/A' + transceiver_dom_info_dict['tx3power'] = 'N/A' + transceiver_dom_info_dict['tx4power'] = 'N/A' + + return transceiver_dom_info_dict + + diff --git a/device/inventec/x86_64-inventec_d6356-r0/sensors.conf b/device/inventec/x86_64-inventec_d6356-r0/sensors.conf index 6f7318168e..3a056f7ca9 100644 --- a/device/inventec/x86_64-inventec_d6356-r0/sensors.conf +++ b/device/inventec/x86_64-inventec_d6356-r0/sensors.conf @@ -2,6 +2,9 @@ chip "ucd90160-*" ignore temp1 +chip "pch_haswell-*" + label temp1 "PCH Temperature" + chip "tmp75-i2c-*-0048" label temp1 "CPU Board Temperature" @@ -31,7 +34,7 @@ chip "inv_cpld-i2c-*-77" label pwm4 "FanModule4 PWM (0-255)" label pwm5 "FanModule5 PWM (0-255)" -chip "pmbus-i2c-*-005a" +chip "pmbus-i2c-*-005b" ignore power3 ignore curr3 label fan1 "PSU1 Fan RPM" @@ -46,7 +49,7 @@ chip "pmbus-i2c-*-005a" label power2 "PSU1 Output Power" label pwm1 "PSU1 PWM (0-100)" -chip "pmbus-i2c-*-005b" +chip "pmbus-i2c-*-005a" ignore power3 ignore curr3 label fan1 "PSU2 Fan RPM" diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/Makefile b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/Makefile index 23e8295b90..6c1acbc88a 100755 --- a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/Makefile +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/Makefile @@ -1,3 +1,7 @@ +obj-m += ucd9000.o +obj-m += i2c-mux-pca9541.o +obj-m += gpio-ich.o +obj-m += lpc_ich.o obj-m += inv_cpld.o obj-m += inv_platform.o obj-m += inv_eeprom.o diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/gpio-ich.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/gpio-ich.c new file mode 100644 index 0000000000..4f6d643516 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/gpio-ich.c @@ -0,0 +1,513 @@ +/* + * Intel ICH6-10, Series 5 and 6, Atom C2000 (Avoton/Rangeley) GPIO driver + * + * Copyright (C) 2010 Extreme Engineering Solutions. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "gpio_ich" + +/* + * GPIO register offsets in GPIO I/O space. + * Each chunk of 32 GPIOs is manipulated via its own USE_SELx, IO_SELx, and + * LVLx registers. Logic in the read/write functions takes a register and + * an absolute bit number and determines the proper register offset and bit + * number in that register. For example, to read the value of GPIO bit 50 + * the code would access offset ichx_regs[2(=GPIO_LVL)][1(=50/32)], + * bit 18 (50%32). + */ +enum GPIO_REG { + GPIO_USE_SEL = 0, + GPIO_IO_SEL, + GPIO_LVL, + GPO_BLINK +}; + +static const u8 ichx_regs[4][3] = { + {0x00, 0x30, 0x40}, /* USE_SEL[1-3] offsets */ + {0x04, 0x34, 0x44}, /* IO_SEL[1-3] offsets */ + {0x0c, 0x38, 0x48}, /* LVL[1-3] offsets */ + {0x18, 0x18, 0x18}, /* BLINK offset */ +}; + +static const u8 ichx_reglen[3] = { + 0x30, 0x10, 0x10, +}; + +static const u8 avoton_regs[4][3] = { + {0x00, 0x80, 0x00}, + {0x04, 0x84, 0x00}, + {0x08, 0x88, 0x00}, +}; + +static const u8 avoton_reglen[3] = { + 0x10, 0x10, 0x00, +}; + +#define ICHX_WRITE(val, reg, base_res) outl(val, (reg) + (base_res)->start) +#define ICHX_READ(reg, base_res) inl((reg) + (base_res)->start) + +struct ichx_desc { + /* Max GPIO pins the chipset can have */ + uint ngpio; + + /* chipset registers */ + const u8 (*regs)[3]; + const u8 *reglen; + + /* GPO_BLINK is available on this chipset */ + bool have_blink; + + /* Whether the chipset has GPIO in GPE0_STS in the PM IO region */ + bool uses_gpe0; + + /* USE_SEL is bogus on some chipsets, eg 3100 */ + u32 use_sel_ignore[3]; + + /* Some chipsets have quirks, let these use their own request/get */ + int (*request)(struct gpio_chip *chip, unsigned offset); + int (*get)(struct gpio_chip *chip, unsigned offset); + + /* + * Some chipsets don't let reading output values on GPIO_LVL register + * this option allows driver caching written output values + */ + bool use_outlvl_cache; +}; + +static struct { + spinlock_t lock; + struct platform_device *dev; + struct gpio_chip chip; + struct resource *gpio_base; /* GPIO IO base */ + struct resource *pm_base; /* Power Mangagment IO base */ + struct ichx_desc *desc; /* Pointer to chipset-specific description */ + u32 orig_gpio_ctrl; /* Orig CTRL value, used to restore on exit */ + u8 use_gpio; /* Which GPIO groups are usable */ + int outlvl_cache[3]; /* cached output values */ +} ichx_priv; + +static int modparam_gpiobase = -1; /* dynamic */ +module_param_named(gpiobase, modparam_gpiobase, int, 0444); +MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, " + "which is the default."); + +static int ichx_write_bit(int reg, unsigned nr, int val, int verify) +{ + unsigned long flags; + u32 data, tmp; + int reg_nr = nr / 32; + int bit = nr & 0x1f; + int ret = 0; + + spin_lock_irqsave(&ichx_priv.lock, flags); + + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) + data = ichx_priv.outlvl_cache[reg_nr]; + else + data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + + if (val) + data |= 1 << bit; + else + data &= ~(1 << bit); + ICHX_WRITE(data, ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) + ichx_priv.outlvl_cache[reg_nr] = data; + + tmp = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + if (verify && data != tmp) + ret = -EPERM; + + spin_unlock_irqrestore(&ichx_priv.lock, flags); + + return ret; +} + +static int ichx_read_bit(int reg, unsigned nr) +{ + unsigned long flags; + u32 data; + int reg_nr = nr / 32; + int bit = nr & 0x1f; + + spin_lock_irqsave(&ichx_priv.lock, flags); + + data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], + ichx_priv.gpio_base); + + if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) + data = ichx_priv.outlvl_cache[reg_nr] | data; + + spin_unlock_irqrestore(&ichx_priv.lock, flags); + + return data & (1 << bit) ? 1 : 0; +} + +static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) +{ + return !!(ichx_priv.use_gpio & (1 << (nr / 32))); +} + +static int ichx_gpio_get_direction(struct gpio_chip *gpio, unsigned nr) +{ + return ichx_read_bit(GPIO_IO_SEL, nr) ? GPIOF_DIR_IN : GPIOF_DIR_OUT; +} + +static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) +{ + /* + * Try setting pin as an input and verify it worked since many pins + * are output-only. + */ + if (ichx_write_bit(GPIO_IO_SEL, nr, 1, 1)) + return -EINVAL; + + return 0; +} + +static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, + int val) +{ + /* Disable blink hardware which is available for GPIOs from 0 to 31. */ + if (nr < 32 && ichx_priv.desc->have_blink) + ichx_write_bit(GPO_BLINK, nr, 0, 0); + + /* Set GPIO output value. */ + ichx_write_bit(GPIO_LVL, nr, val, 0); + + /* + * Try setting pin as an output and verify it worked since many pins + * are input-only. + */ + if (ichx_write_bit(GPIO_IO_SEL, nr, 0, 1)) + return -EINVAL; + + return 0; +} + +static int ichx_gpio_get(struct gpio_chip *chip, unsigned nr) +{ + return ichx_read_bit(GPIO_LVL, nr); +} + +static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr) +{ + unsigned long flags; + u32 data; + + /* + * GPI 0 - 15 need to be read from the power management registers on + * a ICH6/3100 bridge. + */ + if (nr < 16) { + if (!ichx_priv.pm_base) + return -ENXIO; + + spin_lock_irqsave(&ichx_priv.lock, flags); + + /* GPI 0 - 15 are latched, write 1 to clear*/ + ICHX_WRITE(1 << (16 + nr), 0, ichx_priv.pm_base); + data = ICHX_READ(0, ichx_priv.pm_base); + + spin_unlock_irqrestore(&ichx_priv.lock, flags); + + return (data >> 16) & (1 << nr) ? 1 : 0; + } else { + return ichx_gpio_get(chip, nr); + } +} + +static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr) +{ + if (!ichx_gpio_check_available(chip, nr)) + return -ENXIO; + + /* + * Note we assume the BIOS properly set a bridge's USE value. Some + * chips (eg Intel 3100) have bogus USE values though, so first see if + * the chipset's USE value can be trusted for this specific bit. + * If it can't be trusted, assume that the pin can be used as a GPIO. + */ + if (ichx_priv.desc->use_sel_ignore[nr / 32] & (1 << (nr & 0x1f))) + return 0; + + return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV; +} + +static int ich6_gpio_request(struct gpio_chip *chip, unsigned nr) +{ + /* + * Fixups for bits 16 and 17 are necessary on the Intel ICH6/3100 + * bridge as they are controlled by USE register bits 0 and 1. See + * "Table 704 GPIO_USE_SEL1 register" in the i3100 datasheet for + * additional info. + */ + if (nr == 16 || nr == 17) + nr -= 16; + + return ichx_gpio_request(chip, nr); +} + +static void ichx_gpio_set(struct gpio_chip *chip, unsigned nr, int val) +{ + ichx_write_bit(GPIO_LVL, nr, val, 0); +} + +static void ichx_gpiolib_setup(struct gpio_chip *chip) +{ + chip->owner = THIS_MODULE; + chip->label = DRV_NAME; + chip->parent = &ichx_priv.dev->dev; + + /* Allow chip-specific overrides of request()/get() */ + chip->request = ichx_priv.desc->request ? + ichx_priv.desc->request : ichx_gpio_request; + chip->get = ichx_priv.desc->get ? + ichx_priv.desc->get : ichx_gpio_get; + + chip->set = ichx_gpio_set; + chip->get_direction = ichx_gpio_get_direction; + chip->direction_input = ichx_gpio_direction_input; + chip->direction_output = ichx_gpio_direction_output; + chip->base = modparam_gpiobase; + chip->ngpio = ichx_priv.desc->ngpio; + chip->can_sleep = false; + chip->dbg_show = NULL; +} + +/* ICH6-based, 631xesb-based */ +static struct ichx_desc ich6_desc = { + /* Bridges using the ICH6 controller need fixups for GPIO 0 - 17 */ + .request = ich6_gpio_request, + .get = ich6_gpio_get, + + /* GPIO 0-15 are read in the GPE0_STS PM register */ + .uses_gpe0 = true, + + .ngpio = 50, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* Intel 3100 */ +static struct ichx_desc i3100_desc = { + /* + * Bits 16,17, 20 of USE_SEL and bit 16 of USE_SEL2 always read 0 on + * the Intel 3100. See "Table 712. GPIO Summary Table" of 3100 + * Datasheet for more info. + */ + .use_sel_ignore = {0x00130000, 0x00010000, 0x0}, + + /* The 3100 needs fixups for GPIO 0 - 17 */ + .request = ich6_gpio_request, + .get = ich6_gpio_get, + + /* GPIO 0-15 are read in the GPE0_STS PM register */ + .uses_gpe0 = true, + + .ngpio = 50, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* ICH7 and ICH8-based */ +static struct ichx_desc ich7_desc = { + .ngpio = 50, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* ICH9-based */ +static struct ichx_desc ich9_desc = { + .ngpio = 61, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* ICH10-based - Consumer/corporate versions have different amount of GPIO */ +static struct ichx_desc ich10_cons_desc = { + .ngpio = 61, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; +static struct ichx_desc ich10_corp_desc = { + .ngpio = 72, + .have_blink = true, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* Intel 5 series, 6 series, 3400 series, and C200 series */ +static struct ichx_desc intel5_desc = { + .ngpio = 76, + .regs = ichx_regs, + .reglen = ichx_reglen, +}; + +/* Avoton */ +static struct ichx_desc avoton_desc = { + /* Avoton has only 59 GPIOs, but we assume the first set of register + * (Core) has 32 instead of 31 to keep gpio-ich compliance + */ + .ngpio = 60, + .regs = avoton_regs, + .reglen = avoton_reglen, + .use_outlvl_cache = true, +}; + +static int ichx_gpio_request_regions(struct device *dev, + struct resource *res_base, const char *name, u8 use_gpio) +{ + int i; + + if (!res_base || !res_base->start || !res_base->end) + return -ENODEV; + + for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) { + if (!(use_gpio & (1 << i))) + continue; + if (!devm_request_region(dev, + res_base->start + ichx_priv.desc->regs[0][i], + ichx_priv.desc->reglen[i], name)) + return -EBUSY; + } + return 0; +} + +static int ichx_gpio_probe(struct platform_device *pdev) +{ + struct resource *res_base, *res_pm; + int err; + struct lpc_ich_info *ich_info = dev_get_platdata(&pdev->dev); + + if (!ich_info) + return -ENODEV; + + ichx_priv.dev = pdev; + + switch (ich_info->gpio_version) { + case ICH_I3100_GPIO: + ichx_priv.desc = &i3100_desc; + break; + case ICH_V5_GPIO: + ichx_priv.desc = &intel5_desc; + break; + case ICH_V6_GPIO: + ichx_priv.desc = &ich6_desc; + break; + case ICH_V7_GPIO: + ichx_priv.desc = &ich7_desc; + break; + case ICH_V9_GPIO: + ichx_priv.desc = &ich9_desc; + break; + case ICH_V10CORP_GPIO: + ichx_priv.desc = &ich10_corp_desc; + break; + case ICH_V10CONS_GPIO: + ichx_priv.desc = &ich10_cons_desc; + break; + case AVOTON_GPIO: + ichx_priv.desc = &avoton_desc; + break; + default: + return -ENODEV; + } + + spin_lock_init(&ichx_priv.lock); + res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO); + ichx_priv.use_gpio = ich_info->use_gpio; + err = ichx_gpio_request_regions(&pdev->dev, res_base, pdev->name, + ichx_priv.use_gpio); + if (err) + return err; + + ichx_priv.gpio_base = res_base; + + /* + * If necessary, determine the I/O address of ACPI/power management + * registers which are needed to read the the GPE0 register for GPI pins + * 0 - 15 on some chipsets. + */ + if (!ichx_priv.desc->uses_gpe0) + goto init; + + res_pm = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPE0); + if (!res_pm) { + pr_warn("ACPI BAR is unavailable, GPI 0 - 15 unavailable\n"); + goto init; + } + + if (!devm_request_region(&pdev->dev, res_pm->start, + resource_size(res_pm), pdev->name)) { + pr_warn("ACPI BAR is busy, GPI 0 - 15 unavailable\n"); + goto init; + } + + ichx_priv.pm_base = res_pm; + +init: + ichx_gpiolib_setup(&ichx_priv.chip); + err = gpiochip_add_data(&ichx_priv.chip, NULL); + if (err) { + pr_err("Failed to register GPIOs\n"); + return err; + } + + pr_info("GPIO from %d to %d on %s\n", ichx_priv.chip.base, + ichx_priv.chip.base + ichx_priv.chip.ngpio - 1, DRV_NAME); + + return 0; +} + +static int ichx_gpio_remove(struct platform_device *pdev) +{ + gpiochip_remove(&ichx_priv.chip); + + return 0; +} + +static struct platform_driver ichx_gpio_driver = { + .driver = { + .name = DRV_NAME, + }, + .probe = ichx_gpio_probe, + .remove = ichx_gpio_remove, +}; + +module_platform_driver(ichx_gpio_driver); + +MODULE_AUTHOR("Peter Tyser "); +MODULE_DESCRIPTION("GPIO interface for Intel ICH series"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:"DRV_NAME); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/i2c-mux-pca9541.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/i2c-mux-pca9541.c new file mode 100644 index 0000000000..68c44dbc53 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/i2c-mux-pca9541.c @@ -0,0 +1,573 @@ +/* + * I2C multiplexer driver for PCA9541 bus master selector + * + * Copyright (c) 2010 Ericsson AB. + * + * Author: Guenter Roeck + * + * Derived from: + * pca954x.c + * + * Copyright (c) 2008-2009 Rodolfo Giometti + * Copyright (c) 2008-2009 Eurotech S.p.A. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * The PCA9541 is a bus master selector. It supports two I2C masters connected + * to a single slave bus. + * + * Before each bus transaction, a master has to acquire bus ownership. After the + * transaction is complete, bus ownership has to be released. This fits well + * into the I2C multiplexer framework, which provides select and release + * functions for this purpose. For this reason, this driver is modeled as + * single-channel I2C bus multiplexer. + * + * This driver assumes that the two bus masters are controlled by two different + * hosts. If a single host controls both masters, platform code has to ensure + * that only one of the masters is instantiated at any given time. + */ + +#define PCA9541_CONTROL 0x01 +#define PCA9541_ISTAT 0x02 + +#define PCA9541_CTL_MYBUS (1 << 0) +#define PCA9541_CTL_NMYBUS (1 << 1) +#define PCA9541_CTL_BUSON (1 << 2) +#define PCA9541_CTL_NBUSON (1 << 3) +#define PCA9541_CTL_BUSINIT (1 << 4) +#define PCA9541_CTL_TESTON (1 << 6) +#define PCA9541_CTL_NTESTON (1 << 7) + +#define PCA9541_ISTAT_INTIN (1 << 0) +#define PCA9541_ISTAT_BUSINIT (1 << 1) +#define PCA9541_ISTAT_BUSOK (1 << 2) +#define PCA9541_ISTAT_BUSLOST (1 << 3) +#define PCA9541_ISTAT_MYTEST (1 << 6) +#define PCA9541_ISTAT_NMYTEST (1 << 7) + +#define PCA9641_ID 0x00 +#define PCA9641_ID_MAGIC 0x38 + +#define PCA9641_CONTROL 0x01 +#define PCA9641_STATUS 0x02 +#define PCA9641_TIME 0x03 + +#define PCA9641_CTL_LOCK_REQ BIT(0) +#define PCA9641_CTL_LOCK_GRANT BIT(1) +#define PCA9641_CTL_BUS_CONNECT BIT(2) +#define PCA9641_CTL_BUS_INIT BIT(3) +#define PCA9641_CTL_SMBUS_SWRST BIT(4) +#define PCA9641_CTL_IDLE_TIMER_DIS BIT(5) +#define PCA9641_CTL_SMBUS_DIS BIT(6) +#define PCA9641_CTL_PRIORITY BIT(7) + +#define PCA9641_STS_OTHER_LOCK BIT(0) +#define PCA9641_STS_BUS_INIT_FAIL BIT(1) +#define PCA9641_STS_BUS_HUNG BIT(2) +#define PCA9641_STS_MBOX_EMPTY BIT(3) +#define PCA9641_STS_MBOX_FULL BIT(4) +#define PCA9641_STS_TEST_INT BIT(5) +#define PCA9641_STS_SCL_IO BIT(6) +#define PCA9641_STS_SDA_IO BIT(7) + +#define PCA9641_RES_TIME 0x03 + + +#define BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON) +#define MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS) +#define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS) +#define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON) + +#define BUSOFF(x, y) (!((x) & PCA9641_CTL_LOCK_GRANT) && \ + !((y) & PCA9641_STS_OTHER_LOCK)) +#define other_lock(x) ((x) & PCA9641_STS_OTHER_LOCK) +#define lock_grant(x) ((x) & PCA9641_CTL_LOCK_GRANT) + +/* arbitration timeouts, in jiffies */ +#define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */ +#define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */ + +/* arbitration retry delays, in us */ +#define SELECT_DELAY_SHORT 50 +#define SELECT_DELAY_LONG 1000 + +struct pca9541 { + struct i2c_client *client; + unsigned long select_timeout; + unsigned long arb_timeout; +}; + +static const struct i2c_device_id pca9541_id[] = { + {"pca9541", 0}, + {"pca9641", 1}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, pca9541_id); + +#ifdef CONFIG_OF +static const struct of_device_id pca9541_of_match[] = { + { .compatible = "nxp,pca9541" }, + { .compatible = "nxp,pca9641" }, + {} +}; +#endif + +/* + * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock the adapter a second time. + */ +static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val) +{ + struct i2c_adapter *adap = client->adapter; + int ret; + + if (adap->algo->master_xfer) { + struct i2c_msg msg; + char buf[2]; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = 2; + buf[0] = command; + buf[1] = val; + msg.buf = buf; + ret = __i2c_transfer(adap, &msg, 1); + } else { + union i2c_smbus_data data; + + data.byte = val; + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_WRITE, + command, + I2C_SMBUS_BYTE_DATA, &data); + } + + return ret; +} + +/* + * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock adapter a second time. + */ +static int pca9541_reg_read(struct i2c_client *client, u8 command) +{ + struct i2c_adapter *adap = client->adapter; + int ret; + u8 val; + + if (adap->algo->master_xfer) { + struct i2c_msg msg[2] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = &command + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 1, + .buf = &val + } + }; + ret = __i2c_transfer(adap, msg, 2); + if (ret == 2) + ret = val; + else if (ret >= 0) + ret = -EIO; + } else { + union i2c_smbus_data data; + + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_READ, + command, + I2C_SMBUS_BYTE_DATA, &data); + if (!ret) + ret = data.byte; + } + return ret; +} + +/* + * Arbitration management functions + */ + +/* Release bus. Also reset NTESTON and BUSINIT if it was set. */ +static void pca9541_release_bus(struct i2c_client *client) +{ + int reg; + + reg = pca9541_reg_read(client, PCA9541_CONTROL); + if (reg >= 0 && !busoff(reg) && mybus(reg)) + pca9541_reg_write(client, PCA9541_CONTROL, + (reg & PCA9541_CTL_NBUSON) >> 1); +} + +/* + * Arbitration is defined as a two-step process. A bus master can only activate + * the slave bus if it owns it; otherwise it has to request ownership first. + * This multi-step process ensures that access contention is resolved + * gracefully. + * + * Bus Ownership Other master Action + * state requested access + * ---------------------------------------------------- + * off - yes wait for arbitration timeout or + * for other master to drop request + * off no no take ownership + * off yes no turn on bus + * on yes - done + * on no - wait for arbitration timeout or + * for other master to release bus + * + * The main contention point occurs if the slave bus is off and both masters + * request ownership at the same time. In this case, one master will turn on + * the slave bus, believing that it owns it. The other master will request + * bus ownership. Result is that the bus is turned on, and master which did + * _not_ own the slave bus before ends up owning it. + */ + +/* Control commands per PCA9541 datasheet */ +static const u8 pca9541_control[16] = { + 4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1 +}; + +/* + * Channel arbitration + * + * Return values: + * <0: error + * 0 : bus not acquired + * 1 : bus acquired + */ +static int pca9541_arbitrate(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca9541 *data = i2c_mux_priv(muxc); + int reg; + + reg = pca9541_reg_read(client, PCA9541_CONTROL); + if (reg < 0) + return reg; + + if (busoff(reg)) { + int istat; + /* + * Bus is off. Request ownership or turn it on unless + * other master requested ownership. + */ + istat = pca9541_reg_read(client, PCA9541_ISTAT); + if (!(istat & PCA9541_ISTAT_NMYTEST) + || time_is_before_eq_jiffies(data->arb_timeout)) { + /* + * Other master did not request ownership, + * or arbitration timeout expired. Take the bus. + */ + pca9541_reg_write(client, + PCA9541_CONTROL, + pca9541_control[reg & 0x0f] + | PCA9541_CTL_NTESTON); + data->select_timeout = SELECT_DELAY_SHORT; + } else { + /* + * Other master requested ownership. + * Set extra long timeout to give it time to acquire it. + */ + data->select_timeout = SELECT_DELAY_LONG * 2; + } + } else if (mybus(reg)) { + /* + * Bus is on, and we own it. We are done with acquisition. + * Reset NTESTON and BUSINIT, then return success. + */ + if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT)) + pca9541_reg_write(client, + PCA9541_CONTROL, + reg & ~(PCA9541_CTL_NTESTON + | PCA9541_CTL_BUSINIT)); + return 1; + } else { + /* + * Other master owns the bus. + * If arbitration timeout has expired, force ownership. + * Otherwise request it. + */ + data->select_timeout = SELECT_DELAY_LONG; + if (time_is_before_eq_jiffies(data->arb_timeout)) { + /* Time is up, take the bus and reset it. */ + pca9541_reg_write(client, + PCA9541_CONTROL, + pca9541_control[reg & 0x0f] + | PCA9541_CTL_BUSINIT + | PCA9541_CTL_NTESTON); + } else { + /* Request bus ownership if needed */ + if (!(reg & PCA9541_CTL_NTESTON)) + pca9541_reg_write(client, + PCA9541_CONTROL, + reg | PCA9541_CTL_NTESTON); + } + } + return 0; +} + +static int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int ret; + unsigned long timeout = jiffies + ARB2_TIMEOUT; + /* give up after this time */ + + data->arb_timeout = jiffies + ARB_TIMEOUT; + /* force bus ownership after this time */ + + do { + ret = pca9541_arbitrate(client); + if (ret) + return ret < 0 ? ret : 0; + + if (data->select_timeout == SELECT_DELAY_SHORT) + udelay(data->select_timeout); + else + msleep(data->select_timeout / 1000); + } while (time_is_after_eq_jiffies(timeout)); + + return -ETIMEDOUT; +} + +static int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + + pca9541_release_bus(client); + return 0; +} + +/* + * Arbitration management functions + */ +static void pca9641_release_bus(struct i2c_client *client) +{ + pca9541_reg_write(client, PCA9641_CONTROL, 0); +} + +/* + * Channel arbitration + * + * Return values: + * <0: error + * 0 : bus not acquired + * 1 : bus acquired + */ +static int pca9641_arbitrate(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + struct pca9541 *data = i2c_mux_priv(muxc); + int reg_ctl, reg_sts; + + reg_ctl = pca9541_reg_read(client, PCA9641_CONTROL); + if (reg_ctl < 0) + return reg_ctl; + reg_sts = pca9541_reg_read(client, PCA9641_STATUS); + + if (BUSOFF(reg_ctl, reg_sts)) { + /* + * Bus is off. Request ownership or turn it on unless + * other master requested ownership. + */ + reg_ctl |= PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + reg_ctl = pca9541_reg_read(client, PCA9641_CONTROL); + + if (lock_grant(reg_ctl)) { + /* + * Other master did not request ownership, + * or arbitration timeout expired. Take the bus. + */ + reg_ctl |= PCA9641_CTL_BUS_CONNECT + | PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + data->select_timeout = SELECT_DELAY_SHORT; + + return 1; + } else { + /* + * Other master requested ownership. + * Set extra long timeout to give it time to acquire it. + */ + data->select_timeout = SELECT_DELAY_LONG * 2; + } + } else if (lock_grant(reg_ctl)) { + /* + * Bus is on, and we own it. We are done with acquisition. + */ + reg_ctl |= PCA9641_CTL_BUS_CONNECT | PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + + return 1; + } else if (other_lock(reg_sts)) { + /* + * Other master owns the bus. + * If arbitration timeout has expired, force ownership. + * Otherwise request it. + */ + data->select_timeout = SELECT_DELAY_LONG; + reg_ctl |= PCA9641_CTL_LOCK_REQ; + pca9541_reg_write(client, PCA9641_CONTROL, reg_ctl); + } + return 0; +} + +static int pca9641_select_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int ret; + unsigned long timeout = jiffies + ARB2_TIMEOUT; + /* give up after this time */ + + data->arb_timeout = jiffies + ARB_TIMEOUT; + /* force bus ownership after this time */ + + do { + ret = pca9641_arbitrate(client); + if (ret) + return ret < 0 ? ret : 0; + + if (data->select_timeout == SELECT_DELAY_SHORT) + udelay(data->select_timeout); + else + msleep(data->select_timeout / 1000); + } while (time_is_after_eq_jiffies(timeout)); + + return -ETIMEDOUT; +} + +static int pca9641_release_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct pca9541 *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + + pca9641_release_bus(client); + return 0; +} + +static int pca9641_detect_id(struct i2c_client *client) +{ + int reg; + + reg = pca9541_reg_read(client, PCA9641_ID); + if (reg == PCA9641_ID_MAGIC) + return 1; + else + return 0; +} + +/* + * I2C init/probing/exit functions + */ +static int pca9541_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = client->adapter; + struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev); + struct i2c_mux_core *muxc; + struct pca9541 *data; + int force; + int ret; + int detect_id; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + detect_id = pca9641_detect_id(client); + /* + * I2C accesses are unprotected here. + * We have to lock the adapter before releasing the bus. + */ + if (detect_id == 0) { + i2c_lock_adapter(adap); + pca9541_release_bus(client); + i2c_unlock_adapter(adap); + } else { + i2c_lock_adapter(adap); + pca9641_release_bus(client); + i2c_unlock_adapter(adap); + } + + /* Create mux adapter */ + + force = 0; + if (pdata) + force = pdata->modes[0].adap_id; + if (detect_id == 0) { + muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), + I2C_MUX_ARBITRATOR, + pca9541_select_chan, pca9541_release_chan); + } else { + muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), + I2C_MUX_ARBITRATOR, + pca9641_select_chan, pca9641_release_chan); + } + if (!muxc) + return -ENOMEM; + + data = i2c_mux_priv(muxc); + data->client = client; + + i2c_set_clientdata(client, muxc); + + ret = i2c_mux_add_adapter(muxc, force, 0, 0); + if (ret) { + dev_err(&client->dev, "failed to register master selector\n"); + return ret; + } + + dev_info(&client->dev, "registered master selector for I2C %s\n", + client->name); + + return 0; +} + +static int pca9541_remove(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + + i2c_mux_del_adapters(muxc); + return 0; +} + +static struct i2c_driver pca9541_driver = { + .driver = { + .name = "pca9541", + .of_match_table = of_match_ptr(pca9541_of_match), + }, + .probe = pca9541_probe, + .remove = pca9541_remove, + .id_table = pca9541_id, +}; + +module_i2c_driver(pca9541_driver); + +MODULE_AUTHOR("Guenter Roeck "); +MODULE_DESCRIPTION("PCA9541 I2C master selector driver"); +MODULE_LICENSE("GPL v2"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_cpld.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_cpld.c index 8ccaf617b3..8e2693d2e2 100644 --- a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_cpld.c +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_cpld.c @@ -30,6 +30,7 @@ #define CPLD_INFO_OFFSET 0x00 #define CPLD_BIOSCS_OFFSET 0x04 #define CPLD_CTL_OFFSET 0x0C +#define CPLD_SYSLED_OFFSET 0x0E #define CPLD_LED_OFFSET 0x2E #define CPLD_INT_OFFSET 0x30 #define CPLD_INTMASK_OFFSET 0x31 @@ -58,6 +59,7 @@ struct cpld_data { struct device *hwmon_dev; struct mutex update_lock; u8 diag; + struct task_struct *tsk; }; /*-----------------------------------------------------------------------*/ @@ -97,6 +99,7 @@ static ssize_t cpld_i2c_write(struct i2c_client *client, char *buf, unsigned off #define CMD_GETDATA 0x31 #define CMD_SETDATA 0x32 #define IPMI_DIAGFLAG_OFFSET 0x00 +#define IPMI_SWITCHTEMP_OFFSET 0x02 struct ipmi_result{ char result[MAX_IPMI_RECV_LENGTH]; @@ -203,6 +206,30 @@ int start_ipmi_command(char NetFn, char cmd,char *data,int data_length, char* re } EXPORT_SYMBOL(start_ipmi_command); +static int cpld_thread(void *p) +{ +#ifndef XORP + struct i2c_client *client = p; + + u8 byte[9]; + uint8_t result[MAX_IPMI_RECV_LENGTH]; + int result_len=0; + + //Handle LED control by the driver + byte[0]=0x01; + cpld_i2c_write(client, byte, CPLD_CTL_OFFSET, 1); + + //Disable BMC Watchdog + byte[0]=0x04; + byte[1]=0x00; + byte[2]=0x00; + byte[3]=0x00; + byte[4]=0x2C; + byte[5]=0x01; + start_ipmi_command(0x06, 0x24, byte, 6, result, &result_len); +#endif + return 0; +} /*-----------------------------------------------------------------------*/ /* sysfs attributes for hwmon */ static ssize_t show_info(struct device *dev, struct device_attribute *da, @@ -231,7 +258,7 @@ static ssize_t show_info(struct device *dev, struct device_attribute *da, sprintf (buf, "%s\nThe CPLD2 release date is %02d/%02d/%d.\n", buf, byte[2] & 0xf, (byte[3] & 0x1f), 2014+(byte[2] >> 4)); /* mm/dd/yyyy*/ - sprintf (buf, "%sThe CPLD version is %d.%d\n", buf, byte[1]>>4, byte[1]&0xf); + sprintf (buf, "%sThe CPLD2 version is %d.%d\n", buf, byte[1]>>4, byte[1]&0xf); } return strlen(buf); @@ -251,7 +278,7 @@ static ssize_t show_powerstatus(struct device *dev, struct device_attribute *da, u8 byte[2] = {0,0}; mutex_lock(&data->update_lock); - len = cpld_i2c_read(client, byte, CPLD_POWERSTATUS_OFFSET, 2); + len = cpld_i2c_read(client2, byte, CPLD_POWERSTATUS_OFFSET, 2); mutex_unlock(&data->update_lock); if (len==0) return 0; @@ -265,8 +292,7 @@ static ssize_t show_powerstatus(struct device *dev, struct device_attribute *da, sprintf (buf, "%sPGD_P0V8_A: %s\n", buf,powerstatus_str[(byte[1]>>7) & 0x01]); sprintf (buf, "%sPGD_P0V89_ROV: %s\n", buf, powerstatus_str[(byte[1]>>6) & 0x01]); sprintf (buf, "%sSW_PWR_READY: %s\n", buf, powerstatus_str[(byte[1]>>3) & 0x01]); - sprintf (buf, "%sCORE_PWRGD_TO_CPLD: %s\n", buf, powerstatus_str[(byte[1]>>2) & 0x01]); - sprintf (buf, "%sCPU_STBY_PWROK: %s\n", buf, powerstatus_str[(byte[1]>>1) & 0x01]); + sprintf (buf, "%sCPU_STBY_PWROK: %s\n", buf, powerstatus_str[(byte[1]>>0) & 0x01]); return strlen(buf); } @@ -302,44 +328,27 @@ static ssize_t set_diag(struct device *dev, return count; } -static char* resetbutton_str[] = { - "No press", //0 - "Reserved", //1 - "Press and hold <5s", //2 - "Press and hold >5s", //3 -}; - -static ssize_t show_resetbuttonstatus(struct device *dev, struct device_attribute *da, +static ssize_t show_thermal(struct device *dev, struct device_attribute *da, char *buf) { - struct i2c_client *client = to_i2c_client(dev); - struct cpld_data *data = i2c_get_clientdata(client); - ssize_t len = 0; - u8 byte = 0; - - mutex_lock(&data->update_lock); - len = cpld_i2c_read(client, &byte, CPLD_RESETBUTTONSTATUS_OFFSET, 1); - mutex_unlock(&data->update_lock); - if (len==0) return 0; - - byte &=0x03; - - return sprintf (buf, "0x%02X:%s\n", byte,resetbutton_str[byte]); + uint8_t ipmisend[]= { IPMI_SWITCHTEMP_OFFSET, 1}; + uint8_t result[MAX_IPMI_RECV_LENGTH]; + int result_len=0; + start_ipmi_command(NETFN_OEM, CMD_GETDATA,ipmisend, 2, result, &result_len); + return sprintf(buf, "%d\n", result[0] * 1000 ); } static char* interrupt_str[] = { "CPU_SEN_ALERT_N", //0 "EXT_USB_OC_N", //1 - "PS2_ALERT_N", //2 - "PS1_ALERT_N", //3 + "", //2 + "", //3 "PLD_SEN5_ALERT_N", //4 "PLD_SEN4_ALERT_N", //5 "PLD_SEN3_ALERT_N", //6 "UCD90160_TEMP_INT_N", //7 "RSTBTN_INT_N", //8 - "WDT_IRQ_N", //9 - "RSTBTN_5s_INT_N", //10 - "Reserved" //11 + "WDT_IRQ_N", //9 }; static ssize_t show_interrupt(struct device *dev, struct device_attribute *da, @@ -359,15 +368,12 @@ static ssize_t show_interrupt(struct device *dev, struct device_attribute *da, if(byte[0]==0xff && byte[2]==0x07) sprintf (buf, "%sNone",buf); if(!(byte[0]&0x01)) sprintf (buf, "%s%s ",buf,interrupt_str[0]); if(!(byte[0]&0x02)) sprintf (buf, "%s%s ",buf,interrupt_str[1]); - if(!(byte[0]&0x04)) sprintf (buf, "%s%s ",buf,interrupt_str[2]); - if(!(byte[0]&0x08)) sprintf (buf, "%s%s ",buf,interrupt_str[3]); if(!(byte[0]&0x10)) sprintf (buf, "%s%s ",buf,interrupt_str[4]); if(!(byte[0]&0x20)) sprintf (buf, "%s%s ",buf,interrupt_str[5]); if(!(byte[0]&0x40)) sprintf (buf, "%s%s ",buf,interrupt_str[6]); if(!(byte[0]&0x80)) sprintf (buf, "%s%s ",buf,interrupt_str[7]); if(!(byte[2]&0x01)) sprintf (buf, "%s%s%s ",buf,interrupt_str[8] ,(byte[3]&0x01)?"(Blocked)":""); if(!(byte[2]&0x02)) sprintf (buf, "%s%s%s ",buf,interrupt_str[9] ,(byte[3]&0x02)?"(Blocked)":""); - if(!(byte[2]&0x04)) sprintf (buf, "%s%s%s ",buf,interrupt_str[10],(byte[3]&0x04)?"(Blocked)":""); return sprintf (buf, "%s\n", buf); } @@ -414,10 +420,10 @@ static ssize_t set_bios_cs(struct device *dev, } static char* led_str[] = { - "OFF", //000 - "ON", //001 - "1 Hz", //010 - "2 Hz", //011 + "OFF", //00 + "Green/Blue", //01 + "Yellow/Orange", //10 + "Red", //11 }; static ssize_t show_led(struct device *dev, struct device_attribute *da, @@ -437,7 +443,7 @@ static ssize_t show_led(struct device *dev, struct device_attribute *da, byte = (byte >> shift) & 0x3; - return sprintf (buf, "%d: %s\n", byte, led_str[byte]); + return sprintf (buf, "%d:%s\n", byte, led_str[byte]); } static ssize_t set_led(struct device *dev, struct device_attribute *da, @@ -462,6 +468,61 @@ static ssize_t set_led(struct device *dev, struct device_attribute *da, return count; } +static char* sysled_str[] = { + "OFF", //000 + "0.5 Hz", //001 + "1 Hz", //010 + "2 Hz", //011 + "4 Hz", //100 + "NA", //101 + "NA", //110 + "ON", //111 +}; + +static ssize_t show_sysled(struct device *dev, struct device_attribute *da, + char *buf) +{ + u32 status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + u8 byte; + int shift = (attr->index == 0)?3:0; + + mutex_lock(&data->update_lock); + status = cpld_i2c_read(client, &byte, CPLD_SYSLED_OFFSET, 1); + mutex_unlock(&data->update_lock); + + byte = (byte >> shift) & 0x7; + status = sprintf (buf, "%d:%s\n", byte, sysled_str[byte]); + + return strlen(buf); +} + +static ssize_t set_sysled(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct cpld_data *data = i2c_get_clientdata(client); + + u8 temp = simple_strtol(buf, NULL, 16); + u8 byte; + int shift = (attr->index == 0)?3:0; + + temp &= 0x7; + + mutex_lock(&data->update_lock); + cpld_i2c_read(client, &byte, CPLD_SYSLED_OFFSET, 1); + byte &= ~(0x7<update_lock); + + return count; +} + static char* psu_str[] = { "unpowered", //00 "normal", //01 @@ -714,12 +775,15 @@ static ssize_t show_watchdog_counter(struct device *dev, struct device_attribute static SENSOR_DEVICE_ATTR(info, S_IRUGO, show_info, 0, 0); static SENSOR_DEVICE_ATTR(diag, S_IWUSR|S_IRUGO, show_diag, set_diag, 0); +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_thermal, 0, 0); static SENSOR_DEVICE_ATTR(interrupt, S_IRUGO, show_interrupt, 0, 0); -static SENSOR_DEVICE_ATTR(stacking_led, S_IWUSR|S_IRUGO, show_led, set_led, 0); -static SENSOR_DEVICE_ATTR(fan_led, S_IWUSR|S_IRUGO, show_led, set_led, 2); -static SENSOR_DEVICE_ATTR(power_led, S_IWUSR|S_IRUGO, show_led, set_led, 4); -static SENSOR_DEVICE_ATTR(service_led, S_IWUSR|S_IRUGO, show_led, set_led, 6); +static SENSOR_DEVICE_ATTR(fan_led, S_IWUSR|S_IRUGO, show_led, set_led, 2); +static SENSOR_DEVICE_ATTR(power_led, S_IWUSR|S_IRUGO, show_led, set_led, 4); +static SENSOR_DEVICE_ATTR(location_led, S_IWUSR|S_IRUGO, show_led, set_led, 6); + +static SENSOR_DEVICE_ATTR(grn_led, S_IWUSR|S_IRUGO, show_sysled, set_sysled, 0); +static SENSOR_DEVICE_ATTR(red_led, S_IWUSR|S_IRUGO, show_sysled, set_sysled, 1); static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 0); static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 1); @@ -761,7 +825,6 @@ static SENSOR_DEVICE_ATTR(fan10_input,S_IRUGO, show_rpm, 0, 9); static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu, 0, 0); static SENSOR_DEVICE_ATTR(psu2, S_IRUGO, show_psu, 0, 1); static SENSOR_DEVICE_ATTR(power_status, S_IRUGO, show_powerstatus, 0, 0); -static SENSOR_DEVICE_ATTR(resetbutton_status, S_IRUGO, show_resetbuttonstatus, 0, 0); static SENSOR_DEVICE_ATTR(watchdog_feed, S_IWUSR, 0, set_watchdog_feed, 0); static SENSOR_DEVICE_ATTR(watchdog_enable, S_IWUSR|S_IRUGO, show_watchdog_enable, set_watchdog_enable, 0); @@ -773,18 +836,20 @@ static SENSOR_DEVICE_ATTR(bios_cs, S_IWUSR|S_IRUGO, show_bios_cs, set_b static struct attribute *cpld_attributes[] = { &sensor_dev_attr_info.dev_attr.attr, &sensor_dev_attr_diag.dev_attr.attr, + &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_stacking_led.dev_attr.attr, &sensor_dev_attr_fan_led.dev_attr.attr, &sensor_dev_attr_power_led.dev_attr.attr, - &sensor_dev_attr_service_led.dev_attr.attr, + &sensor_dev_attr_location_led.dev_attr.attr, + + &sensor_dev_attr_grn_led.dev_attr.attr, + &sensor_dev_attr_red_led.dev_attr.attr, &sensor_dev_attr_interrupt.dev_attr.attr, &sensor_dev_attr_psu1.dev_attr.attr, &sensor_dev_attr_psu2.dev_attr.attr, &sensor_dev_attr_power_status.dev_attr.attr, - &sensor_dev_attr_resetbutton_status.dev_attr.attr, &sensor_dev_attr_pwm1.dev_attr.attr, &sensor_dev_attr_pwm2.dev_attr.attr, @@ -839,7 +904,6 @@ cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct cpld_data *data; int status; - u8 byte[5]; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) @@ -879,11 +943,7 @@ cpld_probe(struct i2c_client *client, const struct i2c_device_id *id) } } - //Handle LED control by the driver - byte[0]=0x01; - cpld_i2c_write(client, byte, CPLD_CTL_OFFSET, 1); - cpld_i2c_write(client2, byte, CPLD_CTL_OFFSET, 1); - + data->tsk = kthread_run(cpld_thread,client,"%s",dev_name(data->hwmon_dev)); dev_info(&client->dev, "%s: sensor '%s'\n", dev_name(data->hwmon_dev), client->name); @@ -908,6 +968,7 @@ static int cpld_remove(struct i2c_client *client) i2c_unregister_device(client2); i2c_set_clientdata(client2, NULL); } + kfree(data); return 0; } diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.c index a303527bec..143aee309d 100644 --- a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.c +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.c @@ -1,22 +1,55 @@ -/* - * 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 "io_expander.h" #include "inv_mux.h" -static struct mux_obj_s *mux_head_p = NULL; +/* For build single module using (Ex: ONL platform) */ +#include +//#include +//#include +static struct mux_obj_s *mux_head_p = NULL; + /* ========== MUX object functions ========== */ +static int +_setup_i2c_value(struct mux_obj_s *self, int offset, int value){ + + return i2c_smbus_write_byte_data(self->i2c_client_p, offset, value); +} + + +static int +_setup_i2c_client(struct mux_obj_s *self, int chan_id, int addr){ + + struct i2c_adapter *adap = NULL; + char *emsg = "ERR"; + + adap = i2c_get_adapter(chan_id); + if (!adap){ + emsg = "can't get adapter"; + goto err_setup_i2c_client; + } + self->i2c_client_p = kzalloc(sizeof(*self->i2c_client_p), GFP_KERNEL); + if (!self->i2c_client_p){ + emsg = "can't kzalloc client"; + goto err_setup_i2c_client; + } + self->i2c_client_p->adapter = adap; + self->i2c_client_p->addr = addr; + return 0; + +err_setup_i2c_client: + SWPS_ERR("%s: %s\n", __func__, emsg); + return ERR_MUX_UNEXCPT; +} + + int _common_force_pull_gpio(int mem_addr, int input, @@ -93,6 +126,78 @@ normal_gpio_pull_low(struct mux_obj_s *self){ } +int +cpld_rst_all_4_pull_low(struct mux_obj_s *self){ + + char *emsg = "ERR"; + int err = ERR_MUX_UNEXCPT; + + switch(self->gpio_num) { + case MUX_RST_CPLD_C0_A77_70_74_RST_ALL: + goto setlow_cpld_rst_all_4_c0_a77_70_74_rst_all; + + default: + break; + } + emsg = "Undefined case"; + goto err_cpld_rst_all_4_pull_low; + +setlow_cpld_rst_all_4_c0_a77_70_74_rst_all: + err = _setup_i2c_value(self, 0x70, 0x0); + if (err < 0) { + emsg = "setup 0x70 fail"; + goto err_cpld_rst_all_4_pull_low; + } + err = _setup_i2c_value(self, 0x74, 0x01); + if (err < 0) { + emsg = "setup 0x74 fail"; + goto err_cpld_rst_all_4_pull_low; + } + return 0; + +err_cpld_rst_all_4_pull_low: + SWPS_INFO("%s: %s :%d :%d\n", + __func__, emsg, self->gpio_num, err); + return ERR_MUX_UNEXCPT; +} + + +int +cpld_rst_all_4_pull_high(struct mux_obj_s *self){ + + char *emsg = "ERR"; + int err = ERR_MUX_UNEXCPT; + + switch(self->gpio_num) { + case MUX_RST_CPLD_C0_A77_70_74_RST_ALL: + goto sethigh_cpld_rst_all_4_c0_a77_70_74_rst_all; + + default: + break; + } + emsg = "Undefined case"; + goto err_cpld_rst_all_4_pull_high; + +sethigh_cpld_rst_all_4_c0_a77_70_74_rst_all: + err = _setup_i2c_value(self, 0x70, 0xfe); + if (err < 0) { + emsg = "setup 0x70 fail"; + goto err_cpld_rst_all_4_pull_high; + } + err = _setup_i2c_value(self, 0x74, 0x03); + if (err < 0) { + emsg = "setup 0x74 fail"; + goto err_cpld_rst_all_4_pull_high; + } + return 0; + +err_cpld_rst_all_4_pull_high: + SWPS_INFO("%s: %s :%d :%d\n", + __func__, emsg, self->gpio_num, err); + return ERR_MUX_UNEXCPT; +} + + int pca9548_reset_mux_all(struct mux_obj_s *self){ /* [Note] Power-on reset (PCA9548A-NXP) @@ -108,16 +213,47 @@ pca9548_reset_mux_all(struct mux_obj_s *self){ SWPS_ERR("%s: _pull_low fail!\n", __func__); return -1; } - mdelay(MUX_RST_WAIT_MS); + mdelay(MUX_RST_WAIT_MS_PCA9548); if (self->_pull_high(self) < 0) { SWPS_ERR("%s: _pull_high fail!\n", __func__); return -1; } - mdelay(MUX_RST_WAIT_MS); + mdelay(MUX_RST_WAIT_MS_PCA9548); return 0; } +int +cpld_reset_mux_all(struct mux_obj_s *self){ + + char *emsg = "ERR"; + int err = ERR_MUX_UNEXCPT; + + switch(self->gpio_num) { + case MUX_RST_CPLD_C0_A77_70_74_RST_ALL: + goto reset_cpld_rst_all_4_c0_a77_70_74_rst_all; + + default: + break; + } + emsg = "Undefined case"; + goto err_cpld_reset_mux_all; + +reset_cpld_rst_all_4_c0_a77_70_74_rst_all: + if (self->_pull_low(self) < 0) { + emsg = "_pull_low fail"; + goto err_cpld_reset_mux_all; + } + mdelay(MUX_RST_WAIT_MS_CPLD); + return 0; + +err_cpld_reset_mux_all: + SWPS_INFO("%s: %s :%d :%d\n", + __func__, emsg, self->gpio_num, err); + return ERR_MUX_UNEXCPT; +} + + int common_reset_mux_all(struct mux_obj_s *self){ SWPS_ERR("%s: not ready!\n", __func__); @@ -127,6 +263,11 @@ common_reset_mux_all(struct mux_obj_s *self){ int init_gpio_4_force(struct mux_obj_s *self){ + + if (self->_pull_high(self) < 0) { + SWPS_ERR("%s: setup default fail!\n", __func__); + return -1; + } return 0; } @@ -134,20 +275,95 @@ init_gpio_4_force(struct mux_obj_s *self){ int init_gpio_4_normal(struct mux_obj_s *self){ - int err = 0; + int err = 0; + char *emsg = "ERR"; if (!gpio_is_valid(self->gpio_num)) { - SWPS_ERR("%s: GIPO:%d isn't valid\n", __func__, self->gpio_num); - return -1; + emsg = "GPIO invalid"; + goto err_init_gpio_4_normal; } err = gpio_request(self->gpio_num, MUX_GPIO_LABEL); if (err < 0) { - SWPS_ERR("%s: gpio_request fail :%d :%d\n", - __func__, err, self->gpio_num); - return -1; + emsg = "gpio_request fail"; + goto err_init_gpio_4_normal; + } + err = self->_pull_high(self); + if (err < 0) { + emsg = "setup default fail"; + goto err_init_gpio_4_normal; } SWPS_DEBUG("%s: gpio_request:%d ok.\n", __func__, self->gpio_num); return 0; + +err_init_gpio_4_normal: + SWPS_ERR("%s: %s :%d :%d\n", + __func__, emsg, self->gpio_num, err); + return -1; +} + + +int +init_cpld_4_rst_all(struct mux_obj_s *self){ + + char *emsg = "ERR"; + int err = ERR_MUX_UNEXCPT; + int chan = ERR_MUX_UNEXCPT; + int addr = ERR_MUX_UNEXCPT; + + switch(self->gpio_num) { + case MUX_RST_CPLD_C0_A77_70_74_RST_ALL: + goto init_cpld_i2c_c0_a77_70_74_rst_all; + + default: + break; + } + emsg = "Undefined case"; + goto err_init_cpld_4_rst_all; + +init_cpld_i2c_c0_a77_70_74_rst_all: + chan = 0; + addr = 0x77; + err = _setup_i2c_client(self, chan, addr); + if (err < 0) { + emsg = "_setup_i2c_client fail"; + goto err_init_cpld_4_rst_all; + } + err = self->_pull_high(self); + if (err < 0) { + emsg = "setup default value fail"; + goto err_init_cpld_4_rst_all; + } + SWPS_DEBUG("%s: init_cpld_i2c_c0_a77_70_74_rst_all ok", __func__); + return 0; + +err_init_cpld_4_rst_all: + SWPS_INFO("%s: %s :%d :%d\n", + __func__, emsg, self->gpio_num, err); + return ERR_MUX_UNEXCPT; +} + + +int +clean_gpio_4_common(struct mux_obj_s *self){ + + if (!self) return 0; + if (!gpio_is_valid(self->gpio_num)) return 0; + self->_pull_high(self); + gpio_free(mux_head_p->gpio_num); + return 0; +} + + +int +clean_cpld_4_rst_all(struct mux_obj_s *self){ + + if (!self) return 0; + self->_pull_high(self); + if (self->i2c_client_p) { + i2c_put_adapter(self->i2c_client_p->adapter); + kfree(self->i2c_client_p); + } + return 0; } @@ -163,6 +379,7 @@ _setup_muxctl_cb(struct mux_obj_s *self, self->_pull_low = rangeley_force_pull_low; self->_pull_high = rangeley_force_pull_high; self->_init = init_gpio_4_force; + self->_clean = clean_gpio_4_common; self->reset = pca9548_reset_mux_all; memset(mod_dsc, 0, 32); snprintf(mod_dsc, 31, "Rangeley force mode"); @@ -173,25 +390,38 @@ _setup_muxctl_cb(struct mux_obj_s *self, self->_pull_low = hedera_force_pull_low; self->_pull_high = hedera_force_pull_high; self->_init = init_gpio_4_force; + self->_clean = clean_gpio_4_common; self->reset = pca9548_reset_mux_all; memset(mod_dsc, 0, 32); snprintf(mod_dsc, 31, "Hedera force mode"); goto ok_setup_muxctl_cb; - case MUX_RST_GPIO_48_PAC9548: - case MUX_RST_GPIO_69_PAC9548: + case MUX_RST_GPIO_48_PCA9548: + case MUX_RST_GPIO_69_PCA9548: case MUX_RST_GPIO_249_PCA9548: - case MUX_RST_GPIO_500_PAC9548: + case MUX_RST_GPIO_500_PCA9548: case MUX_RST_GPIO_505_PCA9548: self->gpio_num = gpio; self->_pull_low = normal_gpio_pull_low; self->_pull_high = normal_gpio_pull_high; self->_init = init_gpio_4_normal; + self->_clean = clean_gpio_4_common; self->reset = pca9548_reset_mux_all; memset(mod_dsc, 0, 32); snprintf(mod_dsc, 31, "Normal mode :%d", (int)gpio); goto ok_setup_muxctl_cb; + case MUX_RST_CPLD_C0_A77_70_74_RST_ALL: + self->gpio_num = gpio; + self->_pull_low = cpld_rst_all_4_pull_low; + self->_pull_high = cpld_rst_all_4_pull_high; + self->_init = init_cpld_4_rst_all; + self->_clean = clean_cpld_4_rst_all; + self->reset = cpld_reset_mux_all; + memset(mod_dsc, 0, 32); + snprintf(mod_dsc, 31, "CPLD mode :%d", (int)gpio); + goto ok_setup_muxctl_cb; + default: break; } @@ -207,23 +437,28 @@ ok_setup_muxctl_cb: /* ========== MUX public functions ========== */ void -clean_mux_gpio(void){ +clean_mux_objs(void){ - if (!mux_head_p) { + struct mux_obj_s *curr_p = mux_head_p; + struct mux_obj_s *next_p = NULL; + + if (!curr_p) { SWPS_DEBUG("%s: mux_head_p is NULL\n", __func__); return; } - if (gpio_is_valid(mux_head_p->gpio_num)) { - gpio_free(mux_head_p->gpio_num); + while (curr_p) { + next_p = curr_p->next; + curr_p->_clean(curr_p); + kfree(curr_p); + curr_p = next_p; } - kfree(mux_head_p); - mux_head_p = NULL; SWPS_DEBUG("%s: done.\n", __func__); } +EXPORT_SYMBOL(clean_mux_objs); int -reset_mux_gpio(void){ +reset_mux_objs(void){ if (!mux_head_p) { SWPS_ERR("%s: MUX ctl object doesn't exist!\n", __func__); @@ -235,46 +470,77 @@ reset_mux_gpio(void){ } return 0; } +EXPORT_SYMBOL(reset_mux_objs); + + +struct mux_obj_s * +_create_mux_obj(unsigned gpio){ + + char *emsg = "ERR"; + struct mux_obj_s *obj_p = NULL; + + obj_p = kzalloc(sizeof(struct mux_obj_s), GFP_KERNEL); + if (!obj_p) { + emsg = "kzalloc fail!"; + goto err_create_mux_obj_1; + } + if (_setup_muxctl_cb(obj_p, gpio) < 0){ + emsg = "_setup_muxctl_cb fail!"; + goto err_create_mux_obj_2; + } + if (obj_p->_init(obj_p) < 0) { + emsg = "_init() fail!"; + goto err_create_mux_obj_2; + } + SWPS_DEBUG("%s: created MUX object :%d\n", __func__, gpio); + return obj_p; + +err_create_mux_obj_2: + kfree(obj_p); +err_create_mux_obj_1: + SWPS_ERR("%s: %s :%d\n", __func__, emsg, gpio); + return NULL; +} int -init_mux_gpio(unsigned gpio){ +init_mux_objs(unsigned gpio){ + + struct mux_obj_s *curr_p = NULL; + char *emsg = "ERR"; /* Create MUX control object */ if (mux_head_p) { SWPS_DEBUG("%s: mux_head_p is not NULL!\n", __func__); - clean_mux_gpio(); + clean_mux_objs(); } /* Currently, it is using single muxctl architecture. - * In the future, it may use the multi-muxctl if HW add new features. - * (Ex: Port power-status control) + * In the future, it may use the multi-muxctl. + * (Ex: Gulmohar's advance I2C control / Peony's reset single mux) */ - mux_head_p = kzalloc(sizeof(struct mux_obj_s), GFP_KERNEL); - if (!mux_head_p) { - SWPS_ERR("%s: kzalloc fail!\n", __func__); - return -1; - } - /* Initial MUX controller */ - if (_setup_muxctl_cb(mux_head_p, gpio) < 0){ - SWPS_ERR("%s: _setup_muxctl_cb fail!\n", __func__); - return -1; - } - if (mux_head_p->_init(mux_head_p) < 0) { - SWPS_ERR("%s: init() fail\n", __func__); - goto err_init_mux_gpio; - } - /* Setup default value */ - if (mux_head_p->_pull_high(mux_head_p) < 0) { - SWPS_ERR("%s: setup default fail!\n", __func__); - goto err_init_mux_gpio; + curr_p = _create_mux_obj(gpio); + if (!curr_p) { + emsg = "_create_mux_obj fail"; + goto err_init_mux_objs; } + curr_p->next = NULL; + mux_head_p = curr_p; + SWPS_DEBUG("%s: all done. :%d\n", __func__, gpio); return 0; -err_init_mux_gpio: - clean_mux_gpio(); +err_init_mux_objs: + clean_mux_objs(); + SWPS_ERR("%s: %s\n", __func__, emsg); return -1; } - +EXPORT_SYMBOL(init_mux_objs); + + +/* For single ko module + * => You need to declare MODULE_LICENSE If you want to build single module along. + * => Ex: For ONL platform + */ +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.h b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.h index f981a30464..a913b24c60 100644 --- a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.h +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_mux.h @@ -1,47 +1,51 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - #ifndef INV_MUX_H #define INV_MUX_H +#include /* MUX basic information */ #define MUX_GPIO_LABEL "SWPS_RST_MUX" /* MUX reset GPIO define */ -#define MUX_RST_GPIO_FORCE (30100) -#define MUX_RST_GPIO_FORCE_RANGELEY (30101) -#define MUX_RST_GPIO_FORCE_HEDERA (30102) -#define MUX_RST_GPIO_48_PAC9548 (48) -#define MUX_RST_GPIO_69_PAC9548 (69) -#define MUX_RST_GPIO_249_PCA9548 (249) -#define MUX_RST_GPIO_500_PAC9548 (500) -#define MUX_RST_GPIO_505_PCA9548 (505) +#define MUX_RST_GPIO_FORCE (30100) +#define MUX_RST_GPIO_FORCE_RANGELEY (30101) +#define MUX_RST_GPIO_FORCE_HEDERA (30102) +#define MUX_RST_GPIO_48_PCA9548 (48) +#define MUX_RST_GPIO_69_PCA9548 (69) +#define MUX_RST_GPIO_249_PCA9548 (249) +#define MUX_RST_GPIO_500_PCA9548 (500) +#define MUX_RST_GPIO_505_PCA9548 (505) +#define MUX_RST_CPLD_C0_A77_70_74_RST_ALL (30201) /* MUX relate value define */ -#define MUX_RST_WAIT_MS (1) -#define MUX_RST_MEM_ADDR_RANGELEY (0) // TBD -#define MUX_RST_MEM_ADDR_HEDERA (0x548) +#define MUX_RST_WAIT_MS_PCA9548 (1) +#define MUX_RST_WAIT_MS_CPLD (10) +#define MUX_RST_MEM_ADDR_RANGELEY (0) // TBD +#define MUX_RST_MEM_ADDR_HEDERA (0x548) + +/* MUX error code define */ +#define ERR_MUX_UNEXCPT (-399) struct mux_obj_s { + struct i2c_client *i2c_client_p; + struct mux_obj_s *next; unsigned gpio_num; int (*_pull_high)(struct mux_obj_s *self); int (*_pull_low)(struct mux_obj_s *self); int (*_init)(struct mux_obj_s *self); + int (*_clean)(struct mux_obj_s *self); int (*reset)(struct mux_obj_s *self); }; -void clean_mux_gpio(void); -int reset_mux_gpio(void); -int init_mux_gpio(unsigned gpio); +void clean_mux_objs(void); +int reset_mux_objs(void); +int init_mux_objs(unsigned gpio); #endif /* INV_MUX_H */ + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_platform.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_platform.c index 42900232dc..212388c8e9 100644 --- a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_platform.c +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_platform.c @@ -137,49 +137,49 @@ static struct pca954x_platform_data mux_data_0_6 = { }; static struct i2c_board_info i2c_device_info0[] __initdata = { - {"pca9641", 0, 0x76, &pca9641_data_1, 0, 0}, //PCA9641-1 - {"pca9641", 0, 0x73, &pca9641_data_3, 0, 0}, //PCA9641-3 - {"pca9641", 0, 0x09, &pca9641_data_4, 0, 0}, //PCA9641-4 + {"pca9641", 0, 0x76, &pca9641_data_1, 0, 0}, //PCA9641-1 + {"pca9641", 0, 0x73, &pca9641_data_3, 0, 0}, //PCA9641-3 + {"pca9641", 0, 0x09, &pca9641_data_4, 0, 0}, //PCA9641-4 }; static struct i2c_board_info i2c_device_info1[] __initdata = { - {"pca9641", 0, 0x0A, &pca9641_data_2, 0, 0}, //PCA9641-2 + {"pca9641", 0, 0x0A, &pca9641_data_2, 0, 0}, //PCA9641-2 }; static struct i2c_board_info i2c_device_info2[] __initdata = { - {"inv_cpld", 0, 0x77, 0, 0, 0}, //CPLD + {"inv_cpld", 0, 0x77, 0, 0, 0}, //CPLD }; static struct i2c_board_info i2c_device_info3[] __initdata = { - {"tmp75", 0, 0x48, 0, 0, 0}, //CPU Board Temp - {"tmp75", 0, 0x4A, 0, 0, 0}, //Temp - {"tmp75", 0, 0x4D, 0, 0, 0}, //Temp - {"tmp75", 0, 0x4E, 0, 0, 0}, //Temp + {"tmp75", 0, 0x48, 0, 0, 0}, //CPU Board Temp + {"tmp75", 0, 0x4A, 0, 0, 0}, //Temp + {"tmp75", 0, 0x4D, 0, 0, 0}, //Temp + {"tmp75", 0, 0x4E, 0, 0, 0}, //Temp }; static struct i2c_board_info i2c_device_info4[] __initdata = { - {"pmbus", 0, 0x5A, 0, 0, 0}, //PSU1 - {"pmbus", 0, 0x5B, 0, 0, 0}, //PSU2 + {"pmbus", 0, 0x5B, 0, 0, 0}, //PSU1 + {"pmbus", 0, 0x5A, 0, 0, 0}, //PSU2 }; static struct i2c_board_info i2c_device_info5[] __initdata = { - {"pca9548", 0, 0x70, &mux_data_0, 0, 0}, //mux root + {"pca9548", 0, 0x70, &mux_data_0, 0, 0}, //mux root }; static struct i2c_board_info i2c_device_info6[] __initdata = { - {"pca9548", 0, 0x72, &mux_data_0_0, 0, 0}, + {"pca9548", 0, 0x72, &mux_data_0_0, 0, 0}, }; static struct i2c_board_info i2c_device_info7[] __initdata = { - {"pca9548", 0, 0x72, &mux_data_0_1, 0, 0}, + {"pca9548", 0, 0x72, &mux_data_0_1, 0, 0}, }; static struct i2c_board_info i2c_device_info8[] __initdata = { - {"pca9548", 0, 0x72, &mux_data_0_2, 0, 0}, + {"pca9548", 0, 0x72, &mux_data_0_2, 0, 0}, }; static struct i2c_board_info i2c_device_info9[] __initdata = { - {"pca9548", 0, 0x72, &mux_data_0_3, 0, 0}, + {"pca9548", 0, 0x72, &mux_data_0_3, 0, 0}, }; static struct i2c_board_info i2c_device_info10[] __initdata = { - {"pca9548", 0, 0x72, &mux_data_0_4, 0, 0}, + {"pca9548", 0, 0x72, &mux_data_0_4, 0, 0}, }; static struct i2c_board_info i2c_device_info11[] __initdata = { - {"pca9548", 0, 0x72, &mux_data_0_5, 0, 0}, + {"pca9548", 0, 0x72, &mux_data_0_5, 0, 0}, }; static struct i2c_board_info i2c_device_info12[] __initdata = { - {"pca9548", 0, 0x72, &mux_data_0_6, 0, 0}, + {"pca9548", 0, 0x72, &mux_data_0_6, 0, 0}, }; @@ -196,19 +196,23 @@ static struct inv_i2c_board_info i2cdev_list[] = { {bus_id(9), ARRAY_SIZE(i2c_device_info9), i2c_device_info9 }, //mux CH3 {bus_id(10),ARRAY_SIZE(i2c_device_info10), i2c_device_info10}, //mux CH4 {bus_id(11),ARRAY_SIZE(i2c_device_info11), i2c_device_info11}, //mux CH5 - {bus_id(12),ARRAY_SIZE(i2c_device_info12), i2c_device_info12}, //mux CH6 + {bus_id(12),ARRAY_SIZE(i2c_device_info12), i2c_device_info12}, //mux CH6 }; +#define INV_PLATFORM_CLIENT_MAX_NUM 50 /*A big enough number for sum of i2cdev_list[i].size */ +static int client_list_index = 0; +static struct i2c_client *client_list[INV_PLATFORM_CLIENT_MAX_NUM] = {0}; + ///////////////////////////////////////////////////////////////////////////////////////// static struct platform_device *device_i2c_gpio0; -static struct i2c_gpio_platform_data i2c_gpio_platdata0 = { - .scl_pin = 58, //494, - .sda_pin = 75, //511, - - .udelay = 5, //5:100kHz - .sda_is_open_drain = 0, - .scl_is_open_drain = 0, - .scl_is_output_only = 0 +static struct i2c_gpio_platform_data i2c_gpio_platdata0 = { + .scl_pin = 58, //494, + .sda_pin = 75, //511, + + .udelay = 5, //5:100kHz + .sda_is_open_drain = 0, + .scl_is_open_drain = 0, + .scl_is_output_only = 0 }; static int __init inv_platform_init(void) @@ -220,7 +224,7 @@ static int __init inv_platform_init(void) //printk("%s \n", __func__); - //use i2c-gpio + //use i2c-gpio //register i2c gpio //config gpio58,75 to gpio function 58=32+3*8+2 75=32*2+8*1+3 gpio69=32*2+8*0+5 outl( inl(0x533) | (1<<2), 0x533); //i2c-gpio sdl (GPIO58) @@ -229,7 +233,7 @@ static int __init inv_platform_init(void) outl( inl(0x500) | (1<<7), 0x500); //SYS_RDY_N (GPIO7) outl( inl(0x501) | (1<<7), 0x501); //BMC_HEART_BEAT (GPIO15) outl( inl(0x503) | (1<<2)|(1<<3), 0x503); //PSOC_HEART_BEAT(26),CPLD_HEART_BEAT(27) - + device_i2c_gpio0 = platform_device_alloc("i2c-gpio", 1); if (!device_i2c_gpio0) { printk(KERN_ERR "i2c-gpio: platform_device_alloc fail\n"); @@ -243,7 +247,8 @@ static int __init inv_platform_init(void) if (ret) { printk(KERN_ERR "i2c-gpio: platform_device_add fail %d\n", ret); } - msleep(10); + msleep(10); + for(i=0; idev.platform_data = NULL; - platform_device_unregister(device_i2c_gpio0); + int i; + + for(i=client_list_index-1; i>=0; i--) { + i2c_unregister_device(client_list[i]); + } + device_i2c_gpio0->dev.platform_data = NULL; + platform_device_unregister(device_i2c_gpio0); + printk("inv_platform_exit done\n"); } module_init(inv_platform_init); @@ -273,3 +294,4 @@ module_exit(inv_platform_exit); MODULE_AUTHOR("Inventec"); MODULE_DESCRIPTION("Platform devices"); MODULE_LICENSE("GPL"); + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.c index cbb22fba29..11b60f78ae 100644 --- a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.c +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.c @@ -1,9 +1,3 @@ -/* - * 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 @@ -15,12 +9,14 @@ #include #include #include +#include #include "inv_swps.h" static int ctl_major; static int port_major; static int ioexp_total; static int port_total; +static int block_polling; static int auto_config; static int flag_i2c_reset; static int flag_mod_state; @@ -29,7 +25,8 @@ static struct class *swp_class_p = NULL; static struct inv_platform_s *platform_p = NULL; static struct inv_ioexp_layout_s *ioexp_layout = NULL; static struct inv_port_layout_s *port_layout = NULL; - +int io_no_init = 0; +module_param(io_no_init, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); static void swp_polling_worker(struct work_struct *work); static DECLARE_DELAYED_WORK(swp_polling, swp_polling_worker); @@ -140,6 +137,47 @@ _get_transvr_obj(char *dev_name) { } +static int +_is_i2c_target_exist(int chan, int addr) { + /* retval: Exist = 1 / Not exist = 0 / Error < 0 + */ + struct i2c_adapter *adap = NULL; + struct i2c_client *client = NULL; + int retval = -1; + int err = -1; + int d_offs = 0; + + adap = i2c_get_adapter(chan); + if (!adap) { + SWPS_DEBUG("%s: can't get adapter\n", __func__); + retval = 0; + goto out_is_i2c_target_exist_1; + } + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) { + SWPS_ERR("%s: kzalloc fail\n", __func__); + retval = -1; + goto out_is_i2c_target_exist_2; + } + client->adapter = adap; + client->addr = addr; + err = i2c_smbus_read_byte_data(client, d_offs); + if (err < 0) { + retval = 0; + } else { + retval = 1; + } + i2c_put_adapter(adap); + kfree(client); + return retval; + +out_is_i2c_target_exist_2: + i2c_put_adapter(adap); +out_is_i2c_target_exist_1: + return retval; +} + + static void unlock_tobj_all(void) { @@ -254,6 +292,22 @@ show_attr_auto_config(struct device *dev_p, } +static ssize_t +show_attr_block_poll(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", block_polling); +} +static ssize_t +show_attr_io_no_init(struct device *dev_p, + struct device_attribute *attr_p, + char *buf_p){ + + return snprintf(buf_p, 8, "%d\n", io_no_init); +} + + static int _check_reset_pwd(const char *buf_p, size_t count) { @@ -360,6 +414,53 @@ store_attr_auto_config(struct device *dev_p, } +static ssize_t +store_attr_block_poll( struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + int input_val = sscanf_2_int(buf_p); + + if (input_val < 0){ + return -EBFONT; + } + if ((input_val != 0) && (input_val != 1)) { + return -EBFONT; + } + + if(input_val != block_polling){ + block_polling = input_val; + if(block_polling){ + cancel_delayed_work_sync(&swp_polling); + } + else{ + schedule_delayed_work(&swp_polling, _get_polling_period()); + } + } + + return count; +} + +static ssize_t +store_attr_io_no_init( struct device *dev_p, + struct device_attribute *attr_p, + const char *buf_p, + size_t count){ + + int input_val = sscanf_2_int(buf_p); + + if ((input_val != 0) && (input_val != 1)) { + return -EBFONT; + } + + if(input_val != io_no_init){ + io_no_init = input_val; + } + + return count; +} + /* ========== Show functions: For transceiver attribute ========== */ static ssize_t @@ -1604,6 +1705,9 @@ static DEVICE_ATTR(status, S_IRUGO, show_attr_status, static DEVICE_ATTR(reset_i2c, S_IWUSR, NULL, store_attr_reset_i2c); static DEVICE_ATTR(reset_swps, S_IWUSR, NULL, store_attr_reset_swps); static DEVICE_ATTR(auto_config, S_IRUGO|S_IWUSR, show_attr_auto_config, store_attr_auto_config); +static DEVICE_ATTR(block_poll, S_IRUGO|S_IWUSR, show_attr_block_poll, store_attr_block_poll); +static DEVICE_ATTR(io_no_init, S_IRUGO|S_IWUSR, show_attr_io_no_init, store_attr_io_no_init); + /* ========== Transceiver attribute: from eeprom ========== */ @@ -1666,12 +1770,12 @@ static DEVICE_ATTR(hard_rs1, S_IRUGO|S_IWUSR, show_attr_hard_rs1, /* ========== Functions for module handling ========== */ static void -clean_port_obj(void){ +clean_port_objs(void){ dev_t dev_num; char dev_name[32]; struct device *device_p; - struct transvr_obj_s *transvr_obj_p; + struct transvr_obj_s *tobj_p; int minor_curr, port_id; for (minor_curr=0; minor_curri2c_client_p); - kfree(transvr_obj_p->vendor_name); - kfree(transvr_obj_p->vendor_pn); - kfree(transvr_obj_p->vendor_rev); - kfree(transvr_obj_p->vendor_sn); - kfree(transvr_obj_p->worker_p); - kfree(transvr_obj_p); + tobj_p = dev_get_drvdata(device_p); + if (tobj_p){ + if (tobj_p->i2c_client_p) { + i2c_put_adapter(tobj_p->i2c_client_p->adapter); + kfree(tobj_p->i2c_client_p); + } + kfree(tobj_p->vendor_name); + kfree(tobj_p->vendor_pn); + kfree(tobj_p->vendor_rev); + kfree(tobj_p->vendor_sn); + kfree(tobj_p->worker_p); + kfree(tobj_p); } dev_num = MKDEV(port_major, minor_curr); device_unregister(device_p); @@ -1713,6 +1820,9 @@ clean_swps_common(void){ device_destroy(swp_class_p, dev_num); } cancel_delayed_work_sync(&swp_polling); + if (platform_p) { + kfree(platform_p); + } SWPS_DEBUG("%s: done.\n", __func__); } @@ -1720,8 +1830,10 @@ clean_swps_common(void){ static int get_platform_type(void){ - int i; - int pf_total = ARRAY_SIZE(platform_map); + int i, tmp; + int auto_chan = -1; + int auto_addr = -1; + int pf_total = ARRAY_SIZE(platform_map); char log_msg[64] = "ERROR"; platform_p = kzalloc(sizeof(struct inv_platform_s), GFP_KERNEL); @@ -1749,6 +1861,30 @@ get_platform_type(void){ platform_p->name); goto err_get_platform_type_2; + case PLATFORM_TYPE_PEONY_AUTO: +#ifdef SWPS_PEONY_SFP + auto_chan = peony_sfp_ioexp_layout[0].addr[0].chan_id; + auto_addr = peony_sfp_ioexp_layout[0].addr[0].chip_addr; +#endif + tmp = _is_i2c_target_exist(auto_chan, auto_addr); + switch (tmp) { + case 0: /* Copper SKU */ + SWPS_INFO("Auto-detected :Peony :Copper\n"); + platform_p->id = PLATFORM_TYPE_PEONY_COPPER_GA; + goto map_platform_name; + + case 1: /* SFP SKU */ + SWPS_INFO("Auto-detected :Peony :SFP\n"); + platform_p->id = PLATFORM_TYPE_PEONY_SFP_GA; + goto map_platform_name; + + default: + break; + } + snprintf(log_msg, sizeof(log_msg), + "Auto detect Peony SKU fail! :%d", tmp); + goto err_get_platform_type_2; + case PLATFORM_TYPE_MAGNOLIA: case PLATFORM_TYPE_MAGNOLIA_FNC: case PLATFORM_TYPE_REDWOOD: @@ -1763,22 +1899,14 @@ get_platform_type(void){ case PLATFORM_TYPE_LAVENDER_GA: case PLATFORM_TYPE_LAVENDER_ONL: case PLATFORM_TYPE_COTTONWOOD_RANGELEY: - case PLATFORM_TYPE_MAPLE: + case PLATFORM_TYPE_MAPLE_GA: + case PLATFORM_TYPE_MAPLE_B: + case PLATFORM_TYPE_GULMOHAR_GA: + case PLATFORM_TYPE_GULMOHAR_2T_EVT1_GA: + case PLATFORM_TYPE_PEONY_SFP_GA: + case PLATFORM_TYPE_PEONY_COPPER_GA: platform_p->id = PLATFORM_SETTINGS; - for (i=0; iname, (sizeof(platform_p->name) - 1), - "%s", platform_map[i].name); - snprintf(log_msg, sizeof(log_msg), - "User setup platform: %d (%s)", - platform_p->id, platform_p->name); - goto ok_get_platform_type_1; - } - } - snprintf(log_msg, sizeof(log_msg), - "Internal error, can not map id:%d", - PLATFORM_SETTINGS); - goto err_get_platform_type_2; + goto map_platform_name; default: break; @@ -1787,6 +1915,22 @@ get_platform_type(void){ "PLATFORM_SETTINGS:%d undefined", PLATFORM_SETTINGS); goto err_get_platform_type_2; +map_platform_name: + for (i=0; iid == platform_map[i].id) { + snprintf(platform_p->name, (sizeof(platform_p->name) - 1), + "%s", platform_map[i].name); + snprintf(log_msg, sizeof(log_msg), + "User setup platform: %d (%s)", + platform_p->id, platform_p->name); + goto ok_get_platform_type_1; + } + } + snprintf(log_msg, sizeof(log_msg), + "Internal error, can not map id:%d", + platform_p->id ); + goto err_get_platform_type_2; + ok_get_platform_type_1: SWPS_DEBUG("%s: %s, :%d\n", __func__, log_msg, PLATFORM_SETTINGS); return 0; @@ -1913,15 +2057,61 @@ get_layout_info(void){ port_total = ARRAY_SIZE(cottonwood_rangeley_port_layout); break; #endif -#ifdef SWPS_MAPLE - case PLATFORM_TYPE_MAPLE: - gpio_rest_mux = maple_gpio_rest_mux; - ioexp_layout = maple_ioexp_layout; - port_layout = maple_port_layout; - ioexp_total = ARRAY_SIZE(maple_ioexp_layout); - port_total = ARRAY_SIZE(maple_port_layout); +#ifdef SWPS_MAPLE_GA + case PLATFORM_TYPE_MAPLE_GA: + gpio_rest_mux = maple_ga_gpio_rest_mux; + ioexp_layout = maple_ga_ioexp_layout; + port_layout = maple_ga_port_layout; + ioexp_total = ARRAY_SIZE(maple_ga_ioexp_layout); + port_total = ARRAY_SIZE(maple_ga_port_layout); break; #endif +#ifdef SWPS_MAPLE_B + case PLATFORM_TYPE_MAPLE_B: + gpio_rest_mux = maple_b_gpio_rest_mux; + ioexp_layout = maple_b_ioexp_layout; + port_layout = maple_b_port_layout; + ioexp_total = ARRAY_SIZE(maple_b_ioexp_layout); + port_total = ARRAY_SIZE(maple_b_port_layout); + break; +#endif +#ifdef SWPS_GULMOHAR + case PLATFORM_TYPE_GULMOHAR_GA: + gpio_rest_mux = gulmohar_gpio_rest_mux; + ioexp_layout = gulmohar_ioexp_layout; + port_layout = gulmohar_port_layout; + ioexp_total = ARRAY_SIZE(gulmohar_ioexp_layout); + port_total = ARRAY_SIZE(gulmohar_port_layout); + break; +#endif +#ifdef SWPS_GULMOHAR_2T_EVT1 + case PLATFORM_TYPE_GULMOHAR_2T_EVT1_GA: + gpio_rest_mux = gulmohar_2t_evt1_gpio_rest_mux; + ioexp_layout = gulmohar_2t_evt1_ioexp_layout; + port_layout = gulmohar_2t_evt1_port_layout; + ioexp_total = ARRAY_SIZE(gulmohar_2t_evt1_ioexp_layout); + port_total = ARRAY_SIZE(gulmohar_2t_evt1_port_layout); + break; +#endif +#ifdef SWPS_PEONY_SFP + case PLATFORM_TYPE_PEONY_SFP_GA: + gpio_rest_mux = peony_sfp_gpio_rest_mux; + ioexp_layout = peony_sfp_ioexp_layout; + port_layout = peony_sfp_port_layout; + ioexp_total = ARRAY_SIZE(peony_sfp_ioexp_layout); + port_total = ARRAY_SIZE(peony_sfp_port_layout); + break; +#endif +#ifdef SWPS_PEONY_COPPER + case PLATFORM_TYPE_PEONY_COPPER_GA: + gpio_rest_mux = peony_copper_gpio_rest_mux; + ioexp_layout = peony_copper_ioexp_layout; + port_layout = peony_copper_port_layout; + ioexp_total = ARRAY_SIZE(peony_copper_ioexp_layout); + port_total = ARRAY_SIZE(peony_copper_port_layout); + break; +#endif + default: SWPS_ERR(" Invalid platform: %d (%s)\n", platform_p->id, platform_p->name); @@ -1952,11 +2142,18 @@ __detect_issues_port(int minor_num) { } if (resync_channel_tier_2(tobj_p) < 0) { if (check_channel_tier_1() < 0) { - alarm_msg_2_user(tobj_p, i2c_emsg); - return -2;; + goto get_target_issues_port; } } + /* Re-check again for i2c-gpio special case */ + if (check_channel_tier_1() < 0) { + goto get_target_issues_port; + } return 0; + +get_target_issues_port: + alarm_msg_2_user(tobj_p, i2c_emsg); + return -2; } @@ -2015,11 +2212,11 @@ _isolate_issues_port(int minor_num) { static int _reset_i2c_topology_tier_1(void) { - if (reset_mux_gpio() < 0) { + if (reset_mux_objs() < 0) { SWPS_ERR("%s: reset MUX GPIO fail!\n", __func__); return -1; } - SWPS_DEBUG("%s: reset_mux_gpio OK.\n", __func__); + SWPS_DEBUG("%s: reset_mux_objs OK.\n", __func__); if (resync_channel_tier_1() < 0) { SWPS_ERR("%s: resync tier-1 channel fail!\n", __func__); return -1; @@ -2596,6 +2793,15 @@ register_modctl_attr(struct device *device_p){ err_msg = "dev_attr_auto_config"; goto err_reg_modctl_attr; } + if (device_create_file(device_p, &dev_attr_block_poll) < 0) { + err_msg = "dev_attr_block_poll"; + goto err_reg_modctl_attr; + } + if (device_create_file(device_p, &dev_attr_io_no_init) < 0) { + err_msg = "dev_attr_io_no_init"; + goto err_reg_modctl_attr; + } + return 0; err_reg_modctl_attr: @@ -2619,13 +2825,19 @@ register_ioexp_attr(struct device *device_p, goto err_reg_ioexp_attr; } break; - case IOEXP_TYPE_CYPRESS_NABC: + case IOEXP_TYPE_MAPLE_NABC: + case IOEXP_TYPE_GULMOHAR_NABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC: + case IOEXP_TYPE_SFP_8P_LAYOUT_1: if (register_ioexp_attr_sfp_2(device_p) < 0){ err_msg = "register_ioexp_attr_sfp_2 fail"; goto err_reg_ioexp_attr; } break; + case IOEXP_TYPE_MAGINOLIA_7AB: case IOEXP_TYPE_SPRUCE_7AB: case IOEXP_TYPE_CYPRESS_7ABC: @@ -2638,6 +2850,9 @@ register_ioexp_attr(struct device *device_p, case IOEXP_TYPE_SEQUOIA_NABC: case IOEXP_TYPE_LAVENDER_P65: case IOEXP_TYPE_MAPLE_0ABC: + case IOEXP_TYPE_GULMOHAR_7ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC: + case IOEXP_TYPE_QSFP_6P_LAYOUT_1: if (register_ioexp_attr_qsfp_1(device_p) < 0){ err_msg = "register_ioexp_attr_qsfp_1 fail"; goto err_reg_ioexp_attr; @@ -2732,7 +2947,7 @@ register_swp_module(void){ SWPS_WARN("Allocate CTL MAJOR failure! \n"); goto err_register_swp_module_1; } - if (alloc_chrdev_region(&port_devt, 0, dev_total, SWP_CLS_NAME) < 0){ + if (alloc_chrdev_region(&port_devt, 0, port_total, SWP_CLS_NAME) < 0){ SWPS_WARN("Allocate PORT MAJOR failure! \n"); goto err_register_swp_module_2; } @@ -2863,13 +3078,13 @@ create_port_objs(void) { /* Success */ ok_count++; } - SWPS_INFO("%s: initialed %d port-dev",__func__, ok_count); + SWPS_INFO("%s: initialed %d port-dev\n",__func__, ok_count); return 0; err_initport_reg_device: kfree(transvr_obj_p); err_initport_create_tranobj: - clean_port_obj(); + clean_port_objs(); SWPS_ERR("%s: %s", __func__, err_msg); SWPS_ERR("Dump: :%d :%d :%d :%d :%d :%d\n", port_id, chan_id, ioexp_id, ioexp_virt_offset, transvr_type, run_mod); @@ -2942,6 +3157,7 @@ init_swps_common(void){ char *err_msg = "ERR"; + block_polling = 0; auto_config = 0; if ((SWP_AUTOCONFIG_ENABLE) && (SWP_POLLING_ENABLE)){ auto_config = 1; @@ -2985,7 +3201,7 @@ swp_module_init(void){ if (create_port_objs() < 0){ goto err_init_portobj; } - if (init_mux_gpio(gpio_rest_mux) < 0){ + if (init_mux_objs(gpio_rest_mux) < 0){ goto err_init_mux; } if (init_dev_topology() < 0){ @@ -2999,13 +3215,12 @@ swp_module_init(void){ err_init_topology: - clean_mux_gpio(); + clean_mux_objs(); err_init_mux: - clean_port_obj(); + clean_port_objs(); err_init_portobj: clean_ioexp_objs(); err_init_ioexp: - class_unregister(swp_class_p); class_destroy(swp_class_p); unregister_chrdev_region(MKDEV(ctl_major, 0), 1); unregister_chrdev_region(MKDEV(port_major, 0), port_total); @@ -3019,10 +3234,9 @@ static void __exit swp_module_exit(void){ clean_swps_common(); - clean_port_obj(); + clean_port_objs(); clean_ioexp_objs(); - clean_mux_gpio(); - class_unregister(swp_class_p); + clean_mux_objs(); class_destroy(swp_class_p); unregister_chrdev_region(MKDEV(ctl_major, 0), 1); unregister_chrdev_region(MKDEV(port_major, 0), port_total); @@ -3035,6 +3249,7 @@ MODULE_AUTHOR(SWP_AUTHOR); MODULE_DESCRIPTION(SWP_DESC); MODULE_VERSION(SWP_VERSION); MODULE_LICENSE(SWP_LICENSE); +MODULE_SOFTDEP("pre: inv_platform"); module_init(swp_module_init); module_exit(swp_module_exit); @@ -3047,3 +3262,5 @@ module_exit(swp_module_exit); + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.h b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.h index d28a0a3c96..ad1f337b0c 100644 --- a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.h +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/inv_swps.h @@ -1,10 +1,3 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - #ifndef INV_SWPS_H #define INV_SWPS_H @@ -24,7 +17,7 @@ /* Module information */ #define SWP_AUTHOR "Neil " #define SWP_DESC "Inventec port and transceiver driver" -#define SWP_VERSION "4.2.9" +#define SWP_VERSION "C1-4.3.5" #define SWP_LICENSE "GPL" /* Module status define */ @@ -52,9 +45,15 @@ #define PLATFORM_TYPE_LAVENDER_GA (181) #define PLATFORM_TYPE_LAVENDER_ONL (182) #define PLATFORM_TYPE_COTTONWOOD_RANGELEY (191) -#define PLATFORM_TYPE_MAPLE (201) +#define PLATFORM_TYPE_MAPLE_GA (201) +#define PLATFORM_TYPE_GULMOHAR_GA (202) +#define PLATFORM_TYPE_GULMOHAR_2T_EVT1_GA (203) +#define PLATFORM_TYPE_PEONY_SFP_GA (204) +#define PLATFORM_TYPE_PEONY_COPPER_GA (205) +#define PLATFORM_TYPE_PEONY_AUTO (206) +#define PLATFORM_TYPE_MAPLE_B (207) /* Current running platfrom */ -#define PLATFORM_SETTINGS PLATFORM_TYPE_MAPLE +#define PLATFORM_SETTINGS PLATFORM_TYPE_MAPLE_B /* Define platform flag and kernel version */ #if (PLATFORM_SETTINGS == PLATFORM_TYPE_MAGNOLIA) @@ -99,12 +98,30 @@ #elif (PLATFORM_SETTINGS == PLATFORM_TYPE_COTTONWOOD_RANGELEY) #define SWPS_COTTONWOOD_RANGELEY (1) #define SWPS_KERN_VER_AF_3_10 (1) -#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAPLE) - #define SWPS_MAPLE (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAPLE_GA) + #define SWPS_MAPLE_GA (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAPLE_B) + #define SWPS_MAPLE_B (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_GULMOHAR_GA) + #define SWPS_GULMOHAR (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_GULMOHAR_2T_EVT1_GA) + #define SWPS_GULMOHAR_2T_EVT1 (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_PEONY_SFP_GA) + #define SWPS_PEONY_SFP (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_PEONY_COPPER_GA) + #define SWPS_PEONY_COPPER (1) + #define SWPS_KERN_VER_AF_3_10 (1) +#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_PEONY_AUTO) + #define SWPS_PEONY_SFP (1) + #define SWPS_PEONY_COPPER (1) #define SWPS_KERN_VER_AF_3_10 (1) #endif - struct inv_platform_s { int id; char name[64]; @@ -147,7 +164,13 @@ struct inv_platform_s platform_map[] = { {PLATFORM_TYPE_LAVENDER_GA, "Lavender_GA" }, {PLATFORM_TYPE_LAVENDER_ONL, "Lavender_ONL" }, {PLATFORM_TYPE_COTTONWOOD_RANGELEY, "Cottonwood_RANGELEY" }, - {PLATFORM_TYPE_MAPLE, "Maple" }, + {PLATFORM_TYPE_MAPLE_GA, "Maple_GA" }, + {PLATFORM_TYPE_MAPLE_B, "Maple_B" }, + {PLATFORM_TYPE_GULMOHAR_GA, "Gulmohar_GA" }, + {PLATFORM_TYPE_GULMOHAR_2T_EVT1_GA, "Gulmohar_2T_EVT1_GA" }, + {PLATFORM_TYPE_PEONY_SFP_GA, "Peony_SFP_GA" }, + {PLATFORM_TYPE_PEONY_COPPER_GA, "Peony_Copper_GA" }, + {PLATFORM_TYPE_PEONY_AUTO, "Peony_Auto_Detect" }, }; @@ -156,7 +179,7 @@ struct inv_platform_s platform_map[] = { * ========================================== */ #ifdef SWPS_MAGNOLIA -unsigned magnolia_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; +unsigned magnolia_gpio_rest_mux = MUX_RST_GPIO_48_PCA9548; struct inv_ioexp_layout_s magnolia_ioexp_layout[] = { /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ @@ -248,7 +271,7 @@ struct inv_port_layout_s magnolia_port_layout[] = { * ========================================== */ #ifdef SWPS_REDWOOD -unsigned redwood_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; +unsigned redwood_gpio_rest_mux = MUX_RST_GPIO_48_PCA9548; struct inv_ioexp_layout_s redwood_ioexp_layout[] = { /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ @@ -313,7 +336,7 @@ struct inv_port_layout_s redwood_port_layout[] = { * ========================================== */ #ifdef SWPS_HUDSON32I_GA -unsigned hudsin32iga_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; +unsigned hudsin32iga_gpio_rest_mux = MUX_RST_GPIO_48_PCA9548; struct inv_ioexp_layout_s hudson32iga_ioexp_layout[] = { /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ @@ -378,7 +401,7 @@ struct inv_port_layout_s hudson32iga_port_layout[] = { * ========================================== */ #ifdef SWPS_SPRUCE -unsigned spruce_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; +unsigned spruce_gpio_rest_mux = MUX_RST_GPIO_48_PCA9548; struct inv_ioexp_layout_s spruce_ioexp_layout[] = { /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ @@ -404,33 +427,33 @@ struct inv_port_layout_s spruce_port_layout[] = { * ========================================== */ #ifdef SWPS_CYPRESS_GA1 -unsigned cypress_ga1_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548; +unsigned cypress_ga1_gpio_rest_mux = MUX_RST_GPIO_69_PCA9548; struct inv_ioexp_layout_s cypress_ga1_ioexp_layout[] = { /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ - {0, IOEXP_TYPE_CYPRESS_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {0, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, - {1, IOEXP_TYPE_CYPRESS_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {1, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, - {2, IOEXP_TYPE_CYPRESS_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {2, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, - {3, IOEXP_TYPE_CYPRESS_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {3, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, - {4, IOEXP_TYPE_CYPRESS_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {4, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, - {5, IOEXP_TYPE_CYPRESS_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {5, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, {6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */ @@ -507,29 +530,29 @@ unsigned cypress_ga2_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA; struct inv_ioexp_layout_s cypress_ga2_ioexp_layout[] = { /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ - {0, IOEXP_TYPE_CYPRESS_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {0, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, - {1, IOEXP_TYPE_CYPRESS_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {1, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, - {2, IOEXP_TYPE_CYPRESS_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {2, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, - {3, IOEXP_TYPE_CYPRESS_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {3, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, - {4, IOEXP_TYPE_CYPRESS_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {4, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, - {5, IOEXP_TYPE_CYPRESS_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {5, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, {6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */ @@ -606,29 +629,29 @@ unsigned cypress_b_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA; struct inv_ioexp_layout_s cypress_b_ioexp_layout[] = { /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ - {0, IOEXP_TYPE_CYPRESS_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {0, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, - {1, IOEXP_TYPE_CYPRESS_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {1, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, - {2, IOEXP_TYPE_CYPRESS_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {2, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, - {3, IOEXP_TYPE_CYPRESS_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {3, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, - {4, IOEXP_TYPE_CYPRESS_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {4, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, - {5, IOEXP_TYPE_CYPRESS_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ - {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ - {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + {5, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ }, {6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */ @@ -701,7 +724,7 @@ struct inv_port_layout_s cypress_b_port_layout[] = { * ========================================== */ #ifdef SWPS_REDWOOD_FSL -unsigned redwood_fsl_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548; +unsigned redwood_fsl_gpio_rest_mux = MUX_RST_GPIO_48_PCA9548; struct inv_ioexp_layout_s redwood_fsl_ioexp_layout[] = { /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ @@ -801,7 +824,7 @@ struct inv_port_layout_s tahoe_port_layout[] = { * ========================================== */ #ifdef SWPS_SEQUOIA -unsigned sequoia_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548; +unsigned sequoia_gpio_rest_mux = MUX_RST_GPIO_69_PCA9548; struct inv_ioexp_layout_s sequoia_ioexp_layout[] = { /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ @@ -917,7 +940,7 @@ struct inv_port_layout_s sequoia_port_layout[] = { #if (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_GA) unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_505_PCA9548; #elif (PLATFORM_SETTINGS == PLATFORM_TYPE_LAVENDER_ONL) -unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548; +unsigned lavender_gpio_rest_mux = MUX_RST_GPIO_69_PCA9548; #endif #ifdef SWPS_LAVENDER @@ -1035,7 +1058,7 @@ struct inv_port_layout_s lavender_port_layout[] = { * =========================================================== */ #ifdef SWPS_COTTONWOOD_RANGELEY -unsigned cottonwood_rangeley_gpio_rest_mux = MUX_RST_GPIO_500_PAC9548; +unsigned cottonwood_rangeley_gpio_rest_mux = MUX_RST_GPIO_500_PCA9548; struct inv_ioexp_layout_s cottonwood_rangeley_ioexp_layout[] = { /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ @@ -1055,13 +1078,13 @@ struct inv_port_layout_s cottonwood_rangeley_port_layout[] = { #endif /* =========================================================== - * Maple Layout configuration + * Maple Layout configuration (Old) * =========================================================== */ -#ifdef SWPS_MAPLE -unsigned maple_gpio_rest_mux = 249; +#ifdef SWPS_MAPLE_GA +unsigned maple_ga_gpio_rest_mux = MUX_RST_GPIO_505_PCA9548; -struct inv_ioexp_layout_s maple_ioexp_layout[] = { +struct inv_ioexp_layout_s maple_ga_ioexp_layout[] = { /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ {0, IOEXP_TYPE_MAPLE_0ABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ @@ -1093,7 +1116,7 @@ struct inv_ioexp_layout_s maple_ioexp_layout[] = { }, }; -struct inv_port_layout_s maple_port_layout[] = { +struct inv_port_layout_s maple_ga_port_layout[] = { /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ { 0, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 1} }, { 1, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 2} }, @@ -1154,6 +1177,438 @@ struct inv_port_layout_s maple_port_layout[] = { }; #endif +/* =========================================================== + * Maple Layout configuration (B version) + * =========================================================== + */ +#ifdef SWPS_MAPLE_B +unsigned maple_b_gpio_rest_mux = MUX_RST_GPIO_69_PCA9548; + +struct inv_ioexp_layout_s maple_b_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_MAPLE_0ABC, { { 6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */ + { 6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + { 6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_MAPLE_NABC, { { 7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + { 7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + { 7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_MAPLE_NABC, { { 8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + { 8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + { 8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_MAPLE_NABC, { { 9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + { 9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + { 9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_MAPLE_NABC, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_MAPLE_NABC, { {11, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {11, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {11, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_MAPLE_NABC, { {12, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {12, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {12, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, +}; + +struct inv_port_layout_s maple_b_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 1, 23, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 2} }, + { 0, 22, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 1} }, + { 3, 25, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 4} }, + { 2, 24, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 3} }, + { 5, 27, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 6} }, + { 4, 26, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 5} }, + { 7, 29, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 8} }, + { 6, 28, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 7} }, + { 9, 31, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 14} }, + { 8, 30, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 13} }, + {11, 33, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 16} }, + {10, 32, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 15} }, + {13, 35, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 22} }, + {12, 34, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 21} }, + {15, 37, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 24} }, + {14, 36, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 23} }, + {17, 39, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 30} }, + {16, 38, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 29} }, + {19, 41, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 32} }, + {18, 40, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 31} }, + {21, 43, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 34} }, + {20, 42, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 33} }, + {23, 45, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 36} }, + {22, 44, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 35} }, + {25, 47, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 42} }, + {24, 46, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 41} }, + {27, 49, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 44} }, + {26, 48, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 43} }, + {29, 51, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 50} }, + {28, 50, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 49} }, + {31, 53, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 52} }, + {30, 52, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 51} }, + {33, 55, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 58} }, + {32, 54, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 57} }, + {35, 57, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 60} }, + {34, 56, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 59} }, + {37, 59, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 62} }, + {36, 58, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 61} }, + {39, 61, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 64} }, + {38, 60, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 63} }, + {41, 63, 6, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 66} }, + {40, 62, 6, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 65} }, + {43, 65, 6, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 68} }, + {42, 64, 6, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 67} }, + {45, 67, 6, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 70} }, + {44, 66, 6, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 69} }, + {47, 69, 6, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 72} }, + {46, 68, 6, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 71} }, + {49, 15, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 77, 78, 79, 80} }, + {48, 14, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 85, 86, 87, 88} }, + {51, 17, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 97, 98, 99,100} }, + {50, 16, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 93, 94, 95, 96} }, + {53, 19, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {105,106,107,108} }, + {52, 18, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {113,114,115,116} }, + {55, 21, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {125,126,127,128} }, + {54, 20, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, {121,122,123,124} }, +}; +#endif + + +/* ========================================== + * Gulmohar Layout configuration + * ========================================== + */ +#ifdef SWPS_GULMOHAR +unsigned gulmohar_gpio_rest_mux = MUX_RST_GPIO_505_PCA9548; + +struct inv_ioexp_layout_s gulmohar_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_GULMOHAR_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_GULMOHAR_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_GULMOHAR_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_GULMOHAR_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_GULMOHAR_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_GULMOHAR_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_GULMOHAR_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xff}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + + + +struct inv_port_layout_s gulmohar_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 1} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 2} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 3} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 4} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 5} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 6} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 7} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 8} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 9} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 10} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 11} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 12} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 21} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 22} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 23} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 24} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 33} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 34} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 35} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 36} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 37} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 38} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 39} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 40} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 41} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 42} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 43} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 44} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 49} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 50} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 51} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 52} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 53} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 54} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 55} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 56} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 65} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 66} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 67} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 68} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 69} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 70} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 71} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 72} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 81} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 82} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 83} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, { 84} }, + {48, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 97, 98, 99,100} }, + {49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, { 85, 86, 87, 88} }, + {50, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {101,102,103,104} }, + {51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {105,106,107,108} }, + {52, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {109,110,111,112} }, + {53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {109,110,111,112} }, +}; +#endif + + +/* ========================================== + * Gulmohar_2T EVT1 Layout configuration + * ========================================== + */ +#ifdef SWPS_GULMOHAR_2T_EVT1 +unsigned gulmohar_2t_evt1_gpio_rest_mux = MUX_RST_GPIO_505_PCA9548; + +struct inv_ioexp_layout_s gulmohar_2t_evt1_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC,{ {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[0] = I/O Expander N A */ + {2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[1] = I/O Expander N B */ + {2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {1, IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC,{ {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[0] = I/O Expander N A */ + {3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[1] = I/O Expander N B */ + {3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC,{ {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[0] = I/O Expander N A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[1] = I/O Expander N B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC,{ {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xf3, 0xf3}, {0xf3, 0xf3}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC,{ {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC,{ {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xdd, 0xdd}, {0xdd, 0xdd}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC,{ {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xd6, 0xda}, {0x18, 0xe3}, }, /* addr[0] = I/O Expander 7 A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xd6, 0xda}, {0x18, 0xe3}, }, /* addr[1] = I/O Expander 7 B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xd6, 0xff}, {0x18, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */ + }, +}; + + + +struct inv_port_layout_s gulmohar_2t_evt1_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 10, 0, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 1, 11, 0, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 2, 12, 0, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 3, 13, 0, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 4, 14, 0, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 5, 15, 0, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 6, 16, 0, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 7, 17, 0, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 8, 18, 1, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + { 9, 19, 1, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {10, 20, 1, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {11, 21, 1, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {12, 22, 1, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {13, 23, 1, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {14, 24, 1, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {15, 25, 1, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {16, 26, 2, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {17, 27, 2, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {18, 28, 2, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {19, 29, 2, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {20, 30, 2, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {21, 31, 2, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {22, 32, 2, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {23, 33, 2, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {24, 34, 3, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {25, 35, 3, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {26, 36, 3, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {27, 37, 3, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {28, 38, 3, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {29, 39, 3, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {30, 40, 3, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {31, 41, 3, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {32, 42, 4, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {33, 43, 4, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {34, 44, 4, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {35, 45, 4, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {36, 46, 4, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {37, 47, 4, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {38, 48, 4, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {39, 49, 4, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {40, 50, 5, 0, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {41, 51, 5, 1, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {42, 52, 5, 2, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {43, 53, 5, 3, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {44, 54, 5, 4, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {45, 55, 5, 5, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {46, 56, 5, 6, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {47, 57, 5, 7, TRANSVR_TYPE_SFP, BF_CHIP_TYPE_TOFINO, {-99} }, + {48, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {-99,-99,-99,-99} }, + {49, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {-99,-99,-99,-99} }, + {50, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {-99,-99,-99,-99} }, + {51, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {-99,-99,-99,-99} }, + {52, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {-99,-99,-99,-99} }, + {53, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {-99,-99,-99,-99} }, + {54, 65, 6, 7, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {-99,-99,-99,-99} }, + {55, 64, 6, 6, TRANSVR_TYPE_QSFP_28, BF_CHIP_TYPE_TOFINO, {-99,-99,-99,-99} }, +}; +#endif + + +/* =========================================================== + * Peony-SFP Layout configuration + * =========================================================== + */ +#ifdef SWPS_PEONY_SFP +unsigned peony_sfp_gpio_rest_mux = MUX_RST_CPLD_C0_A77_70_74_RST_ALL; + +struct inv_ioexp_layout_s peony_sfp_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_QSFP_6P_LAYOUT_1, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 0 A */ + {4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, + {1, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {2, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {3, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {4, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {5, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, + {6, IOEXP_TYPE_SFP_8P_LAYOUT_1, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */ + {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */ + {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */ + }, +}; + +struct inv_port_layout_s peony_sfp_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + { 0, 20, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 1} }, + { 1, 21, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 2} }, + { 2, 22, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 3} }, + { 3, 23, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 4} }, + { 4, 24, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 5} }, + { 5, 25, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 6} }, + { 6, 26, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 7} }, + { 7, 27, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 8} }, + { 8, 28, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 13} }, + { 9, 29, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 14} }, + {10, 30, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 15} }, + {11, 31, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 16} }, + {12, 32, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 21} }, + {13, 33, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 22} }, + {14, 34, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 23} }, + {15, 35, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 24} }, + {16, 36, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 29} }, + {17, 37, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 30} }, + {18, 38, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 31} }, + {19, 39, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 32} }, + {20, 40, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 33} }, + {21, 41, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 34} }, + {22, 42, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 35} }, + {23, 43, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 36} }, + {24, 44, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 65} }, + {25, 45, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 66} }, + {26, 46, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 67} }, + {27, 47, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 68} }, + {28, 48, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 69} }, + {29, 49, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 70} }, + {30, 50, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 71} }, + {31, 51, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 72} }, + {32, 52, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 97} }, + {33, 53, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 98} }, + {34, 54, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, { 99} }, + {35, 55, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {100} }, + {36, 56, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {105} }, + {37, 57, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {106} }, + {38, 58, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {107} }, + {39, 59, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {108} }, + {40, 60, 6, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {113} }, + {41, 61, 6, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {114} }, + {42, 62, 6, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {115} }, + {43, 63, 6, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {116} }, + {44, 64, 6, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {121} }, + {45, 65, 6, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {122} }, + {46, 66, 6, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {123} }, + {47, 67, 6, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_3, {124} }, + {48, 12, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 49, 50, 51, 52} }, + {49, 13, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 57, 58, 59, 60} }, + {50, 14, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 61, 62, 63, 64} }, + {51, 15, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 77, 78, 79, 80} }, + {52, 16, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 85, 86, 87, 88} }, + {53, 17, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 93, 94, 95, 96} }, +}; +#endif + + +/* =========================================================== + * Peony-Copper Layout configuration + * =========================================================== + */ +#ifdef SWPS_PEONY_COPPER +unsigned peony_copper_gpio_rest_mux = MUX_RST_CPLD_C0_A77_70_74_RST_ALL; + +struct inv_ioexp_layout_s peony_copper_ioexp_layout[] = { + /* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */ + {0, IOEXP_TYPE_QSFP_6P_LAYOUT_1, { {10, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 0 A */ + {10, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xff}, }, /* addr[1] = I/O Expander 0 B */ + {10, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */ + }, +}; + +struct inv_port_layout_s peony_copper_port_layout[] = { + /* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */ + {48, 4, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 49, 50, 51, 52} }, + {49, 5, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 57, 58, 59, 60} }, + {50, 6, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 61, 62, 63, 64} }, + {51, 7, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 77, 78, 79, 80} }, + {52, 8, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 85, 86, 87, 88} }, + {53, 9, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TRIDENT_3, { 93, 94, 95, 96} }, +}; +#endif + + + #endif /* INV_SWPS_H */ @@ -1162,3 +1617,5 @@ struct inv_port_layout_s maple_port_layout[] = { + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.c index 4564b5855f..985bfbb45e 100644 --- a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.c +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.c @@ -2,9 +2,14 @@ #include #include "io_expander.h" +/* For build single module using (Ex: ONL platform) */ +#include +//#include + + static struct ioexp_obj_s *ioexp_head_p = NULL; static struct ioexp_obj_s *ioexp_tail_p = NULL; - +extern int io_no_init; /* ========== Register IOEXP layout ========== */ @@ -571,6 +576,7 @@ struct ioexp_map_s cpld_map_cottonwood = { }, }; + struct ioexp_map_s ioexp_map_maple_0abc = { .chip_amount = 3, @@ -614,6 +620,7 @@ struct ioexp_map_s ioexp_map_maple_0abc = { }, }; + struct ioexp_map_s ioexp_map_maple_nabc = { .chip_amount = 3, @@ -675,6 +682,440 @@ struct ioexp_map_s ioexp_map_maple_nabc = { }, }; + +struct ioexp_map_s ioexp_map_gulmohar_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 4}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 1, 5}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 1, 4}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 1, 5}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 0, 2}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 0, 3}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 0, 2}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 3}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 1, 0}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 1, 1}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 0}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 1}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 0, 6}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 0, 7}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 0, 6}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 0, 7}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_gulmohar_7abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + }, + .map_reset = { {0, 1, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + }, +}; + + +struct ioexp_map_s ioexp_map_gulmohar_2t_evt1_nabc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 2}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 6}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 1, 6}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 2}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 6}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 1, 2}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 1, 6}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 0, 1}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 0, 5}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 1}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 5}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 0, 1}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 5}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 1}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 5}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 4}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 1, 0}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 1, 4}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 4}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 0}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 4}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 0, 3}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 0, 7}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 3}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 0, 3}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 0, 7}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 3}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_gulmohar_2t_evt1_1abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 2}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 6}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 1, 6}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 1, 4}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 1, 5}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 0, 1}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 0, 5}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 1}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 5}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 0, 2}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 3}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 4}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 1, 0}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 1, 4}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 0}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 1}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 0, 3}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 0, 7}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 3}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 0, 6}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 0, 7}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +struct ioexp_map_s ioexp_map_gulmohar_2t_evt1_3abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 4}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 1, 5}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 2}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 6}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 1, 2}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 1, 6}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 0, 2}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 0, 3}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 0, 1}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 0, 5}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 1}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 5}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 1, 0}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 1, 1}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 4}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 1, 0}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 1, 4}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 0, 6}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 0, 7}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 0, 3}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 0, 7}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 3}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + + +struct ioexp_map_s ioexp_map_gulmohar_2t_evt1_7abc = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 1, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {1, 0, 4}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 1, 1}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 1, 6}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {2, 0, 4}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {2, 1, 1}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_reset = { {0, 0, 1}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 0, 6}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 3}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {1, 0, 1}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {1, 0, 6}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {1, 1, 3}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + {2, 0, 1}, /* map_reset[6] = QRESET_QSFP_N_P(X+6) */ + {2, 0, 6}, /* map_reset[7] = QRESET_QSFP_N_P(X+7) */ + }, + .map_lpmod = { {0, 0, 2}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {0, 0, 7}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {0, 1, 4}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {1, 0, 2}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 7}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 1, 4}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + {2, 0, 2}, /* map_lpmod[6] = LPMODE_QSFP_P(X+6) */ + {2, 0, 7}, /* map_lpmod[7] = LPMODE_QSFP_P(X+7) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 5}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {1, 0, 0}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {1, 0, 5}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {1, 1, 2}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + {2, 0, 0}, /* map_modsel[6] = MODSEL_QSFP_N_P(X+6) */ + {2, 0, 5}, /* map_modsel[7] = MODSEL_QSFP_N_P(X+7) */ + }, +}; + + +/* PortType: SFP / 8 port + * Platform: Cypress, Peony_SFP + */ +struct ioexp_map_s ioexp_map_sfp_8p_layout_1 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {0, 0, 4}, /* map_present[0] = MOD_ABS_PORT(X) */ + {0, 0, 5}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {0, 0, 6}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {0, 0, 7}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {1, 0, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {1, 0, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + {1, 0, 6}, /* map_present[6] = MOD_ABS_PORT(X+6) */ + {1, 0, 7}, /* map_present[7] = MOD_ABS_PORT(X+7) */ + }, + .map_tx_disable = { {0, 1, 0}, /* map_tx_disable[0] = TXDISABLE_SFP+_P(X) */ + {0, 1, 1}, /* map_tx_disable[1] = TXDISABLE_SFP+_P(X+1) */ + {0, 1, 2}, /* map_tx_disable[2] = TXDISABLE_SFP+_P(X+2) */ + {0, 1, 3}, /* map_tx_disable[3] = TXDISABLE_SFP+_P(X+3) */ + {1, 1, 0}, /* map_tx_disable[4] = TXDISABLE_SFP+_P(X+4) */ + {1, 1, 1}, /* map_tx_disable[5] = TXDISABLE_SFP+_P(X+5) */ + {1, 1, 2}, /* map_tx_disable[6] = TXDISABLE_SFP+_P(X+6) */ + {1, 1, 3}, /* map_tx_disable[7] = TXDISABLE_SFP+_P(X+7) */ + }, + .map_tx_fault = { {0, 0, 0}, /* map_tx_fault[0] = TXFAULT_SFP+_P(X) */ + {0, 0, 1}, /* map_tx_fault[1] = TXFAULT_SFP+_P(X+1) */ + {0, 0, 2}, /* map_tx_fault[2] = TXFAULT_SFP+_P(X+2) */ + {0, 0, 3}, /* map_tx_fault[3] = TXFAULT_SFP+_P(X+3) */ + {1, 0, 0}, /* map_tx_fault[4] = TXFAULT_SFP+_P(X+4) */ + {1, 0, 1}, /* map_tx_fault[5] = TXFAULT_SFP+_P(X+5) */ + {1, 0, 2}, /* map_tx_fault[6] = TXFAULT_SFP+_P(X+6) */ + {1, 0, 3}, /* map_tx_fault[7] = TXFAULT_SFP+_P(X+7) */ + }, + .map_rxlos = { {0, 1, 4}, /* map_rxlos[0] = OPRXLOS_PORT(X) */ + {0, 1, 5}, /* map_rxlos[1] = OPRXLOS_PORT(X+1) */ + {0, 1, 6}, /* map_rxlos[2] = OPRXLOS_PORT(X+2) */ + {0, 1, 7}, /* map_rxlos[3] = OPRXLOS_PORT(X+3) */ + {1, 1, 4}, /* map_rxlos[4] = OPRXLOS_PORT(X+4) */ + {1, 1, 5}, /* map_rxlos[5] = OPRXLOS_PORT(X+5) */ + {1, 1, 6}, /* map_rxlos[6] = OPRXLOS_PORT(X+6) */ + {1, 1, 7}, /* map_rxlos[7] = OPRXLOS_PORT(X+7) */ + }, + .map_hard_rs0 = { {2, 0, 0}, /* map_hard_rs0[0] = RS0_SFP28_P(X) */ + {2, 0, 2}, /* map_hard_rs0[1] = RS0_SFP28_P(X+1) */ + {2, 0, 4}, /* map_hard_rs0[2] = RS0_SFP28_P(X+2) */ + {2, 0, 6}, /* map_hard_rs0[3] = RS0_SFP28_P(X+3) */ + {2, 1, 0}, /* map_hard_rs0[4] = RS0_SFP28_P(X+4) */ + {2, 1, 2}, /* map_hard_rs0[5] = RS0_SFP28_P(X+5) */ + {2, 1, 4}, /* map_hard_rs0[6] = RS0_SFP28_P(X+6) */ + {2, 1, 6}, /* map_hard_rs0[7] = RS0_SFP28_P(X+7) */ + }, + .map_hard_rs1 = { {2, 0, 1}, /* map_hard_rs1[0] = RS1_SFP28_P(X) */ + {2, 0, 3}, /* map_hard_rs1[1] = RS1_SFP28_P(X+1) */ + {2, 0, 5}, /* map_hard_rs1[2] = RS1_SFP28_P(X+2) */ + {2, 0, 7}, /* map_hard_rs1[3] = RS1_SFP28_P(X+3) */ + {2, 1, 1}, /* map_hard_rs1[4] = RS1_SFP28_P(X+4) */ + {2, 1, 3}, /* map_hard_rs1[5] = RS1_SFP28_P(X+5) */ + {2, 1, 5}, /* map_hard_rs1[6] = RS1_SFP28_P(X+6) */ + {2, 1, 7}, /* map_hard_rs1[7] = RS1_SFP28_P(X+7) */ + }, +}; + + +/* PortType: QSFP / 6 port + * Platform: Gulmohar, Peony_SFP, Peony_Copper + */ +struct ioexp_map_s ioexp_map_6p_qsfp_type_1 = { + + .chip_amount = 3, + .data_width = 2, + + .map_present = { {2, 1, 0}, /* map_present[0] = MOD_ABS_PORT(X) */ + {2, 1, 1}, /* map_present[1] = MOD_ABS_PORT(X+1) */ + {2, 1, 2}, /* map_present[2] = MOD_ABS_PORT(X+2) */ + {2, 1, 3}, /* map_present[3] = MOD_ABS_PORT(X+3) */ + {2, 1, 4}, /* map_present[4] = MOD_ABS_PORT(X+4) */ + {2, 1, 5}, /* map_present[5] = MOD_ABS_PORT(X+5) */ + }, + .map_reset = { {0, 1, 0}, /* map_reset[0] = QRESET_QSFP_N_P(X) */ + {0, 1, 1}, /* map_reset[1] = QRESET_QSFP_N_P(X+1) */ + {0, 1, 2}, /* map_reset[2] = QRESET_QSFP_N_P(X+2) */ + {0, 1, 3}, /* map_reset[3] = QRESET_QSFP_N_P(X+3) */ + {0, 1, 4}, /* map_reset[4] = QRESET_QSFP_N_P(X+4) */ + {0, 1, 5}, /* map_reset[5] = QRESET_QSFP_N_P(X+5) */ + }, + .map_lpmod = { {1, 0, 0}, /* map_lpmod[0] = LPMODE_QSFP_P(X) */ + {1, 0, 1}, /* map_lpmod[1] = LPMODE_QSFP_P(X+1) */ + {1, 0, 2}, /* map_lpmod[2] = LPMODE_QSFP_P(X+2) */ + {1, 0, 3}, /* map_lpmod[3] = LPMODE_QSFP_P(X+3) */ + {1, 0, 4}, /* map_lpmod[4] = LPMODE_QSFP_P(X+4) */ + {1, 0, 5}, /* map_lpmod[5] = LPMODE_QSFP_P(X+5) */ + }, + .map_modsel = { {0, 0, 0}, /* map_modsel[0] = MODSEL_QSFP_N_P(X) */ + {0, 0, 1}, /* map_modsel[1] = MODSEL_QSFP_N_P(X+1) */ + {0, 0, 2}, /* map_modsel[2] = MODSEL_QSFP_N_P(X+2) */ + {0, 0, 3}, /* map_modsel[3] = MODSEL_QSFP_N_P(X+3) */ + {0, 0, 4}, /* map_modsel[4] = MODSEL_QSFP_N_P(X+4) */ + {0, 0, 5}, /* map_modsel[5] = MODSEL_QSFP_N_P(X+5) */ + }, +}; + + /* ========== Private functions ========== */ int check_channel_tier_1(void); @@ -1125,32 +1566,35 @@ common_ioexp_init(struct ioexp_obj_s *self) { if (self->mode == IOEXP_MODE_DIRECT) { goto update_common_ioexp_init; } - /* Setup default value to each physical IO Expander */ - for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ - /* Get address mapping */ - addr_p = &(self->ioexp_map_p->map_addr[chip_id]); - if (!addr_p){ - SWPS_ERR("%s: IOEXP config incorrect! :%d \n", - __func__, chip_id); - return -1; - } - /* Setup default value */ - for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){ - - /* [Desc] Skip the setup default value behavior - [Note] Setup default value = -1 if you don't want to write the value to IOEXP or CPLD - */ - if(addr_p->write_offset[offset] < 0){ - SWPS_DEBUG("skip a write_offset <%d>\n", addr_p->conf_offset[offset]); - continue; + if (!io_no_init) { /*normal init*/ + + /* Setup default value to each physical IO Expander */ + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ + /* Get address mapping */ + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + SWPS_ERR("%s: IOEXP config incorrect! :%d \n", + __func__, chip_id); + return -1; } - err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id), - addr_p->write_offset[offset], - addr_p->data_default[offset]); - if (err_code < 0){ - SWPS_ERR("%s: set default fail! :%d \n", - __func__, err_code); - return ERR_IOEXP_UNEXCPT; + /* Setup default value */ + for (offset=0; offset<(self->ioexp_map_p->data_width); offset++){ + + /* [Desc] Skip the setup default value behavior + [Note] Setup default value = -1 if you don't want to write the value to IOEXP or CPLD + */ + if(addr_p->write_offset[offset] < 0){ + SWPS_DEBUG("skip a write_offset <%d>\n", addr_p->conf_offset[offset]); + continue; + } + err_code = i2c_smbus_write_byte_data(_get_i2c_client(self, chip_id), + addr_p->write_offset[offset], + addr_p->data_default[offset]); + if (err_code < 0){ + SWPS_ERR("%s: set default fail! :%d \n", + __func__, err_code); + return ERR_IOEXP_UNEXCPT; + } } } } @@ -1171,24 +1615,56 @@ update_common_ioexp_init: int _is_channel_ready(struct ioexp_obj_s *self){ - int buf = 0; - int chip_id = 0; /* Use first chip which be registered */ - int data_id = 0; /* Use first byte which be registered */ - struct ioexp_addr_s *ioexp_addr = NULL; + int chip_id = 0; + int byte_id = 0; + int getval = ERR_IOEXP_UNEXCPT; + int chkval = ERR_IOEXP_UNEXCPT; + char *emsg = "ERR"; + struct ioexp_addr_s *addr_p = NULL; - ioexp_addr = &(self->ioexp_map_p->map_addr[chip_id]); - if (!ioexp_addr){ - SWPS_ERR("%s: config incorrect!\n", __func__); - return ERR_IOEXP_UNEXCPT; + for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++) { + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + if (!addr_p){ + emsg = "IOEXP config incorrect"; + goto err_is_channel_ready; + } + for (byte_id=0; byte_id<(self->ioexp_map_p->data_width); byte_id++) { + if (addr_p->conf_offset[byte_id] < 0) { + continue; + } + if ((addr_p->conf_default[byte_id]) != 0) { + goto go_is_channel_ready; + } + } + if (chip_id == ((self->ioexp_map_p->chip_amount) - 1)) { + SWPS_DEBUG("%s: no non-zero config", __func__); + break; + } } - buf = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), - ioexp_addr->read_offset[data_id]); - if (buf >= 0){ + chip_id = 0; + byte_id = 0; + +go_is_channel_ready: + addr_p = &(self->ioexp_map_p->map_addr[chip_id]); + chkval = addr_p->conf_default[byte_id]; + getval = i2c_smbus_read_byte_data(_get_i2c_client(self, chip_id), + addr_p->conf_offset[byte_id]); + + SWPS_DEBUG("%s: target info :%d :%d :%d :%d :%d\n", + __func__, self->ioexp_id, chip_id, byte_id, chkval, getval); + + if ((getval >= 0) && (getval == chkval)) { return 1; } return 0; + +err_is_channel_ready: + SWPS_ERR("%s: %s :%d :%d :%d :%d :%d\n", + __func__, emsg, self->ioexp_id, chip_id, byte_id, chkval, getval); + return ERR_IOEXP_UNEXCPT; } + int _ioexp_init_handler(struct ioexp_obj_s *self){ @@ -1395,8 +1871,6 @@ get_ioexp_map(int ioexp_type){ return &ioexp_map_hudson32iga_p01p08_p17p24; case IOEXP_TYPE_HUDSON32IGA_P09P16: return &ioexp_map_hudson32iga_p09p16_p25p32; - case IOEXP_TYPE_CYPRESS_NABC: - return &ioexp_map_cypress_nabc; case IOEXP_TYPE_CYPRESS_7ABC: return &ioexp_map_cypress_7abc; case IOEXP_TYPE_TAHOE_5A: @@ -1413,6 +1887,22 @@ get_ioexp_map(int ioexp_type){ return &ioexp_map_maple_0abc; case IOEXP_TYPE_MAPLE_NABC: return &ioexp_map_maple_nabc; + case IOEXP_TYPE_GULMOHAR_NABC: + return &ioexp_map_gulmohar_nabc; + case IOEXP_TYPE_GULMOHAR_7ABC: + return &ioexp_map_gulmohar_7abc; + case IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC: + return &ioexp_map_gulmohar_2t_evt1_nabc; + case IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC: + return &ioexp_map_gulmohar_2t_evt1_1abc; + case IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC: + return &ioexp_map_gulmohar_2t_evt1_3abc; + case IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC: + return &ioexp_map_gulmohar_2t_evt1_7abc; + case IOEXP_TYPE_SFP_8P_LAYOUT_1: + return &ioexp_map_sfp_8p_layout_1; + case IOEXP_TYPE_QSFP_6P_LAYOUT_1: + return &ioexp_map_6p_qsfp_type_1; default: return NULL; } @@ -1497,8 +1987,13 @@ setup_ioexp_public_cb(struct ioexp_obj_s *self, self->set_hard_rs0 = ioexp_set_not_support; self->set_hard_rs1 = ioexp_set_not_support; return 0; - case IOEXP_TYPE_CYPRESS_NABC: + case IOEXP_TYPE_MAPLE_NABC: + case IOEXP_TYPE_GULMOHAR_NABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC: + case IOEXP_TYPE_SFP_8P_LAYOUT_1: self->get_present = common_get_present; self->get_tx_fault = common_get_tx_fault; self->get_rxlos = common_get_rxlos; @@ -1515,6 +2010,7 @@ setup_ioexp_public_cb(struct ioexp_obj_s *self, self->set_hard_rs0 = common_set_hard_rs0; self->set_hard_rs1 = common_set_hard_rs1; return 0; + case IOEXP_TYPE_MAGINOLIA_7AB: case IOEXP_TYPE_SPRUCE_7AB: case IOEXP_TYPE_REDWOOD_P01P08: @@ -1527,6 +2023,9 @@ setup_ioexp_public_cb(struct ioexp_obj_s *self, case IOEXP_TYPE_SEQUOIA_NABC: case IOEXP_TYPE_LAVENDER_P65: case IOEXP_TYPE_MAPLE_0ABC: + case IOEXP_TYPE_GULMOHAR_7ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC: + case IOEXP_TYPE_QSFP_6P_LAYOUT_1: self->get_present = common_get_present; self->get_tx_fault = ioexp_get_not_support; self->get_rxlos = ioexp_get_not_support; @@ -1565,7 +2064,6 @@ setup_ioexp_private_cb(struct ioexp_obj_s *self, case IOEXP_TYPE_REDWOOD_P09P16: case IOEXP_TYPE_HUDSON32IGA_P01P08: case IOEXP_TYPE_HUDSON32IGA_P09P16: - case IOEXP_TYPE_CYPRESS_NABC: case IOEXP_TYPE_CYPRESS_7ABC: case IOEXP_TYPE_TAHOE_5A: case IOEXP_TYPE_TAHOE_6ABC: @@ -1574,6 +2072,14 @@ setup_ioexp_private_cb(struct ioexp_obj_s *self, case CPLD_TYPE_COTTONWOOD: case IOEXP_TYPE_MAPLE_NABC: case IOEXP_TYPE_MAPLE_0ABC: + case IOEXP_TYPE_GULMOHAR_NABC: + case IOEXP_TYPE_GULMOHAR_7ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC: + case IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC: + case IOEXP_TYPE_SFP_8P_LAYOUT_1: + case IOEXP_TYPE_QSFP_6P_LAYOUT_1: self->init = common_ioexp_init; self->check = common_ioexp_check; self->update_all = common_ioexp_update_all; @@ -1600,11 +2106,6 @@ setup_i2c_client_one(struct ioexp_obj_s *self, struct ioexp_i2c_s *i2c_curr_p = NULL; int chan_id = self->ioexp_map_p->map_addr[chip_id].chan_id; - adap = i2c_get_adapter(chan_id); - if(!adap){ - err_msg = "Can not get adap!"; - goto err_ioexp_setup_i2c_1; - } client = kzalloc(sizeof(*client), GFP_KERNEL); if (!client){ err_msg = "Can not kzalloc client!"; @@ -1615,6 +2116,11 @@ setup_i2c_client_one(struct ioexp_obj_s *self, err_msg = "Can not kzalloc i2c_obj_p!"; goto err_ioexp_setup_i2c_2; } + adap = i2c_get_adapter(chan_id); + if(!adap){ + err_msg = "Can not get adap!"; + goto err_ioexp_setup_i2c_3; + } client->adapter = adap; client->addr = self->ioexp_map_p->map_addr[chip_id].chip_addr; i2c_obj_p->i2c_client_p = client; @@ -1631,6 +2137,8 @@ setup_i2c_client_one(struct ioexp_obj_s *self, } return 0; +err_ioexp_setup_i2c_3: + kfree(i2c_obj_p); err_ioexp_setup_i2c_2: kfree(client); err_ioexp_setup_i2c_1: @@ -1661,6 +2169,11 @@ setup_ioexp_config(struct ioexp_obj_s *self) { int chip_id, offset, err_code; struct ioexp_addr_s *addr_p; + if (io_no_init) { + + SWPS_INFO("io_no_init:%d \n", io_no_init); + return 0; + } for (chip_id=0; chip_id<(self->ioexp_map_p->chip_amount); chip_id++){ addr_p = &(self->ioexp_map_p->map_addr[chip_id]); @@ -1743,7 +2256,10 @@ err_create_ioexp_setup_i2c_fail: i2c_next_p = result_p->i2c_head_p; while (i2c_curr_p){ i2c_next_p = i2c_curr_p->next; - kfree(i2c_curr_p->i2c_client_p); + if (i2c_curr_p->i2c_client_p) { + i2c_put_adapter(i2c_curr_p->i2c_client_p->adapter); + kfree(i2c_curr_p->i2c_client_p); + } kfree(i2c_curr_p); i2c_curr_p = i2c_next_p; } @@ -1778,6 +2294,7 @@ create_ioexp_obj(int ioexp_id, ioexp_tail_p = ioexp_p; return 0; } +EXPORT_SYMBOL(create_ioexp_obj); static int @@ -1818,7 +2335,6 @@ init_ioexp_objs(void){ * -1: Detect topology error * -2: SWPS internal error */ - struct ioexp_obj_s *curr_p = ioexp_head_p; if (!curr_p) { @@ -1835,6 +2351,7 @@ init_ioexp_objs(void){ SWPS_DEBUG("%s: done.\n", __func__); return 0; } +EXPORT_SYMBOL(init_ioexp_objs); void @@ -1861,7 +2378,10 @@ clean_ioexp_objs(void){ i2c_curr_p = ioexp_curr_p->i2c_head_p; while (i2c_curr_p) { i2c_next_p = i2c_curr_p->next; - kfree(i2c_curr_p->i2c_client_p); + if (i2c_curr_p->i2c_client_p) { + i2c_put_adapter(i2c_curr_p->i2c_client_p->adapter); + kfree(i2c_curr_p->i2c_client_p); + } kfree(i2c_curr_p); i2c_curr_p = i2c_next_p; } @@ -1871,6 +2391,7 @@ clean_ioexp_objs(void){ ioexp_tail_p = NULL; SWPS_DEBUG("%s: done.\n", __func__); } +EXPORT_SYMBOL(clean_ioexp_objs); int @@ -1888,6 +2409,7 @@ check_ioexp_objs(void){ } return 0; } +EXPORT_SYMBOL(check_ioexp_objs); struct ioexp_obj_s * @@ -1905,6 +2427,7 @@ get_ioexp_obj(int ioexp_id){ } return result_p; } +EXPORT_SYMBOL(get_ioexp_obj); void @@ -1917,7 +2440,7 @@ unlock_ioexp_all(void) { ioexp_curr_p = ioexp_curr_p->next; } } - +EXPORT_SYMBOL(unlock_ioexp_all); int lock_ioexp_all(void) { @@ -1930,6 +2453,7 @@ lock_ioexp_all(void) { } return 0; } +EXPORT_SYMBOL(lock_ioexp_all); int @@ -1941,6 +2465,7 @@ check_channel_tier_1(void) { } return 0; } +EXPORT_SYMBOL(check_channel_tier_1); static int @@ -2037,10 +2562,11 @@ err_resync_ioexp_status_1: SWPS_ERR("%s: %s\n", __func__, emsg); return -1; } - - - - +EXPORT_SYMBOL(resync_channel_tier_1); + + +/* For build single module using (Ex: ONL platform) */ +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.h b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.h index 1af909e246..6f9f7b4629 100644 --- a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.h +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/io_expander.h @@ -1,10 +1,3 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - #ifndef IO_EXPANDER_H #define IO_EXPANDER_H @@ -12,24 +5,31 @@ /* IOEXP type define (SFP series) */ -#define IOEXP_TYPE_MAGINOLIA_NAB (10101) -#define IOEXP_TYPE_MAGINOLIA_4AB (10102) -#define IOEXP_TYPE_CYPRESS_NABC (10103) -#define IOEXP_TYPE_MAPLE_NABC (10104) +#define IOEXP_TYPE_MAGINOLIA_NAB (10101) +#define IOEXP_TYPE_MAGINOLIA_4AB (10102) +#define IOEXP_TYPE_MAPLE_NABC (10104) +#define IOEXP_TYPE_GULMOHAR_NABC (10105) +#define IOEXP_TYPE_GULMOHAR_2T_EVT1_NABC (10106) +#define IOEXP_TYPE_SFP_8P_LAYOUT_1 (10107) +#define IOEXP_TYPE_GULMOHAR_2T_EVT1_1ABC (10108) +#define IOEXP_TYPE_GULMOHAR_2T_EVT1_3ABC (10109) /* IOEXP type define (QSFP series) */ -#define IOEXP_TYPE_MAGINOLIA_7AB (10201) -#define IOEXP_TYPE_REDWOOD_P01P08 (10202) -#define IOEXP_TYPE_REDWOOD_P09P16 (10203) -#define IOEXP_TYPE_HUDSON32IGA_P01P08 (10204) -#define IOEXP_TYPE_HUDSON32IGA_P09P16 (10205) -#define IOEXP_TYPE_SPRUCE_7AB (10206) -#define IOEXP_TYPE_CYPRESS_7ABC (10207) -#define IOEXP_TYPE_TAHOE_5A (10208) -#define IOEXP_TYPE_TAHOE_6ABC (10209) -#define IOEXP_TYPE_SEQUOIA_NABC (10210) -#define IOEXP_TYPE_LAVENDER_P65 (10211) -#define IOEXP_TYPE_MAPLE_0ABC (10212) +#define IOEXP_TYPE_MAGINOLIA_7AB (10201) +#define IOEXP_TYPE_REDWOOD_P01P08 (10202) +#define IOEXP_TYPE_REDWOOD_P09P16 (10203) +#define IOEXP_TYPE_HUDSON32IGA_P01P08 (10204) +#define IOEXP_TYPE_HUDSON32IGA_P09P16 (10205) +#define IOEXP_TYPE_SPRUCE_7AB (10206) +#define IOEXP_TYPE_CYPRESS_7ABC (10207) +#define IOEXP_TYPE_TAHOE_5A (10208) +#define IOEXP_TYPE_TAHOE_6ABC (10209) +#define IOEXP_TYPE_SEQUOIA_NABC (10210) +#define IOEXP_TYPE_LAVENDER_P65 (10211) +#define IOEXP_TYPE_MAPLE_0ABC (10212) +#define IOEXP_TYPE_GULMOHAR_7ABC (10213) +#define IOEXP_TYPE_GULMOHAR_2T_EVT1_7ABC (10214) +#define IOEXP_TYPE_QSFP_6P_LAYOUT_1 (10215) /* CPLD type define */ #define CPLD_TYPE_COTTONWOOD (10301) @@ -87,8 +87,8 @@ struct ioexp_bitmap_s { }; struct ioexp_map_s { - int chip_amount; /* Number of chips that IOEXP object content */ - int data_width; /* Number of (Read/Write/Config) bytes */ + int chip_amount; /* Number of chips that IOEXP object content */ + int data_width; /* Number of (Read/Write/Config) bytes */ struct ioexp_addr_s *map_addr; /* Chip address info */ struct ioexp_bitmap_s map_present[10]; /* IOEXP for SFP / QSFP */ struct ioexp_bitmap_s map_tx_disable[10]; /* IOEXP for SFP */ @@ -185,3 +185,5 @@ int resync_channel_tier_1(void); + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/lpc_ich.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/lpc_ich.c new file mode 100644 index 0000000000..66ff6e694d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/lpc_ich.c @@ -0,0 +1,1131 @@ +/* + * lpc_ich.c - LPC interface for Intel ICH + * + * LPC bridge function of the Intel ICH contains many other + * functional units, such as Interrupt controllers, Timers, + * Power Management, System Management, GPIO, RTC, and LPC + * Configuration Registers. + * + * This driver is derived from lpc_sch. + + * Copyright (c) 2011 Extreme Engineering Solution, Inc. + * Author: Aaron Sierra + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * This driver supports the following I/O Controller hubs: + * (See the intel documentation on http://developer.intel.com.) + * document number 290655-003, 290677-014: 82801AA (ICH), 82801AB (ICHO) + * document number 290687-002, 298242-027: 82801BA (ICH2) + * document number 290733-003, 290739-013: 82801CA (ICH3-S) + * document number 290716-001, 290718-007: 82801CAM (ICH3-M) + * document number 290744-001, 290745-025: 82801DB (ICH4) + * document number 252337-001, 252663-008: 82801DBM (ICH4-M) + * document number 273599-001, 273645-002: 82801E (C-ICH) + * document number 252516-001, 252517-028: 82801EB (ICH5), 82801ER (ICH5R) + * document number 300641-004, 300884-013: 6300ESB + * document number 301473-002, 301474-026: 82801F (ICH6) + * document number 313082-001, 313075-006: 631xESB, 632xESB + * document number 307013-003, 307014-024: 82801G (ICH7) + * document number 322896-001, 322897-001: NM10 + * document number 313056-003, 313057-017: 82801H (ICH8) + * document number 316972-004, 316973-012: 82801I (ICH9) + * document number 319973-002, 319974-002: 82801J (ICH10) + * document number 322169-001, 322170-003: 5 Series, 3400 Series (PCH) + * document number 320066-003, 320257-008: EP80597 (IICH) + * document number 324645-001, 324646-001: Cougar Point (CPT) + * document number TBD : Patsburg (PBG) + * document number TBD : DH89xxCC + * document number TBD : Panther Point + * document number TBD : Lynx Point + * document number TBD : Lynx Point-LP + * document number TBD : Wellsburg + * document number TBD : Avoton SoC + * document number TBD : Coleto Creek + * document number TBD : Wildcat Point-LP + * document number TBD : 9 Series + * document number TBD : Lewisburg + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#define ACPIBASE 0x40 +#define ACPIBASE_GPE_OFF 0x28 +#define ACPIBASE_GPE_END 0x2f +#define ACPIBASE_SMI_OFF 0x30 +#define ACPIBASE_SMI_END 0x33 +#define ACPIBASE_PMC_OFF 0x08 +#define ACPIBASE_PMC_END 0x0c +#define ACPIBASE_TCO_OFF 0x60 +#define ACPIBASE_TCO_END 0x7f +#define ACPICTRL_PMCBASE 0x44 + +#define ACPIBASE_GCS_OFF 0x3410 +#define ACPIBASE_GCS_END 0x3414 + +#define GPIOBASE_ICH0 0x58 +#define GPIOCTRL_ICH0 0x5C +#define GPIOBASE_ICH6 0x48 +#define GPIOCTRL_ICH6 0x4C + +#define RCBABASE 0xf0 + +#define wdt_io_res(i) wdt_res(0, i) +#define wdt_mem_res(i) wdt_res(ICH_RES_MEM_OFF, i) +#define wdt_res(b, i) (&wdt_ich_res[(b) + (i)]) + +struct lpc_ich_priv { + int chipset; + + int abase; /* ACPI base */ + int actrl_pbase; /* ACPI control or PMC base */ + int gbase; /* GPIO base */ + int gctrl; /* GPIO control */ + + int abase_save; /* Cached ACPI base value */ + int actrl_pbase_save; /* Cached ACPI control or PMC base value */ + int gctrl_save; /* Cached GPIO control value */ +}; + +static struct resource wdt_ich_res[] = { + /* ACPI - TCO */ + { + .flags = IORESOURCE_IO, + }, + /* ACPI - SMI */ + { + .flags = IORESOURCE_IO, + }, + /* GCS or PMC */ + { + .flags = IORESOURCE_MEM, + }, +}; + +static struct resource gpio_ich_res[] = { + /* GPIO */ + { + .flags = IORESOURCE_IO, + }, + /* ACPI - GPE0 */ + { + .flags = IORESOURCE_IO, + }, +}; + +static struct mfd_cell lpc_ich_wdt_cell = { + .name = "iTCO_wdt", + .num_resources = ARRAY_SIZE(wdt_ich_res), + .resources = wdt_ich_res, + .ignore_resource_conflicts = true, +}; + +static struct mfd_cell lpc_ich_gpio_cell = { + .name = "gpio_ich", + .num_resources = ARRAY_SIZE(gpio_ich_res), + .resources = gpio_ich_res, + .ignore_resource_conflicts = true, +}; + +/* chipset related info */ +enum lpc_chipsets { + LPC_ICH = 0, /* ICH */ + LPC_ICH0, /* ICH0 */ + LPC_ICH2, /* ICH2 */ + LPC_ICH2M, /* ICH2-M */ + LPC_ICH3, /* ICH3-S */ + LPC_ICH3M, /* ICH3-M */ + LPC_ICH4, /* ICH4 */ + LPC_ICH4M, /* ICH4-M */ + LPC_CICH, /* C-ICH */ + LPC_ICH5, /* ICH5 & ICH5R */ + LPC_6300ESB, /* 6300ESB */ + LPC_ICH6, /* ICH6 & ICH6R */ + LPC_ICH6M, /* ICH6-M */ + LPC_ICH6W, /* ICH6W & ICH6RW */ + LPC_631XESB, /* 631xESB/632xESB */ + LPC_ICH7, /* ICH7 & ICH7R */ + LPC_ICH7DH, /* ICH7DH */ + LPC_ICH7M, /* ICH7-M & ICH7-U */ + LPC_ICH7MDH, /* ICH7-M DH */ + LPC_NM10, /* NM10 */ + LPC_ICH8, /* ICH8 & ICH8R */ + LPC_ICH8DH, /* ICH8DH */ + LPC_ICH8DO, /* ICH8DO */ + LPC_ICH8M, /* ICH8M */ + LPC_ICH8ME, /* ICH8M-E */ + LPC_ICH9, /* ICH9 */ + LPC_ICH9R, /* ICH9R */ + LPC_ICH9DH, /* ICH9DH */ + LPC_ICH9DO, /* ICH9DO */ + LPC_ICH9M, /* ICH9M */ + LPC_ICH9ME, /* ICH9M-E */ + LPC_ICH10, /* ICH10 */ + LPC_ICH10R, /* ICH10R */ + LPC_ICH10D, /* ICH10D */ + LPC_ICH10DO, /* ICH10DO */ + LPC_PCH, /* PCH Desktop Full Featured */ + LPC_PCHM, /* PCH Mobile Full Featured */ + LPC_P55, /* P55 */ + LPC_PM55, /* PM55 */ + LPC_H55, /* H55 */ + LPC_QM57, /* QM57 */ + LPC_H57, /* H57 */ + LPC_HM55, /* HM55 */ + LPC_Q57, /* Q57 */ + LPC_HM57, /* HM57 */ + LPC_PCHMSFF, /* PCH Mobile SFF Full Featured */ + LPC_QS57, /* QS57 */ + LPC_3400, /* 3400 */ + LPC_3420, /* 3420 */ + LPC_3450, /* 3450 */ + LPC_EP80579, /* EP80579 */ + LPC_CPT, /* Cougar Point */ + LPC_CPTD, /* Cougar Point Desktop */ + LPC_CPTM, /* Cougar Point Mobile */ + LPC_PBG, /* Patsburg */ + LPC_DH89XXCC, /* DH89xxCC */ + LPC_PPT, /* Panther Point */ + LPC_LPT, /* Lynx Point */ + LPC_LPT_LP, /* Lynx Point-LP */ + LPC_WBG, /* Wellsburg */ + LPC_AVN, /* Avoton SoC */ + LPC_BAYTRAIL, /* Bay Trail SoC */ + LPC_COLETO, /* Coleto Creek */ + LPC_WPT_LP, /* Wildcat Point-LP */ + LPC_BRASWELL, /* Braswell SoC */ + LPC_LEWISBURG, /* Lewisburg */ + LPC_9S, /* 9 Series */ +}; + +static struct lpc_ich_info lpc_chipset_info[] = { + [LPC_ICH] = { + .name = "ICH", + .iTCO_version = 1, + }, + [LPC_ICH0] = { + .name = "ICH0", + .iTCO_version = 1, + }, + [LPC_ICH2] = { + .name = "ICH2", + .iTCO_version = 1, + }, + [LPC_ICH2M] = { + .name = "ICH2-M", + .iTCO_version = 1, + }, + [LPC_ICH3] = { + .name = "ICH3-S", + .iTCO_version = 1, + }, + [LPC_ICH3M] = { + .name = "ICH3-M", + .iTCO_version = 1, + }, + [LPC_ICH4] = { + .name = "ICH4", + .iTCO_version = 1, + }, + [LPC_ICH4M] = { + .name = "ICH4-M", + .iTCO_version = 1, + }, + [LPC_CICH] = { + .name = "C-ICH", + .iTCO_version = 1, + }, + [LPC_ICH5] = { + .name = "ICH5 or ICH5R", + .iTCO_version = 1, + }, + [LPC_6300ESB] = { + .name = "6300ESB", + .iTCO_version = 1, + }, + [LPC_ICH6] = { + .name = "ICH6 or ICH6R", + .iTCO_version = 2, + .gpio_version = ICH_V6_GPIO, + }, + [LPC_ICH6M] = { + .name = "ICH6-M", + .iTCO_version = 2, + .gpio_version = ICH_V6_GPIO, + }, + [LPC_ICH6W] = { + .name = "ICH6W or ICH6RW", + .iTCO_version = 2, + .gpio_version = ICH_V6_GPIO, + }, + [LPC_631XESB] = { + .name = "631xESB/632xESB", + .iTCO_version = 2, + .gpio_version = ICH_V6_GPIO, + }, + [LPC_ICH7] = { + .name = "ICH7 or ICH7R", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH7DH] = { + .name = "ICH7DH", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH7M] = { + .name = "ICH7-M or ICH7-U", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH7MDH] = { + .name = "ICH7-M DH", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_NM10] = { + .name = "NM10", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH8] = { + .name = "ICH8 or ICH8R", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH8DH] = { + .name = "ICH8DH", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH8DO] = { + .name = "ICH8DO", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH8M] = { + .name = "ICH8M", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH8ME] = { + .name = "ICH8M-E", + .iTCO_version = 2, + .gpio_version = ICH_V7_GPIO, + }, + [LPC_ICH9] = { + .name = "ICH9", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH9R] = { + .name = "ICH9R", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH9DH] = { + .name = "ICH9DH", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH9DO] = { + .name = "ICH9DO", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH9M] = { + .name = "ICH9M", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH9ME] = { + .name = "ICH9M-E", + .iTCO_version = 2, + .gpio_version = ICH_V9_GPIO, + }, + [LPC_ICH10] = { + .name = "ICH10", + .iTCO_version = 2, + .gpio_version = ICH_V10CONS_GPIO, + }, + [LPC_ICH10R] = { + .name = "ICH10R", + .iTCO_version = 2, + .gpio_version = ICH_V10CONS_GPIO, + }, + [LPC_ICH10D] = { + .name = "ICH10D", + .iTCO_version = 2, + .gpio_version = ICH_V10CORP_GPIO, + }, + [LPC_ICH10DO] = { + .name = "ICH10DO", + .iTCO_version = 2, + .gpio_version = ICH_V10CORP_GPIO, + }, + [LPC_PCH] = { + .name = "PCH Desktop Full Featured", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_PCHM] = { + .name = "PCH Mobile Full Featured", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_P55] = { + .name = "P55", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_PM55] = { + .name = "PM55", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_H55] = { + .name = "H55", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_QM57] = { + .name = "QM57", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_H57] = { + .name = "H57", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_HM55] = { + .name = "HM55", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_Q57] = { + .name = "Q57", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_HM57] = { + .name = "HM57", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_PCHMSFF] = { + .name = "PCH Mobile SFF Full Featured", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_QS57] = { + .name = "QS57", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_3400] = { + .name = "3400", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_3420] = { + .name = "3420", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_3450] = { + .name = "3450", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_EP80579] = { + .name = "EP80579", + .iTCO_version = 2, + }, + [LPC_CPT] = { + .name = "Cougar Point", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_CPTD] = { + .name = "Cougar Point Desktop", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_CPTM] = { + .name = "Cougar Point Mobile", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_PBG] = { + .name = "Patsburg", + .iTCO_version = 2, + }, + [LPC_DH89XXCC] = { + .name = "DH89xxCC", + .iTCO_version = 2, + }, + [LPC_PPT] = { + .name = "Panther Point", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_LPT] = { + .name = "Lynx Point", + .iTCO_version = 2, + .gpio_version = ICH_V5_GPIO, + }, + [LPC_LPT_LP] = { + .name = "Lynx Point_LP", + .iTCO_version = 2, + }, + [LPC_WBG] = { + .name = "Wellsburg", + .iTCO_version = 2, + }, + [LPC_AVN] = { + .name = "Avoton SoC", + .iTCO_version = 3, + .gpio_version = AVOTON_GPIO, + }, + [LPC_BAYTRAIL] = { + .name = "Bay Trail SoC", + .iTCO_version = 3, + }, + [LPC_COLETO] = { + .name = "Coleto Creek", + .iTCO_version = 2, + }, + [LPC_WPT_LP] = { + .name = "Wildcat Point_LP", + .iTCO_version = 2, + }, + [LPC_BRASWELL] = { + .name = "Braswell SoC", + .iTCO_version = 3, + }, + [LPC_LEWISBURG] = { + .name = "Lewisburg", + .iTCO_version = 2, + }, + [LPC_9S] = { + .name = "9 Series", + .iTCO_version = 2, + }, +}; + +/* + * This data only exists for exporting the supported PCI ids + * via MODULE_DEVICE_TABLE. We do not actually register a + * pci_driver, because the I/O Controller Hub has also other + * functions that probably will be registered by other drivers. + */ +static const struct pci_device_id lpc_ich_ids[] = { + { PCI_VDEVICE(INTEL, 0x0f1c), LPC_BAYTRAIL}, + { PCI_VDEVICE(INTEL, 0x1c41), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c42), LPC_CPTD}, + { PCI_VDEVICE(INTEL, 0x1c43), LPC_CPTM}, + { PCI_VDEVICE(INTEL, 0x1c44), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c45), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c46), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c47), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c48), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c49), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4a), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4b), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4c), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4d), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4e), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c4f), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c50), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c51), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c52), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c53), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c54), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c55), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c56), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c57), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c58), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c59), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5a), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5b), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5c), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5d), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5e), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1c5f), LPC_CPT}, + { PCI_VDEVICE(INTEL, 0x1d40), LPC_PBG}, + { PCI_VDEVICE(INTEL, 0x1d41), LPC_PBG}, + { PCI_VDEVICE(INTEL, 0x1e40), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e41), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e42), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e43), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e44), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e45), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e46), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e47), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e48), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e49), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4a), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4b), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4c), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4d), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4e), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e4f), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e50), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e51), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e52), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e53), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e54), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e55), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e56), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e57), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e58), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e59), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5a), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5b), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5c), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5d), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5e), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1e5f), LPC_PPT}, + { PCI_VDEVICE(INTEL, 0x1f38), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f39), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f3a), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x1f3b), LPC_AVN}, + { PCI_VDEVICE(INTEL, 0x229c), LPC_BRASWELL}, + { PCI_VDEVICE(INTEL, 0x2310), LPC_DH89XXCC}, + { PCI_VDEVICE(INTEL, 0x2390), LPC_COLETO}, + { PCI_VDEVICE(INTEL, 0x2410), LPC_ICH}, + { PCI_VDEVICE(INTEL, 0x2420), LPC_ICH0}, + { PCI_VDEVICE(INTEL, 0x2440), LPC_ICH2}, + { PCI_VDEVICE(INTEL, 0x244c), LPC_ICH2M}, + { PCI_VDEVICE(INTEL, 0x2450), LPC_CICH}, + { PCI_VDEVICE(INTEL, 0x2480), LPC_ICH3}, + { PCI_VDEVICE(INTEL, 0x248c), LPC_ICH3M}, + { PCI_VDEVICE(INTEL, 0x24c0), LPC_ICH4}, + { PCI_VDEVICE(INTEL, 0x24cc), LPC_ICH4M}, + { PCI_VDEVICE(INTEL, 0x24d0), LPC_ICH5}, + { PCI_VDEVICE(INTEL, 0x25a1), LPC_6300ESB}, + { PCI_VDEVICE(INTEL, 0x2640), LPC_ICH6}, + { PCI_VDEVICE(INTEL, 0x2641), LPC_ICH6M}, + { PCI_VDEVICE(INTEL, 0x2642), LPC_ICH6W}, + { PCI_VDEVICE(INTEL, 0x2670), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2671), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2672), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2673), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2674), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2675), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2676), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2677), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2678), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x2679), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267a), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267b), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267c), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267d), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267e), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x267f), LPC_631XESB}, + { PCI_VDEVICE(INTEL, 0x27b0), LPC_ICH7DH}, + { PCI_VDEVICE(INTEL, 0x27b8), LPC_ICH7}, + { PCI_VDEVICE(INTEL, 0x27b9), LPC_ICH7M}, + { PCI_VDEVICE(INTEL, 0x27bc), LPC_NM10}, + { PCI_VDEVICE(INTEL, 0x27bd), LPC_ICH7MDH}, + { PCI_VDEVICE(INTEL, 0x2810), LPC_ICH8}, + { PCI_VDEVICE(INTEL, 0x2811), LPC_ICH8ME}, + { PCI_VDEVICE(INTEL, 0x2812), LPC_ICH8DH}, + { PCI_VDEVICE(INTEL, 0x2814), LPC_ICH8DO}, + { PCI_VDEVICE(INTEL, 0x2815), LPC_ICH8M}, + { PCI_VDEVICE(INTEL, 0x2912), LPC_ICH9DH}, + { PCI_VDEVICE(INTEL, 0x2914), LPC_ICH9DO}, + { PCI_VDEVICE(INTEL, 0x2916), LPC_ICH9R}, + { PCI_VDEVICE(INTEL, 0x2917), LPC_ICH9ME}, + { PCI_VDEVICE(INTEL, 0x2918), LPC_ICH9}, + { PCI_VDEVICE(INTEL, 0x2919), LPC_ICH9M}, + { PCI_VDEVICE(INTEL, 0x3a14), LPC_ICH10DO}, + { PCI_VDEVICE(INTEL, 0x3a16), LPC_ICH10R}, + { PCI_VDEVICE(INTEL, 0x3a18), LPC_ICH10}, + { PCI_VDEVICE(INTEL, 0x3a1a), LPC_ICH10D}, + { PCI_VDEVICE(INTEL, 0x3b00), LPC_PCH}, + { PCI_VDEVICE(INTEL, 0x3b01), LPC_PCHM}, + { PCI_VDEVICE(INTEL, 0x3b02), LPC_P55}, + { PCI_VDEVICE(INTEL, 0x3b03), LPC_PM55}, + { PCI_VDEVICE(INTEL, 0x3b06), LPC_H55}, + { PCI_VDEVICE(INTEL, 0x3b07), LPC_QM57}, + { PCI_VDEVICE(INTEL, 0x3b08), LPC_H57}, + { PCI_VDEVICE(INTEL, 0x3b09), LPC_HM55}, + { PCI_VDEVICE(INTEL, 0x3b0a), LPC_Q57}, + { PCI_VDEVICE(INTEL, 0x3b0b), LPC_HM57}, + { PCI_VDEVICE(INTEL, 0x3b0d), LPC_PCHMSFF}, + { PCI_VDEVICE(INTEL, 0x3b0f), LPC_QS57}, + { PCI_VDEVICE(INTEL, 0x3b12), LPC_3400}, + { PCI_VDEVICE(INTEL, 0x3b14), LPC_3420}, + { PCI_VDEVICE(INTEL, 0x3b16), LPC_3450}, + { PCI_VDEVICE(INTEL, 0x5031), LPC_EP80579}, + { PCI_VDEVICE(INTEL, 0x8c40), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c41), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c42), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c43), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c44), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c45), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c46), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c47), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c48), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c49), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4a), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4b), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4c), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4d), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4e), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c4f), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c50), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c51), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c52), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c53), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c54), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c55), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c56), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c57), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c58), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c59), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5a), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5b), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5c), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5d), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5e), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8c5f), LPC_LPT}, + { PCI_VDEVICE(INTEL, 0x8cc1), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8cc2), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8cc3), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8cc4), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8cc6), LPC_9S}, + { PCI_VDEVICE(INTEL, 0x8d40), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d41), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d42), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d43), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d44), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d45), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d46), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d47), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d48), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d49), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4a), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4b), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4c), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4d), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4e), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d4f), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d50), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d51), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d52), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d53), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d54), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d55), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d56), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d57), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d58), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d59), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5a), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5b), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5c), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5d), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5e), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x8d5f), LPC_WBG}, + { PCI_VDEVICE(INTEL, 0x9c40), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c41), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c42), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c43), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c44), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c45), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c46), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9c47), LPC_LPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc1), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc2), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc3), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc5), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc6), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc7), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0x9cc9), LPC_WPT_LP}, + { PCI_VDEVICE(INTEL, 0xa1c1), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c2), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c3), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c4), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c5), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c6), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa1c7), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa242), LPC_LEWISBURG}, + { PCI_VDEVICE(INTEL, 0xa243), LPC_LEWISBURG}, + { 0, }, /* End of list */ +}; +MODULE_DEVICE_TABLE(pci, lpc_ich_ids); + +static void lpc_ich_restore_config_space(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + + if (priv->abase_save >= 0) { + pci_write_config_byte(dev, priv->abase, priv->abase_save); + priv->abase_save = -1; + } + + if (priv->actrl_pbase_save >= 0) { + pci_write_config_byte(dev, priv->actrl_pbase, + priv->actrl_pbase_save); + priv->actrl_pbase_save = -1; + } + + if (priv->gctrl_save >= 0) { + pci_write_config_byte(dev, priv->gctrl, priv->gctrl_save); + priv->gctrl_save = -1; + } +} + +static void lpc_ich_enable_acpi_space(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + u8 reg_save; + + switch (lpc_chipset_info[priv->chipset].iTCO_version) { + case 3: + /* + * Some chipsets (eg Avoton) enable the ACPI space in the + * ACPI BASE register. + */ + pci_read_config_byte(dev, priv->abase, ®_save); + pci_write_config_byte(dev, priv->abase, reg_save | 0x2); + priv->abase_save = reg_save; + break; + default: + /* + * Most chipsets enable the ACPI space in the ACPI control + * register. + */ + pci_read_config_byte(dev, priv->actrl_pbase, ®_save); + pci_write_config_byte(dev, priv->actrl_pbase, reg_save | 0x80); + priv->actrl_pbase_save = reg_save; + break; + } +} + +static void lpc_ich_enable_gpio_space(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + u8 reg_save; + + pci_read_config_byte(dev, priv->gctrl, ®_save); + pci_write_config_byte(dev, priv->gctrl, reg_save | 0x10); + priv->gctrl_save = reg_save; +} + +static void lpc_ich_enable_pmc_space(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + u8 reg_save; + + pci_read_config_byte(dev, priv->actrl_pbase, ®_save); + pci_write_config_byte(dev, priv->actrl_pbase, reg_save | 0x2); + + priv->actrl_pbase_save = reg_save; +} + +static int lpc_ich_finalize_wdt_cell(struct pci_dev *dev) +{ + struct itco_wdt_platform_data *pdata; + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + struct lpc_ich_info *info; + struct mfd_cell *cell = &lpc_ich_wdt_cell; + + pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + info = &lpc_chipset_info[priv->chipset]; + + pdata->version = info->iTCO_version; + strlcpy(pdata->name, info->name, sizeof(pdata->name)); + + cell->platform_data = pdata; + cell->pdata_size = sizeof(*pdata); + return 0; +} + +static void lpc_ich_finalize_gpio_cell(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + struct mfd_cell *cell = &lpc_ich_gpio_cell; + + cell->platform_data = &lpc_chipset_info[priv->chipset]; + cell->pdata_size = sizeof(struct lpc_ich_info); +} + +/* + * We don't check for resource conflict globally. There are 2 or 3 independent + * GPIO groups and it's enough to have access to one of these to instantiate + * the device. + */ +static int lpc_ich_check_conflict_gpio(struct resource *res) +{ + int ret; + u8 use_gpio = 0; + + if (resource_size(res) >= 0x50 && + !acpi_check_region(res->start + 0x40, 0x10, "LPC ICH GPIO3")) + use_gpio |= 1 << 2; + + if (!acpi_check_region(res->start + 0x30, 0x10, "LPC ICH GPIO2")) + use_gpio |= 1 << 1; + + ret = acpi_check_region(res->start + 0x00, 0x30, "LPC ICH GPIO1"); + if (!ret) + use_gpio |= 1 << 0; + + return use_gpio ? use_gpio : ret; +} + +static int lpc_ich_init_gpio(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + u32 base_addr_cfg; + u32 base_addr; + int ret; + bool acpi_conflict = false; + struct resource *res; + + /* Setup power management base register */ + pci_read_config_dword(dev, priv->abase, &base_addr_cfg); + base_addr = base_addr_cfg & 0x0000ff80; + if (!base_addr) { + dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); + lpc_ich_gpio_cell.num_resources--; + goto gpe0_done; + } + + res = &gpio_ich_res[ICH_RES_GPE0]; + res->start = base_addr + ACPIBASE_GPE_OFF; + res->end = base_addr + ACPIBASE_GPE_END; + ret = acpi_check_resource_conflict(res); + if (ret) { + /* + * This isn't fatal for the GPIO, but we have to make sure that + * the platform_device subsystem doesn't see this resource + * or it will register an invalid region. + */ + lpc_ich_gpio_cell.num_resources--; + acpi_conflict = true; + } else { + lpc_ich_enable_acpi_space(dev); + } + +gpe0_done: + /* Setup GPIO base register */ + pci_read_config_dword(dev, priv->gbase, &base_addr_cfg); + base_addr = base_addr_cfg & 0x0000ff80; + if (!base_addr) { + dev_notice(&dev->dev, "I/O space for GPIO uninitialized\n"); + ret = -ENODEV; + goto gpio_done; + } + + /* Older devices provide fewer GPIO and have a smaller resource size. */ + res = &gpio_ich_res[ICH_RES_GPIO]; + res->start = base_addr; + switch (lpc_chipset_info[priv->chipset].gpio_version) { + case ICH_V5_GPIO: + case ICH_V10CORP_GPIO: + res->end = res->start + 128 - 1; + break; + default: + res->end = res->start + 64 - 1; + break; + } + + ret = lpc_ich_check_conflict_gpio(res); + if (ret < 0) { + /* this isn't necessarily fatal for the GPIO */ + acpi_conflict = true; + goto gpio_done; + } + lpc_chipset_info[priv->chipset].use_gpio = ret; + lpc_ich_enable_gpio_space(dev); + + lpc_ich_finalize_gpio_cell(dev); + ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO, + &lpc_ich_gpio_cell, 1, NULL, 0, NULL); + +gpio_done: + if (acpi_conflict) + pr_warn("Resource conflict(s) found affecting %s\n", + lpc_ich_gpio_cell.name); + return ret; +} + +static int lpc_ich_init_wdt(struct pci_dev *dev) +{ + struct lpc_ich_priv *priv = pci_get_drvdata(dev); + u32 base_addr_cfg; + u32 base_addr; + int ret; + struct resource *res; + + /* If we have ACPI based watchdog use that instead */ + if (acpi_has_watchdog()) + return -ENODEV; + + /* Setup power management base register */ + pci_read_config_dword(dev, priv->abase, &base_addr_cfg); + base_addr = base_addr_cfg & 0x0000ff80; + if (!base_addr) { + dev_notice(&dev->dev, "I/O space for ACPI uninitialized\n"); + ret = -ENODEV; + goto wdt_done; + } + + res = wdt_io_res(ICH_RES_IO_TCO); + res->start = base_addr + ACPIBASE_TCO_OFF; + res->end = base_addr + ACPIBASE_TCO_END; + + res = wdt_io_res(ICH_RES_IO_SMI); + res->start = base_addr + ACPIBASE_SMI_OFF; + res->end = base_addr + ACPIBASE_SMI_END; + + lpc_ich_enable_acpi_space(dev); + + /* + * iTCO v2: + * Get the Memory-Mapped GCS register. To get access to it + * we have to read RCBA from PCI Config space 0xf0 and use + * it as base. GCS = RCBA + ICH6_GCS(0x3410). + * + * iTCO v3: + * Get the Power Management Configuration register. To get access + * to it we have to read the PMC BASE from config space and address + * the register at offset 0x8. + */ + if (lpc_chipset_info[priv->chipset].iTCO_version == 1) { + /* Don't register iomem for TCO ver 1 */ + lpc_ich_wdt_cell.num_resources--; + } else if (lpc_chipset_info[priv->chipset].iTCO_version == 2) { + pci_read_config_dword(dev, RCBABASE, &base_addr_cfg); + base_addr = base_addr_cfg & 0xffffc000; + if (!(base_addr_cfg & 1)) { + dev_notice(&dev->dev, "RCBA is disabled by " + "hardware/BIOS, device disabled\n"); + ret = -ENODEV; + goto wdt_done; + } + res = wdt_mem_res(ICH_RES_MEM_GCS_PMC); + res->start = base_addr + ACPIBASE_GCS_OFF; + res->end = base_addr + ACPIBASE_GCS_END; + } else if (lpc_chipset_info[priv->chipset].iTCO_version == 3) { + lpc_ich_enable_pmc_space(dev); + pci_read_config_dword(dev, ACPICTRL_PMCBASE, &base_addr_cfg); + base_addr = base_addr_cfg & 0xfffffe00; + + res = wdt_mem_res(ICH_RES_MEM_GCS_PMC); + res->start = base_addr + ACPIBASE_PMC_OFF; + res->end = base_addr + ACPIBASE_PMC_END; + } + + ret = lpc_ich_finalize_wdt_cell(dev); + if (ret) + goto wdt_done; + + ret = mfd_add_devices(&dev->dev, PLATFORM_DEVID_AUTO, + &lpc_ich_wdt_cell, 1, NULL, 0, NULL); + +wdt_done: + return ret; +} + +static int lpc_ich_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + struct lpc_ich_priv *priv; + int ret; + bool cell_added = false; + + priv = devm_kzalloc(&dev->dev, + sizeof(struct lpc_ich_priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->chipset = id->driver_data; + + priv->actrl_pbase_save = -1; + priv->abase_save = -1; + + priv->abase = ACPIBASE; + priv->actrl_pbase = ACPICTRL_PMCBASE; + + priv->gctrl_save = -1; + if (priv->chipset <= LPC_ICH5) { + priv->gbase = GPIOBASE_ICH0; + priv->gctrl = GPIOCTRL_ICH0; + } else { + priv->gbase = GPIOBASE_ICH6; + priv->gctrl = GPIOCTRL_ICH6; + } + + pci_set_drvdata(dev, priv); + + if (lpc_chipset_info[priv->chipset].iTCO_version) { + ret = lpc_ich_init_wdt(dev); + if (!ret) + cell_added = true; + } + + if (lpc_chipset_info[priv->chipset].gpio_version) { + ret = lpc_ich_init_gpio(dev); + if (!ret) + cell_added = true; + } + + /* + * We only care if at least one or none of the cells registered + * successfully. + */ + if (!cell_added) { + dev_warn(&dev->dev, "No MFD cells added\n"); + lpc_ich_restore_config_space(dev); + return -ENODEV; + } + + return 0; +} + +static void lpc_ich_remove(struct pci_dev *dev) +{ + mfd_remove_devices(&dev->dev); + lpc_ich_restore_config_space(dev); +} + +static struct pci_driver lpc_ich_driver = { + .name = "lpc_ich", + .id_table = lpc_ich_ids, + .probe = lpc_ich_probe, + .remove = lpc_ich_remove, +}; + +module_pci_driver(lpc_ich_driver); + +MODULE_AUTHOR("Aaron Sierra "); +MODULE_DESCRIPTION("LPC interface for Intel ICH"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/pmbus.h b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/pmbus.h new file mode 100644 index 0000000000..4efa2bd4f6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/pmbus.h @@ -0,0 +1,425 @@ +/* + * pmbus.h - Common defines and structures for PMBus devices + * + * Copyright (c) 2010, 2011 Ericsson AB. + * Copyright (c) 2012 Guenter Roeck + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef PMBUS_H +#define PMBUS_H + +#include +#include + +/* + * Registers + */ +enum pmbus_regs { + PMBUS_PAGE = 0x00, + PMBUS_OPERATION = 0x01, + PMBUS_ON_OFF_CONFIG = 0x02, + PMBUS_CLEAR_FAULTS = 0x03, + PMBUS_PHASE = 0x04, + + PMBUS_CAPABILITY = 0x19, + PMBUS_QUERY = 0x1A, + + PMBUS_VOUT_MODE = 0x20, + PMBUS_VOUT_COMMAND = 0x21, + PMBUS_VOUT_TRIM = 0x22, + PMBUS_VOUT_CAL_OFFSET = 0x23, + PMBUS_VOUT_MAX = 0x24, + PMBUS_VOUT_MARGIN_HIGH = 0x25, + PMBUS_VOUT_MARGIN_LOW = 0x26, + PMBUS_VOUT_TRANSITION_RATE = 0x27, + PMBUS_VOUT_DROOP = 0x28, + PMBUS_VOUT_SCALE_LOOP = 0x29, + PMBUS_VOUT_SCALE_MONITOR = 0x2A, + + PMBUS_COEFFICIENTS = 0x30, + PMBUS_POUT_MAX = 0x31, + + PMBUS_FAN_CONFIG_12 = 0x3A, + PMBUS_FAN_COMMAND_1 = 0x3B, + PMBUS_FAN_COMMAND_2 = 0x3C, + PMBUS_FAN_CONFIG_34 = 0x3D, + PMBUS_FAN_COMMAND_3 = 0x3E, + PMBUS_FAN_COMMAND_4 = 0x3F, + + PMBUS_VOUT_OV_FAULT_LIMIT = 0x40, + PMBUS_VOUT_OV_FAULT_RESPONSE = 0x41, + PMBUS_VOUT_OV_WARN_LIMIT = 0x42, + PMBUS_VOUT_UV_WARN_LIMIT = 0x43, + PMBUS_VOUT_UV_FAULT_LIMIT = 0x44, + PMBUS_VOUT_UV_FAULT_RESPONSE = 0x45, + PMBUS_IOUT_OC_FAULT_LIMIT = 0x46, + PMBUS_IOUT_OC_FAULT_RESPONSE = 0x47, + PMBUS_IOUT_OC_LV_FAULT_LIMIT = 0x48, + PMBUS_IOUT_OC_LV_FAULT_RESPONSE = 0x49, + PMBUS_IOUT_OC_WARN_LIMIT = 0x4A, + PMBUS_IOUT_UC_FAULT_LIMIT = 0x4B, + PMBUS_IOUT_UC_FAULT_RESPONSE = 0x4C, + + PMBUS_OT_FAULT_LIMIT = 0x4F, + PMBUS_OT_FAULT_RESPONSE = 0x50, + PMBUS_OT_WARN_LIMIT = 0x51, + PMBUS_UT_WARN_LIMIT = 0x52, + PMBUS_UT_FAULT_LIMIT = 0x53, + PMBUS_UT_FAULT_RESPONSE = 0x54, + PMBUS_VIN_OV_FAULT_LIMIT = 0x55, + PMBUS_VIN_OV_FAULT_RESPONSE = 0x56, + PMBUS_VIN_OV_WARN_LIMIT = 0x57, + PMBUS_VIN_UV_WARN_LIMIT = 0x58, + PMBUS_VIN_UV_FAULT_LIMIT = 0x59, + + PMBUS_IIN_OC_FAULT_LIMIT = 0x5B, + PMBUS_IIN_OC_WARN_LIMIT = 0x5D, + + PMBUS_POUT_OP_FAULT_LIMIT = 0x68, + PMBUS_POUT_OP_WARN_LIMIT = 0x6A, + PMBUS_PIN_OP_WARN_LIMIT = 0x6B, + + PMBUS_STATUS_BYTE = 0x78, + PMBUS_STATUS_WORD = 0x79, + PMBUS_STATUS_VOUT = 0x7A, + PMBUS_STATUS_IOUT = 0x7B, + PMBUS_STATUS_INPUT = 0x7C, + PMBUS_STATUS_TEMPERATURE = 0x7D, + PMBUS_STATUS_CML = 0x7E, + PMBUS_STATUS_OTHER = 0x7F, + PMBUS_STATUS_MFR_SPECIFIC = 0x80, + PMBUS_STATUS_FAN_12 = 0x81, + PMBUS_STATUS_FAN_34 = 0x82, + + PMBUS_READ_VIN = 0x88, + PMBUS_READ_IIN = 0x89, + PMBUS_READ_VCAP = 0x8A, + PMBUS_READ_VOUT = 0x8B, + PMBUS_READ_IOUT = 0x8C, + PMBUS_READ_TEMPERATURE_1 = 0x8D, + PMBUS_READ_TEMPERATURE_2 = 0x8E, + PMBUS_READ_TEMPERATURE_3 = 0x8F, + PMBUS_READ_FAN_SPEED_1 = 0x90, + PMBUS_READ_FAN_SPEED_2 = 0x91, + PMBUS_READ_FAN_SPEED_3 = 0x92, + PMBUS_READ_FAN_SPEED_4 = 0x93, + PMBUS_READ_DUTY_CYCLE = 0x94, + PMBUS_READ_FREQUENCY = 0x95, + PMBUS_READ_POUT = 0x96, + PMBUS_READ_PIN = 0x97, + + PMBUS_REVISION = 0x98, + PMBUS_MFR_ID = 0x99, + PMBUS_MFR_MODEL = 0x9A, + PMBUS_MFR_REVISION = 0x9B, + PMBUS_MFR_LOCATION = 0x9C, + PMBUS_MFR_DATE = 0x9D, + PMBUS_MFR_SERIAL = 0x9E, + +/* + * Virtual registers. + * Useful to support attributes which are not supported by standard PMBus + * registers but exist as manufacturer specific registers on individual chips. + * Must be mapped to real registers in device specific code. + * + * Semantics: + * Virtual registers are all word size. + * READ registers are read-only; writes are either ignored or return an error. + * RESET registers are read/write. Reading reset registers returns zero + * (used for detection), writing any value causes the associated history to be + * reset. + * Virtual registers have to be handled in device specific driver code. Chip + * driver code returns non-negative register values if a virtual register is + * supported, or a negative error code if not. The chip driver may return + * -ENODATA or any other error code in this case, though an error code other + * than -ENODATA is handled more efficiently and thus preferred. Either case, + * the calling PMBus core code will abort if the chip driver returns an error + * code when reading or writing virtual registers. + */ + PMBUS_VIRT_BASE = 0x100, + PMBUS_VIRT_READ_TEMP_AVG, + PMBUS_VIRT_READ_TEMP_MIN, + PMBUS_VIRT_READ_TEMP_MAX, + PMBUS_VIRT_RESET_TEMP_HISTORY, + PMBUS_VIRT_READ_VIN_AVG, + PMBUS_VIRT_READ_VIN_MIN, + PMBUS_VIRT_READ_VIN_MAX, + PMBUS_VIRT_RESET_VIN_HISTORY, + PMBUS_VIRT_READ_IIN_AVG, + PMBUS_VIRT_READ_IIN_MIN, + PMBUS_VIRT_READ_IIN_MAX, + PMBUS_VIRT_RESET_IIN_HISTORY, + PMBUS_VIRT_READ_PIN_AVG, + PMBUS_VIRT_READ_PIN_MIN, + PMBUS_VIRT_READ_PIN_MAX, + PMBUS_VIRT_RESET_PIN_HISTORY, + PMBUS_VIRT_READ_POUT_AVG, + PMBUS_VIRT_READ_POUT_MIN, + PMBUS_VIRT_READ_POUT_MAX, + PMBUS_VIRT_RESET_POUT_HISTORY, + PMBUS_VIRT_READ_VOUT_AVG, + PMBUS_VIRT_READ_VOUT_MIN, + PMBUS_VIRT_READ_VOUT_MAX, + PMBUS_VIRT_RESET_VOUT_HISTORY, + PMBUS_VIRT_READ_IOUT_AVG, + PMBUS_VIRT_READ_IOUT_MIN, + PMBUS_VIRT_READ_IOUT_MAX, + PMBUS_VIRT_RESET_IOUT_HISTORY, + PMBUS_VIRT_READ_TEMP2_AVG, + PMBUS_VIRT_READ_TEMP2_MIN, + PMBUS_VIRT_READ_TEMP2_MAX, + PMBUS_VIRT_RESET_TEMP2_HISTORY, + + PMBUS_VIRT_READ_VMON, + PMBUS_VIRT_VMON_UV_WARN_LIMIT, + PMBUS_VIRT_VMON_OV_WARN_LIMIT, + PMBUS_VIRT_VMON_UV_FAULT_LIMIT, + PMBUS_VIRT_VMON_OV_FAULT_LIMIT, + PMBUS_VIRT_STATUS_VMON, +}; + +/* + * OPERATION + */ +#define PB_OPERATION_CONTROL_ON BIT(7) + +/* + * CAPABILITY + */ +#define PB_CAPABILITY_SMBALERT BIT(4) +#define PB_CAPABILITY_ERROR_CHECK BIT(7) + +/* + * VOUT_MODE + */ +#define PB_VOUT_MODE_MODE_MASK 0xe0 +#define PB_VOUT_MODE_PARAM_MASK 0x1f + +#define PB_VOUT_MODE_LINEAR 0x00 +#define PB_VOUT_MODE_VID 0x20 +#define PB_VOUT_MODE_DIRECT 0x40 + +/* + * Fan configuration + */ +#define PB_FAN_2_PULSE_MASK (BIT(0) | BIT(1)) +#define PB_FAN_2_RPM BIT(2) +#define PB_FAN_2_INSTALLED BIT(3) +#define PB_FAN_1_PULSE_MASK (BIT(4) | BIT(5)) +#define PB_FAN_1_RPM BIT(6) +#define PB_FAN_1_INSTALLED BIT(7) + +/* + * STATUS_BYTE, STATUS_WORD (lower) + */ +#define PB_STATUS_NONE_ABOVE BIT(0) +#define PB_STATUS_CML BIT(1) +#define PB_STATUS_TEMPERATURE BIT(2) +#define PB_STATUS_VIN_UV BIT(3) +#define PB_STATUS_IOUT_OC BIT(4) +#define PB_STATUS_VOUT_OV BIT(5) +#define PB_STATUS_OFF BIT(6) +#define PB_STATUS_BUSY BIT(7) + +/* + * STATUS_WORD (upper) + */ +#define PB_STATUS_UNKNOWN BIT(8) +#define PB_STATUS_OTHER BIT(9) +#define PB_STATUS_FANS BIT(10) +#define PB_STATUS_POWER_GOOD_N BIT(11) +#define PB_STATUS_WORD_MFR BIT(12) +#define PB_STATUS_INPUT BIT(13) +#define PB_STATUS_IOUT_POUT BIT(14) +#define PB_STATUS_VOUT BIT(15) + +/* + * STATUS_IOUT + */ +#define PB_POUT_OP_WARNING BIT(0) +#define PB_POUT_OP_FAULT BIT(1) +#define PB_POWER_LIMITING BIT(2) +#define PB_CURRENT_SHARE_FAULT BIT(3) +#define PB_IOUT_UC_FAULT BIT(4) +#define PB_IOUT_OC_WARNING BIT(5) +#define PB_IOUT_OC_LV_FAULT BIT(6) +#define PB_IOUT_OC_FAULT BIT(7) + +/* + * STATUS_VOUT, STATUS_INPUT + */ +#define PB_VOLTAGE_UV_FAULT BIT(4) +#define PB_VOLTAGE_UV_WARNING BIT(5) +#define PB_VOLTAGE_OV_WARNING BIT(6) +#define PB_VOLTAGE_OV_FAULT BIT(7) + +/* + * STATUS_INPUT + */ +#define PB_PIN_OP_WARNING BIT(0) +#define PB_IIN_OC_WARNING BIT(1) +#define PB_IIN_OC_FAULT BIT(2) + +/* + * STATUS_TEMPERATURE + */ +#define PB_TEMP_UT_FAULT BIT(4) +#define PB_TEMP_UT_WARNING BIT(5) +#define PB_TEMP_OT_WARNING BIT(6) +#define PB_TEMP_OT_FAULT BIT(7) + +/* + * STATUS_FAN + */ +#define PB_FAN_AIRFLOW_WARNING BIT(0) +#define PB_FAN_AIRFLOW_FAULT BIT(1) +#define PB_FAN_FAN2_SPEED_OVERRIDE BIT(2) +#define PB_FAN_FAN1_SPEED_OVERRIDE BIT(3) +#define PB_FAN_FAN2_WARNING BIT(4) +#define PB_FAN_FAN1_WARNING BIT(5) +#define PB_FAN_FAN2_FAULT BIT(6) +#define PB_FAN_FAN1_FAULT BIT(7) + +/* + * CML_FAULT_STATUS + */ +#define PB_CML_FAULT_OTHER_MEM_LOGIC BIT(0) +#define PB_CML_FAULT_OTHER_COMM BIT(1) +#define PB_CML_FAULT_PROCESSOR BIT(3) +#define PB_CML_FAULT_MEMORY BIT(4) +#define PB_CML_FAULT_PACKET_ERROR BIT(5) +#define PB_CML_FAULT_INVALID_DATA BIT(6) +#define PB_CML_FAULT_INVALID_COMMAND BIT(7) + +enum pmbus_sensor_classes { + PSC_VOLTAGE_IN = 0, + PSC_VOLTAGE_OUT, + PSC_CURRENT_IN, + PSC_CURRENT_OUT, + PSC_POWER, + PSC_TEMPERATURE, + PSC_FAN, + PSC_NUM_CLASSES /* Number of power sensor classes */ +}; + +#define PMBUS_PAGES 32 /* Per PMBus specification */ + +/* Functionality bit mask */ +#define PMBUS_HAVE_VIN BIT(0) +#define PMBUS_HAVE_VCAP BIT(1) +#define PMBUS_HAVE_VOUT BIT(2) +#define PMBUS_HAVE_IIN BIT(3) +#define PMBUS_HAVE_IOUT BIT(4) +#define PMBUS_HAVE_PIN BIT(5) +#define PMBUS_HAVE_POUT BIT(6) +#define PMBUS_HAVE_FAN12 BIT(7) +#define PMBUS_HAVE_FAN34 BIT(8) +#define PMBUS_HAVE_TEMP BIT(9) +#define PMBUS_HAVE_TEMP2 BIT(10) +#define PMBUS_HAVE_TEMP3 BIT(11) +#define PMBUS_HAVE_STATUS_VOUT BIT(12) +#define PMBUS_HAVE_STATUS_IOUT BIT(13) +#define PMBUS_HAVE_STATUS_INPUT BIT(14) +#define PMBUS_HAVE_STATUS_TEMP BIT(15) +#define PMBUS_HAVE_STATUS_FAN12 BIT(16) +#define PMBUS_HAVE_STATUS_FAN34 BIT(17) +#define PMBUS_HAVE_VMON BIT(18) +#define PMBUS_HAVE_STATUS_VMON BIT(19) + +enum pmbus_data_format { linear = 0, direct, vid }; +enum vrm_version { vr11 = 0, vr12, vr13 }; + +struct pmbus_driver_info { + int pages; /* Total number of pages */ + enum pmbus_data_format format[PSC_NUM_CLASSES]; + enum vrm_version vrm_version; + /* + * Support one set of coefficients for each sensor type + * Used for chips providing data in direct mode. + */ + int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */ + int b[PSC_NUM_CLASSES]; /* offset */ + int R[PSC_NUM_CLASSES]; /* exponent */ + + u32 func[PMBUS_PAGES]; /* Functionality, per page */ + /* + * The following functions map manufacturing specific register values + * to PMBus standard register values. Specify only if mapping is + * necessary. + * Functions return the register value (read) or zero (write) if + * successful. A return value of -ENODATA indicates that there is no + * manufacturer specific register, but that a standard PMBus register + * may exist. Any other negative return value indicates that the + * register does not exist, and that no attempt should be made to read + * the standard register. + */ + int (*read_byte_data)(struct i2c_client *client, int page, int reg); + int (*read_word_data)(struct i2c_client *client, int page, int reg); + int (*write_word_data)(struct i2c_client *client, int page, int reg, + u16 word); + int (*write_byte)(struct i2c_client *client, int page, u8 value); + /* + * The identify function determines supported PMBus functionality. + * This function is only necessary if a chip driver supports multiple + * chips, and the chip functionality is not pre-determined. + */ + int (*identify)(struct i2c_client *client, + struct pmbus_driver_info *info); + + /* Regulator functionality, if supported by this chip driver. */ + int num_regulators; + const struct regulator_desc *reg_desc; +}; + +/* Regulator ops */ + +extern const struct regulator_ops pmbus_regulator_ops; + +/* Macro for filling in array of struct regulator_desc */ +#define PMBUS_REGULATOR(_name, _id) \ + [_id] = { \ + .name = (_name # _id), \ + .id = (_id), \ + .of_match = of_match_ptr(_name # _id), \ + .regulators_node = of_match_ptr("regulators"), \ + .ops = &pmbus_regulator_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + } + +/* Function declarations */ + +void pmbus_clear_cache(struct i2c_client *client); +int pmbus_set_page(struct i2c_client *client, u8 page); +int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); +int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word); +int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg); +int pmbus_write_byte(struct i2c_client *client, int page, u8 value); +int pmbus_write_byte_data(struct i2c_client *client, int page, u8 reg, + u8 value); +int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg, + u8 mask, u8 value); +void pmbus_clear_faults(struct i2c_client *client); +bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); +bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); +int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, + struct pmbus_driver_info *info); +int pmbus_do_remove(struct i2c_client *client); +const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client + *client); + +#endif /* PMBUS_H */ diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.c index 6fe8f599fb..27c45173ee 100644 --- a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.c +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.c @@ -1,10 +1,3 @@ -/* - * 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 @@ -12,7 +5,12 @@ #include "io_expander.h" #include "transceiver.h" +/* For build single module using (Ex: ONL platform) */ +#include +//#include +//#include +extern int io_no_init; /* ========== Register EEPROM address mapping ========== */ struct eeprom_map_s eeprom_map_sfp = { @@ -152,7 +150,7 @@ alarm_msg_2_user(struct transvr_obj_s *self, SWPS_ERR("%s on %s.\n", emsg, self->swp_name); } - +EXPORT_SYMBOL(alarm_msg_2_user); /* ========== Private functions ========== */ @@ -181,6 +179,7 @@ lock_transvr_obj(struct transvr_obj_s *self) { mutex_lock(&self->lock); self->curr_page = VAL_TRANSVR_PAGE_FREE; } +EXPORT_SYMBOL(lock_transvr_obj); void @@ -189,6 +188,7 @@ unlock_transvr_obj(struct transvr_obj_s *self) { self->curr_page = VAL_TRANSVR_PAGE_FREE; mutex_unlock(&self->lock); } +EXPORT_SYMBOL(unlock_transvr_obj); static int @@ -4833,6 +4833,11 @@ _taskfunc_qsfp_setup_power_mod(struct transvr_obj_s *self, int curr_val = DEBUG_TRANSVR_INT_VAL; int err_val = DEBUG_TRANSVR_INT_VAL; char *err_msg = DEBUG_TRANSVR_STR_VAL; + if (io_no_init) { + + SWPS_INFO("%s no_io_init\n",__func__); + return EVENT_TRANSVR_TASK_DONE; + } curr_val = self->ioexp_obj_p->get_lpmod(self->ioexp_obj_p, self->ioexp_virt_offset); @@ -8259,6 +8264,7 @@ err_create_transvr_fail: __func__, err_msg, chan_id, ioexp_virt_offset, transvr_type); return NULL; } +EXPORT_SYMBOL(create_transvr_obj); static int @@ -8290,11 +8296,17 @@ _reload_transvr_obj(struct transvr_obj_s *self, if (setup_transvr_private_cb(self, new_type) < 0){ goto err_private_reload_func_3; } + if(old_i2c_p){ + i2c_put_adapter(old_i2c_p->adapter); + } kfree(old_i2c_p); return 0; err_private_reload_func_3: SWPS_INFO("%s: init() fail!\n", __func__); + if(old_i2c_p){ + i2c_put_adapter(old_i2c_p->adapter); + } kfree(old_i2c_p); self->state = STATE_TRANSVR_UNEXCEPTED; self->type = TRANSVR_TYPE_ERROR; @@ -8341,6 +8353,7 @@ isolate_transvr_obj(struct transvr_obj_s *self) { SWPS_INFO("%s: %s be isolated\n", __func__, self->swp_name); return 0; } +EXPORT_SYMBOL(isolate_transvr_obj); int @@ -8359,6 +8372,10 @@ resync_channel_tier_2(struct transvr_obj_s *self) { } return 0; } +EXPORT_SYMBOL(resync_channel_tier_2); + +/* For build single module using (Ex: ONL platform) */ +MODULE_LICENSE("GPL"); /* ----------------------------------------- @@ -8387,3 +8404,5 @@ resync_channel_tier_2(struct transvr_obj_s *self) { + + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.h b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.h index f17b7fde71..0438a35127 100644 --- a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.h +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/transceiver.h @@ -1,10 +1,3 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - #ifndef TRANSCEIVER_H #define TRANSCEIVER_H @@ -813,3 +806,4 @@ void alarm_msg_2_user(struct transvr_obj_s *self, char *emsg); + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/ucd9000.c b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/ucd9000.c new file mode 100644 index 0000000000..3e3aa95027 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/modules/ucd9000.c @@ -0,0 +1,247 @@ +/* + * Hardware monitoring driver for UCD90xxx Sequencer and System Health + * Controller series + * + * Copyright (C) 2011 Ericsson AB. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "pmbus.h" + +enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd9090, ucd90910 }; + +#define UCD9000_MONITOR_CONFIG 0xd5 +#define UCD9000_NUM_PAGES 0xd6 +#define UCD9000_FAN_CONFIG_INDEX 0xe7 +#define UCD9000_FAN_CONFIG 0xe8 +#define UCD9000_DEVICE_ID 0xfd + +#define UCD9000_MON_TYPE(x) (((x) >> 5) & 0x07) +#define UCD9000_MON_PAGE(x) ((x) & 0x0f) + +#define UCD9000_MON_VOLTAGE 1 +#define UCD9000_MON_TEMPERATURE 2 +#define UCD9000_MON_CURRENT 3 +#define UCD9000_MON_VOLTAGE_HW 4 + +#define UCD9000_NUM_FAN 4 + +struct ucd9000_data { + u8 fan_data[UCD9000_NUM_FAN][I2C_SMBUS_BLOCK_MAX]; + struct pmbus_driver_info info; +}; +#define to_ucd9000_data(_info) container_of(_info, struct ucd9000_data, info) + +static int ucd9000_get_fan_config(struct i2c_client *client, int fan) +{ + int fan_config = 0; + struct ucd9000_data *data + = to_ucd9000_data(pmbus_get_driver_info(client)); + + if (data->fan_data[fan][3] & 1) + fan_config |= PB_FAN_2_INSTALLED; /* Use lower bit position */ + + /* Pulses/revolution */ + fan_config |= (data->fan_data[fan][3] & 0x06) >> 1; + + return fan_config; +} + +static int ucd9000_read_byte_data(struct i2c_client *client, int page, int reg) +{ + int ret = 0; + int fan_config; + + switch (reg) { + case PMBUS_FAN_CONFIG_12: + if (page > 0) + return -ENXIO; + + ret = ucd9000_get_fan_config(client, 0); + if (ret < 0) + return ret; + fan_config = ret << 4; + ret = ucd9000_get_fan_config(client, 1); + if (ret < 0) + return ret; + fan_config |= ret; + ret = fan_config; + break; + case PMBUS_FAN_CONFIG_34: + if (page > 0) + return -ENXIO; + + ret = ucd9000_get_fan_config(client, 2); + if (ret < 0) + return ret; + fan_config = ret << 4; + ret = ucd9000_get_fan_config(client, 3); + if (ret < 0) + return ret; + fan_config |= ret; + ret = fan_config; + break; + default: + ret = -ENODATA; + break; + } + return ret; +} + +static const struct i2c_device_id ucd9000_id[] = { + {"ucd9000", ucd9000}, + {"ucd90120", ucd90120}, + {"ucd90124", ucd90124}, + {"ucd90160", ucd90160}, + {"ucd9090", ucd9090}, + {"ucd90910", ucd90910}, + {} +}; +MODULE_DEVICE_TABLE(i2c, ucd9000_id); + +static int ucd9000_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1]; + struct ucd9000_data *data; + struct pmbus_driver_info *info; + const struct i2c_device_id *mid; + int i, ret; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA)) + return -ENODEV; + + ret = i2c_smbus_read_block_data(client, UCD9000_DEVICE_ID, + block_buffer); + if (ret < 0) { + dev_err(&client->dev, "Failed to read device ID\n"); + return ret; + } + block_buffer[ret] = '\0'; + dev_info(&client->dev, "Device ID %s\n", block_buffer); + + for (mid = ucd9000_id; mid->name[0]; mid++) { + if (!strncasecmp(mid->name, block_buffer, strlen(mid->name))) + break; + } + if (!mid->name[0]) { + dev_err(&client->dev, "Unsupported device\n"); + return -ENODEV; + } + + if (id->driver_data != ucd9000 && id->driver_data != mid->driver_data) + dev_notice(&client->dev, + "Device mismatch: Configured %s, detected %s\n", + id->name, mid->name); + + data = devm_kzalloc(&client->dev, sizeof(struct ucd9000_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + info = &data->info; + + ret = i2c_smbus_read_byte_data(client, UCD9000_NUM_PAGES); + if (ret < 0) { + dev_err(&client->dev, + "Failed to read number of active pages\n"); + return ret; + } + info->pages = ret; + if (!info->pages) { + dev_err(&client->dev, "No pages configured\n"); + return -ENODEV; + } + + /* The internal temperature sensor is always active */ + info->func[0] = PMBUS_HAVE_TEMP; + + /* Everything else is configurable */ + ret = i2c_smbus_read_block_data(client, UCD9000_MONITOR_CONFIG, + block_buffer); + if (ret <= 0) { + dev_err(&client->dev, "Failed to read configuration data\n"); + return -ENODEV; + } + for (i = 0; i < ret; i++) { + int page = UCD9000_MON_PAGE(block_buffer[i]); + + if (page >= info->pages) + continue; + + switch (UCD9000_MON_TYPE(block_buffer[i])) { + case UCD9000_MON_VOLTAGE: + case UCD9000_MON_VOLTAGE_HW: + info->func[page] |= PMBUS_HAVE_VOUT + | PMBUS_HAVE_STATUS_VOUT; + break; + case UCD9000_MON_TEMPERATURE: + info->func[page] |= PMBUS_HAVE_TEMP2 + | PMBUS_HAVE_STATUS_TEMP; + break; + case UCD9000_MON_CURRENT: + info->func[page] |= PMBUS_HAVE_IOUT + | PMBUS_HAVE_STATUS_IOUT; + break; + default: + break; + } + } + + /* Fan configuration */ + if (mid->driver_data == ucd90124) { + for (i = 0; i < UCD9000_NUM_FAN; i++) { + i2c_smbus_write_byte_data(client, + UCD9000_FAN_CONFIG_INDEX, i); + ret = i2c_smbus_read_block_data(client, + UCD9000_FAN_CONFIG, + data->fan_data[i]); + if (ret < 0) + return ret; + } + i2c_smbus_write_byte_data(client, UCD9000_FAN_CONFIG_INDEX, 0); + + info->read_byte_data = ucd9000_read_byte_data; + info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 + | PMBUS_HAVE_FAN34 | PMBUS_HAVE_STATUS_FAN34; + } + + return pmbus_do_probe(client, mid, info); +} + +/* This is the driver that will be inserted */ +static struct i2c_driver ucd9000_driver = { + .driver = { + .name = "ucd9000", + }, + .probe = ucd9000_probe, + .remove = pmbus_do_remove, + .id_table = ucd9000_id, +}; + +module_i2c_driver(ucd9000_driver); + +MODULE_AUTHOR("Guenter Roeck"); +MODULE_DESCRIPTION("PMBus driver for TI UCD90xxx"); +MODULE_LICENSE("GPL"); diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/setup.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/setup.py new file mode 100644 index 0000000000..8b45987a54 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/setup.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os +import sys +from setuptools import setup +os.listdir + +setup( + name='sonic_platform', + version='1.0', + description='Module to initialize Ivnetec D6356 platforms', + + packages=['sonic_platform'], +) + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/__init__.py new file mode 100644 index 0000000000..4bfefa0fb6 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/__init__.py @@ -0,0 +1,3 @@ +__all__ = ["platform", "chassis"] +from sonic_platform import * + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/chassis.py new file mode 100644 index 0000000000..761d21cf46 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/chassis.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python +# +# Name: chassis.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + from sonic_platform_base.chassis_base import ChassisBase + from sonic_platform.eeprom import Eeprom + from sonic_platform.fan import Fan + from sonic_platform.psu import Psu + from sonic_platform.sfp import Sfp + from sonic_platform.qsfp import QSfp + from sonic_platform.thermal import Thermal +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Chassis(ChassisBase): + + def __init__(self): + ChassisBase.__init__(self) + self.__num_of_fans = 8 + self.__num_of_psus = 2 + self.__num_of_sfps = 56 + self.__start_of_qsfp = 48 + self.__num_of_thermals = 5 + + # Initialize EEPROM + self._eeprom = Eeprom() + + # Initialize FAN + for index in range(1, self.__num_of_fans + 1): + fan = Fan(index, False, 0) + self._fan_list.append(fan) + + # Initialize PSU + for index in range(1, self.__num_of_psus + 1): + psu = Psu(index) + self._psu_list.append(psu) + + # Initialize SFP + for index in range(0, self.__num_of_sfps): + if index < self.__start_of_qsfp: + sfp = Sfp(index) + else: + sfp = QSfp(index) + self._sfp_list.append(sfp) + + # Initialize THERMAL + for index in range(0, self.__num_of_thermals): + thermal = Thermal(index) + self._thermal_list.append(thermal) + + +############################################## +# Device methods +############################################## + + 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 + Returns: + string: Serial number of chassis + """ + return self._eeprom.serial_number_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 + +############################################## +# Chassis methods +############################################## + + def get_base_mac(self): + """ + Retrieves the base MAC address for the chassis + + Returns: + A string containing the MAC address in the format + 'XX:XX:XX:XX:XX:XX' + """ + return self._eeprom.base_mac_address() + + 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_system_eeprom_info(self): + """ + Retrieves the full content of system EEPROM information for the chassis + + Returns: + A dictionary where keys are the type code defined in + OCP ONIE TlvInfo EEPROM format and values are their corresponding + values. + Ex. { '0x21':'AG9064', '0x22':'V1.0', '0x23':'AG9064-0109867821', + '0x24':'001c0f000fcd0a', '0x25':'02/03/2018 16:22:00', + '0x26':'01', '0x27':'REV01', '0x28':'AG9064-C2358-16G'} + """ + return self._eeprom.system_eeprom_info() + + def get_reboot_cause(self): + """ + Retrieves the cause of the previous reboot + Returns: + A tuple (string, string) where the first element is a string + containing the cause of the previous reboot. This string must be + one of the predefined strings in this class. If the first string + is "REBOOT_CAUSE_HARDWARE_OTHER", the second string can be used + to pass a description of the reboot cause. + """ + raise NotImplementedError diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/eeprom.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/eeprom.py new file mode 100644 index 0000000000..5840246fdd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/eeprom.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# +# Name: eeprom.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + from sonic_eeprom import eeprom_tlvinfo + import binascii +except ImportError, e: + raise ImportError(str(e) + "- required module not found") + +class Eeprom(eeprom_tlvinfo.TlvInfoDecoder): + + def __init__(self): + self.__eeprom_path = "/sys/class/i2c-adapter/i2c-2/2-0055/eeprom" + super(Eeprom, self).__init__(self.__eeprom_path, 0, '', True) + self.__eeprom_tlv_dict = dict() + try: + self.__eeprom_data = self.read_eeprom() + except: + self.__eeprom_data = "N/A" + raise RuntimeError("Eeprom is not Programmed") + else: + eeprom = self.__eeprom_data + + if not self.is_valid_tlvinfo_header(eeprom): + return + + total_length = (ord(eeprom[9]) << 8) | ord(eeprom[10]) + tlv_index = self._TLV_INFO_HDR_LEN + tlv_end = self._TLV_INFO_HDR_LEN + total_length + + while (tlv_index + 2) < len(eeprom) and tlv_index < tlv_end: + if not self.is_valid_tlv(eeprom[tlv_index:]): + break + + tlv = eeprom[tlv_index:tlv_index + 2 + + ord(eeprom[tlv_index + 1])] + code = "0x%02X" % (ord(tlv[0])) + + if ord(tlv[0]) == self._TLV_CODE_VENDOR_EXT: + value = str((ord(tlv[2]) << 24) | (ord(tlv[3]) << 16) | + (ord(tlv[4]) << 8) | ord(tlv[5])) + value += str(tlv[6:6 + ord(tlv[1])]) + else: + name, value = self.decoder(None, tlv) + + self.__eeprom_tlv_dict[code] = value + if ord(eeprom[tlv_index]) == self._TLV_CODE_CRC_32: + break + + tlv_index += ord(eeprom[tlv_index+1]) + 2 + + def serial_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERIAL_NUMBER) + if not is_valid: + return "N/A" + return results[2] + + def base_mac_address(self): + (is_valid, t) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_MAC_BASE) + if not is_valid or t[1] != 6: + return super(eeprom_tlvinfo.TlvInfoDecoder, self).switchaddrstr(self.__eeprom_data) + + return ":".join([binascii.b2a_hex(T) for T in t[2]]) + + def modelstr(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PRODUCT_NAME) + if not is_valid: + return "N/A" + + return results[2] + + def part_number_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_PART_NUMBER) + if not is_valid: + return "N/A" + + return results[2] + + def serial_tag_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_SERVICE_TAG) + if not is_valid: + return "N/A" + + return results[2] + + def revision_str(self): + (is_valid, results) = self.get_tlv_field( + self.__eeprom_data, self._TLV_CODE_DEVICE_VERSION) + if not is_valid: + return "N/A" + + return results[2] + + def 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-inventec/d6356/sonic_platform/fan.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/fan.py new file mode 100644 index 0000000000..b9423e43dc --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/fan.py @@ -0,0 +1,204 @@ +#!/usr/bin/env python +# +# Name: fan.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import math + import os + from sonic_platform_base.fan_base import FanBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Fan(FanBase): + + def __init__(self, index, is_psu_fan=False, psu_index=0): + self.__index = index + self.__is_psu_fan = is_psu_fan + + if self.__is_psu_fan: + self.__psu_index = psu_index + self.__presence_attr = "/sys/class/hwmon/hwmon{}/fan{}_input".format((self.__psu_index + 6), self.__index) + self.__speed_rpm_attr = "/sys/class/hwmon/hwmon{}/fan{}_input".format((self.__psu_index + 6), self.__index) + self.__pwm_attr = None + else: + self.__presence_attr = "/sys/class/hwmon/hwmon2/device/fan{}_input".format(self.__index) + self.__speed_rpm_attr = "/sys/class/hwmon/hwmon2/device/fan{}_input".format(self.__index) + self.__pwm_attr = "/sys/class/hwmon/hwmon2/device/pwm{}".format((self.__index + 1)/2) + + def __get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + if self.__is_psu_fan: + return "PSU{}-FAN{}".format(self.__psu_index, self.__index) + else: + return "FAN{}".format(self.__index) + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + presence = False + attr_path = self.__presence_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) != 0): + presence = True + + return presence + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + + Returns: + string: Model/part number of device + """ + return "N/A" + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + return "N/A" + + def get_status(self): + """ + Retrieves the operational status of the device + + Returns: + A boolean value, True if device is operating properly, False if not + """ + return self.get_presence() + +############################################## +# FAN methods +############################################## + + def get_direction(self): + """ + Retrieves the direction of fan + + Returns: + A string, either FAN_DIRECTION_INTAKE or FAN_DIRECTION_EXHAUST + depending on fan direction + """ + raise NotImplementedError + + def get_speed(self): + """ + Retrieves the speed of fan as a percentage of full speed + + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + speed = 0 + + if self.__is_psu_fan: + attr_path = self.__speed_rpm_attr + else: + attr_path = self.__pwm_attr + + if self.get_presence() and None != attr_path: + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if self.__is_psu_fan: + fan_speed_rpm = int(attr_rv) + speed = math.ceil(float(fan_speed_rpm) * 100 / 11000) + else: + pwm = int(attr_rv) + speed = math.ceil(float(pwm * 100 / 255)) + + return speed + + def get_target_speed(self): + """ + Retrieves the target (expected) speed of the fan + + Returns: + An integer, the percentage of full fan speed, in the range 0 (off) + to 100 (full speed) + """ + raise NotImplementedError + + def get_speed_tolerance(self): + """ + Retrieves the speed tolerance of the fan + + Returns: + An integer, the percentage of variance from target speed which is + considered tolerable + """ + raise NotImplementedError + + def set_speed(self, speed): + """ + Sets the fan speed + + Args: + speed: An integer, the percentage of full fan speed to set fan to, + in the range 0 (off) to 100 (full speed) + + Returns: + A boolean, True if speed is set successfully, False if not + """ + raise NotImplementedError + + def set_status_led(self, color): + """ + Sets the state of the fan module status LED + + Args: + color: A string representing the color with which to set the + fan module status LED + + Returns: + bool: True if status LED state is set successfully, False if not + """ + raise NotImplementedError + + def get_status_led(self): + """ + Gets the state of the fan status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + if self.get_status() and self.get_speed() > 0: + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_OFF + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/platform.py new file mode 100644 index 0000000000..7d6bda4502 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/platform.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +# +# Name: platform.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + + +try: + from sonic_platform_base.platform_base import PlatformBase + from sonic_platform.chassis import Chassis +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + + +class Platform(PlatformBase): + + def __init__(self): + PlatformBase.__init__(self) + self._chassis = Chassis() diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/psu.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/psu.py new file mode 100644 index 0000000000..3798ef9e5b --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/psu.py @@ -0,0 +1,202 @@ +#!/usr/bin/env python +# +# Name: psu.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + from sonic_platform_base.psu_base import PsuBase + from sonic_platform.fan import Fan +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Psu(PsuBase): + + def __init__(self, index): + self.__num_of_fans = 1 + self.__index = index + self.__psu_presence_attr = "/sys/class/hwmon/hwmon2/device/psu{}".format(self.__index) + self.__psu_power_in_attr = "/sys/class/hwmon/hwmon{}/power1_input".format(self.__index + 6) + self.__psu_power_out_attr = "/sys/class/hwmon/hwmon{}/power2_input".format(self.__index + 6) + self.__psu_voltage_out_attr = "/sys/class/hwmon/hwmon{}/in2_input".format(self.__index + 6) + self.__psu_current_out_attr = "/sys/class/hwmon/hwmon{}/curr2_input".format(self.__index + 6) + + # Overriding _fan_list class variable defined in PsuBase, to make it unique per Psu object + self._fan_list = [] + + # Initialize FAN + for x in range(1, self.__num_of_fans + 1): + fan = Fan(x, True, self.__index) + self._fan_list.append(fan) + + def __get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return "PSU{}".format(self.__index) + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + presence = False + attr_normal = "1:normal" + attr_path = self.__psu_presence_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (attr_rv == attr_normal): + presence = True + + return presence + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + + Returns: + string: Model/part number of device + """ + return "N/A" + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + return "N/A" + + def get_status(self): + """ + Retrieves the operational status of the device + + Returns: + A boolean value, True if device is operating properly, False if not + """ + status = False + attr_path = self.__psu_power_in_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) != 0): + status = True + + return status + +############################################## +# PSU methods +############################################## + + def get_voltage(self): + """ + Retrieves current PSU voltage output + + Returns: + A float number, the output voltage in volts, + e.g. 12.1 + """ + voltage_out = 0.0 + attr_path = self.__psu_voltage_out_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + voltage_out = float(attr_rv) / 1000 + + return voltage_out + + def get_current(self): + """ + Retrieves present electric current supplied by PSU + + Returns: + A float number, the electric current in amperes, e.g 15.4 + """ + current_out = 0.0 + attr_path = self.__psu_current_out_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + current_out = float(attr_rv) / 1000 + + return current_out + + def get_power(self): + """ + Retrieves current energy supplied by PSU + + Returns: + A float number, the power in watts, e.g. 302.6 + """ + power_out = 0.0 + attr_path = self.__psu_power_out_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + power_out = float(attr_rv) / 1000000 + + return power_out + + def get_powergood_status(self): + """ + Retrieves the powergood status of PSU + + Returns: + A boolean, True if PSU has stablized its output voltages and passed all + its internal self-tests, False if not. + """ + return self.get_status() + + def set_status_led(self, color): + """ + Sets the state of the PSU status LED + + Args: + color: A string representing the color with which to set the + PSU status LED + + Returns: + bool: True if status LED state is set successfully, False if not + """ + raise NotImplementedError + + def get_status_led(self): + """ + Gets the state of the PSU status LED + + Returns: + A string, one of the predefined STATUS_LED_COLOR_* strings above + """ + if self.get_powergood_status(): + return self.STATUS_LED_COLOR_GREEN + else: + return self.STATUS_LED_COLOR_OFF + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/qsfp.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/qsfp.py new file mode 100644 index 0000000000..f3f873be08 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/qsfp.py @@ -0,0 +1,925 @@ +#!/usr/bin/env python +# +# Name: qsfp.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + import sys + import time + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8436 import sff8436Dom + from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +INFO_OFFSET = 128 +DOM_OFFSET = 0 + +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_QSFP = 20 +XCVR_HW_REV_WIDTH_QSFP = 2 +XCVR_CABLE_LENGTH_WIDTH_QSFP = 5 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_OSFP = 2 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 1 + +# Offset for values in QSFP eeprom +QSFP_DOM_REV_OFFSET = 1 +QSFP_DOM_REV_WIDTH = 1 +QSFP_TEMPE_OFFSET = 22 +QSFP_TEMPE_WIDTH = 2 +QSFP_VOLT_OFFSET = 26 +QSFP_VOLT_WIDTH = 2 +QSFP_CHANNL_MON_OFFSET = 34 +QSFP_CHANNL_MON_WIDTH = 16 +QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH = 24 +QSFP_CONTROL_OFFSET = 86 +QSFP_CONTROL_WIDTH = 8 +QSFP_CHANNL_RX_LOS_STATUS_OFFSET = 3 +QSFP_CHANNL_RX_LOS_STATUS_WIDTH = 1 +QSFP_CHANNL_TX_FAULT_STATUS_OFFSET = 4 +QSFP_CHANNL_TX_FAULT_STATUS_WIDTH = 1 +QSFP_POWEROVERRIDE_OFFSET = 93 +QSFP_POWEROVERRIDE_WIDTH = 1 +QSFP_MODULE_THRESHOLD_OFFSET = 128 +QSFP_MODULE_THRESHOLD_WIDTH = 24 +QSFP_CHANNEL_THRESHOLD_OFFSET = 176 +QSFP_CHANNEL_THRESHOLD_WIDTH = 16 + +class QSfp(SfpBase): + + def __init__(self, index): + self.__index = index + + self.__platform = "x86_64-inventec_d6356-r0" + self.__hwsku = "INVENTEC-D6356" + + self.__port_to_i2c_mapping = { + 0:22, 1:23, 2:24, 3:25, 4:26, 5:27, 6:28, 7:29, + 8:30, 9:31, 10:32, 11:33, 12:34, 13:35, 14:36, 15:37, + 16:38, 17:39, 18:40, 19:41, 20:42, 21:43, 22:44, 23:45, + 24:46, 25:47, 26:48, 27:49, 28:50, 29:51, 30:52, 31:53, + 32:54, 33:55, 34:56, 35:57, 36:58, 37:59, 38:60, 39:61, + 40:62, 41:63, 42:64, 43:65, 44:66, 45:67, 46:68, 47:69, + 48:14, 49:15, 50:16, 51:17, 52:18, 53:19, 54:20, 55:21 + } + self.__port_end = len(self.__port_to_i2c_mapping) - 1; + + self.__presence_attr = None + self.__eeprom_path = None + if self.__index in range(0, self.__port_end + 1): + self.__presence_attr = "/sys/class/swps/port{}/present".format(self.__index) + self.__lpmode_attr = "/sys/class/swps/port{}/lpmod".format(self.__index) + self.__reset_attr = "/sys/class/swps/port{}/reset".format(self.__index) + self.__eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom".format(self.__port_to_i2c_mapping[self.__index]) + + #print(self.__eeprom_path) + + SfpBase.__init__(self) + + def __get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + + def __is_host(self): + return os.system("docker > /dev/null 2>&1") == 0 + + def __get_path_to_port_config_file(self): + host_platform_root_path = '/usr/share/sonic/device' + docker_hwsku_path = '/usr/share/sonic/hwsku' + + host_platform_path = "/".join([host_platform_root_path, self.__platform]) + hwsku_path = "/".join([host_platform_path, self.__hwsku]) if self.__is_host() else docker_hwsku_path + + return "/".join([hwsku_path, "port_config.ini"]) + + def __read_eeprom_specific_bytes(self, offset, num_bytes): + sysfsfile_eeprom = None + eeprom_raw = [] + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + sysfs_eeprom_path = self.__eeprom_path + try: + sysfsfile_eeprom = open(sysfs_eeprom_path, mode="rb", buffering=0) + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + raw_len = len(raw) + for n in range(0, raw_len): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except: + pass + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + + return eeprom_raw + + def __convert_string_to_num(self, value_str): + if "-inf" in value_str: + return 'N/A' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + name = None + + sfputil_helper = SfpUtilHelper() + sfputil_helper.read_porttab_mappings(self.__get_path_to_port_config_file()) + name = sfputil_helper.logical[self.__index] or "Unknown" + return name + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + presence = False + attr_path = self.__presence_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) == 0): + presence = True + + return presence + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + + Returns: + string: Model/part number of device + """ + transceiver_info_dict = self.get_transceiver_info() + return transceiver_info_dict.get("modelname", "N/A") + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + transceiver_info_dict = self.get_transceiver_info() + return transceiver_info_dict.get("serialnum", "N/A") + + def get_status(self): + """ + Retrieves the operational status of the device + + Returns: + A boolean value, True if device is operating properly, False if not + """ + return self.get_presence() and not self.get_reset_status() + +############################################## +# SFP methods +############################################## + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardwarerev |1*255VCHAR |hardware version of SFP + serialnum |1*255VCHAR |serial number of the SFP + manufacturename |1*255VCHAR |SFP vendor name + modelname |1*255VCHAR |SFP model name + Connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + mominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + + transceiver_info_dict_keys = ['type', 'hardwarerev', + 'serialnum', 'manufacturename', + 'modelname', 'Connector', + 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', + 'cable_length', 'nominal_bit_rate', + 'specification_compliance', 'vendor_date', + 'vendor_oui'] + + qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', + 'Length OM2(m)', 'Length OM1(m)', 'Length Cable Assembly(m)') + + qsfp_compliance_code_tup = ('10/40G Ethernet Compliance Code', 'SONET Compliance codes', + 'SAS/SATA compliance codes', 'Gigabit Ethernet Compliant codes', + 'Fibre Channel link length/Transmitter Technology', 'Fibre Channel transmission media', + 'Fibre Channel Speed') + + sfpi_obj = sff8436InterfaceId() + if not self.get_presence() or not sfpi_obj: + return {} + + offset = INFO_OFFSET + + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes((offset + XCVR_INTFACE_BULK_OFFSET), XCVR_INTFACE_BULK_WIDTH_QSFP) + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw, 0) + + sfp_vendor_name_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) + + sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + + sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes((offset + XCVR_HW_REV_OFFSET), XCVR_HW_REV_WIDTH_QSFP) + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) + + sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + + sfp_vendor_oui_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) + if sfp_vendor_oui_raw is not None: + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_vendor_oui_raw, 0) + + sfp_vendor_date_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH) + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_vendor_date_raw, 0) + + transceiver_info_dict = dict.fromkeys(transceiver_info_dict_keys, 'N/A') + + if sfp_interface_bulk_data: + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['Connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value'] + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) + + transceiver_info_dict['manufacturename'] = sfp_vendor_name_data['data']['Vendor Name']['value'] if sfp_vendor_name_data else 'N/A' + transceiver_info_dict['modelname'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] if sfp_vendor_pn_data else 'N/A' + transceiver_info_dict['hardwarerev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] if sfp_vendor_rev_data else 'N/A' + transceiver_info_dict['serialnum'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] if sfp_vendor_sn_data else 'N/A' + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] if sfp_vendor_oui_data else 'N/A' + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] if sfp_vendor_date_data else 'N/A' + + transceiver_info_dict['cable_type'] = "Unknown" + transceiver_info_dict['cable_length'] = "Unknown" + for key in qsfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + compliance_code_dict = dict() + for key in qsfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + + return transceiver_info_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + transceiver_dom_info_dict_keys = ['rx_los', 'tx_fault', + 'reset_status', 'power_lpmode', + 'tx_disable', 'tx_disable_channel', + 'temperature', 'voltage', + 'rx1power', 'rx2power', + 'rx3power', 'rx4power', + 'tx1bias', 'tx2bias', + 'tx3bias', 'tx4bias', + 'tx1power', 'tx2power', + 'tx3power', 'tx4power'] + + sfpd_obj = sff8436Dom() + sfpi_obj = sff8436InterfaceId() + + if not self.get_presence() or not sfpi_obj or not sfpd_obj: + return {} + + transceiver_dom_info_dict = dict.fromkeys(transceiver_dom_info_dict_keys, 'N/A') + offset = DOM_OFFSET + offset_xcvr = INFO_OFFSET + + # QSFP capability byte parse, through this byte can know whether it support tx_power or not. + # TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436, + # need to add more code for determining the capability and version compliance + # in SFF-8636 dom capability definitions evolving with the versions. + qsfp_dom_capability_raw = self.__read_eeprom_specific_bytes((offset_xcvr + XCVR_DOM_CAPABILITY_OFFSET), XCVR_DOM_CAPABILITY_WIDTH) + if qsfp_dom_capability_raw is not None: + qspf_dom_capability_data = sfpi_obj.parse_qsfp_dom_capability(qsfp_dom_capability_raw, 0) + else: + return None + + dom_temperature_raw = self.__read_eeprom_specific_bytes((offset + QSFP_TEMPE_OFFSET), QSFP_TEMPE_WIDTH) + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + + dom_voltage_raw = self.__read_eeprom_specific_bytes((offset + QSFP_VOLT_OFFSET), QSFP_VOLT_WIDTH) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + + qsfp_dom_rev_raw = self.__read_eeprom_specific_bytes((offset + QSFP_DOM_REV_OFFSET), QSFP_DOM_REV_WIDTH) + if qsfp_dom_rev_raw is not None: + qsfp_dom_rev_data = sfpd_obj.parse_sfp_dom_rev(qsfp_dom_rev_raw, 0) + qsfp_dom_rev = qsfp_dom_rev_data['data']['dom_rev']['value'] + + # The tx_power monitoring is only available on QSFP which compliant with SFF-8636 + # and claimed that it support tx_power with one indicator bit. + dom_channel_monitor_data = {} + dom_channel_monitor_raw = None + qsfp_tx_power_support = qspf_dom_capability_data['data']['Tx_power_support']['value'] + if (qsfp_dom_rev[0:8] != 'SFF-8636' or (qsfp_dom_rev[0:8] == 'SFF-8636' and qsfp_tx_power_support != 'on')): + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes((offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + + else: + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes((offset + QSFP_CHANNL_MON_OFFSET), QSFP_CHANNL_MON_WITH_TX_POWER_WIDTH) + if dom_channel_monitor_raw is not None: + dom_channel_monitor_data = sfpd_obj.parse_channel_monitor_params_with_tx_power(dom_channel_monitor_raw, 0) + transceiver_dom_info_dict['tx1power'] = dom_channel_monitor_data['data']['TX1Power']['value'] + transceiver_dom_info_dict['tx2power'] = dom_channel_monitor_data['data']['TX2Power']['value'] + transceiver_dom_info_dict['tx3power'] = dom_channel_monitor_data['data']['TX3Power']['value'] + transceiver_dom_info_dict['tx4power'] = dom_channel_monitor_data['data']['TX4Power']['value'] + + if dom_channel_monitor_raw: + transceiver_dom_info_dict['rx1power'] = dom_channel_monitor_data['data']['RX1Power']['value'] + transceiver_dom_info_dict['rx2power'] = dom_channel_monitor_data['data']['RX2Power']['value'] + transceiver_dom_info_dict['rx3power'] = dom_channel_monitor_data['data']['RX3Power']['value'] + transceiver_dom_info_dict['rx4power'] = dom_channel_monitor_data['data']['RX4Power']['value'] + transceiver_dom_info_dict['tx1bias'] = dom_channel_monitor_data['data']['TX1Bias']['value'] + transceiver_dom_info_dict['tx2bias'] = dom_channel_monitor_data['data']['TX2Bias']['value'] + transceiver_dom_info_dict['tx3bias'] = dom_channel_monitor_data['data']['TX3Bias']['value'] + transceiver_dom_info_dict['tx4bias'] = dom_channel_monitor_data['data']['TX4Bias']['value'] + + for key in transceiver_dom_info_dict: + transceiver_dom_info_dict[key] = self.__convert_string_to_num(transceiver_dom_info_dict[key]) + + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() + transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['tx_disable'] = self.get_tx_disable() + transceiver_dom_info_dict['tx_disable_channel'] = self.get_tx_disable_channel() + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + + + return transceiver_dom_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + transceiver_dom_threshold_info_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + + sfpd_obj = sff8436Dom() + if not self.get_presence() or not sfpd_obj: + return {} + + transceiver_dom_threshold_dict = dict.fromkeys(transceiver_dom_threshold_info_dict_keys, 'N/A') + offset = DOM_OFFSET + + dom_module_threshold_raw = self.__read_eeprom_specific_bytes((offset + QSFP_MODULE_THRESHOLD_OFFSET), QSFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw: + module_threshold_values = sfpd_obj.parse_module_threshold_values(dom_module_threshold_raw, 0) + module_threshold_data = module_threshold_values.get('data') + if module_threshold_data: + transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['TempHighAlarm']['value'] + transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['TempLowAlarm']['value'] + transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['TempHighWarning']['value'] + transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['TempLowWarning']['value'] + transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['VccHighAlarm']['value'] + transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['VccLowAlarm']['value'] + transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['VccHighWarning']['value'] + transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['VccLowWarning']['value'] + + dom_channel_thres_raw = self.__read_eeprom_specific_bytes((offset + QSFP_CHANNEL_THRESHOLD_OFFSET), QSFP_CHANNEL_THRESHOLD_WIDTH) + channel_threshold_values = sfpd_obj.parse_channel_threshold_values(dom_channel_thres_raw, 0) + channel_threshold_data = channel_threshold_values.get('data') + if channel_threshold_data: + transceiver_dom_threshold_dict['rxpowerhighalarm'] = channel_threshold_data['RxPowerHighAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerlowalarm'] = channel_threshold_data['RxPowerLowAlarm']['value'] + transceiver_dom_threshold_dict['rxpowerhighwarning'] = channel_threshold_data['RxPowerHighWarning']['value'] + transceiver_dom_threshold_dict['rxpowerlowwarning'] = channel_threshold_data['RxPowerLowWarning']['value'] + transceiver_dom_threshold_dict['txpowerhighalarm'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerlowalarm'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerhighwarning'] = "0.0dBm" + transceiver_dom_threshold_dict['txpowerlowwarning'] = "0.0dBm" + transceiver_dom_threshold_dict['txbiashighalarm'] = channel_threshold_data['TxBiasHighAlarm']['value'] + transceiver_dom_threshold_dict['txbiaslowalarm'] = channel_threshold_data['TxBiasLowAlarm']['value'] + transceiver_dom_threshold_dict['txbiashighwarning'] = channel_threshold_data['TxBiasHighWarning']['value'] + transceiver_dom_threshold_dict['txbiaslowwarning'] = channel_threshold_data['TxBiasLowWarning']['value'] + + for key in transceiver_dom_threshold_dict: + transceiver_dom_threshold_dict[key] = self.__convert_string_to_num(transceiver_dom_threshold_dict[key]) + + return transceiver_dom_threshold_dict + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + + Returns: + A Boolean, True if reset enabled, False if disabled + """ + reset_status = False + attr_path = self.__reset_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) == 0): + reset_status = True + + return reset_status + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + rx_los = False + rx_los_list = [] + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(QSFP_CHANNL_RX_LOS_STATUS_OFFSET, QSFP_CHANNL_RX_LOS_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + rx_los_data = int(dom_channel_monitor_raw[0], 16) + rx_los_list.append(rx_los_data & 0x01 != 0) + rx_los_list.append(rx_los_data & 0x02 != 0) + rx_los_list.append(rx_los_data & 0x04 != 0) + rx_los_list.append(rx_los_data & 0x08 != 0) + rx_los = rx_los_list[0] and rx_los_list[1] and rx_los_list[2] and rx_los_list[3] + return rx_los + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + tx_fault = False + tx_fault_list = [] + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes(QSFP_CHANNL_TX_FAULT_STATUS_OFFSET, QSFP_CHANNL_TX_FAULT_STATUS_WIDTH) + if dom_channel_monitor_raw is not None: + tx_fault_data = int(dom_channel_monitor_raw[0], 16) + tx_fault_list.append(tx_fault_data & 0x01 != 0) + tx_fault_list.append(tx_fault_data & 0x02 != 0) + tx_fault_list.append(tx_fault_data & 0x04 != 0) + tx_fault_list.append(tx_fault_data & 0x08 != 0) + tx_fault = tx_fault_list[0] and tx_fault_list[1] and tx_fault_list[2] and tx_fault_list[3] + + return tx_fault + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + tx_disable = False + tx_disable_list = [] + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return tx_disable + + dom_control_raw = self.__read_eeprom_specific_bytes(QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + tx_disable_list.append('On' == dom_control_data['data']['TX1Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX2Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX3Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX4Disable']['value']) + tx_disable = tx_disable_list[0] and tx_disable_list[1] and tx_disable_list[2] and tx_disable_list[3] + + return tx_disable + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + tx_disable_channel = 0 + tx_disable_list = [] + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return tx_disable_channel + + dom_control_raw = self.__read_eeprom_specific_bytes(QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + tx_disable_list.append('On' == dom_control_data['data']['TX1Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX2Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX3Disable']['value']) + tx_disable_list.append('On' == dom_control_data['data']['TX4Disable']['value']) + + for i in range(len(tx_disable_list)): + if tx_disable_list[i]: + tx_disable_channel |= 1 << i + + return tx_disable_channel + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + lpmode = False + attr_path = self.__lpmode_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) == 1): + lpmode = True + + return lpmode + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + power_override = False + + sfpd_obj = sff8436Dom() + if sfpd_obj is None: + return power_override + + dom_control_raw = self.__read_eeprom_specific_bytes(QSFP_CONTROL_OFFSET, QSFP_CONTROL_WIDTH) + if dom_control_raw is not None: + dom_control_data = sfpd_obj.parse_control_bytes(dom_control_raw, 0) + power_override = ('On' == dom_control_data['data']['PowerOverride']['value']) + + return power_override + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + + Returns: + An integer number of current temperature in Celsius + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + return transceiver_dom_info_dict.get("temperature", "N/A") + + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + + Returns: + An integer number of supply voltage in mV + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + return transceiver_dom_info_dict.get("voltage", "N/A") + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + tx1_bs = transceiver_dom_info_dict.get("tx1bias", "N/A") + tx2_bs = transceiver_dom_info_dict.get("tx2bias", "N/A") + tx3_bs = transceiver_dom_info_dict.get("tx3bias", "N/A") + tx4_bs = transceiver_dom_info_dict.get("tx4bias", "N/A") + return [tx1_bs, tx2_bs, tx3_bs, tx4_bs] if transceiver_dom_info_dict else [] + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + rx1_pw = transceiver_dom_info_dict.get("rx1power", "N/A") + rx2_pw = transceiver_dom_info_dict.get("rx2power", "N/A") + rx3_pw = transceiver_dom_info_dict.get("rx3power", "N/A") + rx4_pw = transceiver_dom_info_dict.get("rx4power", "N/A") + return [rx1_pw, rx2_pw, rx3_pw, rx4_pw] if transceiver_dom_info_dict else [] + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + tx1_pw = transceiver_dom_info_dict.get("tx1power", "N/A") + tx2_pw = transceiver_dom_info_dict.get("tx2power", "N/A") + tx3_pw = transceiver_dom_info_dict.get("tx3power", "N/A") + tx4_pw = transceiver_dom_info_dict.get("tx4power", "N/A") + return [tx1_pw, tx2_pw, tx3_pw, tx4_pw] + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + + Returns: + A boolean, True if successful, False if not + """ + + try: + reg_file = open(self.__reset_attr, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = 0 + reg_file.write(hex(reg_value)) + reg_file.close() + + # Sleep 2 second to allow it to settle + time.sleep(2) + + try: + reg_file = open(self.__reset_attr, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = 1 + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + sysfs_eeprom_path = self.__eeprom_path + sysfsfile_eeprom = None + try: + tx_disable_ctl = 0xf if tx_disable else 0x0 + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom = open(sysfs_eeprom_path, "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + + Returns: + A boolean, True if successful, False if not + """ + sysfs_eeprom_path = self.__eeprom_path + sysfsfile_eeprom = None + try: + channel_state = self.get_tx_disable_channel() + tx_enable_mask = [0xe, 0xd, 0xb, 0x7] + tx_disable_mask = [0x1, 0x3, 0x7, 0xf] + tx_disable_ctl = channel_state | tx_disable_mask[channel] if disable else channel_state & tx_enable_mask[channel] + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom = open(sysfs_eeprom_path, "r+b") + sysfsfile_eeprom.seek(QSFP_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + try: + reg_file = open(self.__lpmode_attr, "r+") + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + reg_value = int(reg_file.readline().rstrip()) + + if lpmode is True: + reg_value = 1 + else: + reg_value = 0 + + reg_file.write(hex(reg_value)) + reg_file.close() + + return True + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + sysfs_eeprom_path = self.__eeprom_path + sysfsfile_eeprom = None + try: + power_override_bit = 0 + if power_override: + power_override_bit |= 1 << 0 + + power_set_bit = 0 + if power_set: + power_set_bit |= 1 << 1 + + buffer = create_string_buffer(1) + buffer[0] = chr(power_override_bit | power_set_bit) + # Write to eeprom + sysfsfile_eeprom = open(sysfs_eeprom_path, "r+b") + sysfsfile_eeprom.seek(QSFP_POWEROVERRIDE_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + finally: + if sysfsfile_eeprom is not None: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/sfp.py new file mode 100644 index 0000000000..d8d88a2df2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/sfp.py @@ -0,0 +1,739 @@ +#!/usr/bin/env python +# +# Name: sfp.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + import sys + from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom + from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId + from sonic_platform_base.sonic_sfp.sff8472 import sffbase + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +INFO_OFFSET = 0 +DOM_OFFSET = 256 + +XCVR_INTFACE_BULK_OFFSET = 0 +XCVR_INTFACE_BULK_WIDTH_SFP = 21 +XCVR_VENDOR_NAME_OFFSET = 20 +XCVR_VENDOR_NAME_WIDTH = 16 +XCVR_VENDOR_OUI_OFFSET = 37 +XCVR_VENDOR_OUI_WIDTH = 3 +XCVR_VENDOR_PN_OFFSET = 40 +XCVR_VENDOR_PN_WIDTH = 16 +XCVR_HW_REV_OFFSET = 56 +XCVR_HW_REV_WIDTH_SFP = 4 +XCVR_VENDOR_SN_OFFSET = 68 +XCVR_VENDOR_SN_WIDTH = 16 +XCVR_VENDOR_DATE_OFFSET = 84 +XCVR_VENDOR_DATE_WIDTH = 8 +XCVR_DOM_CAPABILITY_OFFSET = 92 +XCVR_DOM_CAPABILITY_WIDTH = 1 + +# Offset for values in SFP eeprom +SFP_TEMPE_OFFSET = 96 +SFP_TEMPE_WIDTH = 2 +SFP_VOLT_OFFSET = 98 +SFP_VOLT_WIDTH = 2 +SFP_CHANNL_MON_OFFSET = 100 +SFP_CHANNL_MON_WIDTH = 6 +SFP_MODULE_THRESHOLD_OFFSET = 0 +SFP_MODULE_THRESHOLD_WIDTH = 40 +SFP_CHANNL_THRESHOLD_OFFSET = 112 +SFP_CHANNL_THRESHOLD_WIDTH = 2 +SFP_STATUS_CONTROL_OFFSET = 110 +SFP_STATUS_CONTROL_WIDTH = 1 +SFP_TX_DISABLE_HARD_BIT = 7 +SFP_TX_DISABLE_SOFT_BIT = 6 + +class Sfp(SfpBase): + + def __init__(self, index): + self.__index = index + + self.__platform = "x86_64-inventec_d6356-r0" + self.__hwsku = "INVENTEC-D6356" + + self.__port_to_i2c_mapping = { + 0:22, 1:23, 2:24, 3:25, 4:26, 5:27, 6:28, 7:29, + 8:30, 9:31, 10:32, 11:33, 12:34, 13:35, 14:36, 15:37, + 16:38, 17:39, 18:40, 19:41, 20:42, 21:43, 22:44, 23:45, + 24:46, 25:47, 26:48, 27:49, 28:50, 29:51, 30:52, 31:53, + 32:54, 33:55, 34:56, 35:57, 36:58, 37:59, 38:60, 39:61, + 40:62, 41:63, 42:64, 43:65, 44:66, 45:67, 46:68, 47:69, + 48:14, 49:15, 50:16, 51:17, 52:18, 53:19, 54:20, 55:21 + } + self.__port_end = len(self.__port_to_i2c_mapping) - 1; + + self.__presence_attr = None + self.__eeprom_path = None + if self.__index in range(0, self.__port_end + 1): + self.__presence_attr = "/sys/class/swps/port{}/present".format(self.__index) + self.__eeprom_path = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom".format(self.__port_to_i2c_mapping[self.__index]) + + SfpBase.__init__(self) + + def __get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + + def __is_host(self): + return os.system("docker > /dev/null 2>&1") == 0 + + def __get_path_to_port_config_file(self): + host_platform_root_path = '/usr/share/sonic/device' + docker_hwsku_path = '/usr/share/sonic/hwsku' + + host_platform_path = "/".join([host_platform_root_path, self.__platform]) + hwsku_path = "/".join([host_platform_path, self.__hwsku]) if self.__is_host() else docker_hwsku_path + + return "/".join([hwsku_path, "port_config.ini"]) + + def __read_eeprom_specific_bytes(self, offset, num_bytes): + sysfsfile_eeprom = None + eeprom_raw = [] + + for i in range(0, num_bytes): + eeprom_raw.append("0x00") + + sysfs_eeprom_path = self.__eeprom_path + try: + sysfsfile_eeprom = open(sysfs_eeprom_path, mode="rb", buffering=0) + sysfsfile_eeprom.seek(offset) + raw = sysfsfile_eeprom.read(num_bytes) + raw_len = len(raw) + for n in range(0, raw_len): + eeprom_raw[n] = hex(ord(raw[n]))[2:].zfill(2) + except: + pass + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + + return eeprom_raw + + def __convert_string_to_num(self, value_str): + if "-inf" in value_str: + return 'N/A' + elif "Unknown" in value_str: + return 'N/A' + elif 'dBm' in value_str: + t_str = value_str.rstrip('dBm') + return float(t_str) + elif 'mA' in value_str: + t_str = value_str.rstrip('mA') + return float(t_str) + elif 'C' in value_str: + t_str = value_str.rstrip('C') + return float(t_str) + elif 'Volts' in value_str: + t_str = value_str.rstrip('Volts') + return float(t_str) + else: + return 'N/A' + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + name = None + + sfputil_helper = SfpUtilHelper() + sfputil_helper.read_porttab_mappings(self.__get_path_to_port_config_file()) + name = sfputil_helper.logical[self.__index] or "Unknown" + return name + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + presence = False + attr_path = self.__presence_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) == 0): + presence = True + + return presence + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + + Returns: + string: Model/part number of device + """ + transceiver_info_dict = self.get_transceiver_info() + return transceiver_info_dict.get("modelname", "N/A") + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + transceiver_info_dict = self.get_transceiver_info() + return transceiver_info_dict.get("serialnum", "N/A") + + def get_status(self): + """ + Retrieves the operational status of the device + + Returns: + A boolean value, True if device is operating properly, False if not + """ + return self.get_presence() and not self.get_reset_status() + +############################################## +# SFP methods +############################################## + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + type |1*255VCHAR |type of SFP + hardwarerev |1*255VCHAR |hardware version of SFP + serialnum |1*255VCHAR |serial number of the SFP + manufacturename |1*255VCHAR |SFP vendor name + modelname |1*255VCHAR |SFP model name + Connector |1*255VCHAR |connector information + encoding |1*255VCHAR |encoding information + ext_identifier |1*255VCHAR |extend identifier + ext_rateselect_compliance |1*255VCHAR |extended rateSelect compliance + cable_length |INT |cable length in m + mominal_bit_rate |INT |nominal bit rate by 100Mbs + specification_compliance |1*255VCHAR |specification compliance + vendor_date |1*255VCHAR |vendor date + vendor_oui |1*255VCHAR |vendor OUI + ======================================================================== + """ + + transceiver_info_dict_keys = ['type', 'hardwarerev', + 'serialnum', 'manufacturename', + 'modelname', 'Connector', + 'encoding', 'ext_identifier', + 'ext_rateselect_compliance', 'cable_type', + 'cable_length', 'nominal_bit_rate', + 'specification_compliance', 'vendor_date', + 'vendor_oui'] + + sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', + 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', + 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') + + sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', + 'ESCONComplianceCodes', 'SONETComplianceCodes', + 'EthernetComplianceCodes', 'FibreChannelLinkLength', + 'FibreChannelTechnology', 'SFP+CableTechnology', + 'FibreChannelTransmissionMedia', 'FibreChannelSpeed') + + sfpi_obj = sff8472InterfaceId() + if not self.get_presence() or not sfpi_obj: + return {} + + offset = INFO_OFFSET + + sfp_interface_bulk_raw = self.__read_eeprom_specific_bytes((offset + XCVR_INTFACE_BULK_OFFSET), XCVR_INTFACE_BULK_WIDTH_SFP) + sfp_interface_bulk_data = sfpi_obj.parse_sfp_info_bulk(sfp_interface_bulk_raw, 0) + + sfp_vendor_name_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_NAME_OFFSET), XCVR_VENDOR_NAME_WIDTH) + sfp_vendor_name_data = sfpi_obj.parse_vendor_name(sfp_vendor_name_raw, 0) + + sfp_vendor_pn_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_PN_OFFSET), XCVR_VENDOR_PN_WIDTH) + sfp_vendor_pn_data = sfpi_obj.parse_vendor_pn(sfp_vendor_pn_raw, 0) + + sfp_vendor_rev_raw = self.__read_eeprom_specific_bytes((offset + XCVR_HW_REV_OFFSET), XCVR_HW_REV_WIDTH_SFP) + sfp_vendor_rev_data = sfpi_obj.parse_vendor_rev(sfp_vendor_rev_raw, 0) + + sfp_vendor_sn_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_SN_OFFSET), XCVR_VENDOR_SN_WIDTH) + sfp_vendor_sn_data = sfpi_obj.parse_vendor_sn(sfp_vendor_sn_raw, 0) + + sfp_vendor_oui_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_OUI_OFFSET), XCVR_VENDOR_OUI_WIDTH) + if sfp_vendor_oui_raw is not None: + sfp_vendor_oui_data = sfpi_obj.parse_vendor_oui(sfp_vendor_oui_raw, 0) + + sfp_vendor_date_raw = self.__read_eeprom_specific_bytes((offset + XCVR_VENDOR_DATE_OFFSET), XCVR_VENDOR_DATE_WIDTH) + sfp_vendor_date_data = sfpi_obj.parse_vendor_date(sfp_vendor_date_raw, 0) + + transceiver_info_dict = dict.fromkeys(transceiver_info_dict_keys, 'N/A') + + if sfp_interface_bulk_data: + transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['Connector'] = sfp_interface_bulk_data['data']['Connector']['value'] + transceiver_info_dict['encoding'] = sfp_interface_bulk_data['data']['EncodingCodes']['value'] + transceiver_info_dict['ext_identifier'] = sfp_interface_bulk_data['data']['Extended Identifier']['value'] + transceiver_info_dict['ext_rateselect_compliance'] = sfp_interface_bulk_data['data']['RateIdentifier']['value'] + transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value'] + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) + + transceiver_info_dict['manufacturename'] = sfp_vendor_name_data['data']['Vendor Name']['value'] if sfp_vendor_name_data else 'N/A' + transceiver_info_dict['modelname'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] if sfp_vendor_pn_data else 'N/A' + transceiver_info_dict['hardwarerev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] if sfp_vendor_rev_data else 'N/A' + transceiver_info_dict['serialnum'] = sfp_vendor_sn_data['data']['Vendor SN']['value'] if sfp_vendor_sn_data else 'N/A' + transceiver_info_dict['vendor_oui'] = sfp_vendor_oui_data['data']['Vendor OUI']['value'] if sfp_vendor_oui_data else 'N/A' + transceiver_info_dict['vendor_date'] = sfp_vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] if sfp_vendor_date_data else 'N/A' + + transceiver_info_dict['cable_type'] = "Unknown" + transceiver_info_dict['cable_length'] = "Unknown" + for key in sfp_cable_length_tup: + if key in sfp_interface_bulk_data['data']: + transceiver_info_dict['cable_type'] = key + transceiver_info_dict['cable_length'] = str(sfp_interface_bulk_data['data'][key]['value']) + + compliance_code_dict = dict() + for key in sfp_compliance_code_tup: + if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + + transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) + + return transceiver_info_dict + + def get_transceiver_bulk_status(self): + """ + Retrieves transceiver bulk status of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + rx_los |BOOLEAN |RX loss-of-signal status, True if has RX los, False if not. + tx_fault |BOOLEAN |TX fault status, True if has TX fault, False if not. + reset_status |BOOLEAN |reset status, True if SFP in reset, False if not. + lp_mode |BOOLEAN |low power mode status, True in lp mode, False if not. + tx_disable |BOOLEAN |TX disable status, True TX disabled, False if not. + tx_disabled_channel |HEX |disabled TX channels in hex, bits 0 to 3 represent channel 0 + | |to channel 3. + temperature |INT |module temperature in Celsius + voltage |INT |supply voltage in mV + txbias |INT |TX Bias Current in mA, n is the channel number, + | |for example, tx2bias stands for tx bias of channel 2. + rxpower |INT |received optical power in mW, n is the channel number, + | |for example, rx2power stands for rx power of channel 2. + txpower |INT |TX output power in mW, n is the channel number, + | |for example, tx2power stands for tx power of channel 2. + ======================================================================== + """ + transceiver_dom_info_dict_keys = ['rx_los', 'tx_fault', + 'reset_status', 'power_lpmode', + 'tx_disable', 'tx_disable_channel', + 'temperature', 'voltage', + 'rx1power', 'rx2power', + 'rx3power', 'rx4power', + 'tx1bias', 'tx2bias', + 'tx3bias', 'tx4bias', + 'tx1power', 'tx2power', + 'tx3power', 'tx4power'] + + sfpd_obj = sff8472Dom() + if not self.get_presence() or not sfpd_obj: + return {} + + eeprom_ifraw = self.__read_eeprom_specific_bytes(0, DOM_OFFSET) + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + cal_type = sfpi_obj.get_calibration_type() + sfpd_obj._calibration_type = cal_type + + offset = DOM_OFFSET + transceiver_dom_info_dict = dict.fromkeys(transceiver_dom_info_dict_keys, 'N/A') + + dom_temperature_raw = self.__read_eeprom_specific_bytes((offset + SFP_TEMPE_OFFSET), SFP_TEMPE_WIDTH) + + if dom_temperature_raw is not None: + dom_temperature_data = sfpd_obj.parse_temperature(dom_temperature_raw, 0) + transceiver_dom_info_dict['temperature'] = dom_temperature_data['data']['Temperature']['value'] + + dom_voltage_raw = self.__read_eeprom_specific_bytes((offset + SFP_VOLT_OFFSET), SFP_VOLT_WIDTH) + if dom_voltage_raw is not None: + dom_voltage_data = sfpd_obj.parse_voltage(dom_voltage_raw, 0) + transceiver_dom_info_dict['voltage'] = dom_voltage_data['data']['Vcc']['value'] + + dom_channel_monitor_raw = self.__read_eeprom_specific_bytes((offset + SFP_CHANNL_MON_OFFSET), SFP_CHANNL_MON_WIDTH) + if dom_channel_monitor_raw is not None: + dom_voltage_data = sfpd_obj.parse_channel_monitor_params(dom_channel_monitor_raw, 0) + transceiver_dom_info_dict['tx1power'] = dom_voltage_data['data']['TXPower']['value'] + transceiver_dom_info_dict['rx1power'] = dom_voltage_data['data']['RXPower']['value'] + transceiver_dom_info_dict['tx1bias'] = dom_voltage_data['data']['TXBias']['value'] + + for key in transceiver_dom_info_dict: + transceiver_dom_info_dict[key] = self.__convert_string_to_num(transceiver_dom_info_dict[key]) + + transceiver_dom_info_dict['reset_status'] = self.get_reset_status() + transceiver_dom_info_dict['rx_los'] = self.get_rx_los() + transceiver_dom_info_dict['tx_fault'] = self.get_tx_fault() + transceiver_dom_info_dict['tx_disable'] = self.get_tx_disable() + transceiver_dom_info_dict['tx_disable_channel'] = self.get_tx_disable_channel() + transceiver_dom_info_dict['lp_mode'] = self.get_lpmode() + + return transceiver_dom_info_dict + + def get_transceiver_threshold_info(self): + """ + Retrieves transceiver threshold info of this SFP + + Returns: + A dict which contains following keys/values : + ======================================================================== + keys |Value Format |Information + ---------------------------|---------------|---------------------------- + temphighalarm |FLOAT |High Alarm Threshold value of temperature in Celsius. + templowalarm |FLOAT |Low Alarm Threshold value of temperature in Celsius. + temphighwarning |FLOAT |High Warning Threshold value of temperature in Celsius. + templowwarning |FLOAT |Low Warning Threshold value of temperature in Celsius. + vcchighalarm |FLOAT |High Alarm Threshold value of supply voltage in mV. + vcclowalarm |FLOAT |Low Alarm Threshold value of supply voltage in mV. + vcchighwarning |FLOAT |High Warning Threshold value of supply voltage in mV. + vcclowwarning |FLOAT |Low Warning Threshold value of supply voltage in mV. + rxpowerhighalarm |FLOAT |High Alarm Threshold value of received power in dBm. + rxpowerlowalarm |FLOAT |Low Alarm Threshold value of received power in dBm. + rxpowerhighwarning |FLOAT |High Warning Threshold value of received power in dBm. + rxpowerlowwarning |FLOAT |Low Warning Threshold value of received power in dBm. + txpowerhighalarm |FLOAT |High Alarm Threshold value of transmit power in dBm. + txpowerlowalarm |FLOAT |Low Alarm Threshold value of transmit power in dBm. + txpowerhighwarning |FLOAT |High Warning Threshold value of transmit power in dBm. + txpowerlowwarning |FLOAT |Low Warning Threshold value of transmit power in dBm. + txbiashighalarm |FLOAT |High Alarm Threshold value of tx Bias Current in mA. + txbiaslowalarm |FLOAT |Low Alarm Threshold value of tx Bias Current in mA. + txbiashighwarning |FLOAT |High Warning Threshold value of tx Bias Current in mA. + txbiaslowwarning |FLOAT |Low Warning Threshold value of tx Bias Current in mA. + ======================================================================== + """ + transceiver_dom_threshold_info_dict_keys = ['temphighalarm', 'temphighwarning', 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', 'txbiaslowalarm', 'txbiaslowwarning'] + + sfpd_obj = sff8472Dom() + + if not self.get_presence() and not sfpd_obj: + return {} + + eeprom_ifraw = self.__read_eeprom_specific_bytes(0, DOM_OFFSET) + sfpi_obj = sff8472InterfaceId(eeprom_ifraw) + cal_type = sfpi_obj.get_calibration_type() + sfpd_obj._calibration_type = cal_type + + offset = DOM_OFFSET + transceiver_dom_threshold_info_dict = dict.fromkeys(transceiver_dom_threshold_info_dict_keys, 'N/A') + dom_module_threshold_raw = self.__read_eeprom_specific_bytes((offset + SFP_MODULE_THRESHOLD_OFFSET), SFP_MODULE_THRESHOLD_WIDTH) + if dom_module_threshold_raw is not None: + dom_module_threshold_data = sfpd_obj.parse_alarm_warning_threshold(dom_module_threshold_raw, 0) + + transceiver_dom_threshold_info_dict['temphighalarm'] = dom_module_threshold_data['data']['TempHighAlarm']['value'] + transceiver_dom_threshold_info_dict['templowalarm'] = dom_module_threshold_data['data']['TempLowAlarm']['value'] + transceiver_dom_threshold_info_dict['temphighwarning'] = dom_module_threshold_data['data']['TempHighWarning']['value'] + transceiver_dom_threshold_info_dict['templowwarning'] = dom_module_threshold_data['data']['TempLowWarning']['value'] + + transceiver_dom_threshold_info_dict['vcchighalarm'] = dom_module_threshold_data['data']['VoltageHighAlarm']['value'] + transceiver_dom_threshold_info_dict['vcclowalarm'] = dom_module_threshold_data['data']['VoltageLowAlarm']['value'] + transceiver_dom_threshold_info_dict['vcchighwarning'] = dom_module_threshold_data['data']['VoltageHighWarning']['value'] + transceiver_dom_threshold_info_dict['vcclowwarning'] = dom_module_threshold_data['data']['VoltageLowWarning']['value'] + + transceiver_dom_threshold_info_dict['txbiashighalarm'] = dom_module_threshold_data['data']['BiasHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiaslowalarm'] = dom_module_threshold_data['data']['BiasLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txbiashighwarning'] = dom_module_threshold_data['data']['BiasHighWarning']['value'] + transceiver_dom_threshold_info_dict['txbiaslowwarning'] = dom_module_threshold_data['data']['BiasLowWarning']['value'] + + transceiver_dom_threshold_info_dict['txpowerhighalarm'] = dom_module_threshold_data['data']['TXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerlowalarm'] = dom_module_threshold_data['data']['TXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['txpowerhighwarning'] = dom_module_threshold_data['data']['TXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['txpowerlowwarning'] = dom_module_threshold_data['data']['TXPowerLowWarning']['value'] + + transceiver_dom_threshold_info_dict['rxpowerhighalarm'] = dom_module_threshold_data['data']['RXPowerHighAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowalarm'] = dom_module_threshold_data['data']['RXPowerLowAlarm']['value'] + transceiver_dom_threshold_info_dict['rxpowerhighwarning'] = dom_module_threshold_data['data']['RXPowerHighWarning']['value'] + transceiver_dom_threshold_info_dict['rxpowerlowwarning'] = dom_module_threshold_data['data']['RXPowerLowWarning']['value'] + + for key in transceiver_dom_threshold_info_dict: + transceiver_dom_threshold_info_dict[key] = self.__convert_string_to_num(transceiver_dom_threshold_info_dict[key]) + + return transceiver_dom_threshold_info_dict + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + + Returns: + A Boolean, True if reset enabled, False if disabled + """ + # SFP doesn't support this feature + return False + + def get_rx_los(self): + """ + Retrieves the RX LOS (lost-of-signal) status of SFP + + Returns: + A Boolean, True if SFP has RX LOS, False if not. + Note : RX LOS status is latched until a call to get_rx_los or a reset. + """ + rx_los = False + status_control_raw = self.__read_eeprom_specific_bytes(SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw: + data = int(status_control_raw[0], 16) + rx_los = (sffbase().test_bit(data, 1) != 0) + + return rx_los + + def get_tx_fault(self): + """ + Retrieves the TX fault status of SFP + + Returns: + A Boolean, True if SFP has TX fault, False if not + Note : TX fault status is lached until a call to get_tx_fault or a reset. + """ + tx_fault = False + status_control_raw = self.__read_eeprom_specific_bytes(SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw: + data = int(status_control_raw[0], 16) + tx_fault = (sffbase().test_bit(data, 2) != 0) + + return tx_fault + + def get_tx_disable(self): + """ + Retrieves the tx_disable status of this SFP + + Returns: + A Boolean, True if tx_disable is enabled, False if disabled + """ + tx_disable = False + tx_fault = False + status_control_raw = self.__read_eeprom_specific_bytes(SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw: + data = int(status_control_raw[0], 16) + tx_disable_hard = (sffbase().test_bit(data, SFP_TX_DISABLE_HARD_BIT) != 0) + tx_disable_soft = (sffbase().test_bit(data, SFP_TX_DISABLE_SOFT_BIT) != 0) + tx_disable = tx_disable_hard | tx_disable_soft + + return tx_disable + + def get_tx_disable_channel(self): + """ + Retrieves the TX disabled channels in this SFP + + Returns: + A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent + TX channels which have been disabled in this SFP. + As an example, a returned value of 0x5 indicates that channel 0 + and channel 2 have been disabled. + """ + # SFP doesn't support this feature + return 0 + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + # SFP doesn't support this feature + return False + + def get_power_override(self): + """ + Retrieves the power-override status of this SFP + + Returns: + A Boolean, True if power-override is enabled, False if disabled + """ + # SFP doesn't support this feature + return False + + def get_temperature(self): + """ + Retrieves the temperature of this SFP + + Returns: + An integer number of current temperature in Celsius + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + return transceiver_dom_info_dict.get("temperature", "N/A") + + + def get_voltage(self): + """ + Retrieves the supply voltage of this SFP + + Returns: + An integer number of supply voltage in mV + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + return transceiver_dom_info_dict.get("voltage", "N/A") + + def get_tx_bias(self): + """ + Retrieves the TX bias current of this SFP + + Returns: + A list of four integer numbers, representing TX bias in mA + for channel 0 to channel 4. + Ex. ['110.09', '111.12', '108.21', '112.09'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + tx1_bs = transceiver_dom_info_dict.get("tx1bias", "N/A") + return [tx1_bs, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] + + def get_rx_power(self): + """ + Retrieves the received optical power for this SFP + + Returns: + A list of four integer numbers, representing received optical + power in mW for channel 0 to channel 4. + Ex. ['1.77', '1.71', '1.68', '1.70'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + rx1_pw = transceiver_dom_info_dict.get("rx1power", "N/A") + return [rx1_pw, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] + + def get_tx_power(self): + """ + Retrieves the TX power of this SFP + + Returns: + A list of four integer numbers, representing TX power in mW + for channel 0 to channel 4. + Ex. ['1.86', '1.86', '1.86', '1.86'] + """ + transceiver_dom_info_dict = self.get_transceiver_bulk_status() + tx1_pw = transceiver_dom_info_dict.get("tx1power", "N/A") + return [tx1_pw, "N/A", "N/A", "N/A"] if transceiver_dom_info_dict else [] + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + + Returns: + A boolean, True if successful, False if not + """ + # SFP doesn't support this feature + return False + + def tx_disable(self, tx_disable): + """ + Disable SFP TX for all channels + + Args: + tx_disable : A Boolean, True to enable tx_disable mode, False to disable + tx_disable mode. + + Returns: + A boolean, True if tx_disable is set successfully, False if not + """ + sysfs_eeprom_path = self.__eeprom_path + status_control_raw = self.__read_eeprom_specific_bytes(SFP_STATUS_CONTROL_OFFSET, SFP_STATUS_CONTROL_WIDTH) + if status_control_raw is not None: + # Set bit 6 for Soft TX Disable Select + # 01000000 = 64 and 10111111 = 191 + tx_disable_bit = 64 if tx_disable else 191 + status_control = int(status_control_raw[0], 16) + tx_disable_ctl = (status_control | tx_disable_bit) if tx_disable else (status_control & tx_disable_bit) + try: + sysfsfile_eeprom = open(sysfs_eeprom_path, mode="r+b", buffering=0) + buffer = create_string_buffer(1) + buffer[0] = chr(tx_disable_ctl) + # Write to eeprom + sysfsfile_eeprom.seek(SFP_STATUS_CONTROL_OFFSET) + sysfsfile_eeprom.write(buffer[0]) + except: + #print("Error: unable to open file: %s" % str(e)) + return False + finally: + if sysfsfile_eeprom: + sysfsfile_eeprom.close() + time.sleep(0.01) + return True + return False + + def tx_disable_channel(self, channel, disable): + """ + Sets the tx_disable for specified SFP channels + + Args: + channel : A hex of 4 bits (bit 0 to bit 3) which represent channel 0 to 3, + e.g. 0x5 for channel 0 and channel 2. + disable : A boolean, True to disable TX channels specified in channel, + False to enable + + Returns: + A boolean, True if successful, False if not + """ + # SFP doesn't support this feature + return False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + # SFP doesn't support this feature + return False + + def set_power_override(self, power_override, power_set): + """ + Sets SFP power level using power_override and power_set + + Args: + power_override : + A Boolean, True to override set_lpmode and use power_set + to control SFP power, False to disable SFP power control + through power_override/power_set and use set_lpmode + to control SFP power. + power_set : + Only valid when power_override is True. + A Boolean, True to set SFP to low power mode, False to set + SFP to high power mode. + + Returns: + A boolean, True if power-override and power_set are set successfully, + False if not + """ + # SFP doesn't support this feature + return False + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/thermal.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/thermal.py new file mode 100644 index 0000000000..eba7ba728d --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/sonic_platform/thermal.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python +# +# Name: thermal.py, version: 1.0 +# +# Description: Module contains the definitions of SONiC platform APIs +# + +try: + import os + from sonic_platform_base.thermal_base import ThermalBase +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +class Thermal(ThermalBase): + + def __init__(self, index): + self.__index = index + + #thermal name list + self.__thermal_name_list = [ "PCH Temperature Sensor", + "CPU Board Temperature Sensor", + "FrontSide Temperature Sensor", + "NearASIC Temperature Sensor", + "RearSide Temperature Sensor" ] + + offset = 0 + if 0 != self.__index: + offset = 2 + self.__presence_attr = "/sys/class/hwmon/hwmon{}/temp1_input".format(self.__index + offset) + self.__temperature_attr = "/sys/class/hwmon/hwmon{}/temp1_input".format(self.__index + offset) + + def __get_attr_value(self, attr_path): + + retval = 'ERR' + if (not os.path.isfile(attr_path)): + return retval + + try: + with open(attr_path, 'r') as fd: + retval = fd.read() + except Exception as error: + logging.error("Unable to open ", attr_path, " file !") + + retval = retval.rstrip(' \t\n\r') + return retval + +############################################## +# Device methods +############################################## + + def get_name(self): + """ + Retrieves the name of the device + + Returns: + string: The name of the device + """ + return self.__thermal_name_list[self.__index] or "Unknown" + + def get_presence(self): + """ + Retrieves the presence of the device + + Returns: + bool: True if device is present, False if not + """ + presence = False + attr_path = self.__presence_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + if (int(attr_rv) != 0): + presence = True + + return presence + + def get_model(self): + """ + Retrieves the model number (or part number) of the device + + Returns: + string: Model/part number of device + """ + return "N/A" + + def get_serial(self): + """ + Retrieves the serial number of the device + + Returns: + string: Serial number of device + """ + return "N/A" + + def get_status(self): + """ + Retrieves the operational status of the device + + Returns: + A boolean value, True if device is operating properly, False if not + """ + return self.get_presence() + +############################################## +# THERMAL methods +############################################## + + def get_temperature(self): + """ + Retrieves current temperature reading from thermal + + Returns: + A float number of current temperature in Celsius up to nearest thousandth + of one degree Celsius, e.g. 30.125 + """ + temperature = 0.0 + attr_path = self.__temperature_attr + + attr_rv = self.__get_attr_value(attr_path) + if (attr_rv != 'ERR'): + temperature = float(attr_rv) / 1000 + + return temperature + + def get_high_threshold(self): + """ + Retrieves the high threshold temperature of thermal + + Returns: + A float number, the high threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + raise NotImplementedError + + def get_low_threshold(self): + """ + Retrieves the low threshold temperature of thermal + + Returns: + A float number, the low threshold temperature of thermal in Celsius + up to nearest thousandth of one degree Celsius, e.g. 30.125 + """ + raise NotImplementedError + + def set_high_threshold(self, temperature): + """ + Sets the high threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + raise NotImplementedError + + def set_low_threshold(self, temperature): + """ + Sets the low threshold temperature of thermal + + Args : + temperature: A float number up to nearest thousandth of one degree Celsius, + e.g. 30.125 + + Returns: + A boolean, True if threshold is set successfully, False if not + """ + raise NotImplementedError + diff --git a/platform/broadcom/sonic-platform-modules-inventec/d6356/utils/inventec_d6356_util.py b/platform/broadcom/sonic-platform-modules-inventec/d6356/utils/inventec_d6356_util.py index e3e696c088..890973cb83 100755 --- a/platform/broadcom/sonic-platform-modules-inventec/d6356/utils/inventec_d6356_util.py +++ b/platform/broadcom/sonic-platform-modules-inventec/d6356/utils/inventec_d6356_util.py @@ -126,7 +126,7 @@ drivers =[ 'inv_eeprom', 'inv_cpld', 'inv_platform', -'monitor', +#'monitor', 'swps'] @@ -141,7 +141,7 @@ def system_install(): status, output = exec_cmd("rmmod lpc_ich ", 1) #insert extra module - status, output = exec_cmd("insmod /lib/modules/3.16.0-5-amd64/extra/gpio-ich.ko gpiobase=0",1) + status, output = exec_cmd("insmod /lib/modules/4.9.0-9-2-amd64/kernel/drivers/gpio/gpio-ich.ko gpiobase=0",1) #install drivers for i in range(0,len(drivers)): @@ -159,52 +159,49 @@ def system_install(): print output if FORCE == 0: return status - - #swps map to i2c-bus +# +# INV_FIX-4037 +# It replaces the original sff8436 driver with the optoe driver +# + #optoe map to i2c-bus for i in range(14,22): - status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-6/i2c-"+str(i)+"/new_device", 1) + status, output =exec_cmd("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-6/i2c-"+str(i)+"/new_device", 1) if status: print output if FORCE == 0: return status for i in range(22,30): - status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-7/i2c-"+str(i)+"/new_device", 1) - status, output =exec_cmd("echo sff8436 0x51 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-7/i2c-"+str(i)+"/new_device", 1) + status, output =exec_cmd("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-7/i2c-"+str(i)+"/new_device", 1) if status: print output if FORCE == 0: return status for i in range(30,38): - status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-8/i2c-"+str(i)+"/new_device", 1) - status, output =exec_cmd("echo sff8436 0x51 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-8/i2c-"+str(i)+"/new_device", 1) + status, output =exec_cmd("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-8/i2c-"+str(i)+"/new_device", 1) if status: print output if FORCE == 0: return status for i in range(38,46): - status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-9/i2c-"+str(i)+"/new_device", 1) - status, output =exec_cmd("echo sff8436 0x51 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-9/i2c-"+str(i)+"/new_device", 1) + status, output =exec_cmd("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-9/i2c-"+str(i)+"/new_device", 1) if status: print output if FORCE == 0: return status for i in range(46,54): - status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-10/i2c-"+str(i)+"/new_device", 1) - status, output =exec_cmd("echo sff8436 0x51 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-10/i2c-"+str(i)+"/new_device", 1) + status, output =exec_cmd("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-10/i2c-"+str(i)+"/new_device", 1) if status: print output if FORCE == 0: return status for i in range(54,62): - status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-11/i2c-"+str(i)+"/new_device", 1) - status, output =exec_cmd("echo sff8436 0x51 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-11/i2c-"+str(i)+"/new_device", 1) + status, output =exec_cmd("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-11/i2c-"+str(i)+"/new_device", 1) if status: print output if FORCE == 0: return status for i in range(62,70): - status, output =exec_cmd("echo sff8436 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-12/i2c-"+str(i)+"/new_device", 1) - status, output =exec_cmd("echo sff8436 0x51 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-12/i2c-"+str(i)+"/new_device", 1) + status, output =exec_cmd("echo optoe2 0x50 > /sys/bus/i2c/devices/i2c-1/i2c-5/i2c-12/i2c-"+str(i)+"/new_device", 1) if status: print output if FORCE == 0: @@ -243,7 +240,7 @@ def uninstall(): def device_found(): ret1, log = exec_cmd("ls "+i2c_prefix+"*0072", 0) ret2, log = exec_cmd("ls "+i2c_prefix+"i2c-5", 0) - return not(ret1 or ret2) + return not(ret1 or ret2) if __name__ == "__main__": main() diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/control b/platform/broadcom/sonic-platform-modules-inventec/debian/control index b3af29108f..6cb6163082 100644 --- a/platform/broadcom/sonic-platform-modules-inventec/debian/control +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/control @@ -27,7 +27,7 @@ Description: kernel modules for platform devices such as fan, led Package: platform-modules-d6356 Architecture: amd64 -Depends: linux-image-4.9.0-8-2-amd64 +Depends: linux-image-4.9.0-9-2-amd64 Description: kernel modules for platform devices such as fan, led Package: platform-modules-d7264q28b diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6356.install b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6356.install index 4c668b9816..6f03ede72e 100644 --- a/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6356.install +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/platform-modules-d6356.install @@ -1 +1,3 @@ -d6356/utils/inventec_d6356_util.py /usr/local/bin +d6356/utils/inventec_d6356_util.py usr/local/bin +d6356/utils/sonic_platform-1.0-py2-none-any.whl usr/share/sonic/device/x86_64-inventec_d6356-r0 +systemd/platform-modules-d6356.service lib/systemd/system diff --git a/platform/broadcom/sonic-platform-modules-inventec/debian/rules b/platform/broadcom/sonic-platform-modules-inventec/debian/rules index 8bfe6e6582..6340540f03 100755 --- a/platform/broadcom/sonic-platform-modules-inventec/debian/rules +++ b/platform/broadcom/sonic-platform-modules-inventec/debian/rules @@ -17,11 +17,17 @@ MOD_SRC_DIR:= $(shell pwd) MODULE_DIRS:= d7032q28b d7054q28b d6254qs d6556 d6356 d7264q28b %: - dh $@ --with=systemd + dh $@ --with python2,systemd override_dh_auto_build: (for mod in $(MODULE_DIRS); do \ make -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules; \ + if [ $$mod = "d6356" ]; then \ + cd $(MOD_SRC_DIR)/$${mod}; \ + python2 setup.py build; \ + python2 setup.py bdist_wheel -d $(MOD_SRC_DIR)/$${mod}/utils; \ + cd $(MOD_SRC_DIR); \ + fi \ done) override_dh_auto_install: @@ -30,11 +36,13 @@ override_dh_auto_install: $(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ cp $(MOD_SRC_DIR)/$${mod}/modules/*.ko \ debian/platform-modules-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \ - dh_installdirs -pplatform-modules-$${mod} usr/local/bin; \ - cp $(MOD_SRC_DIR)/$${mod}/utils/* \ - debian/platform-modules-$${mod}/usr/local/bin; \ + if [ $$mod = "d6356" ]; then \ + cd $(MOD_SRC_DIR)/$${mod}; \ + python2 setup.py install --root=$(MOD_SRC_DIR)/debian/platform-modules-$${mod} --install-layout=deb; \ + cd $(MOD_SRC_DIR); \ + fi \ done) - + override_dh_usrlocal: override_dh_pysupport: diff --git a/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6356.service b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6356.service new file mode 100644 index 0000000000..85fa47a726 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-inventec/systemd/platform-modules-d6356.service @@ -0,0 +1,13 @@ +[Unit] +Description=Inventec d6356 Platform modules +After=local-fs.target +Before=pmon.service + +[Service] +Type=oneshot +ExecStart=-/etc/init.d/platform-modules-d6356 start +ExecStop=-/etc/init.d/platform-modules-d6356 stop +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target