diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/media_settings.json b/device/juniper/x86_64-juniper_qfx5200-r0/media_settings.json
old mode 100755
new mode 100644
diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/plugins/eeprom.py b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/eeprom.py
old mode 100755
new mode 100644
diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/plugins/led_control.py b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/led_control.py
old mode 100755
new mode 100644
diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/plugins/psuutil.py b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/psuutil.py
old mode 100755
new mode 100644
diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/plugins/qfx5200_eeprom_data.py b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/qfx5200_eeprom_data.py
old mode 100755
new mode 100644
diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/plugins/qfx5200_sfp_init.py b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/qfx5200_sfp_init.py
old mode 100755
new mode 100644
diff --git a/device/juniper/x86_64-juniper_qfx5200-r0/plugins/sfputil.py b/device/juniper/x86_64-juniper_qfx5200-r0/plugins/sfputil.py
old mode 100755
new mode 100644
diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/led_proc_init.soc b/device/juniper/x86_64-juniper_qfx5210-r0/led_proc_init.soc
old mode 100755
new mode 100644
diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/plugins/psuutil.py b/device/juniper/x86_64-juniper_qfx5210-r0/plugins/psuutil.py
old mode 100755
new mode 100644
diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/plugins/qfx5210_eeprom_data.py b/device/juniper/x86_64-juniper_qfx5210-r0/plugins/qfx5210_eeprom_data.py
new file mode 100644
index 0000000000..973a2abe49
--- /dev/null
+++ b/device/juniper/x86_64-juniper_qfx5210-r0/plugins/qfx5210_eeprom_data.py
@@ -0,0 +1,331 @@
+#!/usr/bin/env python
+#
+# Name: juniper_qfx5210_eepromconv.py version: 1.0
+#
+# Description: This file contains the code to store the contents of Board EEPROM in file
+#
+# Copyright (c) 2020, Juniper Networks, Inc.
+# All rights reserved.
+#
+# Notice and Disclaimer: This code is licensed to you under the GNU General
+# Public License as published by the Free Software Foundation, version 3 or
+# any later version. This code is not an official Juniper product. You can
+# obtain a copy of the License at
+#
+# OSS License:
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Third-Party Code: This code may depend on other components under separate
+# copyright notice and license terms. Your use of the source code for those
+# components is subject to the terms and conditions of the respective license
+# as noted in the Third-Party source code file.
+
+import os
+import commands
+import binascii
+from sonic_eeprom import eeprom_tlvinfo
+
+def main():
+ eeprom_qfx5210 = Eeprom()
+
+ FANTYPE_PATH = '/sys/bus/i2c/devices/17-0068/fan1_direction'
+ isPlatformAFO = False
+ try:
+ fan_type_file = open(FANTYPE_PATH)
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ fan_type = -1
+ else:
+ fan_type = fan_type_file.read()
+ fan_type_file.close()
+
+ if (int(fan_type) == -1 or int(fan_type) == 0):
+ if (int(fan_type) == -1):
+ print "unable to open sys file for fan handling, defaulting it to AFO"
+
+ isPlatformAFO = True
+ else:
+ isPlatformAFO = False
+
+ # creating the "/var/run/eeprom" file and storing values of CPU board EEPROM in this file.
+ eeprom_file = open ("/var/run/eeprom", "a+")
+ eeprom_file.write("\n")
+ if isPlatformAFO == True:
+ eeprom_file.write("Fan Type=AFO\r\n")
+ else:
+ eeprom_file.write("Fan Type=AFI\r\n")
+ eeprom_file.write("\n")
+
+ # Write the contents of CPU Board EEPROM to file
+ eeprom_file.write("CPU Board EEPROM (0x56)\r\n")
+ eeprom_file.write("===============================\r\n")
+ eeprom_file.write("Product Name=%s\r\n" % eeprom_qfx5210.modelstr())
+ eeprom_file.write("Part Number=%s\r\n" % eeprom_qfx5210.part_number_str())
+ eeprom_file.write("Serial Number=%s\r\n" % eeprom_qfx5210.serial_number_str())
+ eeprom_file.write("MAC Address=%s\r\n" % eeprom_qfx5210.base_mac_address())
+ eeprom_file.write("Manufacture Date=%s\r\n" % eeprom_qfx5210.manuDate_str())
+ eeprom_file.write("Platform Name=%s\r\n" % eeprom_qfx5210.platform_str())
+ eeprom_file.write("Number of MAC Addresses=%s\r\n" % eeprom_qfx5210.MACsize_str())
+ eeprom_file.write("Vendor Name=%s\r\n" % eeprom_qfx5210.vendor_name_str())
+ eeprom_file.write("Manufacture Name=%s\r\n" % eeprom_qfx5210.manufacture_name_str())
+
+ CPUeepromFileCmd = 'cat /sys/devices/pci0000:00/0000:00:1f.3/i2c-0/0-0056/eeprom > /etc/init.d/eeprom_qfx5210_ascii'
+ # Write the contents of CPU EEPROM to file
+ try:
+ os.system(CPUeepromFileCmd)
+ except OSError:
+ print 'Error: Execution of "%s" failed', CPUeepromFileCmd
+ return False
+
+ eeprom_ascii = '/etc/init.d/eeprom_qfx5210_ascii'
+ # Read file contents in Hex format
+ with open(eeprom_ascii, 'rb') as Hexformat:
+ content = Hexformat.read()
+ Hexformatoutput = binascii.hexlify(content)
+
+ eeprom_hex = '/etc/init.d/eeprom_qfx5210_hex'
+ with open(eeprom_hex, 'wb+') as Hexfile:
+ Hexfile.write(Hexformatoutput)
+
+ #Write contents of CPU EEPROM to new file in hexa format
+ with open(eeprom_hex, 'rb') as eeprom_hexfile:
+ eeprom_hexfile.seek(350, 0)
+ vendorext_read = eeprom_hexfile.read(124)
+ vendorext=""
+ vendorext += "0x" + vendorext_read[0:2]
+ for i in range(2,124,2):
+ vendorext += " 0x" + vendorext_read[i:i+2]
+ eeprom_file.write("Vendor Extension=%s\r\n" % str(vendorext))
+
+ eeprom_hexfile.seek(350, 0)
+ IANA_read = eeprom_hexfile.read(8)
+ IANAName = binascii.unhexlify(IANA_read)
+ eeprom_file.write("IANA=%s\r\n" % str(IANAName))
+
+ eeprom_hexfile.seek(358, 0)
+ ASMpartrev_read = eeprom_hexfile.read(4)
+ ASMpartrev = binascii.unhexlify(ASMpartrev_read)
+ eeprom_file.write("Assembly Part Number Rev=%s\r\n" % str(ASMpartrev))
+
+ eeprom_hexfile.seek(374, 0)
+ ASMpartnum_read = eeprom_hexfile.read(20)
+ ASMpartnum_read = binascii.unhexlify(ASMpartnum_read)
+ eeprom_file.write("Assembly Part Number=%s\r\n" % str(ASMpartnum_read))
+
+ eeprom_hexfile.seek(402, 0)
+ ASMID_read = eeprom_hexfile.read(4)
+ ASMID_read_upper = ASMID_read.upper()
+ eeprom_file.write("Assembly ID=0x%s\r\n" % str(ASMID_read_upper))
+
+ ASMHWMajRev_position = eeprom_hexfile.seek(410, 0)
+ ASMHWMajRev_read = eeprom_hexfile.read(2)
+ eeprom_file.write("Assembly Major Revision=0x%s\r\n" % str(ASMHWMajRev_read))
+
+ eeprom_hexfile.seek(416, 0)
+ ASMHWMinRev_read = eeprom_hexfile.read(2)
+ eeprom_file.write("Assembly Minor Revision=0x%s\r\n" % str(ASMHWMinRev_read))
+
+ eeprom_hexfile.seek(422, 0)
+ Deviation_read = eeprom_hexfile.read(28)
+ Deviation_read_upper = Deviation_read.upper()
+ eeprom_file.write("Deviation=0x%s\r\n" % str(Deviation_read_upper))
+
+ eeprom_hexfile.seek(450, 0)
+ CLEI_read = eeprom_hexfile.read(20)
+ CLEI_name = binascii.unhexlify(CLEI_read)
+ eeprom_file.write("CLEI code=%s\r\n" % str(CLEI_name))
+
+ eeprom_dict = eeprom_qfx5210.system_eeprom_info()
+ key = '0x29'
+ if key in eeprom_dict.keys():
+ onie_version_str = eeprom_dict.get('0x29', None)
+ else:
+ onie_version_str = "N/A"
+ eeprom_file.write("ONIE Version=%s\r\n" % onie_version_str)
+
+ crc_str = eeprom_dict.get('0xFE', None)
+ eeprom_file.write("CRC=%s\r\n" % crc_str)
+ eeprom_file.close()
+ return True
+
+class Eeprom(eeprom_tlvinfo.TlvInfoDecoder):
+ def __init__(self):
+ self.__eeprom_path = "/sys/class/i2c-adapter/i2c-0/0-0056/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 manuDate_str(self):
+ (is_valid, results) = self.get_tlv_field(
+ self.__eeprom_data, self._TLV_CODE_MANUF_DATE)
+ if not is_valid:
+ return "N/A"
+
+ return results[2]
+
+ def platform_str(self):
+ (is_valid, results) = self.get_tlv_field(
+ self.__eeprom_data, self._TLV_CODE_PLATFORM_NAME)
+ if not is_valid:
+ return "N/A"
+
+ return results[2]
+
+ def MACsize_str(self):
+ (is_valid, t) = self.get_tlv_field(self.__eeprom_data, self._TLV_CODE_MAC_SIZE)
+
+ if not is_valid:
+ return "N/A"
+
+ return str((ord(t[2][0]) << 8) | ord(t[2][1]))
+
+ def vendor_name_str(self):
+ (is_valid, results) = self.get_tlv_field(
+ self.__eeprom_data, self._TLV_CODE_VENDOR_NAME)
+ if not is_valid:
+ return "N/A"
+
+ return results[2]
+
+ def manufacture_name_str(self):
+ (is_valid, results) = self.get_tlv_field(
+ self.__eeprom_data, self._TLV_CODE_MANUF_NAME)
+ if not is_valid:
+ return "N/A"
+
+ return results[2]
+
+ def onie_version_str(self):
+ value = ""
+ (is_valid, results) = self.get_tlv_field(
+ self.__eeprom_data, self._TLV_CODE_ONIE_VERSION)
+ if not is_valid:
+ return "N/A"
+
+ for c in results[2:2 + ord(results[1])]:
+ value += "0x%02X " % (ord(c),)
+
+ return value
+
+ def vendor_ext_str(self):
+
+ (is_valid, results) = self.get_tlv_field(
+ self.__eeprom_data, self._TLV_CODE_VENDOR_EXT)
+
+ if not is_valid:
+ return "N/A"
+
+ vendor_value_formatted = ''.join( [ " 0x" + "%02X " % ord( x ) for x in results[2] ] ).strip()
+ vendor_value_hexvalue = ''.join( ["%02X" % ord( x ) for x in results[2] ] ).strip()
+
+ return vendor_value_formatted, vendor_value_hexvalue
+
+ def crc_str(self):
+ (is_valid, results) = self.get_tlv_field(
+ self.__eeprom_data, self._TLV_CODE_CRC_32)
+ if not is_valid:
+ return "N/A"
+
+ 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
+
+if __name__ == "__main__":
+ main()
diff --git a/device/juniper/x86_64-juniper_qfx5210-r0/pmon_daemon_control.json b/device/juniper/x86_64-juniper_qfx5210-r0/pmon_daemon_control.json
index 94592fa8ce..a3ecea34bc 100644
--- a/device/juniper/x86_64-juniper_qfx5210-r0/pmon_daemon_control.json
+++ b/device/juniper/x86_64-juniper_qfx5210-r0/pmon_daemon_control.json
@@ -1,3 +1,4 @@
{
+ "skip_thermalctld": true,
"skip_ledd": true
}
diff --git a/platform/broadcom/sonic-platform-modules-juniper/common/modules/gpio-tmc.c b/platform/broadcom/sonic-platform-modules-juniper/common/modules/gpio-tmc.c
new file mode 100644
index 0000000000..7b02e8a5bc
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-juniper/common/modules/gpio-tmc.c
@@ -0,0 +1,661 @@
+/*
+ * Juniper Networks TMC GPIO driver
+ *
+ * Copyright (C) 2020 Juniper Networks
+ * Author: Ashish Bhensdadia
+ *
+ * This driver implement the GPIO set/get functionality
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "jnx-tmc.h"
+
+#define TMC_GPIO_MAX_BITS_PER_REG 16
+#define TMC_GPIO_SFP_MAX_BITS_PER_REG 2
+#define TMC_GPIO_PTPCFG_MAX_BITS_PER_REG 8
+
+#define TMC_GPIO_FIND_GROUP(gpio) \
+ ((gpio) / TMC_GPIO_MAX_BITS_PER_REG)
+#define TMC_GPIO_FIND_GPIO(gpio) \
+ ((gpio) % TMC_GPIO_MAX_BITS_PER_REG)
+
+#define TMC_GPIO_SFP_FIND_GROUP(gpio) \
+ ((gpio) / TMC_GPIO_SFP_MAX_BITS_PER_REG)
+#define TMC_GPIO_SFP_FIND_GPIO(gpio) \
+ ((gpio) % TMC_GPIO_SFP_MAX_BITS_PER_REG)
+
+#define TMC_GPIO_PTPCFG_FIND_GPIO(gpio) \
+ ((gpio) % TMC_GPIO_PTPCFG_MAX_BITS_PER_REG)
+
+#define TMC_GPIO_MAX_NGPIO_PER_GROUP 320
+
+#define TMC_PFE_QSFP_RESET_OFFSET 0x4
+#define TMC_PFE_QSFP_PRESENT_OFFSET 0x8
+#define TMC_PFE_QSFP_PHY_RESET_OFFSET 0x10
+#define TMC_PFE_QSFP_LPMOD_OFFSET 0x78
+#define TMC_PFE_QSFP_LED_CTRL_OFFSET 0x20
+
+#define TMC_PFE_LANES_GREEN_LED_VALUE 0x3
+#define TMC_PFE_LANE0_GREEN_LED_BIT_POSITION 0
+#define TMC_PFE_LANE1_GREEN_LED_BIT_POSITION 2
+#define TMC_PFE_LANE2_GREEN_LED_BIT_POSITION 4
+#define TMC_PFE_LANE3_GREEN_LED_BIT_POSITION 6
+
+#define TMC_PFE_LANES_BEACON_LED_VALUE 0x2
+#define TMC_PFE_LANE0_BEACON_LED_BIT_POSITION 0
+#define TMC_PFE_LANE1_BEACON_LED_BIT_POSITION 2
+#define TMC_PFE_LANE2_BEACON_LED_BIT_POSITION 4
+#define TMC_PFE_LANE3_BEACON_LED_BIT_POSITION 6
+
+#define TMC_PFE_LANES_FAULT_LED_VALUE 0x1
+#define TMC_PFE_LANE0_FAULT_LED_BIT_POSITION 0
+#define TMC_PFE_LANE1_FAULT_LED_BIT_POSITION 2
+#define TMC_PFE_LANE2_FAULT_LED_BIT_POSITION 4
+#define TMC_PFE_LANE3_FAULT_LED_BIT_POSITION 6
+
+#define TMC_PFE_SFPSB0_TX_DISABLE_OFFSET 0x0
+#define TMC_PFE_SFPSB0_LED_CTRL_OFFSET 0xC
+#define TMC_PFE_SFPSB0_LED_ACTIVITY_OFFSET 0x14
+#define TMC_PFE_SFPSB0_PRESENT_OFFSET 0x18
+#define TMC_PFE_SFPSB0_LOSS_OFFSET 0x1C
+#define TMC_PFE_SFPSB0_TX_FAULT_OFFSET 0x20
+
+#define TMC_PFE_SFPSB1_TX_DISABLE_OFFSET 0x0
+#define TMC_PFE_SFPSB1_LED_CTRL_OFFSET 0x8
+#define TMC_PFE_SFPSB1_LED_ACTIVITY_OFFSET 0x10
+#define TMC_PFE_SFPSB1_PRESENT_OFFSET 0x14
+#define TMC_PFE_SFPSB1_LOSS_OFFSET 0x18
+#define TMC_PFE_SFPSB1_TX_FAULT_OFFSET 0x1C
+
+/*
+ * Index 4 to 15 is used for QSFP starting with
+ * QSFP_LED_LANE0_GREEN. To keep multibit set/get common
+ * starting SFP_LED_LANE0_GREEN with 16 which will avoid
+ * conflict with QSFP enums.
+ */
+#define SFP_LED_OP_START_INDEX 16
+
+/*
+ * Used for off-setting SFP led op index
+ */
+#define SFP_LED_OP_OFFSET 0xB
+
+/*
+ * SFP slave blocks
+ */
+#define SFP_SLAVE0_BLOCK 0x1
+#define SFP_SLAVE1_BLOCK 0x2
+
+/*
+ * each group represent the 16 gpios.
+ * QSFP_RST - QSFP_LPMODE
+ * each bit represent the one gpio
+ * exemple: bits[0:15] - bit0 - gpio0
+ * QSFP_LED_LANE0_GREEN - QSFP_LED_LANE3_FAULT
+ * here, number represent the one gpio
+ * exemple: bits[0:1]
+ * 00 - gpio off, 01 - gpio on [ gpio0]
+ * 00 - gpio off, 10 - gpio on [ gpio1]
+ * 00 - gpio off, 11 - gpio on [ gpio2]
+ *
+ */
+enum {
+ QSFP_RST,
+ QSFP_PRESENT,
+ QSFP_PHY_RST,
+ QSFP_LPMOD,
+ QSFP_LED_LANE0_GREEN,
+ QSFP_LED_LANE1_GREEN,
+ QSFP_LED_LANE2_GREEN,
+ QSFP_LED_LANE3_GREEN,
+ QSFP_LED_LANE0_BEACON,
+ QSFP_LED_LANE1_BEACON,
+ QSFP_LED_LANE2_BEACON,
+ QSFP_LED_LANE3_BEACON,
+ QSFP_LED_LANE0_FAULT,
+ QSFP_LED_LANE1_FAULT,
+ QSFP_LED_LANE2_FAULT,
+ QSFP_LED_LANE3_FAULT,
+ TMC_PFE_GPIO_GROUP_MAX
+};
+
+enum sfp_op {
+ SFP_TX_DISABLE,
+ SFP_LED_ACTIVITY,
+ SFP_PRESENT,
+ SFP_SFP_LOS,
+ SFP_TX_FAULT,
+ SFP_LED_LANE0_GREEN = SFP_LED_OP_START_INDEX,
+ SFP_LED_LANE1_GREEN,
+ SFP_LED_LANE2_GREEN,
+ SFP_LED_LANE3_GREEN,
+ SFP_LED_LANE0_BEACON,
+ SFP_LED_LANE1_BEACON,
+ SFP_LED_LANE2_BEACON,
+ SFP_LED_LANE3_BEACON,
+ SFP_LED_LANE0_FAULT,
+ SFP_LED_LANE1_FAULT,
+ SFP_LED_LANE2_FAULT,
+ SFP_LED_LANE3_FAULT,
+ TMC_PFE_SFP_GPIO_GROUP_MAX
+};
+
+static const u32 group_offset[TMC_PFE_GPIO_GROUP_MAX] = {
+ TMC_PFE_QSFP_RESET_OFFSET,
+ TMC_PFE_QSFP_PRESENT_OFFSET,
+ TMC_PFE_QSFP_PHY_RESET_OFFSET,
+ TMC_PFE_QSFP_LPMOD_OFFSET,
+ TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE0 GREEN */
+ TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE1 GREEN */
+ TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE2 GREEN */
+ TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE3 GREEN */
+ TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE0 BEACON */
+ TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE1 BEACON */
+ TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE2 BEACON */
+ TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE3 BEACON */
+ TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE0 FAULT */
+ TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE1 FAULT */
+ TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE2 FAULT */
+ TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE3 FAULT */
+};
+
+static const u32 sfp_slaveb0_group_offset[TMC_PFE_SFP_GPIO_GROUP_MAX] = {
+ TMC_PFE_SFPSB0_TX_DISABLE_OFFSET,
+ TMC_PFE_SFPSB0_LED_ACTIVITY_OFFSET,
+ TMC_PFE_SFPSB0_PRESENT_OFFSET,
+ TMC_PFE_SFPSB0_LOSS_OFFSET,
+ TMC_PFE_SFPSB0_TX_FAULT_OFFSET,
+ TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE0 GREEN */
+ TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE1 GREEN */
+ TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE2 GREEN */
+ TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE3 GREEN */
+ TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE0 BEACON */
+ TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE1 BEACON */
+ TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE2 BEACON */
+ TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE3 BEACON */
+ TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE0 FAULT */
+ TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE1 FAULT */
+ TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE2 FAULT */
+ TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE3 FAULT */
+};
+
+static const u32 sfp_slaveb1_group_offset[TMC_PFE_SFP_GPIO_GROUP_MAX] = {
+ TMC_PFE_SFPSB1_TX_DISABLE_OFFSET,
+ TMC_PFE_SFPSB1_LED_ACTIVITY_OFFSET,
+ TMC_PFE_SFPSB1_PRESENT_OFFSET,
+ TMC_PFE_SFPSB1_LOSS_OFFSET,
+ TMC_PFE_SFPSB1_TX_FAULT_OFFSET,
+ TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE0 GREEN */
+ TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE1 GREEN */
+ TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE2 GREEN */
+ TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE3 GREEN */
+ TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE0 BEACON */
+ TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE1 BEACON */
+ TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE2 BEACON */
+ TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE3 BEACON */
+ TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE0 FAULT */
+ TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE1 FAULT */
+ TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE2 FAULT */
+ TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE3 FAULT */
+};
+
+struct tmc_gpio_info {
+ int (*get)(struct gpio_chip *, unsigned int);
+ void (*set)(struct gpio_chip *, unsigned int, int);
+ int (*dirin)(struct gpio_chip *, unsigned int);
+ int (*dirout)(struct gpio_chip *, unsigned int, int);
+};
+
+struct tmc_gpio_chip {
+ const struct tmc_gpio_info *info;
+ void __iomem *base;
+ struct device *dev;
+ struct gpio_chip gpio;
+ int ngpio;
+ spinlock_t gpio_lock; /* gpio lock */
+ int sfp_slave_block;
+};
+
+/* slave gpio max */
+static int gpio_max = 320;
+module_param(gpio_max, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(gpio_max, "Maximum number of gpio for SLAVE TMC GPIO");
+
+/*
+ * generic bit operation functions
+ */
+static u32 tmc_gpio_reset_bits(u32 state, u32 val, u32 shift)
+{
+ state &= ~(val << shift);
+ return state;
+};
+
+static u32 tmc_gpio_set_bits(u32 state, u32 val, u32 shift)
+{
+ state |= (val << shift);
+ return state;
+};
+
+static u32 tmc_gpio_find_bits_val(u32 state, u32 shift, u32 mask)
+{
+ return ((state >> shift)) & mask;
+};
+
+#define to_tmc_chip(chip) \
+ container_of((chip), struct tmc_gpio_chip, gpio)
+
+/*
+ * tmc_gpio_multiple_bitsop - Generic TMC GPIO multiple bits operation
+ */
+static void tmc_gpio_multiple_bitsop(struct tmc_gpio_chip *chip,
+ unsigned int gpiono, u32 group, u32 offset, bool set)
+{
+ u32 gpio_state, led_val, bit_shift;
+ unsigned long flags;
+ void __iomem *iobase;
+
+ iobase = chip->base + offset;
+
+ dev_dbg(chip->dev, "TMC GPIO multiple bitop group=%u, "
+ "gpiono=%u, offet:=%u, set=%u\n", group, gpiono, offset, set);
+
+ spin_lock_irqsave(&chip->gpio_lock, flags);
+
+ switch (group) {
+ case QSFP_LED_LANE0_GREEN:
+ case SFP_LED_LANE0_GREEN:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ led_val = TMC_PFE_LANES_GREEN_LED_VALUE;
+ bit_shift = TMC_PFE_LANE0_GREEN_LED_BIT_POSITION;
+ break;
+ case QSFP_LED_LANE1_GREEN:
+ case SFP_LED_LANE1_GREEN:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ led_val = TMC_PFE_LANES_GREEN_LED_VALUE;
+ bit_shift = TMC_PFE_LANE1_GREEN_LED_BIT_POSITION;
+ break;
+ case QSFP_LED_LANE2_GREEN:
+ case SFP_LED_LANE2_GREEN:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ led_val = TMC_PFE_LANES_GREEN_LED_VALUE;
+ bit_shift = TMC_PFE_LANE2_GREEN_LED_BIT_POSITION;
+ break;
+ case QSFP_LED_LANE3_GREEN:
+ case SFP_LED_LANE3_GREEN:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ led_val = TMC_PFE_LANES_GREEN_LED_VALUE;
+ bit_shift = TMC_PFE_LANE3_GREEN_LED_BIT_POSITION;
+ break;
+ case QSFP_LED_LANE0_BEACON:
+ case SFP_LED_LANE0_BEACON:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ led_val = TMC_PFE_LANES_BEACON_LED_VALUE;
+ bit_shift = TMC_PFE_LANE0_BEACON_LED_BIT_POSITION;
+ break;
+ case QSFP_LED_LANE1_BEACON:
+ case SFP_LED_LANE1_BEACON:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ led_val = TMC_PFE_LANES_BEACON_LED_VALUE;
+ bit_shift = TMC_PFE_LANE1_BEACON_LED_BIT_POSITION;
+ break;
+ case QSFP_LED_LANE2_BEACON:
+ case SFP_LED_LANE2_BEACON:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ led_val = TMC_PFE_LANES_BEACON_LED_VALUE;
+ bit_shift = TMC_PFE_LANE2_BEACON_LED_BIT_POSITION;
+ break;
+ case QSFP_LED_LANE3_BEACON:
+ case SFP_LED_LANE3_BEACON:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ led_val = TMC_PFE_LANES_BEACON_LED_VALUE;
+ bit_shift = TMC_PFE_LANE3_BEACON_LED_BIT_POSITION;
+ break;
+ case QSFP_LED_LANE0_FAULT:
+ case SFP_LED_LANE0_FAULT:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ led_val = TMC_PFE_LANES_FAULT_LED_VALUE;
+ bit_shift = TMC_PFE_LANE0_FAULT_LED_BIT_POSITION;
+ break;
+ case QSFP_LED_LANE1_FAULT:
+ case SFP_LED_LANE1_FAULT:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ led_val = TMC_PFE_LANES_FAULT_LED_VALUE;
+ bit_shift = TMC_PFE_LANE1_FAULT_LED_BIT_POSITION;
+ break;
+ case QSFP_LED_LANE2_FAULT:
+ case SFP_LED_LANE2_FAULT:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ led_val = TMC_PFE_LANES_FAULT_LED_VALUE;
+ bit_shift = TMC_PFE_LANE2_FAULT_LED_BIT_POSITION;
+ break;
+ case QSFP_LED_LANE3_FAULT:
+ case SFP_LED_LANE3_FAULT:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ led_val = TMC_PFE_LANES_FAULT_LED_VALUE;
+ bit_shift = TMC_PFE_LANE3_FAULT_LED_BIT_POSITION;
+ break;
+
+ default:
+ spin_unlock_irqrestore(&chip->gpio_lock, flags);
+ return;
+ }
+
+ if (set) {
+ gpio_state = tmc_gpio_reset_bits(gpio_state, 0x3, bit_shift);
+ gpio_state = tmc_gpio_set_bits(gpio_state, led_val, bit_shift);
+ } else {
+ gpio_state = tmc_gpio_reset_bits(gpio_state, 0x3, bit_shift);
+ }
+
+ iowrite32(gpio_state, (iobase+(0x004*gpiono)));
+
+ spin_unlock_irqrestore(&chip->gpio_lock, flags);
+
+ return;
+};
+
+/*
+ * tmc_gpio_one_bitop - Generic TMC GPIO single bit operation
+ */
+static void tmc_gpio_one_bitop(struct tmc_gpio_chip *chip,
+ unsigned int bit, u32 offset, bool set)
+{
+ u32 gpio_state;
+ unsigned long flags;
+ void __iomem *iobase;
+
+ iobase = chip->base + offset;
+
+ dev_dbg(chip->dev, "TMC GPIO one bitop bit=%u, offset=%x, "
+ "set=%u\n", bit, offset, set);
+
+ spin_lock_irqsave(&chip->gpio_lock, flags);
+
+ gpio_state = ioread32(iobase);
+ if (set)
+ gpio_state |= BIT(bit);
+ else
+ gpio_state &= ~BIT(bit);
+
+ iowrite32(gpio_state, iobase);
+
+ spin_unlock_irqrestore(&chip->gpio_lock, flags);
+
+ return;
+}
+
+/*
+ * tmc_gpio_get_multiple_bitsop - Generic TMC get GPIO multiple bits operation
+ */
+static int tmc_gpio_get_multiple_bitsop(struct tmc_gpio_chip *chip,
+ unsigned int gpiono, u32 group, u32 offset)
+{
+ u32 gpio_state;
+ void __iomem *iobase;
+
+ iobase = chip->base + offset;
+
+ dev_dbg(chip->dev, "TMC GPIO get multiple bitsop group=%u, "
+ "gpiono=%u, offset=%u\n", group, gpiono, offset);
+
+ switch (group) {
+ case QSFP_LED_LANE0_GREEN:
+ case SFP_LED_LANE0_GREEN:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ return (TMC_PFE_LANES_GREEN_LED_VALUE ==
+ tmc_gpio_find_bits_val(gpio_state,
+ TMC_PFE_LANE0_GREEN_LED_BIT_POSITION, 0x3));
+ case QSFP_LED_LANE1_GREEN:
+ case SFP_LED_LANE1_GREEN:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ return (TMC_PFE_LANES_GREEN_LED_VALUE ==
+ tmc_gpio_find_bits_val(gpio_state,
+ TMC_PFE_LANE1_GREEN_LED_BIT_POSITION, 0x3));
+ case QSFP_LED_LANE2_GREEN:
+ case SFP_LED_LANE2_GREEN:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ return (TMC_PFE_LANES_GREEN_LED_VALUE ==
+ tmc_gpio_find_bits_val(gpio_state,
+ TMC_PFE_LANE2_GREEN_LED_BIT_POSITION, 0x3));
+ case QSFP_LED_LANE3_GREEN:
+ case SFP_LED_LANE3_GREEN:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ return (TMC_PFE_LANES_GREEN_LED_VALUE ==
+ tmc_gpio_find_bits_val(gpio_state,
+ TMC_PFE_LANE3_GREEN_LED_BIT_POSITION, 0x3));
+ case QSFP_LED_LANE0_BEACON:
+ case SFP_LED_LANE0_BEACON:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ return (TMC_PFE_LANES_BEACON_LED_VALUE ==
+ tmc_gpio_find_bits_val(gpio_state,
+ TMC_PFE_LANE0_BEACON_LED_BIT_POSITION, 0x3));
+ case QSFP_LED_LANE1_BEACON:
+ case SFP_LED_LANE1_BEACON:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ return (TMC_PFE_LANES_BEACON_LED_VALUE ==
+ tmc_gpio_find_bits_val(gpio_state,
+ TMC_PFE_LANE1_BEACON_LED_BIT_POSITION, 0x3));
+ case QSFP_LED_LANE2_BEACON:
+ case SFP_LED_LANE2_BEACON:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ return (TMC_PFE_LANES_BEACON_LED_VALUE ==
+ tmc_gpio_find_bits_val(gpio_state,
+ TMC_PFE_LANE2_BEACON_LED_BIT_POSITION, 0x3));
+ case QSFP_LED_LANE3_BEACON:
+ case SFP_LED_LANE3_BEACON:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ return (TMC_PFE_LANES_BEACON_LED_VALUE ==
+ tmc_gpio_find_bits_val(gpio_state,
+ TMC_PFE_LANE3_BEACON_LED_BIT_POSITION, 0x3));
+ case QSFP_LED_LANE0_FAULT:
+ case SFP_LED_LANE0_FAULT:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ return (TMC_PFE_LANES_FAULT_LED_VALUE ==
+ tmc_gpio_find_bits_val(gpio_state,
+ TMC_PFE_LANE0_FAULT_LED_BIT_POSITION, 0x3));
+ case QSFP_LED_LANE1_FAULT:
+ case SFP_LED_LANE1_FAULT:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ return (TMC_PFE_LANES_FAULT_LED_VALUE ==
+ tmc_gpio_find_bits_val(gpio_state,
+ TMC_PFE_LANE1_FAULT_LED_BIT_POSITION, 0x3));
+ case QSFP_LED_LANE2_FAULT:
+ case SFP_LED_LANE2_FAULT:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ return (TMC_PFE_LANES_FAULT_LED_VALUE ==
+ tmc_gpio_find_bits_val(gpio_state,
+ TMC_PFE_LANE2_FAULT_LED_BIT_POSITION, 0x3));
+ case QSFP_LED_LANE3_FAULT:
+ case SFP_LED_LANE3_FAULT:
+ gpio_state = ioread32(iobase+(0x004*gpiono));
+ return (TMC_PFE_LANES_FAULT_LED_VALUE ==
+ tmc_gpio_find_bits_val(gpio_state,
+ TMC_PFE_LANE3_FAULT_LED_BIT_POSITION, 0x3));
+ default:
+ return 0;
+ }
+};
+
+/*
+ * tmc_gpio_get - Read the specified signal of the GPIO device.
+ */
+static int tmc_gpio_get(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct tmc_gpio_chip *chip = to_tmc_chip(gc);
+ unsigned int group = TMC_GPIO_FIND_GROUP(gpio);
+ unsigned int bit = TMC_GPIO_FIND_GPIO(gpio);
+
+ if (group >= TMC_PFE_GPIO_GROUP_MAX)
+ return 0;
+
+ switch (group) {
+ case QSFP_RST:
+ case QSFP_PRESENT:
+ case QSFP_PHY_RST:
+ case QSFP_LPMOD:
+ dev_dbg(chip->dev, "TMC GPIO get one bitop group=%u, gpio=%u, "
+ "bit=%u\n", group, gpio, bit);
+ return !!(ioread32(chip->base + group_offset[group])
+ & BIT(bit));
+ default:
+ return tmc_gpio_get_multiple_bitsop(chip, bit, group, group_offset[group]);
+ }
+}
+
+/*
+ * tmc_gpio_set - Write the specified signal of the GPIO device.
+ */
+static void tmc_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+ struct tmc_gpio_chip *chip = to_tmc_chip(gc);
+ unsigned int group = TMC_GPIO_FIND_GROUP(gpio);
+ unsigned int bit = TMC_GPIO_FIND_GPIO(gpio);
+
+ if (group >= TMC_PFE_GPIO_GROUP_MAX)
+ return;
+
+ switch (group) {
+ case QSFP_RST:
+ case QSFP_PRESENT:
+ case QSFP_PHY_RST:
+ case QSFP_LPMOD:
+ dev_dbg(chip->dev, "TMC GPIO one bitop group=%d\n", group);
+ tmc_gpio_one_bitop(chip, bit, group_offset[group], val);
+ break;
+ default:
+ tmc_gpio_multiple_bitsop(chip, bit, group, group_offset[group], val);
+ break;
+ }
+}
+
+static struct tmc_gpio_info tmc_gpios[] = {
+ {
+ .get = tmc_gpio_get,
+ .set = tmc_gpio_set,
+ },
+};
+
+static void tmc_gpio_setup(struct tmc_gpio_chip *sgc, int id)
+{
+ struct gpio_chip *chip = &sgc->gpio;
+ const struct tmc_gpio_info *info = sgc->info;
+
+ chip->get = info->get;
+ chip->set = info->set;
+ chip->direction_input = info->dirin;
+ chip->direction_output = info->dirout;
+ chip->dbg_show = NULL;
+ chip->can_sleep = 0;
+
+ if (id == 0) {
+ chip->base = 0;
+ } else if (id == 1) {
+ chip->base = (gpio_max * id);
+ } else {
+ chip->base = -1;
+ }
+
+ chip->ngpio = sgc->ngpio;
+ chip->label = dev_name(sgc->dev);
+ chip->parent = sgc->dev;
+ chip->owner = THIS_MODULE;
+}
+
+static int tmc_gpio_of_init(struct device *dev,
+ struct tmc_gpio_chip *chip)
+{
+ chip->info = &tmc_gpios[0];
+ chip->ngpio = gpio_max;
+
+ return 0;
+}
+
+static int tmc_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct tmc_gpio_chip *chip;
+ struct resource *res;
+ int ret;
+
+ const struct mfd_cell *cell = mfd_get_cell(pdev);
+
+ dev_dbg(dev, "TMC GPIO probe\n");
+
+ chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ dev_info(dev, "TMC GPIO resource 0x%llx, %llu\n",
+ res->start, resource_size(res));
+
+ chip->base = devm_ioremap_nocache(dev, res->start, resource_size(res));
+ if (!chip->base)
+ return -ENOMEM;
+
+ ret = tmc_gpio_of_init(dev, chip);
+ if (ret)
+ return ret;
+
+ chip->dev = dev;
+ spin_lock_init(&chip->gpio_lock);
+
+ tmc_gpio_setup(chip, cell->id);
+
+ ret = gpiochip_add(&chip->gpio);
+ if (ret) {
+ dev_err(dev,
+ "Failed to register TMC gpiochip : %d\n", ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, chip);
+ dev_info(dev, "TMC GPIO registered at 0x%lx, gpiobase: %d\n",
+ (long unsigned)chip->base, chip->gpio.base);
+
+ return 0;
+}
+
+static int tmc_gpio_remove(struct platform_device *pdev)
+{
+ struct tmc_gpio_chip *chip = platform_get_drvdata(pdev);
+
+ gpiochip_remove(&chip->gpio);
+
+ return 0;
+}
+
+static struct platform_driver tmc_gpio_driver = {
+ .driver = {
+ .name = "gpioslave-tmc",
+ .owner = THIS_MODULE,
+ },
+ .probe = tmc_gpio_probe,
+ .remove = tmc_gpio_remove,
+};
+
+module_platform_driver(tmc_gpio_driver);
+
+MODULE_DESCRIPTION("Juniper Networks TMC FPGA GPIO driver");
+MODULE_AUTHOR("Ashish Bhensdadia ");
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-juniper/common/modules/i2c-tmc.c b/platform/broadcom/sonic-platform-modules-juniper/common/modules/i2c-tmc.c
new file mode 100644
index 0000000000..afd0311dc1
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-juniper/common/modules/i2c-tmc.c
@@ -0,0 +1,1107 @@
+/*
+ * Juniper Networks TMC I2C Accelerator driver
+ *
+ * Copyright (C) 2020 Juniper Networks
+ * Author: Ashish Bhensdadia
+ *
+ * This driver implement the I2C functionality
+ *
+ * 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; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "jnx-tmc.h"
+
+
+#define TMC_I2C_MASTER_I2C_SCAN_RESET_BIT BIT(31)
+
+#define TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET 0x0
+#define TMC_I2C_MSTR_AUTOMATION_I2C_DPMEM_OFFSET 0x10
+
+#define TMC_I2C_MSTR_AUTOMATION_I2C(adap, offset) \
+ ((adap)->membase + offset)
+
+#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_0 0x0
+#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8 0x8
+#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_4 0x4
+#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_C 0xC
+#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10 0x10
+#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_14 0x14
+#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_18 0x18
+#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_1C 0x1C
+#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_20 0x20
+#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_24 0x24
+
+#define TMC_I2C_MSTR_I2C_DPMEM(adap, offset) \
+ ((adap)->dpmbase + offset)
+
+#define TMC_I2C_TRANS_LEN 2
+#define tmc_iowrite(val, addr) iowrite32((val), (addr))
+
+#define TMC_I2C_CTRL_GROUP(g) (((g) & 0xFF) << 8)
+#define TMC_I2C_CTRL_WRCNT(w) (((w) & 0x3F) << 16)
+#define TMC_I2C_CTRL_RDCNT(r) (((r) & 0x3F) << 16)
+#define TMC_I2C_CTRL_DEVADDR(d) (((d) & 0xFF) << 8)
+#define TMC_I2C_CTRL_OFFSET(o) ((o) & 0xFF)
+
+
+#define TMC_I2C_MEM_CTRL_VLD BIT(31)
+
+#define TMC_I2C_CTRL_ERR(s) ((s) & 0x0F000000)
+#define TMC_I2C_CTRL_DONE_BIT(s) ((s) & BIT(31))
+#define TMC_I2C_CTRL_STATUS_OK(s) (TMC_I2C_CTRL_DONE_BIT(s) & \
+ TMC_I2C_CTRL_ERR(s))
+#define TMC_I2C_CTRL_DONE(s) (TMC_I2C_CTRL_DONE_BIT(s) == BIT(31))
+
+#define TMC_I2C_STAT_INC(adap, s) (((adap)->stat.s)++)
+#define TMC_I2C_STAT_INCN(adap, s, n) (((adap)->stat.s) += (n))
+#define TMC_I2C_GET_MASTER(tadap) ((tadap)->tctrl)
+
+#define TMC_I2C_READ 0x1
+#define TMC_I2C_WRITE 0x2
+
+#define TMC_I2C_MASTER_LOCK(s, flags) \
+do { \
+ spin_lock_irqsave(&(s)->lock, flags); \
+} while (0)
+
+#define TMC_I2C_MASTER_UNLOCK(s, flags) \
+do { \
+ spin_unlock_irqrestore(&(s)->lock, flags); \
+} while (0)
+
+#define tmc_i2c_dbg(dev, fmt, args...) \
+do { \
+ if (tmc_i2c_debug >= 1) \
+ dev_err(dev, fmt, ## args); \
+} while (0)
+
+
+/* pfe TMC i2c channel */
+static int pfe_channel = 32;
+module_param(pfe_channel, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(pfe_channel, "Maximum number of channel for PFE TMC");
+
+/* chassid TMC i2c channel */
+static int chd_channel = 11;
+module_param(chd_channel, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(chd_channel, "Maximum number of channel for CHASSID TMC");
+
+static u32 wr_index_to_oper[] = {0x01000000, 0x02000000,
+ 0x84000000, 0x85000000, 0x83000000};
+static u32 rd_index_to_oper[] = {0x08000000, 0x09000000, 0x0A000000,
+ 0x8B000000, 0x8C000000, 0x8D000000, 0x83000000};
+
+struct tmc_i2c_adapter_stats {
+ u32 abort;
+ u32 go;
+ u32 mstr_rdy;
+ u32 mstr_busy;
+ u32 trans_compl;
+ u32 msg_cnt;
+ u32 rd_cnt;
+ u32 wr_cnt;
+ u32 byte_cnt;
+ u32 slave_timeo;
+ u32 scl_bus_loss;
+ u32 sda_bus_loss;
+ u32 ack_ptimeo;
+ u32 rd_cnt_0;
+ u32 rd_cnt_gt32;
+ u32 rst_tgt;
+ u32 rst_mstr;
+};
+
+struct tmc_i2c_adapter {
+ void __iomem *membase;
+ void __iomem *dpmbase;
+ struct i2c_adapter adap;
+ struct i2c_mux_core *muxc;
+ struct tmc_i2c_ctrl *tctrl;
+ int mux_channels;
+ int mux_select;
+ u32 i2c_delay;
+ int entries;
+ int master;
+ u32 control;
+ u32 speed;
+ bool done;
+ bool polling;
+ bool use_block;
+ wait_queue_head_t wait;
+ struct tmc_i2c_adapter_stats stat;
+};
+
+struct tmc_i2c_ctrl {
+ void __iomem *membase;
+ void __iomem *dpmbase;
+ struct i2c_adapter **adap;
+ struct device *dev;
+ int num_masters;
+ int mux_channels;
+ u32 i2c_delay;
+ u32 master_mask;
+ spinlock_t lock; /* master lock */
+};
+
+/*
+ * Reset the Tmc I2C master
+ */
+static void tmc_i2c_reset_master(struct i2c_adapter *adap)
+{
+ struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
+ struct tmc_i2c_ctrl *tmc = TMC_I2C_GET_MASTER(tadap);
+ u32 val, master = tadap->master;
+ unsigned long flags;
+ void __iomem *addr;
+
+ dev_warn(&adap->dev, "Re-setting i2c master: %d\n", master);
+
+ TMC_I2C_MASTER_LOCK(tmc, flags);
+
+ addr = tmc->membase + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET;
+ val = ioread32(addr);
+ tmc_iowrite(val | (TMC_I2C_MASTER_I2C_SCAN_RESET_BIT), addr);
+ tmc_iowrite(val & ~(TMC_I2C_MASTER_I2C_SCAN_RESET_BIT), addr);
+ TMC_I2C_STAT_INC(tadap, rst_mstr);
+
+ TMC_I2C_MASTER_UNLOCK(tmc, flags);
+}
+
+/*
+ * check if the Tmc I2C master is ready
+ */
+static int tmc_i2c_mstr_wait_rdy(struct i2c_adapter *adap, u8 rw, u32 delay)
+{
+ struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
+ unsigned long timeout;
+ u32 val;
+
+ val = ioread32(TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
+ if (val) {
+ tmc_iowrite(0x80000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
+ mdelay(5);
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
+ val = ioread32(TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
+ } else {
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
+ }
+
+ if ((rw == TMC_I2C_READ) && (delay)) {
+ tmc_iowrite(0x80000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
+ return 0;
+ }
+
+ timeout = jiffies + adap->timeout;
+ do {
+ val = ioread32(TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
+ if (!val)
+ return 0;
+
+ if (tadap->polling) {
+ usleep_range(50, 100);
+ } else {
+ tadap->done = false;
+ wait_event_timeout(tadap->wait, tadap->done,
+ adap->timeout);
+ }
+ } while (time_before(jiffies, timeout));
+
+ TMC_I2C_STAT_INC(tadap, mstr_busy);
+
+ return -EBUSY;
+}
+
+/*
+ * Wait for master completion
+ */
+static u32 tmc_i2c_mstr_wait_completion(struct i2c_adapter *adap,
+ u32 dp_entry_offset)
+{
+ struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
+ u32 val;
+
+ if (tadap->polling) {
+ /* Poll for the results */
+ unsigned long timeout = jiffies + adap->timeout;
+
+ do {
+ usleep_range(1000, 1200);
+ val = ioread32(TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ dp_entry_offset));
+ if (TMC_I2C_CTRL_DONE(val))
+ break;
+ } while (time_before(jiffies, timeout));
+ } else {
+ wait_event_timeout(tadap->wait, tadap->done, adap->timeout);
+ val = ioread32(TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ dp_entry_offset));
+ }
+
+ return TMC_I2C_CTRL_STATUS_OK(val);
+}
+
+/*
+ * TMC I2C delay read/write operation
+ */
+static int tmc_i2c_delay_rw_op(struct i2c_adapter *adap, u8 rw, u32 mux,
+ u32 addr, u32 offset, u32 len, u32 delay, u8 *buf)
+{
+ struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
+ struct device *dev = &adap->dev;
+ int err, n;
+ u32 control = 0, data = 0;
+ u32 val;
+
+ err = tmc_i2c_mstr_wait_rdy(adap, rw, 0);
+ if (err < 0) {
+ tmc_i2c_reset_master(adap);
+ return err;
+ }
+
+ TMC_I2C_STAT_INC(tadap, mstr_rdy);
+
+ /* initialize the start address and mux */
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_DPMEM_OFFSET));
+
+ tmc_iowrite(mux, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_0));
+ tmc_iowrite(0x84400000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_4));
+
+ /* populate delay */
+ if (delay) {
+ if (delay > 1000) {
+ delay = delay/1000;
+ delay |= (1 << 16);
+ }
+ }
+ tmc_iowrite(delay, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8));
+ tmc_iowrite(0x86000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_C));
+
+ /* prepare control command */
+ control |= TMC_I2C_CTRL_DEVADDR(addr);
+ control |= TMC_I2C_CTRL_OFFSET(offset);
+
+ if (rw == TMC_I2C_WRITE) {
+ for (n = 0; n < len; n++)
+ data |= (buf[n] << ((len - 1 - n) * 8));
+ tmc_iowrite(data, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10));
+ control |= TMC_I2C_CTRL_WRCNT(len);
+ control |= wr_index_to_oper[len-1];
+ dev_dbg(dev, "WR Data: [%#04x, %#04x, %#04x, %#04x]\n",
+ ((data >> 24) & 0xff), ((data >> 16) & 0xff),
+ ((data >> 8) & 0xff), (data & 0xff));
+
+ } else {
+ /* read */
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10));
+ control |= TMC_I2C_CTRL_RDCNT(len);
+ control |= rd_index_to_oper[len-1];
+ }
+
+ /*
+ * valid this transaction as well
+ */
+ control |= TMC_I2C_MEM_CTRL_VLD;
+
+ tadap->control = control;
+
+ /*
+ * operation control command
+ */
+ tmc_iowrite(control, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_14));
+
+ /*
+ * End commands
+ */
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_18));
+ tmc_iowrite(0x8E000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_1C));
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_20));
+ tmc_iowrite(0x8F000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_24));
+
+ dev_dbg(dev, "Control (%#x): RD_WR_TYPE:%#02x, RD_WR_LEN:%d,"
+ "Addr:%#01x, Offset:%#02x\n", control,
+ ((control >> 24) & 0x3F), ((control >> 16) & 0x3F),
+ ((control >> 8) & 0xff), ((control) & 0xff));
+
+ tadap->done = false;
+
+ /* fire the transaction */
+ tmc_iowrite(0x00000001, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
+
+ TMC_I2C_STAT_INC(tadap, go);
+
+ val = tmc_i2c_mstr_wait_completion(adap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10);
+ if (val) {
+ dev_err(&adap->dev,
+ "i2c transaction error (0x%08x)\n", val);
+
+ /* stop the transaction */
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
+ return -EIO;
+ }
+
+ /*
+ * read a word of data
+ */
+ if (rw == TMC_I2C_READ) {
+ data = ioread32(TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10));
+ for (n = 0; n < len; n++)
+ buf[n] = (data >> (n * 8)) & 0xff;
+
+ dev_dbg(dev, "RD Data: [%#04x, %#04x, %#04x, %#04x]\n",
+ ((data >> 24) & 0xff), ((data >> 16) & 0xff),
+ ((data >> 8) & 0xff), (data & 0xff));
+
+ TMC_I2C_STAT_INC(tadap, rd_cnt);
+ } else {
+ /* write */
+ TMC_I2C_STAT_INC(tadap, wr_cnt);
+ }
+
+ /* stop the transaction */
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
+
+ return 0;
+
+}
+
+/*
+ *TMC I2C none delay Read/write opertion
+ */
+static int tmc_i2c_none_delay_rw_op(struct i2c_adapter *adap, u8 rw, u32 mux,
+ u32 addr, u32 offset, u32 len, u8 *buf)
+{
+ struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
+ struct device *dev = &adap->dev;
+ int err, n;
+ u32 control = 0, data = 0;
+ u32 val;
+
+ err = tmc_i2c_mstr_wait_rdy(adap, rw, 0);
+ if (err < 0) {
+ tmc_i2c_reset_master(adap);
+ return err;
+ }
+
+ TMC_I2C_STAT_INC(tadap, mstr_rdy);
+
+ /* initialize the start address and mux */
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_DPMEM_OFFSET));
+
+ tmc_iowrite(mux, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_0));
+ tmc_iowrite(0x84400000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_4));
+
+
+ /* prepare control command */
+ control |= TMC_I2C_CTRL_DEVADDR(addr);
+ control |= TMC_I2C_CTRL_OFFSET(offset);
+
+ if (rw == TMC_I2C_WRITE) {
+ for (n = 0; n < len; n++)
+ data |= (buf[n] << (n * 8));
+ tmc_iowrite(data, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8));
+ control |= wr_index_to_oper[len-1];
+ dev_dbg(dev, "WR Data: [%#04x, %#04x, %#04x, %#04x]\n",
+ ((data >> 24) & 0xff), ((data >> 16) & 0xff),
+ ((data >> 8) & 0xff), (data & 0xff));
+
+ } else {
+ /* read */
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8));
+ control |= rd_index_to_oper[len-1];
+ }
+
+ /*
+ * valid this transaction as well
+ */
+ control |= TMC_I2C_MEM_CTRL_VLD;
+
+ tadap->control = control;
+
+ /*
+ * operation control command
+ */
+ tmc_iowrite(control, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_C));
+
+ /*
+ * End commands
+ */
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10));
+ tmc_iowrite(0x8E000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_14));
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_18));
+ tmc_iowrite(0x8F000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_1C));
+
+ dev_dbg(dev, "Control (%#x): RD_WR_TYPE:%#02x, RD_WR_LEN:%d,"
+ "Addr:%#01x, Offset:%#02x\n", control,
+ ((control >> 24) & 0x3F), ((control >> 16) & 0x3F),
+ ((control >> 8) & 0xff), ((control) & 0xff));
+
+ tadap->done = false;
+
+ /* fire the transaction */
+ tmc_iowrite(0x00000001, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
+
+ TMC_I2C_STAT_INC(tadap, go);
+
+ /* wait till transaction complete */
+ val = tmc_i2c_mstr_wait_completion(adap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8);
+ if (val) {
+ dev_err(&adap->dev,
+ "i2c transaction error (0x%08x)\n", val);
+
+ /* stop the transaction */
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
+ return -EIO;
+ }
+
+ /*
+ * read a word of data
+ */
+ if (rw == TMC_I2C_READ) {
+ data = ioread32(TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8));
+ for (n = 0; n < len; n++)
+ buf[n] = (data >> (n * 8)) & 0xff;
+
+ dev_dbg(dev, "RD Data: [%#04x, %#04x, %#04x, %#04x]\n",
+ ((data >> 24) & 0xff), ((data >> 16) & 0xff),
+ ((data >> 8) & 0xff), (data & 0xff));
+ TMC_I2C_STAT_INC(tadap, rd_cnt);
+ } else {
+ /* write */
+ TMC_I2C_STAT_INC(tadap, wr_cnt);
+ }
+
+ /* stop the transaction */
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
+
+ return 0;
+}
+
+/*
+ * TMC I2C read/write operation
+ */
+static int tmc_i2c_rw_op(struct i2c_adapter *adap, u8 rw, u32 mux,
+ u32 addr, u32 offset, u32 len, u8 *buf)
+{
+ struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
+ u32 i2c_delay = tadap->i2c_delay;
+
+ if (i2c_delay) {
+ return tmc_i2c_delay_rw_op(adap, rw, mux, addr, offset,
+ len, i2c_delay, buf);
+ } else {
+ return tmc_i2c_none_delay_rw_op(adap, rw, mux, addr, offset,
+ len, buf);
+ }
+}
+
+static int tmc_i2c_calc_entries(int msglen)
+{
+ int entries = msglen / TMC_I2C_TRANS_LEN;
+
+ return (entries += (msglen % TMC_I2C_TRANS_LEN) ? 1 : 0);
+}
+
+static int tmc_i2c_block_read(struct i2c_adapter *adap,
+ struct i2c_msg *msgs, int num)
+{
+ struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
+ struct device *dev = &adap->dev;
+ int curmsg, entries, len;
+ int offset = 0;
+ struct i2c_msg *msg;
+ int err, n = 0;
+ u8 rwbuf[4] = {0};
+
+ dev_dbg(dev, "Read i2c Block\n");
+
+ for (curmsg = 0, offset = 0; curmsg < num; curmsg++) {
+ msg = &msgs[curmsg];
+ len = msg->len;
+
+ if (msg->flags & I2C_M_RECV_LEN)
+ len = (I2C_SMBUS_BLOCK_MAX + 1);
+
+ entries = tmc_i2c_calc_entries(len);
+
+ if (msg->flags & I2C_M_RD) {
+ if (curmsg == 1 && ((msg->flags & I2C_M_RECV_LEN &&
+ !(msgs[0].flags & I2C_M_RD)) ||
+ (msg->len > TMC_I2C_TRANS_LEN))) {
+ offset = msgs[0].buf[0];
+ }
+
+ while (entries) {
+ err = tmc_i2c_rw_op(adap, TMC_I2C_READ,
+ tadap->mux_select,
+ msgs[0].addr, offset,
+ TMC_I2C_TRANS_LEN, rwbuf);
+ if (err < 0)
+ return err;
+ msg = &msgs[num - 1];
+ msg->buf[n] = rwbuf[0];
+ msg->buf[n+1] = rwbuf[1];
+ n = n + TMC_I2C_TRANS_LEN;
+ offset = offset + TMC_I2C_TRANS_LEN;
+ entries--;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/*
+ *TMC I2C SMB Read opertion
+ */
+static int tmc_i2c_smb_block_read_op(struct i2c_adapter *adap, u8 rw, u32 mux,
+ u32 addr, u32 offset, u32 len, u8 *buf)
+{
+ struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
+ int err, i = 0;
+ u32 control = 0, data = 0;
+ u32 start_add;
+
+ err = tmc_i2c_mstr_wait_rdy(adap, rw, 0);
+ if (err < 0) {
+ tmc_i2c_reset_master(adap);
+ return err;
+ }
+
+ TMC_I2C_STAT_INC(tadap, mstr_rdy);
+
+ /* initialize the start address and mux */
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_DPMEM_OFFSET));
+
+ tmc_iowrite(mux, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_0));
+ tmc_iowrite(0x84400000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_4));
+
+
+ /* prepare control command */
+ control |= TMC_I2C_CTRL_DEVADDR(addr);
+ control |= TMC_I2C_CTRL_OFFSET(offset);
+
+ /* read */
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8));
+ control |= TMC_I2C_CTRL_RDCNT(len);;
+ control |= rd_index_to_oper[6];
+
+ tadap->control = control;
+
+ /*
+ * operation control command
+ */
+ tmc_iowrite(control, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_C));
+
+ /*
+ * End commands
+ */
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10));
+ tmc_iowrite(0x8E000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_14));
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_18));
+ tmc_iowrite(0x8F000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
+ TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_1C));
+
+ tadap->done = false;
+
+ /* fire the transaction */
+ tmc_iowrite(0x00000001, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
+
+ TMC_I2C_STAT_INC(tadap, go);
+
+ /*
+ * read a block of data
+ */
+ start_add = TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8;
+ while (len > 0) {
+ usleep_range(10000, 12000);
+ data = ioread32(TMC_I2C_MSTR_I2C_DPMEM(tadap, start_add));
+ buf[i] = data & 0xff;
+ buf[i + 1] = (data >> 8) & 0xff;
+ start_add = start_add + 8;
+ i = i + 2;
+ len = len - 2;
+
+ TMC_I2C_STAT_INC(tadap, rd_cnt);
+ }
+
+ /* stop the transaction */
+ tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
+ TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
+
+ return 0;
+}
+
+static int tmc_i2c_smb_block_read(struct i2c_adapter *adap,
+ struct i2c_msg *msgs, int num)
+{
+ struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
+ int curmsg, len;
+ int offset = 0;
+ struct i2c_msg *msg;
+ int err, i = 0;
+ u8 rwbuf[32] = {0};
+
+ for (curmsg = 0, offset = 0; curmsg < num; curmsg++) {
+ msg = &msgs[curmsg];
+ len = msg->len;
+
+ if (msg->flags & I2C_M_RECV_LEN)
+ len = (I2C_SMBUS_BLOCK_MAX + 1);
+
+ if (msg->flags & I2C_M_RD) {
+ if ((curmsg == 1) && (msg->flags & I2C_M_RECV_LEN) &&
+ !(msgs[0].flags & I2C_M_RD)) {
+ offset = msgs[0].buf[0];
+ }
+
+ err = tmc_i2c_smb_block_read_op(adap, TMC_I2C_READ,
+ tadap->mux_select,
+ msgs[0].addr, offset,
+ 32, rwbuf);
+ if (err < 0) {
+ return err;
+ }
+ msg = &msgs[num - 1];
+ for (i = 0; i < len - 1; i++) {
+ msg->buf[i] = rwbuf[i];
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int tmc_i2c_mstr_xfer(struct i2c_adapter *adap,
+ struct i2c_msg *msgs, int num)
+{
+ struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
+ struct device *dev = &adap->dev;
+ int n, curmsg, len = 0;
+ int err = 0;
+ struct i2c_msg *msg;
+ bool read;
+ u8 rwbuf[4] = {0};
+
+ dev_dbg(dev, "Num messages -> %d\n", num);
+
+ /*
+ * Initialize all vars
+ */
+ tadap->entries = 0;
+ tadap->use_block = false;
+
+ for (curmsg = 0; curmsg < num; curmsg++) {
+ msg = &msgs[curmsg];
+ dev_dbg(dev, "[%02d] %d bytes, flag %#02x buf %#02x\n",
+ curmsg, msg->len, msg->flags, msg->buf[0]);
+ if ((msg->len > TMC_I2C_TRANS_LEN) ||
+ ((msg->flags & I2C_M_RD) &&
+ (msg->flags & I2C_M_RECV_LEN))) {
+ /* If PEC is enabled len will come as 3 for a word read.
+ * We don't want to use block read for this case.
+ */
+ if ((msg->flags & I2C_CLIENT_PEC) &&
+ (msg->len == TMC_I2C_TRANS_LEN+1)) {
+ tadap->use_block = false;
+ } else {
+ tadap->use_block = true;
+ }
+ break;
+ }
+ }
+
+ if (tadap->use_block) {
+ /* Read Block */
+ if ((msg->flags & I2C_M_RD) && (msg->flags & I2C_M_RECV_LEN)) {
+ err = tmc_i2c_smb_block_read(adap, msgs, num);
+ } else {
+ err = tmc_i2c_block_read(adap, msgs, num);
+ }
+ if (err < 0)
+ return err;
+ } else {
+ read = msgs[num - 1].flags & I2C_M_RD;
+ for (curmsg = 0; curmsg < num; curmsg++) {
+ msg = &msgs[curmsg];
+ len = msg->len;
+
+ dev_dbg(dev, " [%02d] %s %d bytes addr %#02x, "
+ "flag %#02x, buf[0] %#02x\n", curmsg,
+ read ? "RD" : "WR", len, msg->addr,
+ msg->flags, msg->buf[0]);
+
+ /* SMBus quick read/write command */
+ if (len == 0 && curmsg == 0 && num == 1) {
+ if (read) {
+ len = 1;
+ }
+ break;
+ }
+
+ if (curmsg == 0) {
+ if (!read) {
+ for (n = 1; n < len; n++)
+ rwbuf[n-1] = (msg->buf[n]);
+ len--;
+ } else {
+ /* read operation */
+ continue;
+ }
+ }
+ }
+
+ if (!read) {
+ /* write */
+ err = tmc_i2c_rw_op(adap, TMC_I2C_WRITE,
+ tadap->mux_select, msgs[0].addr,
+ msgs[0].buf[0], len, rwbuf);
+ } else {
+ /* read */
+ /*
+ * If PEC is enabled read only 2 bytes as expected in
+ * case of a word read instead of 3 to make it compatible
+ * with word write implementation.
+ */
+ if (msg->flags & I2C_CLIENT_PEC && (len == TMC_I2C_TRANS_LEN + 1)) {
+ len--;
+ }
+
+ err = tmc_i2c_rw_op(adap, TMC_I2C_READ,
+ tadap->mux_select,
+ msgs[0].addr, msgs[0].buf[0],
+ len, rwbuf);
+ msg = &msgs[num - 1];
+ len = msg->len;
+ /*
+ * To avoid failure in PEC enabled case clear flag.
+ */
+ if (len == TMC_I2C_TRANS_LEN + 1) {
+ msgs[num - 1].flags &= ~I2C_M_RD;
+ }
+ for (n = 0; n < len; n++)
+ msg->buf[n] = rwbuf[n];
+ }
+ if (err < 0)
+ return err;
+ }
+
+ TMC_I2C_STAT_INCN(tadap, msg_cnt, num);
+
+ return num;
+}
+
+static u32 tmc_i2c_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
+ | I2C_FUNC_SMBUS_READ_BLOCK_DATA;
+}
+
+static const struct i2c_algorithm tmc_i2c_algo = {
+ .master_xfer = tmc_i2c_mstr_xfer,
+ .functionality = tmc_i2c_func,
+};
+
+static int tmc_i2c_mux_group_sel(struct i2c_mux_core *muxc, u32 chan)
+{
+ struct tmc_i2c_adapter *tadap = i2c_mux_priv(muxc);
+
+ dev_dbg(muxc->dev, "chan = %d\n", chan);
+
+ if (!tadap || chan > TMC_I2C_MSTR_MAX_GROUPS)
+ return -ENODEV;
+ tadap->mux_select = chan;
+
+ return 0;
+}
+
+static int tmc_i2c_mux_init(struct i2c_adapter *adap)
+{
+ struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
+ int chan, ret;
+
+ tadap->muxc = i2c_mux_alloc(adap, &adap->dev, tadap->mux_channels,
+ 0, 0, tmc_i2c_mux_group_sel, NULL);
+
+ if (!tadap->muxc)
+ return -ENOMEM;
+
+ tadap->muxc->priv = tadap;
+ for (chan = 0; chan < tadap->mux_channels; chan++) {
+ ret = i2c_mux_add_adapter(tadap->muxc, 0, chan, 0);
+ if (ret) {
+ dev_err(&adap->dev, "Failed to add adapter %d\n", chan);
+ i2c_mux_del_adapters(tadap->muxc);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static struct i2c_adapter *
+tmc_i2c_init_one(struct tmc_i2c_ctrl *tmc,
+ int master, int id)
+{
+ struct tmc_i2c_adapter *adapter;
+ struct device *dev = tmc->dev;
+ int err;
+
+ adapter = devm_kzalloc(dev, sizeof(*adapter), GFP_KERNEL);
+ if (!adapter)
+ return ERR_PTR(-ENOMEM);
+
+ init_waitqueue_head(&adapter->wait);
+ adapter->adap.owner = THIS_MODULE;
+ adapter->adap.algo = &tmc_i2c_algo;
+ adapter->adap.nr = -1;
+ adapter->adap.timeout = HZ / 5;
+ adapter->master = master;
+ adapter->mux_channels = tmc->mux_channels;
+ adapter->i2c_delay = tmc->i2c_delay;
+ adapter->membase = tmc->membase;
+ adapter->dpmbase = tmc->dpmbase;
+ adapter->polling = 1;
+ adapter->tctrl = tmc;
+
+ i2c_set_adapdata(&adapter->adap, adapter);
+ snprintf(adapter->adap.name, sizeof(adapter->adap.name),
+ "%s:%d", dev_name(dev), master);
+
+ adapter->adap.dev.parent = dev;
+ err = i2c_add_numbered_adapter(&adapter->adap);
+ if (err)
+ goto error;
+
+ err = tmc_i2c_mux_init(&adapter->adap);
+ if (err)
+ goto err_remove;
+
+ dev_dbg(dev, "Adapter[%02d-%02d]: "
+ "dpmbase: 0x%lx\n", id, master,
+ (unsigned long)adapter->dpmbase);
+ return &adapter->adap;
+
+err_remove:
+ i2c_del_adapter(&adapter->adap);
+error:
+ return ERR_PTR(err);
+}
+
+static void tmc_i2c_cleanup_one(struct i2c_adapter *adap)
+{
+ struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
+
+ i2c_mux_del_adapters(tadap->muxc);
+ i2c_del_adapter(adap);
+
+}
+
+
+static int tmc_i2c_of_init(struct device *dev,
+ struct tmc_i2c_ctrl *tmc, int id)
+{
+ u32 mux_channels, master, num_masters = 0, master_mask = 0;
+ u32 i2c_delay = 0;
+
+ if (!(master_mask & BIT(master)))
+ num_masters++;
+ master_mask |= BIT(master);
+
+ if (id == 0) {
+ /* chassisd */
+ mux_channels = chd_channel;
+ num_masters = 1;
+ i2c_delay = 0;
+ } else if (id == 1) {
+ /* pfe */
+ mux_channels = pfe_channel;
+ num_masters = 1;
+ i2c_delay = 20;
+ } else {
+ return -EINVAL;
+ }
+
+ tmc->adap = devm_kcalloc(dev, num_masters,
+ sizeof(struct i2c_adapter *),
+ GFP_KERNEL);
+ if (!tmc->adap)
+ return -ENOMEM;
+
+ tmc->num_masters = num_masters;
+ tmc->master_mask = master_mask;
+ tmc->mux_channels = mux_channels;
+ tmc->i2c_delay = i2c_delay;
+
+ return 0;
+}
+
+static int tmc_i2c_probe(struct platform_device *pdev)
+{
+ int i, n, err;
+ struct resource *res;
+ struct i2c_adapter *adap;
+ struct device *dev = &pdev->dev;
+ struct tmc_i2c_ctrl *tmc;
+
+ const struct mfd_cell *cell = mfd_get_cell(pdev);
+
+ /*
+ * Allocate memory for the Tmc FPGA
+ */
+ tmc = devm_kzalloc(dev, sizeof(*tmc), GFP_KERNEL);
+ if (!tmc)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, tmc);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ dev_info(dev, "Tmc I2C Accel resource 0x%llx, %llu\n",
+ res->start, resource_size(res));
+
+ tmc->membase = devm_ioremap_nocache(dev, res->start,
+ resource_size(res));
+ if (!tmc->membase)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res)
+ return -ENODEV;
+
+ dev_info(dev, "Tmc I2C Mem resource 0x%llx, %llu\n",
+ res->start, resource_size(res));
+
+ tmc->dpmbase = devm_ioremap_nocache(dev, res->start,
+ resource_size(res));
+ if (!tmc->dpmbase)
+ return -ENOMEM;
+
+ tmc->dev = dev;
+ spin_lock_init(&tmc->lock);
+
+ err = tmc_i2c_of_init(dev, tmc, cell->id);
+ if (err)
+ return err;
+
+ dev_info(dev, "Tmc I2C Masters: %d\n", tmc->num_masters);
+ dev_info(dev, "Tmc I2C Delay: %d\n", tmc->i2c_delay);
+
+ for (n = 0, i = 0; i < TMC_I2C_MASTER_NR_MSTRS; i++) {
+ if (tmc->master_mask & BIT(i)) {
+ adap = tmc_i2c_init_one(tmc, i, n);
+ if (IS_ERR(adap)) {
+ err = PTR_ERR(adap);
+ dev_err(dev, "Failed to initialize master "
+ "adapter %d: %d\n", i, err);
+ goto err_remove;
+ }
+ tmc->adap[n++] = adap;
+ }
+ }
+
+ return 0;
+
+err_remove:
+ for (n--; n >= 0; n--)
+ tmc_i2c_cleanup_one(tmc->adap[n]);
+ return err;
+}
+
+static int tmc_i2c_remove(struct platform_device *pdev)
+{
+ struct tmc_i2c_ctrl *tmc = platform_get_drvdata(pdev);
+ int i;
+
+ /* Disable all masters */
+ tmc_iowrite(0, tmc->membase + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET);
+
+ for (i = 0; i < tmc->num_masters; i++)
+ tmc_i2c_cleanup_one(tmc->adap[i]);
+
+ return 0;
+}
+
+static struct platform_driver tmc_i2c_driver = {
+ .driver = {
+ .name = "i2c-tmc",
+ .owner = THIS_MODULE,
+ },
+ .probe = tmc_i2c_probe,
+ .remove = tmc_i2c_remove,
+};
+
+module_platform_driver(tmc_i2c_driver);
+
+MODULE_DESCRIPTION("Juniper Networks TMC FPGA I2C Accelerator driver");
+MODULE_AUTHOR("Ashish Bhensdadia ");
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-refpga-tmc.c b/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-refpga-tmc.c
new file mode 100644
index 0000000000..ef36bca72e
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-refpga-tmc.c
@@ -0,0 +1,603 @@
+/*
+ * Juniper Networks RE-FPGA qfx platform specific driver
+ *
+ * Copyright (C) 2020 Juniper Networks
+ * Author: Ciju Rajan K
+ *
+ * This driver implements various features such as
+ * - ALARM led driver
+ * - Fan full speed reset control
+ * - FAN precense detection
+ * - FAN type detection
+ * - Any new QFX specific features which uses RE-FPGA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define NUM_LEDS 7 /* Max number of Alarm + FAN LEDs */
+
+#define ALARM_MINOR_LED 0
+#define ALARM_MAJOR_LED 1
+
+#define REFPGA_PCIE_RESET_CTRL 0x13
+#define REFPGA_PCIE_ALARM 0x33
+#define REFPGA_FAN0_CTRL_STAT 0x28
+
+#define REFPGA_RESET_FAN_SPEED BIT(3)
+#define REFPGA_OPER_TYPE BIT(0)
+#define REFPGA_OPER_START BIT(1)
+#define REFPGA_OPER_DONE BIT(2)
+
+#define TMC_REFPGA_ADDR_REG 0x0 /* TMC offset: 0x228 */
+#define TMC_REFPGA_DATA_REG 0x4 /* TMC offset: 0x22C */
+#define TMC_REFPGA_CTRL_REG 0x8 /* TMC offset: 0x230 */
+
+#define TMC_REFPGA_READ_CMD 0x3
+#define TMC_REFPGA_WRITE_CMD 0x2
+
+#define REFPGA_INTR_NR_GROUPS 1
+#define REFPGA_INTR_MAX_IRQS_PG 32
+
+#define MAX_FANS 5
+
+#define REFPGA_IRQ_MAX_BITS_PER_REG 32
+
+#define POLL_INTERVAL 5000
+
+#define AFI_MASK (0x01)
+#define AFO_MASK (0x02)
+#define AFI_AFO_MASK (0x03)
+/*
+ * LED specific data structures
+ */
+struct refpga_led {
+ struct led_classdev lc;
+ struct work_struct work;
+ int blink;
+ int on;
+ int bit;
+ void __iomem *addr;
+};
+
+struct refpga_led_data {
+ int num_leds;
+ struct refpga_led *leds;
+};
+
+static DEFINE_MUTEX(alarm_led_lock);
+
+/*
+ * Common routines
+ */
+struct refpga_chip {
+ struct refpga_led_data *led;
+};
+
+static struct refpga_chip *refpga;
+
+static DEFINE_MUTEX(refpga_lock);
+
+static void __iomem *tmc_membase;
+
+static void wait_for_refpga_oper(void __iomem *base_addr)
+{
+ volatile u32 done = ~(-1);
+ unsigned long int timeout;
+ void __iomem *addr;
+
+ addr = base_addr + (TMC_REFPGA_CTRL_REG);
+ /*
+ * Wait till the transaction is complete
+ */
+ timeout = jiffies + msecs_to_jiffies(100);
+
+ do {
+ usleep_range(50, 100);
+ done = ioread32(addr);
+ if (done & (REFPGA_OPER_DONE))
+ break;
+ } while(time_before(jiffies, timeout));
+}
+static u32 refpga_read(void __iomem *base_addr, u32 refpga_offset)
+{
+ u32 value;
+
+ mutex_lock(&refpga_lock);
+ iowrite32(refpga_offset, base_addr + (TMC_REFPGA_ADDR_REG));
+ iowrite32(TMC_REFPGA_READ_CMD, base_addr + (TMC_REFPGA_CTRL_REG));
+ wait_for_refpga_oper(base_addr);
+ value = ioread32(base_addr + (TMC_REFPGA_DATA_REG));
+ mutex_unlock(&refpga_lock);
+
+ return value;
+}
+
+static void refpga_write(void __iomem *base_addr, u32 refpga_offset, u32 val)
+{
+ mutex_lock(&refpga_lock);
+ iowrite32(refpga_offset, base_addr + (TMC_REFPGA_ADDR_REG));
+ iowrite32(val, base_addr + (TMC_REFPGA_DATA_REG));
+ iowrite32(TMC_REFPGA_WRITE_CMD, base_addr + (TMC_REFPGA_CTRL_REG));
+ wait_for_refpga_oper(base_addr);
+ mutex_unlock(&refpga_lock);
+}
+
+static bool get_fan_presense(u8 idx)
+{
+ u8 value = 0x00;
+ u8 offset = REFPGA_FAN0_CTRL_STAT;
+ bool ret = 0;
+
+ value = refpga_read(tmc_membase, (offset + (idx * 2)));
+ /*
+ * Get the last two bits of REFPGA_FANx_CTRL_STAT.
+ * REFPGA_FANx_CTRL_STAT register of REFPGA gives the fan airflow
+ * status. There are 5 fans in QFX5200. Last two bits give the AFI
+ * & AFO status. If any of these bits are set, fan is present.
+ */
+ value = (value & BIT(0)) | (value & BIT(1));
+ if (value)
+ ret = 1;
+
+ return ret;
+}
+
+static int get_fan_type(u8 idx)
+{
+ u8 value = 0x00;
+ u8 offset = REFPGA_FAN0_CTRL_STAT;
+ int ret = -1;
+
+ value = refpga_read(tmc_membase, (offset + (idx * 2)));
+ /*
+ * Get the last two bits of REFPGA_FANx_CTRL_STAT.
+ * REFPGA_FANx_CTRL_STAT register of REFPGA gives the fan airflow
+ * status. There are 5 fans in QFX5200. Last two bits give the AFI
+ * & AFO status. If bit1 is set, it's AFO and if bit 0 is set,
+ * it's AFI.
+ *
+ * This function will return '1' for AFO, '0' for AFI, and '-1'
+ * if there is no fan or if both AFI & AFO bits are set.
+ */
+ value &= AFI_AFO_MASK;
+
+ switch(value) {
+ case AFI_MASK:
+ ret = 0;
+ break;
+ case AFO_MASK:
+ ret = 1;
+ break;
+ default:
+ ret = -1;
+ break;
+ };
+
+ return ret;
+}
+
+enum sysfs_fan_attributes {
+ FAN0_PRESENT,
+ FAN1_PRESENT,
+ FAN2_PRESENT,
+ FAN3_PRESENT,
+ FAN4_PRESENT,
+};
+
+enum sysfs_fan_type_attributes {
+ FAN0_TYPE,
+ FAN1_TYPE,
+ FAN2_TYPE,
+ FAN3_TYPE,
+ FAN4_TYPE,
+};
+
+/*
+ * The sysfs files will be present in this path
+ * /sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/refpga-tmc.15/fan*_present
+ * /sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/refpga-tmc.15/fan*_type
+ */
+
+#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \
+ static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, refpga_fan_presense_show, NULL, FAN##index##_PRESENT)
+#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr
+
+#define DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(index) \
+ static SENSOR_DEVICE_ATTR(fan##index##_type, S_IRUGO, refpga_fan_type_show, NULL, FAN##index##_TYPE)
+#define DECLARE_FAN_TYPE_ATTR(index) &sensor_dev_attr_fan##index##_type.dev_attr.attr
+
+static ssize_t refpga_fan_presense_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute *s_attr = to_sensor_dev_attr(attr);
+
+ return sprintf(buf, "%d\n", get_fan_presense(s_attr->index));
+
+}
+
+static ssize_t refpga_fan_type_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute *s_attr = to_sensor_dev_attr(attr);
+
+ return sprintf(buf, "%d\n", get_fan_type(s_attr->index));
+
+}
+
+DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(0);
+DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1);
+DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2);
+DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3);
+DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4);
+
+DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(0);
+DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(1);
+DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(2);
+DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(3);
+DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(4);
+
+static struct attribute *refpga_fan_attrs[] = {
+ DECLARE_FAN_PRESENT_ATTR(0),
+ DECLARE_FAN_PRESENT_ATTR(1),
+ DECLARE_FAN_PRESENT_ATTR(2),
+ DECLARE_FAN_PRESENT_ATTR(3),
+ DECLARE_FAN_PRESENT_ATTR(4),
+ DECLARE_FAN_TYPE_ATTR(0),
+ DECLARE_FAN_TYPE_ATTR(1),
+ DECLARE_FAN_TYPE_ATTR(2),
+ DECLARE_FAN_TYPE_ATTR(3),
+ DECLARE_FAN_TYPE_ATTR(4),
+ NULL
+};
+
+static struct attribute_group refpga_fan_attr_group = {
+ .attrs = refpga_fan_attrs,
+};
+
+/*
+ * There is only a single ALARM led in QFX5200 and that
+ * is used for both Major & Minor alarm indicator.
+ * These are represented by two different bits in RE-FPGA
+ * PCIE_ALARM register. Only one of the bit (either Red or
+ * Yellow) should be set a time. If both the bits are set,
+ * it's an undefined behaviour.
+ *
+ * The following table describes how the conditions are
+ * handled in the driver as there can be both Major & Minor
+ * alarms can be triggered from userspace.
+ *
+ * Major Minor Colour
+ *
+ * 0 0 Nil
+ * 0 1 Yellow
+ * 1 1 Red
+ * 1 0 Red
+ *
+ */
+static void manage_alarm_led(void __iomem *addr, int led_type, int value)
+{
+ static int alarm_major = 0, alarm_minor = 0;
+ u32 reg = 0x0;
+
+ mutex_lock(&alarm_led_lock);
+ reg = refpga_read(addr, REFPGA_PCIE_ALARM);
+
+ (led_type == ALARM_MAJOR_LED) ?
+ ((value == 1) ? (alarm_major = 1) : (alarm_major = 0)) :
+ ((value == 1) ? (alarm_minor = 1) : (alarm_minor = 0));
+ if (alarm_major) {
+ reg &= ~BIT(ALARM_MINOR_LED);
+ reg |= BIT(ALARM_MAJOR_LED);
+ } else {
+ if (alarm_minor) {
+ reg &= ~BIT(ALARM_MAJOR_LED);
+ reg |= BIT(ALARM_MINOR_LED);
+ } else {
+ reg &= ~BIT(ALARM_MINOR_LED);
+ reg &= ~BIT(ALARM_MAJOR_LED);
+ }
+ }
+ refpga_write(addr, REFPGA_PCIE_ALARM, reg);
+ mutex_unlock(&alarm_led_lock);
+}
+
+static void manage_fan_led(void __iomem *addr, int fan_slot, int value)
+{
+ u8 offset = REFPGA_FAN0_CTRL_STAT + (fan_slot * 2);
+ u32 reg = 0x0;
+
+ reg = refpga_read(addr, offset);
+ if(value) {
+ /* Turn on s/w control */
+ reg = reg | BIT(4);
+ /* Turn off green led */
+ reg &= ~BIT(5);
+ /* Turn on yellow led & make it blink */
+ reg |= (BIT(6) | BIT(7));
+ } else {
+ /* Clear yellow led & stop blink */
+ reg &= ~(BIT(6) | BIT(7));
+ /* Stop s/w control */
+ reg &= ~BIT(4);
+ }
+ refpga_write(addr, offset, reg);
+}
+
+static void refpga_led_work(struct work_struct *work)
+{
+ struct refpga_led *led = container_of(work, struct refpga_led, work);
+ void __iomem *addr;
+
+ addr = led->addr;
+
+ if(strstr(led->lc.name, "fan"))
+ manage_fan_led(addr, led->bit, led->on);
+ else
+ manage_alarm_led(addr, led->bit, led->on);
+}
+
+static void refpga_led_brightness_set(struct led_classdev *lc,
+ enum led_brightness brightness)
+{
+ struct refpga_led *led = container_of(lc, struct refpga_led, lc);
+
+ led->on = (brightness != LED_OFF);
+ led->blink = 0; /* always turn off hw blink on brightness_set() */
+ schedule_work(&led->work);
+}
+
+struct led_table
+{
+ const char *name;
+ int reg;
+};
+
+static struct led_table qfx5200_led_data[] = {
+ {
+ .name = "alarm-minor",
+ .reg = 0,
+ },
+ {
+ .name = "alarm-major",
+ .reg = 1,
+ },
+ {
+ .name = "fan0-fault",
+ .reg = 0,
+ },
+ {
+ .name = "fan1-fault",
+ .reg = 1,
+ },
+ {
+ .name = "fan2-fault",
+ .reg = 2,
+ },
+ {
+ .name = "fan3-fault",
+ .reg = 3,
+ },
+ {
+ .name = "fan4-fault",
+ .reg = 4,
+ }
+};
+
+static int refpga_led_init_one(struct device *dev,
+ struct refpga_led_data *ild,
+ int num)
+{
+ struct refpga_led *led;
+ int ret = 0;
+
+ led = &ild->leds[num];
+ led->addr = tmc_membase;
+
+ led->lc.name = qfx5200_led_data[num].name;
+ led->bit = qfx5200_led_data[num].reg;
+ led->lc.brightness = LED_OFF;
+ led->lc.brightness_set = refpga_led_brightness_set;
+
+ ret = devm_led_classdev_register(dev, &led->lc);
+ if (ret) {
+ dev_err(dev, "devm_led_classdev_register failed\n");
+ return ret;
+ }
+
+ INIT_WORK(&led->work, refpga_led_work);
+
+ return 0;
+}
+
+static int refpga_led_qfx5200_init(struct device *dev, struct refpga_led_data *ild)
+{
+ int ret = 0, idx = 0;
+
+
+ if (!dev->parent) {
+ dev_err(dev, "dev->parent is null\n");
+ return -ENODEV;
+ }
+
+ ild->num_leds = NUM_LEDS;
+ ild->leds = devm_kzalloc(dev, sizeof(struct refpga_led) * NUM_LEDS,
+ GFP_KERNEL);
+ if (!ild->leds) {
+ dev_err(dev, "LED allocation failed\n");
+ return -ENOMEM;
+ }
+
+ for(idx=0; idxdev;
+ struct refpga_led_data *ild;
+ int ret;
+
+ ild = devm_kzalloc(dev, sizeof(*ild), GFP_KERNEL);
+ if (!ild) {
+ dev_err(dev, "ild allocation failed\n");
+ return -ENOMEM;
+ }
+
+ ret = refpga_led_qfx5200_init(dev, ild);
+ if (ret < 0)
+ return ret;
+
+ refpga->led = ild;
+
+ return 0;
+}
+
+static int jnx_refpga_led_remove(struct platform_device *pdev)
+{
+ struct refpga_chip *drv_data = platform_get_drvdata(pdev);
+ struct refpga_led_data *ild = drv_data->led;
+ int i;
+
+ for (i = 0; i < ild->num_leds; i++) {
+ devm_led_classdev_unregister(&pdev->dev, &ild->leds[i].lc);
+ cancel_work_sync(&ild->leds[i].work);
+ }
+ if (ild) {
+ if (ild->leds)
+ devm_kfree(&pdev->dev, ild->leds);
+ devm_kfree(&pdev->dev, ild);
+ }
+ return 0;
+}
+
+static void reset_fan_full_speed(struct device *dev)
+{
+ u32 val = ~(-1), tmp = ~(-1);
+
+ /*
+ * Reading the REFPGA_PCIE_RESET_CTRL register
+ */
+ val = refpga_read(tmc_membase, REFPGA_PCIE_RESET_CTRL);
+ /*
+ * Clearing the fan full_speed bit
+ */
+ val &= ~(REFPGA_RESET_FAN_SPEED);
+ /*
+ * Writing the REFPGA_PCIE_RESET_CTRL register
+ */
+ refpga_write(tmc_membase, REFPGA_PCIE_RESET_CTRL, val);
+ /*
+ * Reading the REFPGA_PCIE_RESET_CTRL register
+ */
+ tmp = refpga_read(tmc_membase, REFPGA_PCIE_RESET_CTRL);
+ dev_info(dev, "After resetting fan full speed control: %X\n", tmp);
+}
+
+static int jnx_refpga_tmc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ int ret = 0;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "resource allocation failed\n");
+ return -ENODEV;
+ }
+
+ tmc_membase = devm_ioremap_nocache(dev, res->start, resource_size(res));
+ if (!tmc_membase) {
+ dev_err(dev, "ioremap failed\n");
+ return -ENOMEM;
+ }
+
+ refpga = devm_kzalloc(dev, sizeof(*refpga), GFP_KERNEL);
+ if (!refpga) {
+ dev_err(dev, "refpga memory allocation failed\n");
+ return -ENOMEM;
+ }
+
+ reset_fan_full_speed(dev);
+
+ ret = jnx_refpga_led_probe(pdev);
+ if (ret != 0) {
+ dev_err(dev, "Refpga LED probe failed\n");
+ return ret;
+ }
+
+ dev_info(dev, "Refpga LED probe successful: TMC memoy base: %p\n",
+ tmc_membase);
+
+ ret = sysfs_create_group(&dev->kobj, &refpga_fan_attr_group);
+ if (ret != 0) {
+ dev_err(dev, "sysfs_create_group failed: %d\n", ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, refpga);
+
+ return 0;
+}
+
+static int jnx_refpga_tmc_remove(struct platform_device *pdev)
+{
+ jnx_refpga_led_remove(pdev);
+ sysfs_remove_group(&pdev->dev.kobj, &refpga_fan_attr_group);
+
+ return 0;
+}
+
+static struct platform_driver jnx_refpga_tmc_driver = {
+ .driver = {
+ .name = "refpga-tmc",
+ .owner = THIS_MODULE,
+ },
+ .probe = jnx_refpga_tmc_probe,
+ .remove = jnx_refpga_tmc_remove,
+};
+
+static int __init jnx_refpga_tmc_driver_init(void)
+{
+ int ret = -1;
+
+ ret = platform_driver_register(&jnx_refpga_tmc_driver);
+
+ return ret;
+
+}
+
+static void __exit jnx_refpga_tmc_driver_exit(void)
+{
+ platform_driver_unregister(&jnx_refpga_tmc_driver);
+}
+
+module_init(jnx_refpga_tmc_driver_init);
+module_exit(jnx_refpga_tmc_driver_exit);
+
+MODULE_DESCRIPTION("Juniper Networks REFPGA / TMC driver");
+MODULE_AUTHOR("Ciju Rajan K ");
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-tmc-core.c b/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-tmc-core.c
new file mode 100644
index 0000000000..833164bfed
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-tmc-core.c
@@ -0,0 +1,477 @@
+/*
+ * Juniper Networks TMC-FPGA MFD Core driver for qfx platform
+ *
+ * Copyright (c) 2020, Juniper Networks
+ * Author: Ashish Bhensdadia
+ *
+ * This driver implement the resource publish for below devices
+ * - I2C
+ * - GPIO
+ * - RE FPGA
+ * - PSU
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "jnx-tmc.h"
+
+#define TMC_DO_SCRATCH_TEST 1
+
+/*
+ * TMC FPGA Device IDs
+ */
+#define PCI_VENDOR_ID_JUNIPER 0x1304
+
+#define PCI_DEVICE_ID_JNX_TMC_CHD 0x007B
+#define PCI_DEVICE_ID_JNX_TMC_PFE 0x007C
+
+/*
+ * TMC resources
+ */
+static struct resource tmc_resource_i2c[] = {
+ /* I2C AUTOMATION Block */
+ {
+ .name = "i2c-tmc",
+ .start = TMC_I2C_AUTOMATION_I2C_CONTROL_START,
+ .end = TMC_I2C_AUTOMATION_I2C_CONTROL_END,
+ .flags = IORESOURCE_MEM,
+ },
+
+ /* I2C DPMEM */
+ {
+ .name = "i2c-tmc-mem",
+ .start = TMC_I2C_DPMEM_ENTRY_START,
+ .end = TMC_I2C_DPMEM_ENTRY_END,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+#define TMC_RES_I2C_NR ARRAY_SIZE(tmc_resource_i2c)
+
+/*
+ * LED resources
+ */
+static struct resource tmc_resource_leds[] = {
+ {
+ .name = "leds-tmc",
+ .start = TMC_LED_CONTROL_START,
+ .end = TMC_LED_CONTROL_END,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+#define TMC_RES_LEDS_NR ARRAY_SIZE(tmc_resource_leds)
+
+/*
+ * TMC RE-FPGA devices
+ */
+static struct resource tmc_resource_refpga[] = {
+ {
+ .name = "refpga-tmc",
+ .start = TMC_REFPGA_ACCESS_START,
+ .end = TMC_REFPGA_ACCESS_END,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+#define TMC_RES_REFPGA_NR ARRAY_SIZE(tmc_resource_refpga)
+
+static struct resource tmc_resource_gpioslave0[] = {
+ /* SLAVE0 Block */
+ {
+ .name = "gpioslave-tmc",
+ .start = TMC_GPIO_SLAVE0_START,
+ .end = TMC_GPIO_SLAVE0_END,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+#define TMC_RES_GPIOSLAVE0_NR ARRAY_SIZE(tmc_resource_gpioslave0)
+
+static struct resource tmc_resource_gpioslave1[] = {
+ /* SLAVE1 Block */
+ {
+ .name = "gpioslave-tmc",
+ .start = TMC_GPIO_SLAVE1_START,
+ .end = TMC_GPIO_SLAVE1_END,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+#define TMC_RES_GPIOSLAVE1_NR ARRAY_SIZE(tmc_resource_gpioslave1)
+
+static struct resource tmc_resource_psu[] = {
+ /* PSU Block */
+ {
+ .name = "psu-tmc",
+ .start = TMC_PSU_START,
+ .end = TMC_PSU_END,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+#define TMC_RES_PSU_NR ARRAY_SIZE(tmc_resource_psu)
+
+/*
+ * CHASSISD TMC MFD devices
+ */
+static struct mfd_cell chassisd_tmc_mfd_devs[] = {
+ {
+ .name = "i2c-tmc",
+ .num_resources = ARRAY_SIZE(tmc_resource_i2c),
+ .resources = &tmc_resource_i2c[0],
+ .of_compatible = "jnx,i2c-tmc",
+ .id = 0,
+ },
+ {
+ .name = "leds-tmc",
+ .num_resources = ARRAY_SIZE(tmc_resource_leds),
+ .resources = &tmc_resource_leds[0],
+ .of_compatible = "jnx,leds-tmc",
+ .id = 0,
+ },
+ {
+ .name = "refpga-tmc",
+ .num_resources = ARRAY_SIZE(tmc_resource_refpga),
+ .resources = &tmc_resource_refpga[0],
+ .of_compatible = "jnx,refpga-tmc",
+ .id = 0,
+ },
+ {
+ .name = "psu-tmc",
+ .num_resources = ARRAY_SIZE(tmc_resource_psu),
+ .resources = &tmc_resource_psu[0],
+ .of_compatible = "jnx,psu-tmc",
+ .id = 0,
+ },
+};
+
+/*
+ * PFE TMC MFD devices
+ */
+static struct mfd_cell pfe_tmc_mfd_devs[] = {
+ {
+ .name = "i2c-tmc",
+ .num_resources = ARRAY_SIZE(tmc_resource_i2c),
+ .resources = &tmc_resource_i2c[0],
+ .of_compatible = "jnx,i2c-tmc",
+ .id = 1,
+ },
+ {
+ .name = "gpioslave-tmc",
+ .num_resources = ARRAY_SIZE(tmc_resource_gpioslave0),
+ .resources = &tmc_resource_gpioslave0[0],
+ .of_compatible = "jnx,gpioslave-tmc",
+ .id = 0,
+ },
+ {
+ .name = "gpioslave-tmc",
+ .num_resources = ARRAY_SIZE(tmc_resource_gpioslave1),
+ .resources = &tmc_resource_gpioslave1[0],
+ .of_compatible = "jnx,gpioslave-tmc",
+ .id = 1,
+ },
+};
+
+
+struct tmc_fpga_data {
+ void __iomem *membase;
+ struct pci_dev *pdev;
+
+ u32 major; /* Device id & Major version*/
+ u32 minor; /* Minor version */
+
+ u32 optic_cpld_major; /* optic cpld major version */
+ u32 optic_cpld_minor; /* optic cpld minor version */
+ u32 optic_cpld_devid; /* optic cpld device id */
+};
+
+/* sysfs entries */
+static ssize_t major_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
+
+ return sprintf(buf, "0x%02X_%06X\n",
+ (tmc->major >> 24) & 0xff,
+ tmc->major & 0xffffff);
+}
+
+static ssize_t minor_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%02X\n", (tmc->minor) & 0xff);
+}
+
+static ssize_t optic_cpld_major_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%01X\n", tmc->optic_cpld_major & 0xf);
+}
+
+static ssize_t optic_cpld_devid_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%01X\n",
+ (tmc->optic_cpld_major >> 4) & 0xf);
+}
+
+static ssize_t optic_cpld_minor_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%02X\n", tmc->optic_cpld_minor & 0xff);
+}
+
+static ssize_t set_sys_shutdown(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf,
+ size_t len)
+{
+
+ struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
+ unsigned long val;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &val);
+ if (ret < 0)
+ return ret;
+
+ if (val != 1)
+ return -EINVAL;
+
+ /* Unlock the shutdown register */
+ iowrite32(0x12345678, tmc->membase + TMC_SYS_SHUTDOWN_LOCK);
+ iowrite32(0x1, tmc->membase + TMC_SYS_SHUTDOWN);
+
+ return len;
+}
+
+
+static DEVICE_ATTR(major, S_IRUGO, major_show, NULL);
+static DEVICE_ATTR(minor, S_IRUGO, minor_show, NULL);
+static DEVICE_ATTR(optic_cpld_major, S_IRUGO, optic_cpld_major_show, NULL);
+static DEVICE_ATTR(optic_cpld_devid, S_IRUGO, optic_cpld_devid_show, NULL);
+static DEVICE_ATTR(optic_cpld_minor, S_IRUGO, optic_cpld_minor_show, NULL);
+static DEVICE_ATTR(shutdown, S_IWUSR, NULL, set_sys_shutdown);
+
+static struct attribute *tmc_attrs[] = {
+ &dev_attr_major.attr,
+ &dev_attr_minor.attr,
+ &dev_attr_optic_cpld_major.attr,
+ &dev_attr_optic_cpld_devid.attr,
+ &dev_attr_optic_cpld_minor.attr,
+ &dev_attr_shutdown.attr,
+ NULL,
+};
+
+static struct attribute_group tmc_attr_group = {
+ .attrs = tmc_attrs,
+};
+
+#if defined TMC_DO_SCRATCH_TEST
+/* Do a quick scratch access test */
+static int tmc_do_test_scratch(struct tmc_fpga_data *tmc)
+{
+ struct pci_dev *pdev = tmc->pdev;
+ struct device *dev = &pdev->dev;
+ int offset = TMC_SCRATCH;
+ u32 acc, val = 0xdeadbeaf;
+
+ /*
+ * Check rw register access -> use the scratch reg.
+ */
+ iowrite32(val, tmc->membase + offset);
+ acc = ioread32(tmc->membase + offset);
+ if (acc != val) {
+ dev_err(dev, "Tmc scratch(0x%x) failed: %08x.%08x!\n",
+ offset, val, acc);
+ return -EIO;
+ }
+
+ for (val = 0; val < 0xf0000000; val += 0x01010101) {
+ iowrite32(val, tmc->membase + offset);
+ acc = ioread32(tmc->membase + offset);
+ if (acc != val) {
+ dev_err(dev, "Tmc scratch(0x%x) failed: %08x.%08x!\n",
+ offset, val, acc);
+ return -EIO;
+ }
+ }
+
+ /*
+ * Write a sig before leaving..
+ */
+ val = 0xcafebabe;
+ iowrite32(val, tmc->membase + offset);
+ dev_dbg(dev, "Tmc scratch result: 0x%08x\n",
+ ioread32(tmc->membase + offset));
+
+ return 0;
+}
+#endif /* TMC_DO_SCRATCH_TEST */
+
+static int tmc_fpga_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int err;
+ struct tmc_fpga_data *tmc;
+ struct device *dev = &pdev->dev;
+
+ dev_dbg(dev, "Tmc FPGA Probe called\n");
+
+ tmc = devm_kzalloc(dev, sizeof(*tmc), GFP_KERNEL);
+ if (!tmc)
+ return -ENOMEM;
+
+ err = pcim_enable_device(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to enable device %d\n", err);
+ return err;
+ }
+
+ err = pcim_iomap_regions(pdev, 1 << 0, "tmc-core");
+ if (err) {
+ dev_err(&pdev->dev, "Failed to iomap regions %d\n", err);
+ goto err_disable;
+ }
+
+ tmc->membase = pcim_iomap_table(pdev)[0];
+ if (IS_ERR(tmc->membase)) {
+ dev_err(dev, "pci_ioremap_bar() failed\n");
+ err = -ENOMEM;
+ goto err_release;
+ }
+
+ tmc->pdev = pdev;
+ pci_set_drvdata(pdev, tmc);
+
+ /* All Tmc uses MSI interrupts - enable bus mastering */
+ pci_set_master(pdev);
+
+#if defined TMC_DO_SCRATCH_TEST
+ /* Check IO before proceeding */
+ dev_dbg(dev, "Tmc FPGA starting scratch test\n");
+ err = tmc_do_test_scratch(tmc);
+ if (err)
+ goto err_unmap;
+
+ dev_dbg(dev, "Tmc FPGA scratch test passed !!!\n");
+#endif /* TMC_DO_SCRATCH_TEST */
+
+ switch (id->device) {
+ case PCI_DEVICE_ID_JNX_TMC_CHD:
+ err = mfd_add_devices(dev, pdev->bus->number,
+ &chassisd_tmc_mfd_devs[0],
+ ARRAY_SIZE(chassisd_tmc_mfd_devs),
+ &pdev->resource[0],
+ 0, NULL /* tmc->irq_domain */);
+ break;
+ case PCI_DEVICE_ID_JNX_TMC_PFE:
+ err = mfd_add_devices(dev, pdev->bus->number,
+ &pfe_tmc_mfd_devs[0],
+ ARRAY_SIZE(pfe_tmc_mfd_devs),
+ &pdev->resource[0],
+ 0, NULL /* tmc->irq_domain */);
+ break;
+ default:
+ dev_err(&pdev->dev, "Invalid PCI Device ID id:%d\n",
+ id->device);
+ goto err_unmap;
+ }
+
+ if (err < 0) {
+ dev_err(&pdev->dev, "Failed to add mfd devices %d\n", err);
+ goto err_unmap;
+ }
+
+ err = sysfs_create_group(&pdev->dev.kobj, &tmc_attr_group);
+ if (err) {
+ sysfs_remove_group(&pdev->dev.kobj, &tmc_attr_group);
+ dev_err(&pdev->dev, "Failed to create attr group\n");
+ goto err_remove_mfd;
+ }
+
+ tmc->major = ioread32(tmc->membase + TMC_REVISION);
+ tmc->minor = ioread32(tmc->membase + TMC_MINOR);
+
+ tmc->optic_cpld_major = ioread32(tmc->membase + TMC_OPTIC_CPLD_MAJOR);
+ tmc->optic_cpld_minor = ioread32(tmc->membase + TMC_OPTIC_CPLD_MINOR);
+
+ dev_info(dev, "Tmc FPGA Revision: 0x%02X_%06X, Minor: %02X\n",
+ (tmc->major >> 24) & 0xff,
+ tmc->major & 0xffffff,
+ (tmc->minor) & 0xff);
+ dev_info(dev, "Tmc FPGA optic cpld Major: 0x%01X, Minor: 0x%02X "
+ "Devid: 0x%01X\n", (tmc->optic_cpld_major) & 0xf,
+ (tmc->optic_cpld_minor) & 0xff,
+ (tmc->optic_cpld_major >> 4) & 0xf);
+ dev_info(dev, "Tmc FPGA mem:0x%lx\n",
+ (unsigned long)tmc->membase);
+
+ return 0;
+
+err_remove_mfd:
+ mfd_remove_devices(dev);
+err_unmap:
+ pci_iounmap(pdev, tmc->membase);
+err_release:
+ pci_release_regions(pdev);
+err_disable:
+ pci_disable_device(pdev);
+
+ return err;
+}
+
+static void tmc_fpga_remove(struct pci_dev *pdev)
+{
+ struct tmc_fpga_data *tmc = dev_get_drvdata(&pdev->dev);
+
+ sysfs_remove_group(&pdev->dev.kobj, &tmc_attr_group);
+ mfd_remove_devices(&pdev->dev);
+}
+
+static const struct pci_device_id tmc_fpga_id_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_TMC_CHD) },
+ { PCI_DEVICE(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_TMC_PFE) },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, tmc_fpga_id_tbl);
+
+static struct pci_driver tmc_fpga_driver = {
+ .name = "tmc-core",
+ .id_table = tmc_fpga_id_tbl,
+ .probe = tmc_fpga_probe,
+ .remove = tmc_fpga_remove,
+};
+
+module_pci_driver(tmc_fpga_driver);
+
+MODULE_DESCRIPTION("Juniper Networks TMC FPGA MFD core driver");
+MODULE_AUTHOR("Ashish Bhensdadia ");
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-tmc.h b/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-tmc.h
new file mode 100644
index 0000000000..dce7d7be33
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-juniper/common/modules/jnx-tmc.h
@@ -0,0 +1,93 @@
+/*
+ * Juniper Tmc FPGA register definitions
+ *
+ * Copyright (C) 2018 Juniper Networks
+ * Author: Ashish Bhensdadia
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __JNX_TMC_H__
+#define __JNX_TMC_H__
+
+
+#define TMC_REVISION 0x00064
+#define TMC_MINOR 0x00068
+#define TMC_SCRATCH 0x00098
+
+#define TMC_OPTIC_CPLD_MAJOR 0x00104
+#define TMC_OPTIC_CPLD_MINOR 0x00108
+
+/*
+ * I2C Master Block
+ */
+#define TMC_I2C_AUTOMATION_I2C_CONTROL_START 0x07000
+#define TMC_I2C_AUTOMATION_I2C_CONTROL_END 0x07500
+
+#define TMC_I2C_DPMEM_ENTRY_START 0x10000
+#define TMC_I2C_DPMEM_ENTRY_END 0x13FFC
+
+#define TMC_LED_CONTROL_START 0x58
+#define TMC_LED_CONTROL_END 0x5B
+
+/*
+ * RE-FPGA block
+ */
+#define TMC_REFPGA_ACCESS_START 0x228
+#define TMC_REFPGA_ACCESS_END 0x233
+
+#define TMC_I2C_MASTER_NR_MSTRS 16
+#define TMC_I2C_MSTR_MAX_GROUPS 66
+
+
+/*
+ * TMC GPIO SLAVE Block
+ */
+#define TMC_GPIO_PTP_RESET_START 0x94
+#define TMC_GPIO_PTP_RESET_END 0x97
+
+#define TMC_GPIO_PTP_CFG_START 0xa4
+#define TMC_GPIO_PTP_CFG_END 0xa7
+
+#define TMC_GPIO_PTP_DATA_START 0xa8
+#define TMC_GPIO_PTP_DATA_END 0xab
+
+#define TMC_GPIO_SLAVE0_START 0xf0
+#define TMC_GPIO_SLAVE0_END 0x16b
+
+#define TMC_GPIO_SLAVE1_START 0x170
+#define TMC_GPIO_SLAVE1_END 0x1eb
+
+#define TMC_GPIO_SLAVE2_START 0x1f0
+#define TMC_GPIO_SLAVE2_END 0x213
+
+#define TMC_GPIO_SLAVE3_START 0x280
+#define TMC_GPIO_SLAVE3_END 0x2eb
+
+#define TMC_GPIO_SFP_SLAVE0_START 0x308
+#define TMC_GPIO_SFP_SLAVE0_END 0x32b
+
+#define TMC_GPIO_SFP_SLAVE1_START 0x32c
+#define TMC_GPIO_SFP_SLAVE1_END 0x34b
+
+/*
+ * TMC PSU Block
+ */
+#define TMC_PSU_START 0x240
+#define TMC_PSU_END 0x243
+
+/*
+ * TMC SHUTDOWN REG
+ */
+#define TMC_SYS_SHUTDOWN_LOCK 0x254
+#define TMC_SYS_SHUTDOWN 0x250
+
+/*
+ * TMC DS100 MUX Block
+ */
+#define TMC_GPIO_MUX_SLAVE_START 0x26c
+#define TMC_GPIO_MUX_SLAVE_END 0x26f
+
+#endif /* __JNX_TMC_H__ */
diff --git a/platform/broadcom/sonic-platform-modules-juniper/common/modules/juniper_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-juniper/common/modules/juniper_i2c_cpld.c
deleted file mode 100644
index 25860a6ac1..0000000000
--- a/platform/broadcom/sonic-platform-modules-juniper/common/modules/juniper_i2c_cpld.c
+++ /dev/null
@@ -1,892 +0,0 @@
-/*
- * A hwmon driver for the juniper_i2c_cpld
- *
- * Tested and validated on Juniper QFX5210
- * Ciju Rajan K
- *
- * Copyright (C) 2013 Accton Technology Corporation.
- * Brandon Chuang
- *
- * Based on ad7414.c
- * Copyright 2006 Stefan Roese , DENX Software Engineering
- *
- * 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
-#include
-#include
-#include
-#include
-
-
-#define MAX_PORT_NUM 64
-#define I2C_RW_RETRY_COUNT 10
-#define I2C_RW_RETRY_INTERVAL 60 /* ms */
-
-#define I2C_ADDR_CPLD1 0x60
-#define I2C_ADDR_CPLD2 0x62
-#define I2C_ADDR_CPLD3 0x64
-#define CPLD_ADDRS {I2C_ADDR_CPLD1, I2C_ADDR_CPLD2, I2C_ADDR_CPLD3}
-
-
-/*
- * Number of additional attribute pointers to allocate
- * with each call to krealloc
- */
-#define ATTR_ALLOC_SIZE 1 /*For last attribute which is NUll.*/
-
-#define NAME_SIZE 24
-#define MAX_RESP_LENGTH 48
-
-typedef ssize_t (*show_func)( struct device *dev,
- struct device_attribute *attr,
- char *buf);
-typedef ssize_t (*store_func)(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count);
-
-enum models {
- AS7712_32X,
- AS7716_32X,
- qfx5210_64X,
- AS7312_54X,
- PLAIN_CPLD, /*No attribute but add i2c addr to the list.*/
- NUM_MODEL
-};
-
-enum sfp_func {
- HAS_SFP = 1<<0 ,
- HAS_QSFP = 1<<1 ,
-};
-
-enum common_attrs {
- CMN_VERSION,
- CMN_ACCESS,
- CMN_PRESENT_ALL,
- NUM_COMMON_ATTR
-};
-
-enum sfp_attrs {
- SFP_PRESENT,
- SFP_RESET,
- SFP_LP_MODE,
- NUM_SFP_ATTR
-};
-
-struct cpld_sensor {
- struct cpld_sensor *next;
- char name[NAME_SIZE+1]; /* sysfs sensor name */
- struct device_attribute attribute;
- bool update; /* runtime sensor update needed */
- int data; /* Sensor data. Negative if there was a read error */
-
- u8 reg; /* register */
- u8 mask; /* bit mask */
- bool invert; /* inverted value*/
-
-};
-
-#define to_cpld_sensor(_attr) \
- container_of(_attr, struct cpld_sensor, attribute)
-
-struct cpld_data {
- struct device *dev;
- struct device *hwmon_dev;
-
- int num_attributes;
- struct attribute_group group;
-
- enum models model;
- struct cpld_sensor *sensors;
- struct mutex update_lock;
- bool valid;
- unsigned long last_updated; /* in jiffies */
-
- int attr_index;
- u16 sfp_num;
- u8 sfp_types;
- struct model_attrs *cmn_attr;
-};
-
-struct cpld_client_node {
- struct i2c_client *client;
- struct list_head list;
-};
-
-
-struct base_attrs {
- const char *name;
- umode_t mode;
- show_func get;
- store_func set;
-};
-
-struct attrs {
- int reg;
- bool invert;
- struct base_attrs *base;
-};
-
-struct model_attrs {
- struct attrs **cmn;
- struct attrs **portly;
-};
-
-
-static ssize_t show_bit(struct device *dev,
- struct device_attribute *devattr, char *buf);
-static ssize_t show_presnet_all(struct device *dev,
- struct device_attribute *devattr, char *buf);
-static ssize_t set_1bit(struct device *dev, struct device_attribute *da,
- const char *buf, size_t count);
-static ssize_t set_byte(struct device *dev, struct device_attribute *da,
- const char *buf, size_t count);
-static ssize_t access(struct device *dev, struct device_attribute *da,
- const char *buf, size_t count);
-
-int juniper_i2c_cpld_read(u8 cpld_addr, u8 reg);
-int juniper_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
-
-
-struct base_attrs common_attrs[NUM_COMMON_ATTR] =
-{
- [CMN_VERSION] = {"version", S_IRUGO, show_bit, NULL},
- [CMN_ACCESS] = {"access", S_IWUSR, NULL, set_byte},
- [CMN_PRESENT_ALL] = {"module_present_all", S_IRUGO, show_presnet_all, NULL},
-};
-
-struct attrs as7712_common[] = {
- [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]},
- [CMN_ACCESS] = {0x00, false, &common_attrs[CMN_ACCESS]},
- [CMN_PRESENT_ALL] = {0x30, false, &common_attrs[CMN_PRESENT_ALL]},
-};
-struct attrs qfx5210_common[] = {
- [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]},
- [CMN_ACCESS] = {0x00, false, &common_attrs[CMN_ACCESS]},
- [CMN_PRESENT_ALL] = {0x30, false, &common_attrs[CMN_PRESENT_ALL]},
-};
-struct attrs as7312_common[] = {
- [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]},
- [CMN_ACCESS] = {0x00, false, &common_attrs[CMN_ACCESS]},
- [CMN_PRESENT_ALL] = {-1, false, &common_attrs[CMN_PRESENT_ALL]},
-};
-struct attrs plain_common[] = {
- [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]},
-};
-
-struct base_attrs portly_attrs[] =
-{
- [SFP_PRESENT] = {"module_present", S_IRUGO, show_bit, NULL},
- // Only root user will have the privilege to write to sysfs
- // [SFP_RESET] = {"module_reset", S_IRUGO|S_IWUGO, show_bit, set_1bit},
- [SFP_RESET] = {"module_reset", S_IRUGO|S_IWUSR, show_bit, set_1bit},
-};
-
-struct attrs as7712_port[] = {
- {0x30, true, &portly_attrs[SFP_PRESENT]},
- {0x04, true, &portly_attrs[SFP_RESET]},
-};
-
-struct attrs qfx5210_port[] = {
- {0x70, true, &portly_attrs[SFP_PRESENT]},
- {0x40, true, &portly_attrs[SFP_RESET]},
-};
-
-struct attrs *as7712_cmn_list[] = {
- &as7712_common[CMN_VERSION],
- &as7712_common[CMN_ACCESS],
- &as7712_common[CMN_PRESENT_ALL],
- NULL
-};
-
-struct attrs *qfx5210_cmn_list[] = {
- &qfx5210_common[CMN_VERSION],
- &qfx5210_common[CMN_ACCESS],
- &qfx5210_common[CMN_PRESENT_ALL],
- NULL
-};
-
-struct attrs *as7312_cmn_list[] = {
- &as7312_common[CMN_VERSION],
- &as7312_common[CMN_ACCESS],
- &as7312_common[CMN_PRESENT_ALL],
- NULL
-};
-
-struct attrs *plain_cmn_list[] = {
- &plain_common[CMN_VERSION],
- NULL
-};
-
-struct attrs *as7712_port_list[] = {
- &as7712_port[SFP_PRESENT],
- &as7712_port[SFP_RESET],
- NULL
-};
-struct attrs *qfx5210_port_list[] = {
- &qfx5210_port[SFP_PRESENT],
- &qfx5210_port[SFP_RESET],
- NULL
-};
-
-struct model_attrs models_attr[NUM_MODEL] = {
- {.cmn = as7712_cmn_list, .portly=as7712_port_list},
- {.cmn = as7712_cmn_list, .portly=as7712_port_list}, /*7716's as 7712*/
- {.cmn = qfx5210_cmn_list, .portly=qfx5210_port_list},
- {.cmn = as7312_cmn_list, .portly=qfx5210_port_list},
- {.cmn = plain_cmn_list, .portly=NULL},
-};
-
-static LIST_HEAD(cpld_client_list);
-static struct mutex list_lock;
-/* Addresses scanned for juniper_i2c_cpld
- */
-static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
-
-static int get_sfp_spec(int model, u16 *num, u8 *types)
-{
- switch (model) {
- case AS7712_32X:
- case AS7716_32X:
- *num = 32;
- *types = HAS_QSFP;
- break;
- case qfx5210_64X:
- *num = 64;
- *types = HAS_QSFP;
- break;
- case AS7312_54X:
- *num = 54;
- *types = HAS_QSFP|HAS_SFP;
- default:
- *types = 0;
- *num = 0;
- break;
- }
-
- return 0;
-}
-
-static int get_present_reg(int model, u8 port, u8 *cpld_addr, u8 *reg, u8 *num)
-{
- u8 cpld_address[] = CPLD_ADDRS;
-
- switch (model) {
- case AS7312_54X:
- if (port < 48) {
- *cpld_addr = cpld_address[1 + port/24];
- *reg = 0x09 + (port%24)/8;
- *num = 8;
- }
- else
- {
- *reg = 0x18;
- *num = 4;
- *cpld_addr = ( port < 52)? cpld_address[1]: cpld_address[2];
- }
- break;
- default:
- return -EINVAL;
- }
-}
-
-
-/*Assume the bits for ports are listed in-a-row.*/
-static int get_reg_bit(u8 reg_start, int port,
- u8 *reg ,u8 *mask)
-{
- *reg = reg_start + ((port)/8);
- *mask = 1 << ((port)%8);
-
- return 0;
-}
-
-static int cpld_write_internal(
- struct i2c_client *client, u8 reg, u8 value)
-{
- int status = 0, retry = I2C_RW_RETRY_COUNT;
-
- while (retry) {
- status = i2c_smbus_write_byte_data(client, reg, value);
- if (unlikely(status < 0)) {
- msleep(I2C_RW_RETRY_INTERVAL);
- retry--;
- continue;
- }
-
- break;
- }
-
- return status;
-}
-
-static int cpld_read_internal(struct i2c_client *client, u8 reg)
-{
- int status = 0, retry = I2C_RW_RETRY_COUNT;
-
- while (retry) {
- status = i2c_smbus_read_byte_data(client, reg);
- if (unlikely(status < 0)) {
- msleep(I2C_RW_RETRY_INTERVAL);
- retry--;
- continue;
- }
-
- break;
- }
-
- return status;
-}
-
-
-/*Turn a numberic array into string with " " between each element.
- * e.g., {0x11, 0x33, 0xff, 0xf1} => "11 33 ff f1"
- */
-static ssize_t array_stringify(char *buf, u8 *input, size_t size) {
-
- int i;
- char t[MAX_RESP_LENGTH+1];
-
- buf[0] = '\0';
- for (i = 0; i < size; i++) {
- snprintf(t, MAX_RESP_LENGTH, "%x ", input[i]);
- strncat(buf, t, MAX_RESP_LENGTH);
- }
-
- if (strlen(buf) > 0)
- buf[strlen(buf)-1] = '\0'; /*Remove tailing blank*/
-
- return snprintf(buf, MAX_RESP_LENGTH, "%s\n", buf);
-}
-
-static ssize_t show_presnet_all_distinct(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct cpld_data *data = i2c_get_clientdata(client);
- u8 i, value, reg;
- u8 cpld_addr, num;
- u8 _value[8];
- u64 *values = (u64 *)_value;
-
- values = 0;
- mutex_lock(&data->update_lock);
- while(i < data->sfp_num)
- {
- get_present_reg(data->model, i, &cpld_addr, ®, &num);
- if(cpld_addr == client->addr)
- value = cpld_read_internal(client, reg);
- else
- value = juniper_i2c_cpld_read(cpld_addr, reg);
-
- if (unlikely(value < 0)) {
- goto exit;
- }
-
- *values |= (value&((1<<(num))-1)) << i;
- i += num;
- }
- mutex_unlock(&data->update_lock);
-
- *values = cpu_to_le64(*values);
- return array_stringify(buf, _value, i);
-exit:
- mutex_unlock(&data->update_lock);
- return value;
-}
-
-static ssize_t show_presnet_all(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct cpld_data *data = i2c_get_clientdata(client);
- struct cpld_sensor *sensor = to_cpld_sensor(devattr);
- u8 i, values[MAX_RESP_LENGTH/8];
-
- if (sensor->reg < 0) {
- return show_presnet_all_distinct(dev, devattr, buf);
- }
-
- mutex_lock(&data->update_lock);
- for (i = 0; i < ((data->sfp_num+7)/8); i++) {
- values[i] = cpld_read_internal(client, sensor->reg + i);
- if (unlikely(values[i] < 0)) {
- goto exit;
- }
- }
- mutex_unlock(&data->update_lock);
- return array_stringify(buf, values, i);
-
-exit:
- mutex_unlock(&data->update_lock);
- return values[i];
-}
-
-static ssize_t show_bit(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- int value;
- struct i2c_client *client = to_i2c_client(dev);
- struct cpld_data *data = i2c_get_clientdata(client);
- struct cpld_sensor *sensor = to_cpld_sensor(devattr);
-
- mutex_lock(&data->update_lock);
- value = cpld_read_internal(client, sensor->reg);
- value = value & sensor->mask;
- if (sensor->invert)
- value = !value;
- mutex_unlock(&data->update_lock);
-
- return snprintf(buf, PAGE_SIZE, "%x\n", value);
-}
-
-static ssize_t set_1bit(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
-{
- long is_reset;
- int value, status;
- struct i2c_client *client = to_i2c_client(dev);
- struct cpld_data *data = i2c_get_clientdata(client);
- struct cpld_sensor *sensor = to_cpld_sensor(devattr);
- u8 cpld_bit, reg;
-
- status = kstrtol(buf, 10, &is_reset);
- if (status) {
- return status;
- }
- reg = sensor->reg;
- cpld_bit = sensor->mask;
- mutex_lock(&data->update_lock);
- value = cpld_read_internal(client, reg);
- if (unlikely(status < 0)) {
- goto exit;
- }
-
- if (sensor->invert)
- is_reset = !is_reset;
-
- if (is_reset) {
- value |= cpld_bit;
- }
- else {
- value &= ~cpld_bit;
- }
-
- status = cpld_write_internal(client, reg, value);
- if (unlikely(status < 0)) {
- goto exit;
- }
- mutex_unlock(&data->update_lock);
- return count;
-
-exit:
- mutex_unlock(&data->update_lock);
- return status;
-}
-
-static ssize_t set_byte(struct device *dev, struct device_attribute *da,
- const char *buf, size_t count)
-{
- return access(dev, da, buf, count);
-}
-
-static ssize_t access(struct device *dev, struct device_attribute *da,
- const char *buf, size_t count)
-{
- int status;
- u32 addr, val;
- struct i2c_client *client = to_i2c_client(dev);
- struct cpld_data *data = i2c_get_clientdata(client);
-
- if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) {
- return -EINVAL;
- }
-
- if (addr > 0xFF || val > 0xFF) {
- return -EINVAL;
- }
-
- mutex_lock(&data->update_lock);
- status = cpld_write_internal(client, addr, val);
- if (unlikely(status < 0)) {
- goto exit;
- }
- mutex_unlock(&data->update_lock);
- return count;
-
-exit:
- mutex_unlock(&data->update_lock);
- return status;
-}
-
-static void juniper_i2c_cpld_add_client(struct i2c_client *client)
-{
- struct cpld_client_node *node =
- kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL);
-
- if (!node) {
- dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n",
- client->addr);
- return;
- }
- node->client = client;
-
- mutex_lock(&list_lock);
- list_add(&node->list, &cpld_client_list);
- mutex_unlock(&list_lock);
-}
-
-static void juniper_i2c_cpld_remove_client(struct i2c_client *client)
-{
- struct list_head *list_node = NULL;
- struct cpld_client_node *cpld_node = NULL;
- int found = 0;
-
- mutex_lock(&list_lock);
-
- list_for_each(list_node, &cpld_client_list)
- {
- cpld_node = list_entry(list_node, struct cpld_client_node, list);
-
- if (cpld_node->client == client) {
- found = 1;
- break;
- }
- }
-
- if (found) {
- list_del(list_node);
- kfree(cpld_node);
- }
-
- mutex_unlock(&list_lock);
-}
-
-static int cpld_add_attribute(struct cpld_data *data, struct attribute *attr)
-{
- int new_max_attrs = ++data->num_attributes + ATTR_ALLOC_SIZE;
- void *new_attrs = krealloc(data->group.attrs,
- new_max_attrs * sizeof(void *),
- GFP_KERNEL);
- if (!new_attrs)
- return -ENOMEM;
- data->group.attrs = new_attrs;
-
-
- data->group.attrs[data->num_attributes-1] = attr;
- data->group.attrs[data->num_attributes] = NULL;
-
- return 0;
-}
-
-static void cpld_dev_attr_init(struct device_attribute *dev_attr,
- const char *name, umode_t mode,
- show_func show, store_func store)
-{
- sysfs_attr_init(&dev_attr->attr);
- dev_attr->attr.name = name;
- dev_attr->attr.mode = mode;
- dev_attr->show = show;
- dev_attr->store = store;
-}
-
-static struct cpld_sensor * add_sensor(struct cpld_data *data,
- const char *name,
- u8 reg, u8 mask, bool invert,
- bool update, umode_t mode,
- show_func get, store_func set)
-{
- struct cpld_sensor *sensor;
- struct device_attribute *a;
-
- sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL);
- if (!sensor)
- return NULL;
- a = &sensor->attribute;
-
- snprintf(sensor->name, sizeof(sensor->name), name);
- sensor->reg = reg;
- sensor->mask = mask;
- sensor->update = update;
- sensor->invert = invert;
- cpld_dev_attr_init(a, sensor->name,
- mode,
- get, set);
-
- if (cpld_add_attribute(data, &a->attr))
- return NULL;
-
- sensor->next = data->sensors;
- data->sensors = sensor;
-
- return sensor;
-}
-
-static int add_attributes_cmn(struct cpld_data *data, struct attrs **cmn)
-{
- u8 reg, i ;
- bool invert;
- struct attrs *a;
- struct base_attrs *b;
-
- if (NULL == cmn)
- return -1;
-
- for (i = 0; cmn[i]; i++)
- {
- a = cmn[i];
-
- reg = a->reg;
- invert = a->invert;
-
- b = a->base;
- if (NULL == b)
- break;
-
- if (add_sensor(data, b->name,
- reg, 0xff, invert,
- true, b->mode,
- b->get, b->set) == NULL)
- {
- return -ENOMEM;
- }
- }
- return 0;
-}
-
-static int add_attributes_portly(struct cpld_data *data, struct attrs **pa)
-{
- char name[NAME_SIZE+1];
- int i, j;
- u8 reg, mask, invert;
- struct attrs *a;
- struct base_attrs *b;
-
- if (NULL == pa)
- return -1;
-
-
- for (i = 0; pa[i]; i++) {
- a = pa[i];
-
- invert = a->invert;
- b = a->base;
- if (b == NULL)
- break;
-
- for (j = 0; j < data->sfp_num; j++)
- {
- snprintf(name, NAME_SIZE, "%s_%d", b->name, j+1);
- get_reg_bit(a->reg, j, ®, &mask);
-
- if (add_sensor(data, name, reg, mask, invert,
- true, b->mode, b->get, b->set) == NULL)
- {
- return -ENOMEM;
- }
- }
- }
- return 0;
-}
-
-static int add_attributes(struct i2c_client *client,
- struct cpld_data *data)
-{
- struct model_attrs *m = data->cmn_attr;
-
- if (m == NULL)
- return -EINVAL;
-
- /* Common attributes.*/
- add_attributes_cmn(data, m->cmn);
-
- /* Port-wise attributes.*/
- add_attributes_portly(data, m->portly);
-
- return 0;
-}
-
-static int juniper_i2c_cpld_probe(struct i2c_client *client,
- const struct i2c_device_id *dev_id)
-{
- int status;
- struct cpld_data *data = NULL;
- struct device *dev = &client->dev;
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
- dev_dbg(dev, "i2c_check_functionality failed (0x%x)\n", client->addr);
- return -EIO;
- }
-
- data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
- if (!data) {
- return -ENOMEM;
- }
-
- data->model = dev_id->driver_data;
- data->cmn_attr = &models_attr[data->model];
- get_sfp_spec(data->model, &data->sfp_num, &data->sfp_types);
-
- i2c_set_clientdata(client, data);
- mutex_init(&data->update_lock);
- data->dev = dev;
- dev_info(dev, "chip found\n");
-
- status = add_attributes(client, data);
- if (status)
- goto out_kfree;
-
- /*
- * If there are no attributes, something is wrong.
- * Bail out instead of trying to register nothing.
- */
- if (!data->num_attributes) {
- dev_err(dev, "No attributes found\n");
- status = -ENODEV;
- goto out_kfree;
- }
-
- /* Register sysfs hooks */
- status = sysfs_create_group(&client->dev.kobj, &data->group);
- if (status) {
- goto out_kfree;
- }
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- status = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- juniper_i2c_cpld_add_client(client);
- dev_info(dev, "%s: cpld '%s'\n",
- dev_name(data->hwmon_dev), client->name);
-
- return 0;
-exit_remove:
- sysfs_remove_group(&client->dev.kobj, &data->group);
-out_kfree:
- kfree(data->group.attrs);
- return status;
-
-}
-
-static int juniper_i2c_cpld_remove(struct i2c_client *client)
-{
- struct cpld_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &data->group);
- kfree(data->group.attrs);
- juniper_i2c_cpld_remove_client(client);
- return 0;
-}
-
-int juniper_i2c_cpld_read(u8 cpld_addr, u8 reg)
-{
- struct list_head *list_node = NULL;
- struct cpld_client_node *cpld_node = NULL;
- int ret = -EPERM;
-
- mutex_lock(&list_lock);
-
- list_for_each(list_node, &cpld_client_list)
- {
- cpld_node = list_entry(list_node, struct cpld_client_node, list);
-
- if (cpld_node->client->addr == cpld_addr) {
- ret = i2c_smbus_read_byte_data(cpld_node->client, reg);
- break;
- }
- }
-
- mutex_unlock(&list_lock);
-
- return ret;
-}
-EXPORT_SYMBOL(juniper_i2c_cpld_read);
-
-int juniper_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value)
-{
- struct list_head *list_node = NULL;
- struct cpld_client_node *cpld_node = NULL;
- int ret = -EIO;
-
- mutex_lock(&list_lock);
-
- list_for_each(list_node, &cpld_client_list)
- {
- cpld_node = list_entry(list_node, struct cpld_client_node, list);
-
- if (cpld_node->client->addr == cpld_addr) {
- ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value);
- break;
- }
- }
-
- mutex_unlock(&list_lock);
-
- return ret;
-}
-EXPORT_SYMBOL(juniper_i2c_cpld_write);
-
-
-static const struct i2c_device_id juniper_i2c_cpld_id[] = {
- { "cpld_as7712", AS7712_32X},
- { "cpld_as7716", AS7716_32X},
- { "cpld_qfx5210", qfx5210_64X},
- { "cpld_as7312", AS7312_54X},
- { "cpld_plain", PLAIN_CPLD},
- { },
-};
-MODULE_DEVICE_TABLE(i2c, juniper_i2c_cpld_id);
-
-static struct i2c_driver juniper_i2c_cpld_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "juniper_i2c_cpld",
- },
- .probe = juniper_i2c_cpld_probe,
- .remove = juniper_i2c_cpld_remove,
- .id_table = juniper_i2c_cpld_id,
- .address_list = normal_i2c,
-};
-
-
-static int __init juniper_i2c_cpld_init(void)
-{
- mutex_init(&list_lock);
- return i2c_add_driver(&juniper_i2c_cpld_driver);
-}
-
-static void __exit juniper_i2c_cpld_exit(void)
-{
- i2c_del_driver(&juniper_i2c_cpld_driver);
-}
-
-module_init(juniper_i2c_cpld_init);
-module_exit(juniper_i2c_cpld_exit);
-
-MODULE_AUTHOR("Brandon Chuang ");
-MODULE_DESCRIPTION("juniper_i2c_cpld driver");
-MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-juniper/common/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-juniper/common/modules/ym2651y.c
deleted file mode 100644
index 3ade568410..0000000000
--- a/platform/broadcom/sonic-platform-modules-juniper/common/modules/ym2651y.c
+++ /dev/null
@@ -1,622 +0,0 @@
-/*
- * An hwmon driver for the 3Y Power YM-2651Y Power Module
- *
- * Tested and validated on Juniper QFX5210
- * Ciju Rajan K
- *
- * Copyright (C) 2014 Accton Technology Corporation.
- * Brandon Chuang
- *
- * Based on ad7414.c
- * Copyright 2006 Stefan Roese , DENX Software Engineering
- *
- * 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
-#include
-
-#define MAX_FAN_DUTY_CYCLE 100
-
-/* Addresses scanned
- */
-static const unsigned short normal_i2c[] = { 0x58, 0x5b, I2C_CLIENT_END };
-
-enum chips {
- YM2651,
- YM2401,
- YM2851,
-};
-
-/* Each client has this additional data
- */
-struct ym2651y_data {
- struct device *hwmon_dev;
- struct mutex update_lock;
- char valid; /* !=0 if registers are valid */
- unsigned long last_updated; /* In jiffies */
- u8 capability; /* Register value */
- u16 status_word; /* Register value */
- u8 fan_fault; /* Register value */
- u8 over_temp; /* Register value */
- u16 v_out; /* Register value */
- u16 i_out; /* Register value */
- u16 p_out; /* Register value */
- u16 temp; /* Register value */
- u16 fan_speed; /* Register value */
- u16 fan_duty_cycle[2]; /* Register value */
- u8 fan_dir[4]; /* Register value */
- u8 pmbus_revision; /* Register value */
- u8 mfr_id[10]; /* Register value */
- u8 mfr_model[10]; /* Register value */
- u8 mfr_revsion[3]; /* Register value */
- u16 mfr_vin_min; /* Register value */
- u16 mfr_vin_max; /* Register value */
- u16 mfr_iin_max; /* Register value */
- u16 mfr_iout_max; /* Register value */
- u16 mfr_pin_max; /* Register value */
- u16 mfr_pout_max; /* Register value */
- u16 mfr_vout_min; /* Register value */
- u16 mfr_vout_max; /* Register value */
-};
-
-static ssize_t show_byte(struct device *dev, struct device_attribute *da,
- char *buf);
-static ssize_t show_word(struct device *dev, struct device_attribute *da,
- char *buf);
-static ssize_t show_linear(struct device *dev, struct device_attribute *da,
- char *buf);
-static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da,
- char *buf);
-static ssize_t show_over_temp(struct device *dev, struct device_attribute *da,
- char *buf);
-static ssize_t show_ascii(struct device *dev, struct device_attribute *da,
- char *buf);
-static struct ym2651y_data *ym2651y_update_device(struct device *dev);
-static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da,
- const char *buf, size_t count);
-static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value);
-
-enum ym2651y_sysfs_attributes {
- PSU_POWER_ON = 0,
- PSU_TEMP_FAULT,
- PSU_POWER_GOOD,
- PSU_FAN1_FAULT,
- PSU_FAN_DIRECTION,
- PSU_OVER_TEMP,
- PSU_V_OUT,
- PSU_I_OUT,
- PSU_P_OUT,
- PSU_P_OUT_UV, /*In Unit of microVolt, instead of mini.*/
- PSU_TEMP1_INPUT,
- PSU_FAN1_SPEED,
- PSU_FAN1_DUTY_CYCLE,
- PSU_PMBUS_REVISION,
- PSU_MFR_ID,
- PSU_MFR_MODEL,
- PSU_MFR_REVISION,
- PSU_MFR_VIN_MIN,
- PSU_MFR_VIN_MAX,
- PSU_MFR_VOUT_MIN,
- PSU_MFR_VOUT_MAX,
- PSU_MFR_IIN_MAX,
- PSU_MFR_IOUT_MAX,
- PSU_MFR_PIN_MAX,
- PSU_MFR_POUT_MAX
-};
-
-/* sysfs attributes for hwmon
- */
-static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON);
-static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT);
-static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD);
-static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT);
-static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP);
-static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_linear, NULL, PSU_V_OUT);
-static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT);
-static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT);
-static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT);
-static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED);
-static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE);
-static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION);
-static SENSOR_DEVICE_ATTR(psu_pmbus_revision, S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION);
-static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID);
-static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL);
-static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION);
-static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN);
-static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX);
-static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN);
-static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX);
-static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX);
-static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX);
-static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX);
-static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX);
-
-/*Duplicate nodes for lm-sensors.*/
-static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_linear, NULL, PSU_V_OUT);
-static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_linear, NULL, PSU_I_OUT);
-static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV);
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT);
-static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED);
-static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT);
-
-static struct attribute *ym2651y_attributes[] = {
- &sensor_dev_attr_psu_power_on.dev_attr.attr,
- &sensor_dev_attr_psu_temp_fault.dev_attr.attr,
- &sensor_dev_attr_psu_power_good.dev_attr.attr,
- &sensor_dev_attr_psu_fan1_fault.dev_attr.attr,
- &sensor_dev_attr_psu_over_temp.dev_attr.attr,
- &sensor_dev_attr_psu_v_out.dev_attr.attr,
- &sensor_dev_attr_psu_i_out.dev_attr.attr,
- &sensor_dev_attr_psu_p_out.dev_attr.attr,
- &sensor_dev_attr_psu_temp1_input.dev_attr.attr,
- &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr,
- &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr,
- &sensor_dev_attr_psu_fan_dir.dev_attr.attr,
- &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_id.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_model.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_revision.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr,
- &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr,
- /*Duplicate nodes for lm-sensors.*/
- &sensor_dev_attr_curr2_input.dev_attr.attr,
- &sensor_dev_attr_in3_input.dev_attr.attr,
- &sensor_dev_attr_power2_input.dev_attr.attr,
- &sensor_dev_attr_temp1_input.dev_attr.attr,
- &sensor_dev_attr_fan1_input.dev_attr.attr,
- &sensor_dev_attr_temp1_fault.dev_attr.attr,
- NULL
-};
-
-static ssize_t show_byte(struct device *dev, struct device_attribute *da,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct ym2651y_data *data = ym2651y_update_device(dev);
-
- return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) :
- sprintf(buf, "0\n");
-}
-
-static ssize_t show_word(struct device *dev, struct device_attribute *da,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct ym2651y_data *data = ym2651y_update_device(dev);
- u16 status = 0;
-
- switch (attr->index) {
- case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */
- status = (data->status_word & 0x40) ? 0 : 1;
- break;
- case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */
- status = (data->status_word & 0x4) >> 2;
- break;
- case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */
- status = (data->status_word & 0x800) ? 0 : 1;
- break;
- }
-
- return sprintf(buf, "%d\n", status);
-}
-
-static int two_complement_to_int(u16 data, u8 valid_bit, int mask)
-{
- u16 valid_data = data & mask;
- bool is_negative = valid_data >> (valid_bit - 1);
-
- return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data;
-}
-
-static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da,
- const char *buf, size_t count)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct i2c_client *client = to_i2c_client(dev);
- struct ym2651y_data *data = i2c_get_clientdata(client);
- int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1;
- long speed;
- int error;
-
- error = kstrtol(buf, 10, &speed);
- if (error)
- return error;
-
- if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE)
- return -EINVAL;
-
- mutex_lock(&data->update_lock);
- data->fan_duty_cycle[nr] = speed;
- ym2651y_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]);
- mutex_unlock(&data->update_lock);
-
- return count;
-}
-
-static ssize_t show_linear(struct device *dev, struct device_attribute *da,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct ym2651y_data *data = ym2651y_update_device(dev);
-
- u16 value = 0;
- int exponent, mantissa;
- int multiplier = 1000;
-
- switch (attr->index) {
- case PSU_V_OUT:
- value = data->v_out;
- break;
- case PSU_I_OUT:
- value = data->i_out;
- break;
- case PSU_P_OUT_UV:
- multiplier = 1000000; /*For lm-sensors, unit is micro-Volt.*/
- /*Passing through*/
- case PSU_P_OUT:
- value = data->p_out;
- break;
- case PSU_TEMP1_INPUT:
- value = data->temp;
- break;
- case PSU_FAN1_SPEED:
- value = data->fan_speed;
- multiplier = 1;
- break;
- case PSU_FAN1_DUTY_CYCLE:
- value = data->fan_duty_cycle[0];
- multiplier = 1;
- break;
- case PSU_MFR_VIN_MIN:
- value = data->mfr_vin_min;
- break;
- case PSU_MFR_VIN_MAX:
- value = data->mfr_vin_max;
- break;
- case PSU_MFR_VOUT_MIN:
- value = data->mfr_vout_min;
- break;
- case PSU_MFR_VOUT_MAX:
- value = data->mfr_vout_max;
- break;
- case PSU_MFR_PIN_MAX:
- value = data->mfr_pin_max;
- break;
- case PSU_MFR_POUT_MAX:
- value = data->mfr_pout_max;
- break;
- case PSU_MFR_IOUT_MAX:
- value = data->mfr_iout_max;
- break;
- case PSU_MFR_IIN_MAX:
- value = data->mfr_iin_max;
- break;
- }
-
- exponent = two_complement_to_int(value >> 11, 5, 0x1f);
- mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff);
- return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) :
- sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent));
-}
-
-static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct ym2651y_data *data = ym2651y_update_device(dev);
-
- u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6;
-
- return sprintf(buf, "%d\n", data->fan_fault >> shift);
-}
-
-static ssize_t show_over_temp(struct device *dev, struct device_attribute *da,
- char *buf)
-{
- struct ym2651y_data *data = ym2651y_update_device(dev);
-
- return sprintf(buf, "%d\n", data->over_temp >> 7);
-}
-
-static ssize_t show_ascii(struct device *dev, struct device_attribute *da,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
- struct ym2651y_data *data = ym2651y_update_device(dev);
- u8 *ptr = NULL;
-
- switch (attr->index) {
- case PSU_FAN_DIRECTION: /* psu_fan_dir */
- ptr = data->fan_dir;
- break;
- case PSU_MFR_ID: /* psu_mfr_id */
- ptr = data->mfr_id;
- break;
- case PSU_MFR_MODEL: /* psu_mfr_model */
- ptr = data->mfr_model;
- break;
- case PSU_MFR_REVISION: /* psu_mfr_revision */
- ptr = data->mfr_revsion;
- break;
- default:
- return 0;
- }
-
- return sprintf(buf, "%s\n", ptr);
-}
-
-static const struct attribute_group ym2651y_group = {
- .attrs = ym2651y_attributes,
-};
-
-static int ym2651y_probe(struct i2c_client *client,
- const struct i2c_device_id *dev_id)
-{
- struct ym2651y_data *data;
- int status;
-
- if (!i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_BYTE_DATA |
- I2C_FUNC_SMBUS_WORD_DATA |
- I2C_FUNC_SMBUS_I2C_BLOCK)) {
- status = -EIO;
- goto exit;
- }
-
- data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL);
- if (!data) {
- status = -ENOMEM;
- goto exit;
- }
-
- i2c_set_clientdata(client, data);
- mutex_init(&data->update_lock);
-
- dev_info(&client->dev, "chip found\n");
-
- /* Register sysfs hooks */
- status = sysfs_create_group(&client->dev.kobj, &ym2651y_group);
- if (status) {
- goto exit_free;
- }
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- status = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- dev_info(&client->dev, "%s: psu '%s'\n",
- dev_name(data->hwmon_dev), client->name);
-
- return 0;
-
-exit_remove:
- sysfs_remove_group(&client->dev.kobj, &ym2651y_group);
-exit_free:
- kfree(data);
-exit:
-
- return status;
-}
-
-static int ym2651y_remove(struct i2c_client *client)
-{
- struct ym2651y_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &ym2651y_group);
- kfree(data);
-
- return 0;
-}
-
-static const struct i2c_device_id ym2651y_id[] = {
- { "ym2651", YM2651 },
- { "ym2401", YM2401 },
- { "ym2851", YM2851 },
- {}
-};
-MODULE_DEVICE_TABLE(i2c, ym2651y_id);
-
-static struct i2c_driver ym2651y_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "ym2651",
- },
- .probe = ym2651y_probe,
- .remove = ym2651y_remove,
- .id_table = ym2651y_id,
- .address_list = normal_i2c,
-};
-
-static int ym2651y_read_byte(struct i2c_client *client, u8 reg)
-{
- return i2c_smbus_read_byte_data(client, reg);
-}
-
-static int ym2651y_read_word(struct i2c_client *client, u8 reg)
-{
- return i2c_smbus_read_word_data(client, reg);
-}
-
-static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value)
-{
- return i2c_smbus_write_word_data(client, reg, value);
-}
-
-static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data,
- int data_len)
-{
- int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data);
-
- if (unlikely(result < 0))
- goto abort;
- if (unlikely(result != data_len)) {
- result = -EIO;
- goto abort;
- }
-
- result = 0;
-
-abort:
- return result;
-}
-
-struct reg_data_byte {
- u8 reg;
- u8 *value;
-};
-
-struct reg_data_word {
- u8 reg;
- u16 *value;
-};
-
-static struct ym2651y_data *ym2651y_update_device(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct ym2651y_data *data = i2c_get_clientdata(client);
-
- mutex_lock(&data->update_lock);
-
- if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
- || !data->valid) {
- int i, status;
- u8 command;
- u8 fan_dir[5] = {0};
- struct reg_data_byte regs_byte[] = { {0x19, &data->capability},
- {0x7d, &data->over_temp},
- {0x81, &data->fan_fault},
- {0x98, &data->pmbus_revision}
- };
- struct reg_data_word regs_word[] = { {0x79, &data->status_word},
- {0x8b, &data->v_out},
- {0x8c, &data->i_out},
- {0x96, &data->p_out},
- {0x8d, &data->temp},
- {0x3b, &(data->fan_duty_cycle[0])},
- {0x3c, &(data->fan_duty_cycle[1])},
- {0x90, &data->fan_speed},
- {0xa0, &data->mfr_vin_min},
- {0xa1, &data->mfr_vin_max},
- {0xa2, &data->mfr_iin_max},
- {0xa3, &data->mfr_pin_max},
- {0xa4, &data->mfr_vout_min},
- {0xa5, &data->mfr_vout_max},
- {0xa6, &data->mfr_iout_max},
- {0xa7, &data->mfr_pout_max}
- };
-
- dev_dbg(&client->dev, "Starting ym2651 update\n");
-
- /* Read byte data */
- for (i = 0; i < ARRAY_SIZE(regs_byte); i++) {
- status = ym2651y_read_byte(client, regs_byte[i].reg);
-
- if (status < 0)
- {
- dev_dbg(&client->dev, "reg %d, err %d\n",
- regs_byte[i].reg, status);
- *(regs_byte[i].value) = 0;
- }
- else {
- *(regs_byte[i].value) = status;
- }
- }
-
- /* Read word data */
- for (i = 0; i < ARRAY_SIZE(regs_word); i++) {
- status = ym2651y_read_word(client, regs_word[i].reg);
-
- if (status < 0)
- {
- dev_dbg(&client->dev, "reg %d, err %d\n",
- regs_word[i].reg, status);
- *(regs_word[i].value) = 0;
- }
- else {
- *(regs_word[i].value) = status;
- }
- }
-
- /* Read fan_direction */
- command = 0xC3;
- status = ym2651y_read_block(client, command, fan_dir, ARRAY_SIZE(fan_dir)-1);
-
- if (status < 0) {
- dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
- }
-
- strncpy(data->fan_dir, fan_dir+1, ARRAY_SIZE(data->fan_dir)-1);
- data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0';
-
- /* Read mfr_id */
- command = 0x99;
- status = ym2651y_read_block(client, command, data->mfr_id,
- ARRAY_SIZE(data->mfr_id)-1);
- data->mfr_id[ARRAY_SIZE(data->mfr_id)-1] = '\0';
-
- if (status < 0)
- dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
-
- /* Read mfr_model */
- command = 0x9a;
- status = ym2651y_read_block(client, command, data->mfr_model,
- ARRAY_SIZE(data->mfr_model)-1);
- data->mfr_model[ARRAY_SIZE(data->mfr_model)-1] = '\0';
-
- if (status < 0)
- dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
-
- /* Read mfr_revsion */
- command = 0x9b;
- status = ym2651y_read_block(client, command, data->mfr_revsion,
- ARRAY_SIZE(data->mfr_revsion)-1);
- data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0';
-
- if (status < 0)
- dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
-
- data->last_updated = jiffies;
- data->valid = 1;
- }
-
- mutex_unlock(&data->update_lock);
-
- return data;
-}
-
-module_i2c_driver(ym2651y_driver);
-
-MODULE_AUTHOR("Brandon Chuang ");
-MODULE_DESCRIPTION("3Y Power YM-2651Y driver");
-MODULE_LICENSE("GPL");
-
-
diff --git a/platform/broadcom/sonic-platform-modules-juniper/debian/rules b/platform/broadcom/sonic-platform-modules-juniper/debian/rules
index d8241eef74..1a781912a5 100755
--- a/platform/broadcom/sonic-platform-modules-juniper/debian/rules
+++ b/platform/broadcom/sonic-platform-modules-juniper/debian/rules
@@ -23,7 +23,6 @@ MODULE_DIRS:= qfx5210 qfx5200
MODULE_DIR := modules
UTILS_DIR := utils
SERVICE_DIR := service
-PLATFORM_DIR := sonic_platform
CONF_DIR := conf
%:
@@ -38,7 +37,7 @@ build:
#make modules -C $(KERNEL_SRC)/build M=$(MODULE_SRC)
(for mod in $(MODULE_DIRS); do \
make modules -C $(KERNEL_SRC)/build M=$(MOD_SRC_DIR)/$${mod}/modules || exit 1; \
- $(PYTHON) $${mod}/setup.py build; \
+ $(PYTHON) setup.py build; \
done)
binary: binary-arch binary-indep
@@ -65,7 +64,7 @@ binary-indep:
cp $(MOD_SRC_DIR)/$${mod}/$(MODULE_DIR)/*.ko debian/$(PACKAGE_PRE_NAME)-$${mod}/$(KERNEL_SRC)/$(INSTALL_MOD_DIR); \
cp $(MOD_SRC_DIR)/$${mod}/$(UTILS_DIR)/* debian/$(PACKAGE_PRE_NAME)-$${mod}/usr/local/bin/; \
cp $(MOD_SRC_DIR)/$${mod}/$(SERVICE_DIR)/*.service debian/$(PACKAGE_PRE_NAME)-$${mod}/lib/systemd/system/; \
- $(PYTHON) $${mod}/setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \
+ $(PYTHON) setup.py install --root=$(MOD_SRC_DIR)/debian/$(PACKAGE_PRE_NAME)-$${mod} --install-layout=deb; \
done)
# Resuming debhelper scripts
dh_testroot
diff --git a/platform/broadcom/sonic-platform-modules-juniper/debian/sonic-platform-juniper-qfx5200.install b/platform/broadcom/sonic-platform-modules-juniper/debian/sonic-platform-juniper-qfx5200.install
index 53692f8fd2..741b6da7b3 100644
--- a/platform/broadcom/sonic-platform-modules-juniper/debian/sonic-platform-juniper-qfx5200.install
+++ b/platform/broadcom/sonic-platform-modules-juniper/debian/sonic-platform-juniper-qfx5200.install
@@ -1,5 +1,3 @@
qfx5200/utils/juniper_qfx5200_util.py usr/local/bin
qfx5200/utils/juniper_qfx5200_monitor.py usr/local/bin
-qfx5200/sonic_platform/chassis.py usr/lib/python2.7/dist-packages/sonic_platform
-qfx5200/sonic_platform/platform.py usr/lib/python2.7/dist-packages/sonic_platform
qfx5200/service/qfx5200-platform-init.service etc/systemd/system
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/gpio-tmc.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/gpio-tmc.c
deleted file mode 100644
index 7b02e8a5bc..0000000000
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/gpio-tmc.c
+++ /dev/null
@@ -1,661 +0,0 @@
-/*
- * Juniper Networks TMC GPIO driver
- *
- * Copyright (C) 2020 Juniper Networks
- * Author: Ashish Bhensdadia
- *
- * This driver implement the GPIO set/get functionality
- *
- * 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; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "jnx-tmc.h"
-
-#define TMC_GPIO_MAX_BITS_PER_REG 16
-#define TMC_GPIO_SFP_MAX_BITS_PER_REG 2
-#define TMC_GPIO_PTPCFG_MAX_BITS_PER_REG 8
-
-#define TMC_GPIO_FIND_GROUP(gpio) \
- ((gpio) / TMC_GPIO_MAX_BITS_PER_REG)
-#define TMC_GPIO_FIND_GPIO(gpio) \
- ((gpio) % TMC_GPIO_MAX_BITS_PER_REG)
-
-#define TMC_GPIO_SFP_FIND_GROUP(gpio) \
- ((gpio) / TMC_GPIO_SFP_MAX_BITS_PER_REG)
-#define TMC_GPIO_SFP_FIND_GPIO(gpio) \
- ((gpio) % TMC_GPIO_SFP_MAX_BITS_PER_REG)
-
-#define TMC_GPIO_PTPCFG_FIND_GPIO(gpio) \
- ((gpio) % TMC_GPIO_PTPCFG_MAX_BITS_PER_REG)
-
-#define TMC_GPIO_MAX_NGPIO_PER_GROUP 320
-
-#define TMC_PFE_QSFP_RESET_OFFSET 0x4
-#define TMC_PFE_QSFP_PRESENT_OFFSET 0x8
-#define TMC_PFE_QSFP_PHY_RESET_OFFSET 0x10
-#define TMC_PFE_QSFP_LPMOD_OFFSET 0x78
-#define TMC_PFE_QSFP_LED_CTRL_OFFSET 0x20
-
-#define TMC_PFE_LANES_GREEN_LED_VALUE 0x3
-#define TMC_PFE_LANE0_GREEN_LED_BIT_POSITION 0
-#define TMC_PFE_LANE1_GREEN_LED_BIT_POSITION 2
-#define TMC_PFE_LANE2_GREEN_LED_BIT_POSITION 4
-#define TMC_PFE_LANE3_GREEN_LED_BIT_POSITION 6
-
-#define TMC_PFE_LANES_BEACON_LED_VALUE 0x2
-#define TMC_PFE_LANE0_BEACON_LED_BIT_POSITION 0
-#define TMC_PFE_LANE1_BEACON_LED_BIT_POSITION 2
-#define TMC_PFE_LANE2_BEACON_LED_BIT_POSITION 4
-#define TMC_PFE_LANE3_BEACON_LED_BIT_POSITION 6
-
-#define TMC_PFE_LANES_FAULT_LED_VALUE 0x1
-#define TMC_PFE_LANE0_FAULT_LED_BIT_POSITION 0
-#define TMC_PFE_LANE1_FAULT_LED_BIT_POSITION 2
-#define TMC_PFE_LANE2_FAULT_LED_BIT_POSITION 4
-#define TMC_PFE_LANE3_FAULT_LED_BIT_POSITION 6
-
-#define TMC_PFE_SFPSB0_TX_DISABLE_OFFSET 0x0
-#define TMC_PFE_SFPSB0_LED_CTRL_OFFSET 0xC
-#define TMC_PFE_SFPSB0_LED_ACTIVITY_OFFSET 0x14
-#define TMC_PFE_SFPSB0_PRESENT_OFFSET 0x18
-#define TMC_PFE_SFPSB0_LOSS_OFFSET 0x1C
-#define TMC_PFE_SFPSB0_TX_FAULT_OFFSET 0x20
-
-#define TMC_PFE_SFPSB1_TX_DISABLE_OFFSET 0x0
-#define TMC_PFE_SFPSB1_LED_CTRL_OFFSET 0x8
-#define TMC_PFE_SFPSB1_LED_ACTIVITY_OFFSET 0x10
-#define TMC_PFE_SFPSB1_PRESENT_OFFSET 0x14
-#define TMC_PFE_SFPSB1_LOSS_OFFSET 0x18
-#define TMC_PFE_SFPSB1_TX_FAULT_OFFSET 0x1C
-
-/*
- * Index 4 to 15 is used for QSFP starting with
- * QSFP_LED_LANE0_GREEN. To keep multibit set/get common
- * starting SFP_LED_LANE0_GREEN with 16 which will avoid
- * conflict with QSFP enums.
- */
-#define SFP_LED_OP_START_INDEX 16
-
-/*
- * Used for off-setting SFP led op index
- */
-#define SFP_LED_OP_OFFSET 0xB
-
-/*
- * SFP slave blocks
- */
-#define SFP_SLAVE0_BLOCK 0x1
-#define SFP_SLAVE1_BLOCK 0x2
-
-/*
- * each group represent the 16 gpios.
- * QSFP_RST - QSFP_LPMODE
- * each bit represent the one gpio
- * exemple: bits[0:15] - bit0 - gpio0
- * QSFP_LED_LANE0_GREEN - QSFP_LED_LANE3_FAULT
- * here, number represent the one gpio
- * exemple: bits[0:1]
- * 00 - gpio off, 01 - gpio on [ gpio0]
- * 00 - gpio off, 10 - gpio on [ gpio1]
- * 00 - gpio off, 11 - gpio on [ gpio2]
- *
- */
-enum {
- QSFP_RST,
- QSFP_PRESENT,
- QSFP_PHY_RST,
- QSFP_LPMOD,
- QSFP_LED_LANE0_GREEN,
- QSFP_LED_LANE1_GREEN,
- QSFP_LED_LANE2_GREEN,
- QSFP_LED_LANE3_GREEN,
- QSFP_LED_LANE0_BEACON,
- QSFP_LED_LANE1_BEACON,
- QSFP_LED_LANE2_BEACON,
- QSFP_LED_LANE3_BEACON,
- QSFP_LED_LANE0_FAULT,
- QSFP_LED_LANE1_FAULT,
- QSFP_LED_LANE2_FAULT,
- QSFP_LED_LANE3_FAULT,
- TMC_PFE_GPIO_GROUP_MAX
-};
-
-enum sfp_op {
- SFP_TX_DISABLE,
- SFP_LED_ACTIVITY,
- SFP_PRESENT,
- SFP_SFP_LOS,
- SFP_TX_FAULT,
- SFP_LED_LANE0_GREEN = SFP_LED_OP_START_INDEX,
- SFP_LED_LANE1_GREEN,
- SFP_LED_LANE2_GREEN,
- SFP_LED_LANE3_GREEN,
- SFP_LED_LANE0_BEACON,
- SFP_LED_LANE1_BEACON,
- SFP_LED_LANE2_BEACON,
- SFP_LED_LANE3_BEACON,
- SFP_LED_LANE0_FAULT,
- SFP_LED_LANE1_FAULT,
- SFP_LED_LANE2_FAULT,
- SFP_LED_LANE3_FAULT,
- TMC_PFE_SFP_GPIO_GROUP_MAX
-};
-
-static const u32 group_offset[TMC_PFE_GPIO_GROUP_MAX] = {
- TMC_PFE_QSFP_RESET_OFFSET,
- TMC_PFE_QSFP_PRESENT_OFFSET,
- TMC_PFE_QSFP_PHY_RESET_OFFSET,
- TMC_PFE_QSFP_LPMOD_OFFSET,
- TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE0 GREEN */
- TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE1 GREEN */
- TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE2 GREEN */
- TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE3 GREEN */
- TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE0 BEACON */
- TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE1 BEACON */
- TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE2 BEACON */
- TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE3 BEACON */
- TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE0 FAULT */
- TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE1 FAULT */
- TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE2 FAULT */
- TMC_PFE_QSFP_LED_CTRL_OFFSET, /* LANE3 FAULT */
-};
-
-static const u32 sfp_slaveb0_group_offset[TMC_PFE_SFP_GPIO_GROUP_MAX] = {
- TMC_PFE_SFPSB0_TX_DISABLE_OFFSET,
- TMC_PFE_SFPSB0_LED_ACTIVITY_OFFSET,
- TMC_PFE_SFPSB0_PRESENT_OFFSET,
- TMC_PFE_SFPSB0_LOSS_OFFSET,
- TMC_PFE_SFPSB0_TX_FAULT_OFFSET,
- TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE0 GREEN */
- TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE1 GREEN */
- TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE2 GREEN */
- TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE3 GREEN */
- TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE0 BEACON */
- TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE1 BEACON */
- TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE2 BEACON */
- TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE3 BEACON */
- TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE0 FAULT */
- TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE1 FAULT */
- TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE2 FAULT */
- TMC_PFE_SFPSB0_LED_CTRL_OFFSET, /* LANE3 FAULT */
-};
-
-static const u32 sfp_slaveb1_group_offset[TMC_PFE_SFP_GPIO_GROUP_MAX] = {
- TMC_PFE_SFPSB1_TX_DISABLE_OFFSET,
- TMC_PFE_SFPSB1_LED_ACTIVITY_OFFSET,
- TMC_PFE_SFPSB1_PRESENT_OFFSET,
- TMC_PFE_SFPSB1_LOSS_OFFSET,
- TMC_PFE_SFPSB1_TX_FAULT_OFFSET,
- TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE0 GREEN */
- TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE1 GREEN */
- TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE2 GREEN */
- TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE3 GREEN */
- TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE0 BEACON */
- TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE1 BEACON */
- TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE2 BEACON */
- TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE3 BEACON */
- TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE0 FAULT */
- TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE1 FAULT */
- TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE2 FAULT */
- TMC_PFE_SFPSB1_LED_CTRL_OFFSET, /* LANE3 FAULT */
-};
-
-struct tmc_gpio_info {
- int (*get)(struct gpio_chip *, unsigned int);
- void (*set)(struct gpio_chip *, unsigned int, int);
- int (*dirin)(struct gpio_chip *, unsigned int);
- int (*dirout)(struct gpio_chip *, unsigned int, int);
-};
-
-struct tmc_gpio_chip {
- const struct tmc_gpio_info *info;
- void __iomem *base;
- struct device *dev;
- struct gpio_chip gpio;
- int ngpio;
- spinlock_t gpio_lock; /* gpio lock */
- int sfp_slave_block;
-};
-
-/* slave gpio max */
-static int gpio_max = 320;
-module_param(gpio_max, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-MODULE_PARM_DESC(gpio_max, "Maximum number of gpio for SLAVE TMC GPIO");
-
-/*
- * generic bit operation functions
- */
-static u32 tmc_gpio_reset_bits(u32 state, u32 val, u32 shift)
-{
- state &= ~(val << shift);
- return state;
-};
-
-static u32 tmc_gpio_set_bits(u32 state, u32 val, u32 shift)
-{
- state |= (val << shift);
- return state;
-};
-
-static u32 tmc_gpio_find_bits_val(u32 state, u32 shift, u32 mask)
-{
- return ((state >> shift)) & mask;
-};
-
-#define to_tmc_chip(chip) \
- container_of((chip), struct tmc_gpio_chip, gpio)
-
-/*
- * tmc_gpio_multiple_bitsop - Generic TMC GPIO multiple bits operation
- */
-static void tmc_gpio_multiple_bitsop(struct tmc_gpio_chip *chip,
- unsigned int gpiono, u32 group, u32 offset, bool set)
-{
- u32 gpio_state, led_val, bit_shift;
- unsigned long flags;
- void __iomem *iobase;
-
- iobase = chip->base + offset;
-
- dev_dbg(chip->dev, "TMC GPIO multiple bitop group=%u, "
- "gpiono=%u, offet:=%u, set=%u\n", group, gpiono, offset, set);
-
- spin_lock_irqsave(&chip->gpio_lock, flags);
-
- switch (group) {
- case QSFP_LED_LANE0_GREEN:
- case SFP_LED_LANE0_GREEN:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- led_val = TMC_PFE_LANES_GREEN_LED_VALUE;
- bit_shift = TMC_PFE_LANE0_GREEN_LED_BIT_POSITION;
- break;
- case QSFP_LED_LANE1_GREEN:
- case SFP_LED_LANE1_GREEN:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- led_val = TMC_PFE_LANES_GREEN_LED_VALUE;
- bit_shift = TMC_PFE_LANE1_GREEN_LED_BIT_POSITION;
- break;
- case QSFP_LED_LANE2_GREEN:
- case SFP_LED_LANE2_GREEN:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- led_val = TMC_PFE_LANES_GREEN_LED_VALUE;
- bit_shift = TMC_PFE_LANE2_GREEN_LED_BIT_POSITION;
- break;
- case QSFP_LED_LANE3_GREEN:
- case SFP_LED_LANE3_GREEN:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- led_val = TMC_PFE_LANES_GREEN_LED_VALUE;
- bit_shift = TMC_PFE_LANE3_GREEN_LED_BIT_POSITION;
- break;
- case QSFP_LED_LANE0_BEACON:
- case SFP_LED_LANE0_BEACON:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- led_val = TMC_PFE_LANES_BEACON_LED_VALUE;
- bit_shift = TMC_PFE_LANE0_BEACON_LED_BIT_POSITION;
- break;
- case QSFP_LED_LANE1_BEACON:
- case SFP_LED_LANE1_BEACON:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- led_val = TMC_PFE_LANES_BEACON_LED_VALUE;
- bit_shift = TMC_PFE_LANE1_BEACON_LED_BIT_POSITION;
- break;
- case QSFP_LED_LANE2_BEACON:
- case SFP_LED_LANE2_BEACON:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- led_val = TMC_PFE_LANES_BEACON_LED_VALUE;
- bit_shift = TMC_PFE_LANE2_BEACON_LED_BIT_POSITION;
- break;
- case QSFP_LED_LANE3_BEACON:
- case SFP_LED_LANE3_BEACON:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- led_val = TMC_PFE_LANES_BEACON_LED_VALUE;
- bit_shift = TMC_PFE_LANE3_BEACON_LED_BIT_POSITION;
- break;
- case QSFP_LED_LANE0_FAULT:
- case SFP_LED_LANE0_FAULT:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- led_val = TMC_PFE_LANES_FAULT_LED_VALUE;
- bit_shift = TMC_PFE_LANE0_FAULT_LED_BIT_POSITION;
- break;
- case QSFP_LED_LANE1_FAULT:
- case SFP_LED_LANE1_FAULT:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- led_val = TMC_PFE_LANES_FAULT_LED_VALUE;
- bit_shift = TMC_PFE_LANE1_FAULT_LED_BIT_POSITION;
- break;
- case QSFP_LED_LANE2_FAULT:
- case SFP_LED_LANE2_FAULT:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- led_val = TMC_PFE_LANES_FAULT_LED_VALUE;
- bit_shift = TMC_PFE_LANE2_FAULT_LED_BIT_POSITION;
- break;
- case QSFP_LED_LANE3_FAULT:
- case SFP_LED_LANE3_FAULT:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- led_val = TMC_PFE_LANES_FAULT_LED_VALUE;
- bit_shift = TMC_PFE_LANE3_FAULT_LED_BIT_POSITION;
- break;
-
- default:
- spin_unlock_irqrestore(&chip->gpio_lock, flags);
- return;
- }
-
- if (set) {
- gpio_state = tmc_gpio_reset_bits(gpio_state, 0x3, bit_shift);
- gpio_state = tmc_gpio_set_bits(gpio_state, led_val, bit_shift);
- } else {
- gpio_state = tmc_gpio_reset_bits(gpio_state, 0x3, bit_shift);
- }
-
- iowrite32(gpio_state, (iobase+(0x004*gpiono)));
-
- spin_unlock_irqrestore(&chip->gpio_lock, flags);
-
- return;
-};
-
-/*
- * tmc_gpio_one_bitop - Generic TMC GPIO single bit operation
- */
-static void tmc_gpio_one_bitop(struct tmc_gpio_chip *chip,
- unsigned int bit, u32 offset, bool set)
-{
- u32 gpio_state;
- unsigned long flags;
- void __iomem *iobase;
-
- iobase = chip->base + offset;
-
- dev_dbg(chip->dev, "TMC GPIO one bitop bit=%u, offset=%x, "
- "set=%u\n", bit, offset, set);
-
- spin_lock_irqsave(&chip->gpio_lock, flags);
-
- gpio_state = ioread32(iobase);
- if (set)
- gpio_state |= BIT(bit);
- else
- gpio_state &= ~BIT(bit);
-
- iowrite32(gpio_state, iobase);
-
- spin_unlock_irqrestore(&chip->gpio_lock, flags);
-
- return;
-}
-
-/*
- * tmc_gpio_get_multiple_bitsop - Generic TMC get GPIO multiple bits operation
- */
-static int tmc_gpio_get_multiple_bitsop(struct tmc_gpio_chip *chip,
- unsigned int gpiono, u32 group, u32 offset)
-{
- u32 gpio_state;
- void __iomem *iobase;
-
- iobase = chip->base + offset;
-
- dev_dbg(chip->dev, "TMC GPIO get multiple bitsop group=%u, "
- "gpiono=%u, offset=%u\n", group, gpiono, offset);
-
- switch (group) {
- case QSFP_LED_LANE0_GREEN:
- case SFP_LED_LANE0_GREEN:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- return (TMC_PFE_LANES_GREEN_LED_VALUE ==
- tmc_gpio_find_bits_val(gpio_state,
- TMC_PFE_LANE0_GREEN_LED_BIT_POSITION, 0x3));
- case QSFP_LED_LANE1_GREEN:
- case SFP_LED_LANE1_GREEN:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- return (TMC_PFE_LANES_GREEN_LED_VALUE ==
- tmc_gpio_find_bits_val(gpio_state,
- TMC_PFE_LANE1_GREEN_LED_BIT_POSITION, 0x3));
- case QSFP_LED_LANE2_GREEN:
- case SFP_LED_LANE2_GREEN:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- return (TMC_PFE_LANES_GREEN_LED_VALUE ==
- tmc_gpio_find_bits_val(gpio_state,
- TMC_PFE_LANE2_GREEN_LED_BIT_POSITION, 0x3));
- case QSFP_LED_LANE3_GREEN:
- case SFP_LED_LANE3_GREEN:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- return (TMC_PFE_LANES_GREEN_LED_VALUE ==
- tmc_gpio_find_bits_val(gpio_state,
- TMC_PFE_LANE3_GREEN_LED_BIT_POSITION, 0x3));
- case QSFP_LED_LANE0_BEACON:
- case SFP_LED_LANE0_BEACON:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- return (TMC_PFE_LANES_BEACON_LED_VALUE ==
- tmc_gpio_find_bits_val(gpio_state,
- TMC_PFE_LANE0_BEACON_LED_BIT_POSITION, 0x3));
- case QSFP_LED_LANE1_BEACON:
- case SFP_LED_LANE1_BEACON:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- return (TMC_PFE_LANES_BEACON_LED_VALUE ==
- tmc_gpio_find_bits_val(gpio_state,
- TMC_PFE_LANE1_BEACON_LED_BIT_POSITION, 0x3));
- case QSFP_LED_LANE2_BEACON:
- case SFP_LED_LANE2_BEACON:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- return (TMC_PFE_LANES_BEACON_LED_VALUE ==
- tmc_gpio_find_bits_val(gpio_state,
- TMC_PFE_LANE2_BEACON_LED_BIT_POSITION, 0x3));
- case QSFP_LED_LANE3_BEACON:
- case SFP_LED_LANE3_BEACON:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- return (TMC_PFE_LANES_BEACON_LED_VALUE ==
- tmc_gpio_find_bits_val(gpio_state,
- TMC_PFE_LANE3_BEACON_LED_BIT_POSITION, 0x3));
- case QSFP_LED_LANE0_FAULT:
- case SFP_LED_LANE0_FAULT:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- return (TMC_PFE_LANES_FAULT_LED_VALUE ==
- tmc_gpio_find_bits_val(gpio_state,
- TMC_PFE_LANE0_FAULT_LED_BIT_POSITION, 0x3));
- case QSFP_LED_LANE1_FAULT:
- case SFP_LED_LANE1_FAULT:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- return (TMC_PFE_LANES_FAULT_LED_VALUE ==
- tmc_gpio_find_bits_val(gpio_state,
- TMC_PFE_LANE1_FAULT_LED_BIT_POSITION, 0x3));
- case QSFP_LED_LANE2_FAULT:
- case SFP_LED_LANE2_FAULT:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- return (TMC_PFE_LANES_FAULT_LED_VALUE ==
- tmc_gpio_find_bits_val(gpio_state,
- TMC_PFE_LANE2_FAULT_LED_BIT_POSITION, 0x3));
- case QSFP_LED_LANE3_FAULT:
- case SFP_LED_LANE3_FAULT:
- gpio_state = ioread32(iobase+(0x004*gpiono));
- return (TMC_PFE_LANES_FAULT_LED_VALUE ==
- tmc_gpio_find_bits_val(gpio_state,
- TMC_PFE_LANE3_FAULT_LED_BIT_POSITION, 0x3));
- default:
- return 0;
- }
-};
-
-/*
- * tmc_gpio_get - Read the specified signal of the GPIO device.
- */
-static int tmc_gpio_get(struct gpio_chip *gc, unsigned int gpio)
-{
- struct tmc_gpio_chip *chip = to_tmc_chip(gc);
- unsigned int group = TMC_GPIO_FIND_GROUP(gpio);
- unsigned int bit = TMC_GPIO_FIND_GPIO(gpio);
-
- if (group >= TMC_PFE_GPIO_GROUP_MAX)
- return 0;
-
- switch (group) {
- case QSFP_RST:
- case QSFP_PRESENT:
- case QSFP_PHY_RST:
- case QSFP_LPMOD:
- dev_dbg(chip->dev, "TMC GPIO get one bitop group=%u, gpio=%u, "
- "bit=%u\n", group, gpio, bit);
- return !!(ioread32(chip->base + group_offset[group])
- & BIT(bit));
- default:
- return tmc_gpio_get_multiple_bitsop(chip, bit, group, group_offset[group]);
- }
-}
-
-/*
- * tmc_gpio_set - Write the specified signal of the GPIO device.
- */
-static void tmc_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
-{
- struct tmc_gpio_chip *chip = to_tmc_chip(gc);
- unsigned int group = TMC_GPIO_FIND_GROUP(gpio);
- unsigned int bit = TMC_GPIO_FIND_GPIO(gpio);
-
- if (group >= TMC_PFE_GPIO_GROUP_MAX)
- return;
-
- switch (group) {
- case QSFP_RST:
- case QSFP_PRESENT:
- case QSFP_PHY_RST:
- case QSFP_LPMOD:
- dev_dbg(chip->dev, "TMC GPIO one bitop group=%d\n", group);
- tmc_gpio_one_bitop(chip, bit, group_offset[group], val);
- break;
- default:
- tmc_gpio_multiple_bitsop(chip, bit, group, group_offset[group], val);
- break;
- }
-}
-
-static struct tmc_gpio_info tmc_gpios[] = {
- {
- .get = tmc_gpio_get,
- .set = tmc_gpio_set,
- },
-};
-
-static void tmc_gpio_setup(struct tmc_gpio_chip *sgc, int id)
-{
- struct gpio_chip *chip = &sgc->gpio;
- const struct tmc_gpio_info *info = sgc->info;
-
- chip->get = info->get;
- chip->set = info->set;
- chip->direction_input = info->dirin;
- chip->direction_output = info->dirout;
- chip->dbg_show = NULL;
- chip->can_sleep = 0;
-
- if (id == 0) {
- chip->base = 0;
- } else if (id == 1) {
- chip->base = (gpio_max * id);
- } else {
- chip->base = -1;
- }
-
- chip->ngpio = sgc->ngpio;
- chip->label = dev_name(sgc->dev);
- chip->parent = sgc->dev;
- chip->owner = THIS_MODULE;
-}
-
-static int tmc_gpio_of_init(struct device *dev,
- struct tmc_gpio_chip *chip)
-{
- chip->info = &tmc_gpios[0];
- chip->ngpio = gpio_max;
-
- return 0;
-}
-
-static int tmc_gpio_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct tmc_gpio_chip *chip;
- struct resource *res;
- int ret;
-
- const struct mfd_cell *cell = mfd_get_cell(pdev);
-
- dev_dbg(dev, "TMC GPIO probe\n");
-
- chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
- if (!chip)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
- dev_info(dev, "TMC GPIO resource 0x%llx, %llu\n",
- res->start, resource_size(res));
-
- chip->base = devm_ioremap_nocache(dev, res->start, resource_size(res));
- if (!chip->base)
- return -ENOMEM;
-
- ret = tmc_gpio_of_init(dev, chip);
- if (ret)
- return ret;
-
- chip->dev = dev;
- spin_lock_init(&chip->gpio_lock);
-
- tmc_gpio_setup(chip, cell->id);
-
- ret = gpiochip_add(&chip->gpio);
- if (ret) {
- dev_err(dev,
- "Failed to register TMC gpiochip : %d\n", ret);
- return ret;
- }
-
- platform_set_drvdata(pdev, chip);
- dev_info(dev, "TMC GPIO registered at 0x%lx, gpiobase: %d\n",
- (long unsigned)chip->base, chip->gpio.base);
-
- return 0;
-}
-
-static int tmc_gpio_remove(struct platform_device *pdev)
-{
- struct tmc_gpio_chip *chip = platform_get_drvdata(pdev);
-
- gpiochip_remove(&chip->gpio);
-
- return 0;
-}
-
-static struct platform_driver tmc_gpio_driver = {
- .driver = {
- .name = "gpioslave-tmc",
- .owner = THIS_MODULE,
- },
- .probe = tmc_gpio_probe,
- .remove = tmc_gpio_remove,
-};
-
-module_platform_driver(tmc_gpio_driver);
-
-MODULE_DESCRIPTION("Juniper Networks TMC FPGA GPIO driver");
-MODULE_AUTHOR("Ashish Bhensdadia ");
-MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/gpio-tmc.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/gpio-tmc.c
new file mode 120000
index 0000000000..257a13181e
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/gpio-tmc.c
@@ -0,0 +1 @@
+../../common/modules/gpio-tmc.c
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/i2c-tmc.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/i2c-tmc.c
deleted file mode 100644
index afd0311dc1..0000000000
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/i2c-tmc.c
+++ /dev/null
@@ -1,1107 +0,0 @@
-/*
- * Juniper Networks TMC I2C Accelerator driver
- *
- * Copyright (C) 2020 Juniper Networks
- * Author: Ashish Bhensdadia
- *
- * This driver implement the I2C functionality
- *
- * 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; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "jnx-tmc.h"
-
-
-#define TMC_I2C_MASTER_I2C_SCAN_RESET_BIT BIT(31)
-
-#define TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET 0x0
-#define TMC_I2C_MSTR_AUTOMATION_I2C_DPMEM_OFFSET 0x10
-
-#define TMC_I2C_MSTR_AUTOMATION_I2C(adap, offset) \
- ((adap)->membase + offset)
-
-#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_0 0x0
-#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8 0x8
-#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_4 0x4
-#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_C 0xC
-#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10 0x10
-#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_14 0x14
-#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_18 0x18
-#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_1C 0x1C
-#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_20 0x20
-#define TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_24 0x24
-
-#define TMC_I2C_MSTR_I2C_DPMEM(adap, offset) \
- ((adap)->dpmbase + offset)
-
-#define TMC_I2C_TRANS_LEN 2
-#define tmc_iowrite(val, addr) iowrite32((val), (addr))
-
-#define TMC_I2C_CTRL_GROUP(g) (((g) & 0xFF) << 8)
-#define TMC_I2C_CTRL_WRCNT(w) (((w) & 0x3F) << 16)
-#define TMC_I2C_CTRL_RDCNT(r) (((r) & 0x3F) << 16)
-#define TMC_I2C_CTRL_DEVADDR(d) (((d) & 0xFF) << 8)
-#define TMC_I2C_CTRL_OFFSET(o) ((o) & 0xFF)
-
-
-#define TMC_I2C_MEM_CTRL_VLD BIT(31)
-
-#define TMC_I2C_CTRL_ERR(s) ((s) & 0x0F000000)
-#define TMC_I2C_CTRL_DONE_BIT(s) ((s) & BIT(31))
-#define TMC_I2C_CTRL_STATUS_OK(s) (TMC_I2C_CTRL_DONE_BIT(s) & \
- TMC_I2C_CTRL_ERR(s))
-#define TMC_I2C_CTRL_DONE(s) (TMC_I2C_CTRL_DONE_BIT(s) == BIT(31))
-
-#define TMC_I2C_STAT_INC(adap, s) (((adap)->stat.s)++)
-#define TMC_I2C_STAT_INCN(adap, s, n) (((adap)->stat.s) += (n))
-#define TMC_I2C_GET_MASTER(tadap) ((tadap)->tctrl)
-
-#define TMC_I2C_READ 0x1
-#define TMC_I2C_WRITE 0x2
-
-#define TMC_I2C_MASTER_LOCK(s, flags) \
-do { \
- spin_lock_irqsave(&(s)->lock, flags); \
-} while (0)
-
-#define TMC_I2C_MASTER_UNLOCK(s, flags) \
-do { \
- spin_unlock_irqrestore(&(s)->lock, flags); \
-} while (0)
-
-#define tmc_i2c_dbg(dev, fmt, args...) \
-do { \
- if (tmc_i2c_debug >= 1) \
- dev_err(dev, fmt, ## args); \
-} while (0)
-
-
-/* pfe TMC i2c channel */
-static int pfe_channel = 32;
-module_param(pfe_channel, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-MODULE_PARM_DESC(pfe_channel, "Maximum number of channel for PFE TMC");
-
-/* chassid TMC i2c channel */
-static int chd_channel = 11;
-module_param(chd_channel, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-MODULE_PARM_DESC(chd_channel, "Maximum number of channel for CHASSID TMC");
-
-static u32 wr_index_to_oper[] = {0x01000000, 0x02000000,
- 0x84000000, 0x85000000, 0x83000000};
-static u32 rd_index_to_oper[] = {0x08000000, 0x09000000, 0x0A000000,
- 0x8B000000, 0x8C000000, 0x8D000000, 0x83000000};
-
-struct tmc_i2c_adapter_stats {
- u32 abort;
- u32 go;
- u32 mstr_rdy;
- u32 mstr_busy;
- u32 trans_compl;
- u32 msg_cnt;
- u32 rd_cnt;
- u32 wr_cnt;
- u32 byte_cnt;
- u32 slave_timeo;
- u32 scl_bus_loss;
- u32 sda_bus_loss;
- u32 ack_ptimeo;
- u32 rd_cnt_0;
- u32 rd_cnt_gt32;
- u32 rst_tgt;
- u32 rst_mstr;
-};
-
-struct tmc_i2c_adapter {
- void __iomem *membase;
- void __iomem *dpmbase;
- struct i2c_adapter adap;
- struct i2c_mux_core *muxc;
- struct tmc_i2c_ctrl *tctrl;
- int mux_channels;
- int mux_select;
- u32 i2c_delay;
- int entries;
- int master;
- u32 control;
- u32 speed;
- bool done;
- bool polling;
- bool use_block;
- wait_queue_head_t wait;
- struct tmc_i2c_adapter_stats stat;
-};
-
-struct tmc_i2c_ctrl {
- void __iomem *membase;
- void __iomem *dpmbase;
- struct i2c_adapter **adap;
- struct device *dev;
- int num_masters;
- int mux_channels;
- u32 i2c_delay;
- u32 master_mask;
- spinlock_t lock; /* master lock */
-};
-
-/*
- * Reset the Tmc I2C master
- */
-static void tmc_i2c_reset_master(struct i2c_adapter *adap)
-{
- struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
- struct tmc_i2c_ctrl *tmc = TMC_I2C_GET_MASTER(tadap);
- u32 val, master = tadap->master;
- unsigned long flags;
- void __iomem *addr;
-
- dev_warn(&adap->dev, "Re-setting i2c master: %d\n", master);
-
- TMC_I2C_MASTER_LOCK(tmc, flags);
-
- addr = tmc->membase + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET;
- val = ioread32(addr);
- tmc_iowrite(val | (TMC_I2C_MASTER_I2C_SCAN_RESET_BIT), addr);
- tmc_iowrite(val & ~(TMC_I2C_MASTER_I2C_SCAN_RESET_BIT), addr);
- TMC_I2C_STAT_INC(tadap, rst_mstr);
-
- TMC_I2C_MASTER_UNLOCK(tmc, flags);
-}
-
-/*
- * check if the Tmc I2C master is ready
- */
-static int tmc_i2c_mstr_wait_rdy(struct i2c_adapter *adap, u8 rw, u32 delay)
-{
- struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
- unsigned long timeout;
- u32 val;
-
- val = ioread32(TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
- if (val) {
- tmc_iowrite(0x80000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
- mdelay(5);
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
- val = ioread32(TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
- } else {
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
- }
-
- if ((rw == TMC_I2C_READ) && (delay)) {
- tmc_iowrite(0x80000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
- return 0;
- }
-
- timeout = jiffies + adap->timeout;
- do {
- val = ioread32(TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
- if (!val)
- return 0;
-
- if (tadap->polling) {
- usleep_range(50, 100);
- } else {
- tadap->done = false;
- wait_event_timeout(tadap->wait, tadap->done,
- adap->timeout);
- }
- } while (time_before(jiffies, timeout));
-
- TMC_I2C_STAT_INC(tadap, mstr_busy);
-
- return -EBUSY;
-}
-
-/*
- * Wait for master completion
- */
-static u32 tmc_i2c_mstr_wait_completion(struct i2c_adapter *adap,
- u32 dp_entry_offset)
-{
- struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
- u32 val;
-
- if (tadap->polling) {
- /* Poll for the results */
- unsigned long timeout = jiffies + adap->timeout;
-
- do {
- usleep_range(1000, 1200);
- val = ioread32(TMC_I2C_MSTR_I2C_DPMEM(tadap,
- dp_entry_offset));
- if (TMC_I2C_CTRL_DONE(val))
- break;
- } while (time_before(jiffies, timeout));
- } else {
- wait_event_timeout(tadap->wait, tadap->done, adap->timeout);
- val = ioread32(TMC_I2C_MSTR_I2C_DPMEM(tadap,
- dp_entry_offset));
- }
-
- return TMC_I2C_CTRL_STATUS_OK(val);
-}
-
-/*
- * TMC I2C delay read/write operation
- */
-static int tmc_i2c_delay_rw_op(struct i2c_adapter *adap, u8 rw, u32 mux,
- u32 addr, u32 offset, u32 len, u32 delay, u8 *buf)
-{
- struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
- struct device *dev = &adap->dev;
- int err, n;
- u32 control = 0, data = 0;
- u32 val;
-
- err = tmc_i2c_mstr_wait_rdy(adap, rw, 0);
- if (err < 0) {
- tmc_i2c_reset_master(adap);
- return err;
- }
-
- TMC_I2C_STAT_INC(tadap, mstr_rdy);
-
- /* initialize the start address and mux */
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_DPMEM_OFFSET));
-
- tmc_iowrite(mux, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_0));
- tmc_iowrite(0x84400000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_4));
-
- /* populate delay */
- if (delay) {
- if (delay > 1000) {
- delay = delay/1000;
- delay |= (1 << 16);
- }
- }
- tmc_iowrite(delay, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8));
- tmc_iowrite(0x86000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_C));
-
- /* prepare control command */
- control |= TMC_I2C_CTRL_DEVADDR(addr);
- control |= TMC_I2C_CTRL_OFFSET(offset);
-
- if (rw == TMC_I2C_WRITE) {
- for (n = 0; n < len; n++)
- data |= (buf[n] << ((len - 1 - n) * 8));
- tmc_iowrite(data, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10));
- control |= TMC_I2C_CTRL_WRCNT(len);
- control |= wr_index_to_oper[len-1];
- dev_dbg(dev, "WR Data: [%#04x, %#04x, %#04x, %#04x]\n",
- ((data >> 24) & 0xff), ((data >> 16) & 0xff),
- ((data >> 8) & 0xff), (data & 0xff));
-
- } else {
- /* read */
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10));
- control |= TMC_I2C_CTRL_RDCNT(len);
- control |= rd_index_to_oper[len-1];
- }
-
- /*
- * valid this transaction as well
- */
- control |= TMC_I2C_MEM_CTRL_VLD;
-
- tadap->control = control;
-
- /*
- * operation control command
- */
- tmc_iowrite(control, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_14));
-
- /*
- * End commands
- */
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_18));
- tmc_iowrite(0x8E000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_1C));
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_20));
- tmc_iowrite(0x8F000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_24));
-
- dev_dbg(dev, "Control (%#x): RD_WR_TYPE:%#02x, RD_WR_LEN:%d,"
- "Addr:%#01x, Offset:%#02x\n", control,
- ((control >> 24) & 0x3F), ((control >> 16) & 0x3F),
- ((control >> 8) & 0xff), ((control) & 0xff));
-
- tadap->done = false;
-
- /* fire the transaction */
- tmc_iowrite(0x00000001, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
-
- TMC_I2C_STAT_INC(tadap, go);
-
- val = tmc_i2c_mstr_wait_completion(adap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10);
- if (val) {
- dev_err(&adap->dev,
- "i2c transaction error (0x%08x)\n", val);
-
- /* stop the transaction */
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
- return -EIO;
- }
-
- /*
- * read a word of data
- */
- if (rw == TMC_I2C_READ) {
- data = ioread32(TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10));
- for (n = 0; n < len; n++)
- buf[n] = (data >> (n * 8)) & 0xff;
-
- dev_dbg(dev, "RD Data: [%#04x, %#04x, %#04x, %#04x]\n",
- ((data >> 24) & 0xff), ((data >> 16) & 0xff),
- ((data >> 8) & 0xff), (data & 0xff));
-
- TMC_I2C_STAT_INC(tadap, rd_cnt);
- } else {
- /* write */
- TMC_I2C_STAT_INC(tadap, wr_cnt);
- }
-
- /* stop the transaction */
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
-
- return 0;
-
-}
-
-/*
- *TMC I2C none delay Read/write opertion
- */
-static int tmc_i2c_none_delay_rw_op(struct i2c_adapter *adap, u8 rw, u32 mux,
- u32 addr, u32 offset, u32 len, u8 *buf)
-{
- struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
- struct device *dev = &adap->dev;
- int err, n;
- u32 control = 0, data = 0;
- u32 val;
-
- err = tmc_i2c_mstr_wait_rdy(adap, rw, 0);
- if (err < 0) {
- tmc_i2c_reset_master(adap);
- return err;
- }
-
- TMC_I2C_STAT_INC(tadap, mstr_rdy);
-
- /* initialize the start address and mux */
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_DPMEM_OFFSET));
-
- tmc_iowrite(mux, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_0));
- tmc_iowrite(0x84400000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_4));
-
-
- /* prepare control command */
- control |= TMC_I2C_CTRL_DEVADDR(addr);
- control |= TMC_I2C_CTRL_OFFSET(offset);
-
- if (rw == TMC_I2C_WRITE) {
- for (n = 0; n < len; n++)
- data |= (buf[n] << (n * 8));
- tmc_iowrite(data, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8));
- control |= wr_index_to_oper[len-1];
- dev_dbg(dev, "WR Data: [%#04x, %#04x, %#04x, %#04x]\n",
- ((data >> 24) & 0xff), ((data >> 16) & 0xff),
- ((data >> 8) & 0xff), (data & 0xff));
-
- } else {
- /* read */
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8));
- control |= rd_index_to_oper[len-1];
- }
-
- /*
- * valid this transaction as well
- */
- control |= TMC_I2C_MEM_CTRL_VLD;
-
- tadap->control = control;
-
- /*
- * operation control command
- */
- tmc_iowrite(control, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_C));
-
- /*
- * End commands
- */
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10));
- tmc_iowrite(0x8E000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_14));
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_18));
- tmc_iowrite(0x8F000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_1C));
-
- dev_dbg(dev, "Control (%#x): RD_WR_TYPE:%#02x, RD_WR_LEN:%d,"
- "Addr:%#01x, Offset:%#02x\n", control,
- ((control >> 24) & 0x3F), ((control >> 16) & 0x3F),
- ((control >> 8) & 0xff), ((control) & 0xff));
-
- tadap->done = false;
-
- /* fire the transaction */
- tmc_iowrite(0x00000001, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
-
- TMC_I2C_STAT_INC(tadap, go);
-
- /* wait till transaction complete */
- val = tmc_i2c_mstr_wait_completion(adap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8);
- if (val) {
- dev_err(&adap->dev,
- "i2c transaction error (0x%08x)\n", val);
-
- /* stop the transaction */
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
- return -EIO;
- }
-
- /*
- * read a word of data
- */
- if (rw == TMC_I2C_READ) {
- data = ioread32(TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8));
- for (n = 0; n < len; n++)
- buf[n] = (data >> (n * 8)) & 0xff;
-
- dev_dbg(dev, "RD Data: [%#04x, %#04x, %#04x, %#04x]\n",
- ((data >> 24) & 0xff), ((data >> 16) & 0xff),
- ((data >> 8) & 0xff), (data & 0xff));
- TMC_I2C_STAT_INC(tadap, rd_cnt);
- } else {
- /* write */
- TMC_I2C_STAT_INC(tadap, wr_cnt);
- }
-
- /* stop the transaction */
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
-
- return 0;
-}
-
-/*
- * TMC I2C read/write operation
- */
-static int tmc_i2c_rw_op(struct i2c_adapter *adap, u8 rw, u32 mux,
- u32 addr, u32 offset, u32 len, u8 *buf)
-{
- struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
- u32 i2c_delay = tadap->i2c_delay;
-
- if (i2c_delay) {
- return tmc_i2c_delay_rw_op(adap, rw, mux, addr, offset,
- len, i2c_delay, buf);
- } else {
- return tmc_i2c_none_delay_rw_op(adap, rw, mux, addr, offset,
- len, buf);
- }
-}
-
-static int tmc_i2c_calc_entries(int msglen)
-{
- int entries = msglen / TMC_I2C_TRANS_LEN;
-
- return (entries += (msglen % TMC_I2C_TRANS_LEN) ? 1 : 0);
-}
-
-static int tmc_i2c_block_read(struct i2c_adapter *adap,
- struct i2c_msg *msgs, int num)
-{
- struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
- struct device *dev = &adap->dev;
- int curmsg, entries, len;
- int offset = 0;
- struct i2c_msg *msg;
- int err, n = 0;
- u8 rwbuf[4] = {0};
-
- dev_dbg(dev, "Read i2c Block\n");
-
- for (curmsg = 0, offset = 0; curmsg < num; curmsg++) {
- msg = &msgs[curmsg];
- len = msg->len;
-
- if (msg->flags & I2C_M_RECV_LEN)
- len = (I2C_SMBUS_BLOCK_MAX + 1);
-
- entries = tmc_i2c_calc_entries(len);
-
- if (msg->flags & I2C_M_RD) {
- if (curmsg == 1 && ((msg->flags & I2C_M_RECV_LEN &&
- !(msgs[0].flags & I2C_M_RD)) ||
- (msg->len > TMC_I2C_TRANS_LEN))) {
- offset = msgs[0].buf[0];
- }
-
- while (entries) {
- err = tmc_i2c_rw_op(adap, TMC_I2C_READ,
- tadap->mux_select,
- msgs[0].addr, offset,
- TMC_I2C_TRANS_LEN, rwbuf);
- if (err < 0)
- return err;
- msg = &msgs[num - 1];
- msg->buf[n] = rwbuf[0];
- msg->buf[n+1] = rwbuf[1];
- n = n + TMC_I2C_TRANS_LEN;
- offset = offset + TMC_I2C_TRANS_LEN;
- entries--;
- }
- }
- }
-
- return 0;
-}
-
-/*
- *TMC I2C SMB Read opertion
- */
-static int tmc_i2c_smb_block_read_op(struct i2c_adapter *adap, u8 rw, u32 mux,
- u32 addr, u32 offset, u32 len, u8 *buf)
-{
- struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
- int err, i = 0;
- u32 control = 0, data = 0;
- u32 start_add;
-
- err = tmc_i2c_mstr_wait_rdy(adap, rw, 0);
- if (err < 0) {
- tmc_i2c_reset_master(adap);
- return err;
- }
-
- TMC_I2C_STAT_INC(tadap, mstr_rdy);
-
- /* initialize the start address and mux */
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_DPMEM_OFFSET));
-
- tmc_iowrite(mux, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_0));
- tmc_iowrite(0x84400000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_4));
-
-
- /* prepare control command */
- control |= TMC_I2C_CTRL_DEVADDR(addr);
- control |= TMC_I2C_CTRL_OFFSET(offset);
-
- /* read */
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8));
- control |= TMC_I2C_CTRL_RDCNT(len);;
- control |= rd_index_to_oper[6];
-
- tadap->control = control;
-
- /*
- * operation control command
- */
- tmc_iowrite(control, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_C));
-
- /*
- * End commands
- */
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_10));
- tmc_iowrite(0x8E000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_14));
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_18));
- tmc_iowrite(0x8F000000, TMC_I2C_MSTR_I2C_DPMEM(tadap,
- TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_1C));
-
- tadap->done = false;
-
- /* fire the transaction */
- tmc_iowrite(0x00000001, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
-
- TMC_I2C_STAT_INC(tadap, go);
-
- /*
- * read a block of data
- */
- start_add = TMC_I2C_MSTR_I2C_DPMEM_ENTRY_OFFSET_8;
- while (len > 0) {
- usleep_range(10000, 12000);
- data = ioread32(TMC_I2C_MSTR_I2C_DPMEM(tadap, start_add));
- buf[i] = data & 0xff;
- buf[i + 1] = (data >> 8) & 0xff;
- start_add = start_add + 8;
- i = i + 2;
- len = len - 2;
-
- TMC_I2C_STAT_INC(tadap, rd_cnt);
- }
-
- /* stop the transaction */
- tmc_iowrite(0x00000000, TMC_I2C_MSTR_AUTOMATION_I2C(tadap,
- TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET));
-
- return 0;
-}
-
-static int tmc_i2c_smb_block_read(struct i2c_adapter *adap,
- struct i2c_msg *msgs, int num)
-{
- struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
- int curmsg, len;
- int offset = 0;
- struct i2c_msg *msg;
- int err, i = 0;
- u8 rwbuf[32] = {0};
-
- for (curmsg = 0, offset = 0; curmsg < num; curmsg++) {
- msg = &msgs[curmsg];
- len = msg->len;
-
- if (msg->flags & I2C_M_RECV_LEN)
- len = (I2C_SMBUS_BLOCK_MAX + 1);
-
- if (msg->flags & I2C_M_RD) {
- if ((curmsg == 1) && (msg->flags & I2C_M_RECV_LEN) &&
- !(msgs[0].flags & I2C_M_RD)) {
- offset = msgs[0].buf[0];
- }
-
- err = tmc_i2c_smb_block_read_op(adap, TMC_I2C_READ,
- tadap->mux_select,
- msgs[0].addr, offset,
- 32, rwbuf);
- if (err < 0) {
- return err;
- }
- msg = &msgs[num - 1];
- for (i = 0; i < len - 1; i++) {
- msg->buf[i] = rwbuf[i];
- }
- }
- }
-
- return 0;
-}
-
-static int tmc_i2c_mstr_xfer(struct i2c_adapter *adap,
- struct i2c_msg *msgs, int num)
-{
- struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
- struct device *dev = &adap->dev;
- int n, curmsg, len = 0;
- int err = 0;
- struct i2c_msg *msg;
- bool read;
- u8 rwbuf[4] = {0};
-
- dev_dbg(dev, "Num messages -> %d\n", num);
-
- /*
- * Initialize all vars
- */
- tadap->entries = 0;
- tadap->use_block = false;
-
- for (curmsg = 0; curmsg < num; curmsg++) {
- msg = &msgs[curmsg];
- dev_dbg(dev, "[%02d] %d bytes, flag %#02x buf %#02x\n",
- curmsg, msg->len, msg->flags, msg->buf[0]);
- if ((msg->len > TMC_I2C_TRANS_LEN) ||
- ((msg->flags & I2C_M_RD) &&
- (msg->flags & I2C_M_RECV_LEN))) {
- /* If PEC is enabled len will come as 3 for a word read.
- * We don't want to use block read for this case.
- */
- if ((msg->flags & I2C_CLIENT_PEC) &&
- (msg->len == TMC_I2C_TRANS_LEN+1)) {
- tadap->use_block = false;
- } else {
- tadap->use_block = true;
- }
- break;
- }
- }
-
- if (tadap->use_block) {
- /* Read Block */
- if ((msg->flags & I2C_M_RD) && (msg->flags & I2C_M_RECV_LEN)) {
- err = tmc_i2c_smb_block_read(adap, msgs, num);
- } else {
- err = tmc_i2c_block_read(adap, msgs, num);
- }
- if (err < 0)
- return err;
- } else {
- read = msgs[num - 1].flags & I2C_M_RD;
- for (curmsg = 0; curmsg < num; curmsg++) {
- msg = &msgs[curmsg];
- len = msg->len;
-
- dev_dbg(dev, " [%02d] %s %d bytes addr %#02x, "
- "flag %#02x, buf[0] %#02x\n", curmsg,
- read ? "RD" : "WR", len, msg->addr,
- msg->flags, msg->buf[0]);
-
- /* SMBus quick read/write command */
- if (len == 0 && curmsg == 0 && num == 1) {
- if (read) {
- len = 1;
- }
- break;
- }
-
- if (curmsg == 0) {
- if (!read) {
- for (n = 1; n < len; n++)
- rwbuf[n-1] = (msg->buf[n]);
- len--;
- } else {
- /* read operation */
- continue;
- }
- }
- }
-
- if (!read) {
- /* write */
- err = tmc_i2c_rw_op(adap, TMC_I2C_WRITE,
- tadap->mux_select, msgs[0].addr,
- msgs[0].buf[0], len, rwbuf);
- } else {
- /* read */
- /*
- * If PEC is enabled read only 2 bytes as expected in
- * case of a word read instead of 3 to make it compatible
- * with word write implementation.
- */
- if (msg->flags & I2C_CLIENT_PEC && (len == TMC_I2C_TRANS_LEN + 1)) {
- len--;
- }
-
- err = tmc_i2c_rw_op(adap, TMC_I2C_READ,
- tadap->mux_select,
- msgs[0].addr, msgs[0].buf[0],
- len, rwbuf);
- msg = &msgs[num - 1];
- len = msg->len;
- /*
- * To avoid failure in PEC enabled case clear flag.
- */
- if (len == TMC_I2C_TRANS_LEN + 1) {
- msgs[num - 1].flags &= ~I2C_M_RD;
- }
- for (n = 0; n < len; n++)
- msg->buf[n] = rwbuf[n];
- }
- if (err < 0)
- return err;
- }
-
- TMC_I2C_STAT_INCN(tadap, msg_cnt, num);
-
- return num;
-}
-
-static u32 tmc_i2c_func(struct i2c_adapter *adap)
-{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
- | I2C_FUNC_SMBUS_READ_BLOCK_DATA;
-}
-
-static const struct i2c_algorithm tmc_i2c_algo = {
- .master_xfer = tmc_i2c_mstr_xfer,
- .functionality = tmc_i2c_func,
-};
-
-static int tmc_i2c_mux_group_sel(struct i2c_mux_core *muxc, u32 chan)
-{
- struct tmc_i2c_adapter *tadap = i2c_mux_priv(muxc);
-
- dev_dbg(muxc->dev, "chan = %d\n", chan);
-
- if (!tadap || chan > TMC_I2C_MSTR_MAX_GROUPS)
- return -ENODEV;
- tadap->mux_select = chan;
-
- return 0;
-}
-
-static int tmc_i2c_mux_init(struct i2c_adapter *adap)
-{
- struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
- int chan, ret;
-
- tadap->muxc = i2c_mux_alloc(adap, &adap->dev, tadap->mux_channels,
- 0, 0, tmc_i2c_mux_group_sel, NULL);
-
- if (!tadap->muxc)
- return -ENOMEM;
-
- tadap->muxc->priv = tadap;
- for (chan = 0; chan < tadap->mux_channels; chan++) {
- ret = i2c_mux_add_adapter(tadap->muxc, 0, chan, 0);
- if (ret) {
- dev_err(&adap->dev, "Failed to add adapter %d\n", chan);
- i2c_mux_del_adapters(tadap->muxc);
- return ret;
- }
- }
-
- return 0;
-}
-
-static struct i2c_adapter *
-tmc_i2c_init_one(struct tmc_i2c_ctrl *tmc,
- int master, int id)
-{
- struct tmc_i2c_adapter *adapter;
- struct device *dev = tmc->dev;
- int err;
-
- adapter = devm_kzalloc(dev, sizeof(*adapter), GFP_KERNEL);
- if (!adapter)
- return ERR_PTR(-ENOMEM);
-
- init_waitqueue_head(&adapter->wait);
- adapter->adap.owner = THIS_MODULE;
- adapter->adap.algo = &tmc_i2c_algo;
- adapter->adap.nr = -1;
- adapter->adap.timeout = HZ / 5;
- adapter->master = master;
- adapter->mux_channels = tmc->mux_channels;
- adapter->i2c_delay = tmc->i2c_delay;
- adapter->membase = tmc->membase;
- adapter->dpmbase = tmc->dpmbase;
- adapter->polling = 1;
- adapter->tctrl = tmc;
-
- i2c_set_adapdata(&adapter->adap, adapter);
- snprintf(adapter->adap.name, sizeof(adapter->adap.name),
- "%s:%d", dev_name(dev), master);
-
- adapter->adap.dev.parent = dev;
- err = i2c_add_numbered_adapter(&adapter->adap);
- if (err)
- goto error;
-
- err = tmc_i2c_mux_init(&adapter->adap);
- if (err)
- goto err_remove;
-
- dev_dbg(dev, "Adapter[%02d-%02d]: "
- "dpmbase: 0x%lx\n", id, master,
- (unsigned long)adapter->dpmbase);
- return &adapter->adap;
-
-err_remove:
- i2c_del_adapter(&adapter->adap);
-error:
- return ERR_PTR(err);
-}
-
-static void tmc_i2c_cleanup_one(struct i2c_adapter *adap)
-{
- struct tmc_i2c_adapter *tadap = i2c_get_adapdata(adap);
-
- i2c_mux_del_adapters(tadap->muxc);
- i2c_del_adapter(adap);
-
-}
-
-
-static int tmc_i2c_of_init(struct device *dev,
- struct tmc_i2c_ctrl *tmc, int id)
-{
- u32 mux_channels, master, num_masters = 0, master_mask = 0;
- u32 i2c_delay = 0;
-
- if (!(master_mask & BIT(master)))
- num_masters++;
- master_mask |= BIT(master);
-
- if (id == 0) {
- /* chassisd */
- mux_channels = chd_channel;
- num_masters = 1;
- i2c_delay = 0;
- } else if (id == 1) {
- /* pfe */
- mux_channels = pfe_channel;
- num_masters = 1;
- i2c_delay = 20;
- } else {
- return -EINVAL;
- }
-
- tmc->adap = devm_kcalloc(dev, num_masters,
- sizeof(struct i2c_adapter *),
- GFP_KERNEL);
- if (!tmc->adap)
- return -ENOMEM;
-
- tmc->num_masters = num_masters;
- tmc->master_mask = master_mask;
- tmc->mux_channels = mux_channels;
- tmc->i2c_delay = i2c_delay;
-
- return 0;
-}
-
-static int tmc_i2c_probe(struct platform_device *pdev)
-{
- int i, n, err;
- struct resource *res;
- struct i2c_adapter *adap;
- struct device *dev = &pdev->dev;
- struct tmc_i2c_ctrl *tmc;
-
- const struct mfd_cell *cell = mfd_get_cell(pdev);
-
- /*
- * Allocate memory for the Tmc FPGA
- */
- tmc = devm_kzalloc(dev, sizeof(*tmc), GFP_KERNEL);
- if (!tmc)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, tmc);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
- dev_info(dev, "Tmc I2C Accel resource 0x%llx, %llu\n",
- res->start, resource_size(res));
-
- tmc->membase = devm_ioremap_nocache(dev, res->start,
- resource_size(res));
- if (!tmc->membase)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!res)
- return -ENODEV;
-
- dev_info(dev, "Tmc I2C Mem resource 0x%llx, %llu\n",
- res->start, resource_size(res));
-
- tmc->dpmbase = devm_ioremap_nocache(dev, res->start,
- resource_size(res));
- if (!tmc->dpmbase)
- return -ENOMEM;
-
- tmc->dev = dev;
- spin_lock_init(&tmc->lock);
-
- err = tmc_i2c_of_init(dev, tmc, cell->id);
- if (err)
- return err;
-
- dev_info(dev, "Tmc I2C Masters: %d\n", tmc->num_masters);
- dev_info(dev, "Tmc I2C Delay: %d\n", tmc->i2c_delay);
-
- for (n = 0, i = 0; i < TMC_I2C_MASTER_NR_MSTRS; i++) {
- if (tmc->master_mask & BIT(i)) {
- adap = tmc_i2c_init_one(tmc, i, n);
- if (IS_ERR(adap)) {
- err = PTR_ERR(adap);
- dev_err(dev, "Failed to initialize master "
- "adapter %d: %d\n", i, err);
- goto err_remove;
- }
- tmc->adap[n++] = adap;
- }
- }
-
- return 0;
-
-err_remove:
- for (n--; n >= 0; n--)
- tmc_i2c_cleanup_one(tmc->adap[n]);
- return err;
-}
-
-static int tmc_i2c_remove(struct platform_device *pdev)
-{
- struct tmc_i2c_ctrl *tmc = platform_get_drvdata(pdev);
- int i;
-
- /* Disable all masters */
- tmc_iowrite(0, tmc->membase + TMC_I2C_MSTR_AUTOMATION_I2C_SCAN_OFFSET);
-
- for (i = 0; i < tmc->num_masters; i++)
- tmc_i2c_cleanup_one(tmc->adap[i]);
-
- return 0;
-}
-
-static struct platform_driver tmc_i2c_driver = {
- .driver = {
- .name = "i2c-tmc",
- .owner = THIS_MODULE,
- },
- .probe = tmc_i2c_probe,
- .remove = tmc_i2c_remove,
-};
-
-module_platform_driver(tmc_i2c_driver);
-
-MODULE_DESCRIPTION("Juniper Networks TMC FPGA I2C Accelerator driver");
-MODULE_AUTHOR("Ashish Bhensdadia ");
-MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/i2c-tmc.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/i2c-tmc.c
new file mode 120000
index 0000000000..6fc8e5f3b4
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/i2c-tmc.c
@@ -0,0 +1 @@
+../../common/modules/i2c-tmc.c
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-refpga-tmc.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-refpga-tmc.c
deleted file mode 100644
index ef36bca72e..0000000000
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-refpga-tmc.c
+++ /dev/null
@@ -1,603 +0,0 @@
-/*
- * Juniper Networks RE-FPGA qfx platform specific driver
- *
- * Copyright (C) 2020 Juniper Networks
- * Author: Ciju Rajan K
- *
- * This driver implements various features such as
- * - ALARM led driver
- * - Fan full speed reset control
- * - FAN precense detection
- * - FAN type detection
- * - Any new QFX specific features which uses RE-FPGA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#define NUM_LEDS 7 /* Max number of Alarm + FAN LEDs */
-
-#define ALARM_MINOR_LED 0
-#define ALARM_MAJOR_LED 1
-
-#define REFPGA_PCIE_RESET_CTRL 0x13
-#define REFPGA_PCIE_ALARM 0x33
-#define REFPGA_FAN0_CTRL_STAT 0x28
-
-#define REFPGA_RESET_FAN_SPEED BIT(3)
-#define REFPGA_OPER_TYPE BIT(0)
-#define REFPGA_OPER_START BIT(1)
-#define REFPGA_OPER_DONE BIT(2)
-
-#define TMC_REFPGA_ADDR_REG 0x0 /* TMC offset: 0x228 */
-#define TMC_REFPGA_DATA_REG 0x4 /* TMC offset: 0x22C */
-#define TMC_REFPGA_CTRL_REG 0x8 /* TMC offset: 0x230 */
-
-#define TMC_REFPGA_READ_CMD 0x3
-#define TMC_REFPGA_WRITE_CMD 0x2
-
-#define REFPGA_INTR_NR_GROUPS 1
-#define REFPGA_INTR_MAX_IRQS_PG 32
-
-#define MAX_FANS 5
-
-#define REFPGA_IRQ_MAX_BITS_PER_REG 32
-
-#define POLL_INTERVAL 5000
-
-#define AFI_MASK (0x01)
-#define AFO_MASK (0x02)
-#define AFI_AFO_MASK (0x03)
-/*
- * LED specific data structures
- */
-struct refpga_led {
- struct led_classdev lc;
- struct work_struct work;
- int blink;
- int on;
- int bit;
- void __iomem *addr;
-};
-
-struct refpga_led_data {
- int num_leds;
- struct refpga_led *leds;
-};
-
-static DEFINE_MUTEX(alarm_led_lock);
-
-/*
- * Common routines
- */
-struct refpga_chip {
- struct refpga_led_data *led;
-};
-
-static struct refpga_chip *refpga;
-
-static DEFINE_MUTEX(refpga_lock);
-
-static void __iomem *tmc_membase;
-
-static void wait_for_refpga_oper(void __iomem *base_addr)
-{
- volatile u32 done = ~(-1);
- unsigned long int timeout;
- void __iomem *addr;
-
- addr = base_addr + (TMC_REFPGA_CTRL_REG);
- /*
- * Wait till the transaction is complete
- */
- timeout = jiffies + msecs_to_jiffies(100);
-
- do {
- usleep_range(50, 100);
- done = ioread32(addr);
- if (done & (REFPGA_OPER_DONE))
- break;
- } while(time_before(jiffies, timeout));
-}
-static u32 refpga_read(void __iomem *base_addr, u32 refpga_offset)
-{
- u32 value;
-
- mutex_lock(&refpga_lock);
- iowrite32(refpga_offset, base_addr + (TMC_REFPGA_ADDR_REG));
- iowrite32(TMC_REFPGA_READ_CMD, base_addr + (TMC_REFPGA_CTRL_REG));
- wait_for_refpga_oper(base_addr);
- value = ioread32(base_addr + (TMC_REFPGA_DATA_REG));
- mutex_unlock(&refpga_lock);
-
- return value;
-}
-
-static void refpga_write(void __iomem *base_addr, u32 refpga_offset, u32 val)
-{
- mutex_lock(&refpga_lock);
- iowrite32(refpga_offset, base_addr + (TMC_REFPGA_ADDR_REG));
- iowrite32(val, base_addr + (TMC_REFPGA_DATA_REG));
- iowrite32(TMC_REFPGA_WRITE_CMD, base_addr + (TMC_REFPGA_CTRL_REG));
- wait_for_refpga_oper(base_addr);
- mutex_unlock(&refpga_lock);
-}
-
-static bool get_fan_presense(u8 idx)
-{
- u8 value = 0x00;
- u8 offset = REFPGA_FAN0_CTRL_STAT;
- bool ret = 0;
-
- value = refpga_read(tmc_membase, (offset + (idx * 2)));
- /*
- * Get the last two bits of REFPGA_FANx_CTRL_STAT.
- * REFPGA_FANx_CTRL_STAT register of REFPGA gives the fan airflow
- * status. There are 5 fans in QFX5200. Last two bits give the AFI
- * & AFO status. If any of these bits are set, fan is present.
- */
- value = (value & BIT(0)) | (value & BIT(1));
- if (value)
- ret = 1;
-
- return ret;
-}
-
-static int get_fan_type(u8 idx)
-{
- u8 value = 0x00;
- u8 offset = REFPGA_FAN0_CTRL_STAT;
- int ret = -1;
-
- value = refpga_read(tmc_membase, (offset + (idx * 2)));
- /*
- * Get the last two bits of REFPGA_FANx_CTRL_STAT.
- * REFPGA_FANx_CTRL_STAT register of REFPGA gives the fan airflow
- * status. There are 5 fans in QFX5200. Last two bits give the AFI
- * & AFO status. If bit1 is set, it's AFO and if bit 0 is set,
- * it's AFI.
- *
- * This function will return '1' for AFO, '0' for AFI, and '-1'
- * if there is no fan or if both AFI & AFO bits are set.
- */
- value &= AFI_AFO_MASK;
-
- switch(value) {
- case AFI_MASK:
- ret = 0;
- break;
- case AFO_MASK:
- ret = 1;
- break;
- default:
- ret = -1;
- break;
- };
-
- return ret;
-}
-
-enum sysfs_fan_attributes {
- FAN0_PRESENT,
- FAN1_PRESENT,
- FAN2_PRESENT,
- FAN3_PRESENT,
- FAN4_PRESENT,
-};
-
-enum sysfs_fan_type_attributes {
- FAN0_TYPE,
- FAN1_TYPE,
- FAN2_TYPE,
- FAN3_TYPE,
- FAN4_TYPE,
-};
-
-/*
- * The sysfs files will be present in this path
- * /sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/refpga-tmc.15/fan*_present
- * /sys/devices/pci0000:00/0000:00:1c.0/0000:0f:00.0/refpga-tmc.15/fan*_type
- */
-
-#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \
- static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, refpga_fan_presense_show, NULL, FAN##index##_PRESENT)
-#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr
-
-#define DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(index) \
- static SENSOR_DEVICE_ATTR(fan##index##_type, S_IRUGO, refpga_fan_type_show, NULL, FAN##index##_TYPE)
-#define DECLARE_FAN_TYPE_ATTR(index) &sensor_dev_attr_fan##index##_type.dev_attr.attr
-
-static ssize_t refpga_fan_presense_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct sensor_device_attribute *s_attr = to_sensor_dev_attr(attr);
-
- return sprintf(buf, "%d\n", get_fan_presense(s_attr->index));
-
-}
-
-static ssize_t refpga_fan_type_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct sensor_device_attribute *s_attr = to_sensor_dev_attr(attr);
-
- return sprintf(buf, "%d\n", get_fan_type(s_attr->index));
-
-}
-
-DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(0);
-DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1);
-DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2);
-DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3);
-DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4);
-
-DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(0);
-DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(1);
-DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(2);
-DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(3);
-DECLARE_FAN_TYPE_SENSOR_DEV_ATTR(4);
-
-static struct attribute *refpga_fan_attrs[] = {
- DECLARE_FAN_PRESENT_ATTR(0),
- DECLARE_FAN_PRESENT_ATTR(1),
- DECLARE_FAN_PRESENT_ATTR(2),
- DECLARE_FAN_PRESENT_ATTR(3),
- DECLARE_FAN_PRESENT_ATTR(4),
- DECLARE_FAN_TYPE_ATTR(0),
- DECLARE_FAN_TYPE_ATTR(1),
- DECLARE_FAN_TYPE_ATTR(2),
- DECLARE_FAN_TYPE_ATTR(3),
- DECLARE_FAN_TYPE_ATTR(4),
- NULL
-};
-
-static struct attribute_group refpga_fan_attr_group = {
- .attrs = refpga_fan_attrs,
-};
-
-/*
- * There is only a single ALARM led in QFX5200 and that
- * is used for both Major & Minor alarm indicator.
- * These are represented by two different bits in RE-FPGA
- * PCIE_ALARM register. Only one of the bit (either Red or
- * Yellow) should be set a time. If both the bits are set,
- * it's an undefined behaviour.
- *
- * The following table describes how the conditions are
- * handled in the driver as there can be both Major & Minor
- * alarms can be triggered from userspace.
- *
- * Major Minor Colour
- *
- * 0 0 Nil
- * 0 1 Yellow
- * 1 1 Red
- * 1 0 Red
- *
- */
-static void manage_alarm_led(void __iomem *addr, int led_type, int value)
-{
- static int alarm_major = 0, alarm_minor = 0;
- u32 reg = 0x0;
-
- mutex_lock(&alarm_led_lock);
- reg = refpga_read(addr, REFPGA_PCIE_ALARM);
-
- (led_type == ALARM_MAJOR_LED) ?
- ((value == 1) ? (alarm_major = 1) : (alarm_major = 0)) :
- ((value == 1) ? (alarm_minor = 1) : (alarm_minor = 0));
- if (alarm_major) {
- reg &= ~BIT(ALARM_MINOR_LED);
- reg |= BIT(ALARM_MAJOR_LED);
- } else {
- if (alarm_minor) {
- reg &= ~BIT(ALARM_MAJOR_LED);
- reg |= BIT(ALARM_MINOR_LED);
- } else {
- reg &= ~BIT(ALARM_MINOR_LED);
- reg &= ~BIT(ALARM_MAJOR_LED);
- }
- }
- refpga_write(addr, REFPGA_PCIE_ALARM, reg);
- mutex_unlock(&alarm_led_lock);
-}
-
-static void manage_fan_led(void __iomem *addr, int fan_slot, int value)
-{
- u8 offset = REFPGA_FAN0_CTRL_STAT + (fan_slot * 2);
- u32 reg = 0x0;
-
- reg = refpga_read(addr, offset);
- if(value) {
- /* Turn on s/w control */
- reg = reg | BIT(4);
- /* Turn off green led */
- reg &= ~BIT(5);
- /* Turn on yellow led & make it blink */
- reg |= (BIT(6) | BIT(7));
- } else {
- /* Clear yellow led & stop blink */
- reg &= ~(BIT(6) | BIT(7));
- /* Stop s/w control */
- reg &= ~BIT(4);
- }
- refpga_write(addr, offset, reg);
-}
-
-static void refpga_led_work(struct work_struct *work)
-{
- struct refpga_led *led = container_of(work, struct refpga_led, work);
- void __iomem *addr;
-
- addr = led->addr;
-
- if(strstr(led->lc.name, "fan"))
- manage_fan_led(addr, led->bit, led->on);
- else
- manage_alarm_led(addr, led->bit, led->on);
-}
-
-static void refpga_led_brightness_set(struct led_classdev *lc,
- enum led_brightness brightness)
-{
- struct refpga_led *led = container_of(lc, struct refpga_led, lc);
-
- led->on = (brightness != LED_OFF);
- led->blink = 0; /* always turn off hw blink on brightness_set() */
- schedule_work(&led->work);
-}
-
-struct led_table
-{
- const char *name;
- int reg;
-};
-
-static struct led_table qfx5200_led_data[] = {
- {
- .name = "alarm-minor",
- .reg = 0,
- },
- {
- .name = "alarm-major",
- .reg = 1,
- },
- {
- .name = "fan0-fault",
- .reg = 0,
- },
- {
- .name = "fan1-fault",
- .reg = 1,
- },
- {
- .name = "fan2-fault",
- .reg = 2,
- },
- {
- .name = "fan3-fault",
- .reg = 3,
- },
- {
- .name = "fan4-fault",
- .reg = 4,
- }
-};
-
-static int refpga_led_init_one(struct device *dev,
- struct refpga_led_data *ild,
- int num)
-{
- struct refpga_led *led;
- int ret = 0;
-
- led = &ild->leds[num];
- led->addr = tmc_membase;
-
- led->lc.name = qfx5200_led_data[num].name;
- led->bit = qfx5200_led_data[num].reg;
- led->lc.brightness = LED_OFF;
- led->lc.brightness_set = refpga_led_brightness_set;
-
- ret = devm_led_classdev_register(dev, &led->lc);
- if (ret) {
- dev_err(dev, "devm_led_classdev_register failed\n");
- return ret;
- }
-
- INIT_WORK(&led->work, refpga_led_work);
-
- return 0;
-}
-
-static int refpga_led_qfx5200_init(struct device *dev, struct refpga_led_data *ild)
-{
- int ret = 0, idx = 0;
-
-
- if (!dev->parent) {
- dev_err(dev, "dev->parent is null\n");
- return -ENODEV;
- }
-
- ild->num_leds = NUM_LEDS;
- ild->leds = devm_kzalloc(dev, sizeof(struct refpga_led) * NUM_LEDS,
- GFP_KERNEL);
- if (!ild->leds) {
- dev_err(dev, "LED allocation failed\n");
- return -ENOMEM;
- }
-
- for(idx=0; idxdev;
- struct refpga_led_data *ild;
- int ret;
-
- ild = devm_kzalloc(dev, sizeof(*ild), GFP_KERNEL);
- if (!ild) {
- dev_err(dev, "ild allocation failed\n");
- return -ENOMEM;
- }
-
- ret = refpga_led_qfx5200_init(dev, ild);
- if (ret < 0)
- return ret;
-
- refpga->led = ild;
-
- return 0;
-}
-
-static int jnx_refpga_led_remove(struct platform_device *pdev)
-{
- struct refpga_chip *drv_data = platform_get_drvdata(pdev);
- struct refpga_led_data *ild = drv_data->led;
- int i;
-
- for (i = 0; i < ild->num_leds; i++) {
- devm_led_classdev_unregister(&pdev->dev, &ild->leds[i].lc);
- cancel_work_sync(&ild->leds[i].work);
- }
- if (ild) {
- if (ild->leds)
- devm_kfree(&pdev->dev, ild->leds);
- devm_kfree(&pdev->dev, ild);
- }
- return 0;
-}
-
-static void reset_fan_full_speed(struct device *dev)
-{
- u32 val = ~(-1), tmp = ~(-1);
-
- /*
- * Reading the REFPGA_PCIE_RESET_CTRL register
- */
- val = refpga_read(tmc_membase, REFPGA_PCIE_RESET_CTRL);
- /*
- * Clearing the fan full_speed bit
- */
- val &= ~(REFPGA_RESET_FAN_SPEED);
- /*
- * Writing the REFPGA_PCIE_RESET_CTRL register
- */
- refpga_write(tmc_membase, REFPGA_PCIE_RESET_CTRL, val);
- /*
- * Reading the REFPGA_PCIE_RESET_CTRL register
- */
- tmp = refpga_read(tmc_membase, REFPGA_PCIE_RESET_CTRL);
- dev_info(dev, "After resetting fan full speed control: %X\n", tmp);
-}
-
-static int jnx_refpga_tmc_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct resource *res;
- int ret = 0;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(dev, "resource allocation failed\n");
- return -ENODEV;
- }
-
- tmc_membase = devm_ioremap_nocache(dev, res->start, resource_size(res));
- if (!tmc_membase) {
- dev_err(dev, "ioremap failed\n");
- return -ENOMEM;
- }
-
- refpga = devm_kzalloc(dev, sizeof(*refpga), GFP_KERNEL);
- if (!refpga) {
- dev_err(dev, "refpga memory allocation failed\n");
- return -ENOMEM;
- }
-
- reset_fan_full_speed(dev);
-
- ret = jnx_refpga_led_probe(pdev);
- if (ret != 0) {
- dev_err(dev, "Refpga LED probe failed\n");
- return ret;
- }
-
- dev_info(dev, "Refpga LED probe successful: TMC memoy base: %p\n",
- tmc_membase);
-
- ret = sysfs_create_group(&dev->kobj, &refpga_fan_attr_group);
- if (ret != 0) {
- dev_err(dev, "sysfs_create_group failed: %d\n", ret);
- return ret;
- }
-
- platform_set_drvdata(pdev, refpga);
-
- return 0;
-}
-
-static int jnx_refpga_tmc_remove(struct platform_device *pdev)
-{
- jnx_refpga_led_remove(pdev);
- sysfs_remove_group(&pdev->dev.kobj, &refpga_fan_attr_group);
-
- return 0;
-}
-
-static struct platform_driver jnx_refpga_tmc_driver = {
- .driver = {
- .name = "refpga-tmc",
- .owner = THIS_MODULE,
- },
- .probe = jnx_refpga_tmc_probe,
- .remove = jnx_refpga_tmc_remove,
-};
-
-static int __init jnx_refpga_tmc_driver_init(void)
-{
- int ret = -1;
-
- ret = platform_driver_register(&jnx_refpga_tmc_driver);
-
- return ret;
-
-}
-
-static void __exit jnx_refpga_tmc_driver_exit(void)
-{
- platform_driver_unregister(&jnx_refpga_tmc_driver);
-}
-
-module_init(jnx_refpga_tmc_driver_init);
-module_exit(jnx_refpga_tmc_driver_exit);
-
-MODULE_DESCRIPTION("Juniper Networks REFPGA / TMC driver");
-MODULE_AUTHOR("Ciju Rajan K ");
-MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-refpga-tmc.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-refpga-tmc.c
new file mode 120000
index 0000000000..355eda2afd
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-refpga-tmc.c
@@ -0,0 +1 @@
+../../common/modules/jnx-refpga-tmc.c
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc-core.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc-core.c
deleted file mode 100644
index 833164bfed..0000000000
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc-core.c
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- * Juniper Networks TMC-FPGA MFD Core driver for qfx platform
- *
- * Copyright (c) 2020, Juniper Networks
- * Author: Ashish Bhensdadia
- *
- * This driver implement the resource publish for below devices
- * - I2C
- * - GPIO
- * - RE FPGA
- * - PSU
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "jnx-tmc.h"
-
-#define TMC_DO_SCRATCH_TEST 1
-
-/*
- * TMC FPGA Device IDs
- */
-#define PCI_VENDOR_ID_JUNIPER 0x1304
-
-#define PCI_DEVICE_ID_JNX_TMC_CHD 0x007B
-#define PCI_DEVICE_ID_JNX_TMC_PFE 0x007C
-
-/*
- * TMC resources
- */
-static struct resource tmc_resource_i2c[] = {
- /* I2C AUTOMATION Block */
- {
- .name = "i2c-tmc",
- .start = TMC_I2C_AUTOMATION_I2C_CONTROL_START,
- .end = TMC_I2C_AUTOMATION_I2C_CONTROL_END,
- .flags = IORESOURCE_MEM,
- },
-
- /* I2C DPMEM */
- {
- .name = "i2c-tmc-mem",
- .start = TMC_I2C_DPMEM_ENTRY_START,
- .end = TMC_I2C_DPMEM_ENTRY_END,
- .flags = IORESOURCE_MEM,
- },
-};
-
-#define TMC_RES_I2C_NR ARRAY_SIZE(tmc_resource_i2c)
-
-/*
- * LED resources
- */
-static struct resource tmc_resource_leds[] = {
- {
- .name = "leds-tmc",
- .start = TMC_LED_CONTROL_START,
- .end = TMC_LED_CONTROL_END,
- .flags = IORESOURCE_MEM,
- },
-};
-
-#define TMC_RES_LEDS_NR ARRAY_SIZE(tmc_resource_leds)
-
-/*
- * TMC RE-FPGA devices
- */
-static struct resource tmc_resource_refpga[] = {
- {
- .name = "refpga-tmc",
- .start = TMC_REFPGA_ACCESS_START,
- .end = TMC_REFPGA_ACCESS_END,
- .flags = IORESOURCE_MEM,
- },
-};
-
-#define TMC_RES_REFPGA_NR ARRAY_SIZE(tmc_resource_refpga)
-
-static struct resource tmc_resource_gpioslave0[] = {
- /* SLAVE0 Block */
- {
- .name = "gpioslave-tmc",
- .start = TMC_GPIO_SLAVE0_START,
- .end = TMC_GPIO_SLAVE0_END,
- .flags = IORESOURCE_MEM,
- }
-};
-
-#define TMC_RES_GPIOSLAVE0_NR ARRAY_SIZE(tmc_resource_gpioslave0)
-
-static struct resource tmc_resource_gpioslave1[] = {
- /* SLAVE1 Block */
- {
- .name = "gpioslave-tmc",
- .start = TMC_GPIO_SLAVE1_START,
- .end = TMC_GPIO_SLAVE1_END,
- .flags = IORESOURCE_MEM,
- }
-};
-
-#define TMC_RES_GPIOSLAVE1_NR ARRAY_SIZE(tmc_resource_gpioslave1)
-
-static struct resource tmc_resource_psu[] = {
- /* PSU Block */
- {
- .name = "psu-tmc",
- .start = TMC_PSU_START,
- .end = TMC_PSU_END,
- .flags = IORESOURCE_MEM,
- }
-};
-
-#define TMC_RES_PSU_NR ARRAY_SIZE(tmc_resource_psu)
-
-/*
- * CHASSISD TMC MFD devices
- */
-static struct mfd_cell chassisd_tmc_mfd_devs[] = {
- {
- .name = "i2c-tmc",
- .num_resources = ARRAY_SIZE(tmc_resource_i2c),
- .resources = &tmc_resource_i2c[0],
- .of_compatible = "jnx,i2c-tmc",
- .id = 0,
- },
- {
- .name = "leds-tmc",
- .num_resources = ARRAY_SIZE(tmc_resource_leds),
- .resources = &tmc_resource_leds[0],
- .of_compatible = "jnx,leds-tmc",
- .id = 0,
- },
- {
- .name = "refpga-tmc",
- .num_resources = ARRAY_SIZE(tmc_resource_refpga),
- .resources = &tmc_resource_refpga[0],
- .of_compatible = "jnx,refpga-tmc",
- .id = 0,
- },
- {
- .name = "psu-tmc",
- .num_resources = ARRAY_SIZE(tmc_resource_psu),
- .resources = &tmc_resource_psu[0],
- .of_compatible = "jnx,psu-tmc",
- .id = 0,
- },
-};
-
-/*
- * PFE TMC MFD devices
- */
-static struct mfd_cell pfe_tmc_mfd_devs[] = {
- {
- .name = "i2c-tmc",
- .num_resources = ARRAY_SIZE(tmc_resource_i2c),
- .resources = &tmc_resource_i2c[0],
- .of_compatible = "jnx,i2c-tmc",
- .id = 1,
- },
- {
- .name = "gpioslave-tmc",
- .num_resources = ARRAY_SIZE(tmc_resource_gpioslave0),
- .resources = &tmc_resource_gpioslave0[0],
- .of_compatible = "jnx,gpioslave-tmc",
- .id = 0,
- },
- {
- .name = "gpioslave-tmc",
- .num_resources = ARRAY_SIZE(tmc_resource_gpioslave1),
- .resources = &tmc_resource_gpioslave1[0],
- .of_compatible = "jnx,gpioslave-tmc",
- .id = 1,
- },
-};
-
-
-struct tmc_fpga_data {
- void __iomem *membase;
- struct pci_dev *pdev;
-
- u32 major; /* Device id & Major version*/
- u32 minor; /* Minor version */
-
- u32 optic_cpld_major; /* optic cpld major version */
- u32 optic_cpld_minor; /* optic cpld minor version */
- u32 optic_cpld_devid; /* optic cpld device id */
-};
-
-/* sysfs entries */
-static ssize_t major_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
-
- return sprintf(buf, "0x%02X_%06X\n",
- (tmc->major >> 24) & 0xff,
- tmc->major & 0xffffff);
-}
-
-static ssize_t minor_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
-
- return sprintf(buf, "%02X\n", (tmc->minor) & 0xff);
-}
-
-static ssize_t optic_cpld_major_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
-
- return sprintf(buf, "%01X\n", tmc->optic_cpld_major & 0xf);
-}
-
-static ssize_t optic_cpld_devid_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
-
- return sprintf(buf, "%01X\n",
- (tmc->optic_cpld_major >> 4) & 0xf);
-}
-
-static ssize_t optic_cpld_minor_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
-
- return sprintf(buf, "%02X\n", tmc->optic_cpld_minor & 0xff);
-}
-
-static ssize_t set_sys_shutdown(struct device *dev,
- struct device_attribute *devattr,
- const char *buf,
- size_t len)
-{
-
- struct tmc_fpga_data *tmc = dev_get_drvdata(dev);
- unsigned long val;
- int ret;
-
- ret = kstrtoul(buf, 0, &val);
- if (ret < 0)
- return ret;
-
- if (val != 1)
- return -EINVAL;
-
- /* Unlock the shutdown register */
- iowrite32(0x12345678, tmc->membase + TMC_SYS_SHUTDOWN_LOCK);
- iowrite32(0x1, tmc->membase + TMC_SYS_SHUTDOWN);
-
- return len;
-}
-
-
-static DEVICE_ATTR(major, S_IRUGO, major_show, NULL);
-static DEVICE_ATTR(minor, S_IRUGO, minor_show, NULL);
-static DEVICE_ATTR(optic_cpld_major, S_IRUGO, optic_cpld_major_show, NULL);
-static DEVICE_ATTR(optic_cpld_devid, S_IRUGO, optic_cpld_devid_show, NULL);
-static DEVICE_ATTR(optic_cpld_minor, S_IRUGO, optic_cpld_minor_show, NULL);
-static DEVICE_ATTR(shutdown, S_IWUSR, NULL, set_sys_shutdown);
-
-static struct attribute *tmc_attrs[] = {
- &dev_attr_major.attr,
- &dev_attr_minor.attr,
- &dev_attr_optic_cpld_major.attr,
- &dev_attr_optic_cpld_devid.attr,
- &dev_attr_optic_cpld_minor.attr,
- &dev_attr_shutdown.attr,
- NULL,
-};
-
-static struct attribute_group tmc_attr_group = {
- .attrs = tmc_attrs,
-};
-
-#if defined TMC_DO_SCRATCH_TEST
-/* Do a quick scratch access test */
-static int tmc_do_test_scratch(struct tmc_fpga_data *tmc)
-{
- struct pci_dev *pdev = tmc->pdev;
- struct device *dev = &pdev->dev;
- int offset = TMC_SCRATCH;
- u32 acc, val = 0xdeadbeaf;
-
- /*
- * Check rw register access -> use the scratch reg.
- */
- iowrite32(val, tmc->membase + offset);
- acc = ioread32(tmc->membase + offset);
- if (acc != val) {
- dev_err(dev, "Tmc scratch(0x%x) failed: %08x.%08x!\n",
- offset, val, acc);
- return -EIO;
- }
-
- for (val = 0; val < 0xf0000000; val += 0x01010101) {
- iowrite32(val, tmc->membase + offset);
- acc = ioread32(tmc->membase + offset);
- if (acc != val) {
- dev_err(dev, "Tmc scratch(0x%x) failed: %08x.%08x!\n",
- offset, val, acc);
- return -EIO;
- }
- }
-
- /*
- * Write a sig before leaving..
- */
- val = 0xcafebabe;
- iowrite32(val, tmc->membase + offset);
- dev_dbg(dev, "Tmc scratch result: 0x%08x\n",
- ioread32(tmc->membase + offset));
-
- return 0;
-}
-#endif /* TMC_DO_SCRATCH_TEST */
-
-static int tmc_fpga_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
-{
- int err;
- struct tmc_fpga_data *tmc;
- struct device *dev = &pdev->dev;
-
- dev_dbg(dev, "Tmc FPGA Probe called\n");
-
- tmc = devm_kzalloc(dev, sizeof(*tmc), GFP_KERNEL);
- if (!tmc)
- return -ENOMEM;
-
- err = pcim_enable_device(pdev);
- if (err) {
- dev_err(&pdev->dev, "Failed to enable device %d\n", err);
- return err;
- }
-
- err = pcim_iomap_regions(pdev, 1 << 0, "tmc-core");
- if (err) {
- dev_err(&pdev->dev, "Failed to iomap regions %d\n", err);
- goto err_disable;
- }
-
- tmc->membase = pcim_iomap_table(pdev)[0];
- if (IS_ERR(tmc->membase)) {
- dev_err(dev, "pci_ioremap_bar() failed\n");
- err = -ENOMEM;
- goto err_release;
- }
-
- tmc->pdev = pdev;
- pci_set_drvdata(pdev, tmc);
-
- /* All Tmc uses MSI interrupts - enable bus mastering */
- pci_set_master(pdev);
-
-#if defined TMC_DO_SCRATCH_TEST
- /* Check IO before proceeding */
- dev_dbg(dev, "Tmc FPGA starting scratch test\n");
- err = tmc_do_test_scratch(tmc);
- if (err)
- goto err_unmap;
-
- dev_dbg(dev, "Tmc FPGA scratch test passed !!!\n");
-#endif /* TMC_DO_SCRATCH_TEST */
-
- switch (id->device) {
- case PCI_DEVICE_ID_JNX_TMC_CHD:
- err = mfd_add_devices(dev, pdev->bus->number,
- &chassisd_tmc_mfd_devs[0],
- ARRAY_SIZE(chassisd_tmc_mfd_devs),
- &pdev->resource[0],
- 0, NULL /* tmc->irq_domain */);
- break;
- case PCI_DEVICE_ID_JNX_TMC_PFE:
- err = mfd_add_devices(dev, pdev->bus->number,
- &pfe_tmc_mfd_devs[0],
- ARRAY_SIZE(pfe_tmc_mfd_devs),
- &pdev->resource[0],
- 0, NULL /* tmc->irq_domain */);
- break;
- default:
- dev_err(&pdev->dev, "Invalid PCI Device ID id:%d\n",
- id->device);
- goto err_unmap;
- }
-
- if (err < 0) {
- dev_err(&pdev->dev, "Failed to add mfd devices %d\n", err);
- goto err_unmap;
- }
-
- err = sysfs_create_group(&pdev->dev.kobj, &tmc_attr_group);
- if (err) {
- sysfs_remove_group(&pdev->dev.kobj, &tmc_attr_group);
- dev_err(&pdev->dev, "Failed to create attr group\n");
- goto err_remove_mfd;
- }
-
- tmc->major = ioread32(tmc->membase + TMC_REVISION);
- tmc->minor = ioread32(tmc->membase + TMC_MINOR);
-
- tmc->optic_cpld_major = ioread32(tmc->membase + TMC_OPTIC_CPLD_MAJOR);
- tmc->optic_cpld_minor = ioread32(tmc->membase + TMC_OPTIC_CPLD_MINOR);
-
- dev_info(dev, "Tmc FPGA Revision: 0x%02X_%06X, Minor: %02X\n",
- (tmc->major >> 24) & 0xff,
- tmc->major & 0xffffff,
- (tmc->minor) & 0xff);
- dev_info(dev, "Tmc FPGA optic cpld Major: 0x%01X, Minor: 0x%02X "
- "Devid: 0x%01X\n", (tmc->optic_cpld_major) & 0xf,
- (tmc->optic_cpld_minor) & 0xff,
- (tmc->optic_cpld_major >> 4) & 0xf);
- dev_info(dev, "Tmc FPGA mem:0x%lx\n",
- (unsigned long)tmc->membase);
-
- return 0;
-
-err_remove_mfd:
- mfd_remove_devices(dev);
-err_unmap:
- pci_iounmap(pdev, tmc->membase);
-err_release:
- pci_release_regions(pdev);
-err_disable:
- pci_disable_device(pdev);
-
- return err;
-}
-
-static void tmc_fpga_remove(struct pci_dev *pdev)
-{
- struct tmc_fpga_data *tmc = dev_get_drvdata(&pdev->dev);
-
- sysfs_remove_group(&pdev->dev.kobj, &tmc_attr_group);
- mfd_remove_devices(&pdev->dev);
-}
-
-static const struct pci_device_id tmc_fpga_id_tbl[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_TMC_CHD) },
- { PCI_DEVICE(PCI_VENDOR_ID_JUNIPER, PCI_DEVICE_ID_JNX_TMC_PFE) },
- { }
-};
-MODULE_DEVICE_TABLE(pci, tmc_fpga_id_tbl);
-
-static struct pci_driver tmc_fpga_driver = {
- .name = "tmc-core",
- .id_table = tmc_fpga_id_tbl,
- .probe = tmc_fpga_probe,
- .remove = tmc_fpga_remove,
-};
-
-module_pci_driver(tmc_fpga_driver);
-
-MODULE_DESCRIPTION("Juniper Networks TMC FPGA MFD core driver");
-MODULE_AUTHOR("Ashish Bhensdadia ");
-MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc-core.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc-core.c
new file mode 120000
index 0000000000..623e7a0188
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc-core.c
@@ -0,0 +1 @@
+../../common/modules/jnx-tmc-core.c
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc.h b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc.h
deleted file mode 100644
index dce7d7be33..0000000000
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Juniper Tmc FPGA register definitions
- *
- * Copyright (C) 2018 Juniper Networks
- * Author: Ashish Bhensdadia
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __JNX_TMC_H__
-#define __JNX_TMC_H__
-
-
-#define TMC_REVISION 0x00064
-#define TMC_MINOR 0x00068
-#define TMC_SCRATCH 0x00098
-
-#define TMC_OPTIC_CPLD_MAJOR 0x00104
-#define TMC_OPTIC_CPLD_MINOR 0x00108
-
-/*
- * I2C Master Block
- */
-#define TMC_I2C_AUTOMATION_I2C_CONTROL_START 0x07000
-#define TMC_I2C_AUTOMATION_I2C_CONTROL_END 0x07500
-
-#define TMC_I2C_DPMEM_ENTRY_START 0x10000
-#define TMC_I2C_DPMEM_ENTRY_END 0x13FFC
-
-#define TMC_LED_CONTROL_START 0x58
-#define TMC_LED_CONTROL_END 0x5B
-
-/*
- * RE-FPGA block
- */
-#define TMC_REFPGA_ACCESS_START 0x228
-#define TMC_REFPGA_ACCESS_END 0x233
-
-#define TMC_I2C_MASTER_NR_MSTRS 16
-#define TMC_I2C_MSTR_MAX_GROUPS 66
-
-
-/*
- * TMC GPIO SLAVE Block
- */
-#define TMC_GPIO_PTP_RESET_START 0x94
-#define TMC_GPIO_PTP_RESET_END 0x97
-
-#define TMC_GPIO_PTP_CFG_START 0xa4
-#define TMC_GPIO_PTP_CFG_END 0xa7
-
-#define TMC_GPIO_PTP_DATA_START 0xa8
-#define TMC_GPIO_PTP_DATA_END 0xab
-
-#define TMC_GPIO_SLAVE0_START 0xf0
-#define TMC_GPIO_SLAVE0_END 0x16b
-
-#define TMC_GPIO_SLAVE1_START 0x170
-#define TMC_GPIO_SLAVE1_END 0x1eb
-
-#define TMC_GPIO_SLAVE2_START 0x1f0
-#define TMC_GPIO_SLAVE2_END 0x213
-
-#define TMC_GPIO_SLAVE3_START 0x280
-#define TMC_GPIO_SLAVE3_END 0x2eb
-
-#define TMC_GPIO_SFP_SLAVE0_START 0x308
-#define TMC_GPIO_SFP_SLAVE0_END 0x32b
-
-#define TMC_GPIO_SFP_SLAVE1_START 0x32c
-#define TMC_GPIO_SFP_SLAVE1_END 0x34b
-
-/*
- * TMC PSU Block
- */
-#define TMC_PSU_START 0x240
-#define TMC_PSU_END 0x243
-
-/*
- * TMC SHUTDOWN REG
- */
-#define TMC_SYS_SHUTDOWN_LOCK 0x254
-#define TMC_SYS_SHUTDOWN 0x250
-
-/*
- * TMC DS100 MUX Block
- */
-#define TMC_GPIO_MUX_SLAVE_START 0x26c
-#define TMC_GPIO_MUX_SLAVE_END 0x26f
-
-#endif /* __JNX_TMC_H__ */
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc.h b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc.h
new file mode 120000
index 0000000000..bfacb7ae01
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/jnx-tmc.h
@@ -0,0 +1 @@
+../../common/modules/jnx-tmc.h
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/pci_ids.h b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/pci_ids.h
deleted file mode 100644
index 090707751b..0000000000
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/modules/pci_ids.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Juniper PCI ID(s) - for devices on Juniper Boards
- *
- * Rajat Jain
- * Copyright 2014 Juniper Networks
- *
- * 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 __JNX_PCI_IDS_H__
-#define __JNX_PCI_IDS_H__
-
-#define PCI_VENDOR_ID_JUNIPER 0x1304
-#define PCI_VENDOR_ID_ERICSSON 0x1519
-#define PCI_VENDOR_ID_ERICSSON_AS 0x1a25
-
-/*
- * PTX SAM FPGA, device ID as present on various Juniper boards, such as
- * - Sangria FPC
- * - Hendricks FPC
- * - Sangria 24x10GE PIC
- * - Gladiator FPC
- */
-#define PCI_DEVICE_ID_JNX_SAM 0x0004
-
-/* Juniper Broadway ASIC family */
-#define PCI_DEVICE_ID_JNX_TF 0x003c
-#define PCI_DEVICE_ID_JNX_TL 0x003d
-#define PCI_DEVICE_ID_JNX_TQ 0x003e
-#define PCI_DEVICE_ID_JNX_OTN_FRAMER 0x0055
-#define PCI_DEVICE_ID_JNX_PE 0x005e
-#define PCI_DEVICE_ID_JNX_PF 0x005f /* Juniper Paradise ASIC */
-#define PCI_DEVICE_ID_JNX_ZF 0x008d /* Juniper ZF Fabric ASIC */
-#define PCI_DEVICE_ID_JNX_ZX 0x008e /* Juniper ZX ASIC */
-#define PCI_DEVICE_ID_JNX_ZT 0x0090 /* Juniper ZT ASIC */
-#define PCI_DEVICE_ID_JNX_BT 0x00B2 /* Juniper BT ASIC */
-
-/* Juniper SAM FPGA - Omega SIB, Sochu SHAM, Gladiator SIB */
-#define PCI_DEVICE_ID_JNX_SAM_OMEGA 0x006a
-
-/* Juniper SAM FPGA - present on GLD FPC board */
-#define PCI_DEVICE_ID_JNX_SAM_X 0x006b
-
-/* Juniper PAM FPGA - present on PTX MLC board */
-#define PCI_DEVICE_ID_JNX_PAM 0x006c
-/* Juniper CBC FPGA - present on PTX1K RCB */
-#define PCI_DEVICE_ID_JNX_CBC 0x006e
-#define PCI_DEVICE_ID_JNX_CBC_P2 0x0079
-#define PCI_DEVICE_ID_JNX_OMG_CBC 0x0083
-
-/* Juniper Summit FPGA */
-#define PCI_DEVICE_ID_JNX_SUMMIT 0x009B
-
-/* Juniper DOON FPGA */
-#define PCI_DEVICE_ID_JNX_DOON_RCB_CBC 0x0098
-
-/* Juniper CBC FPGA in PTX-5K MTRCB */
-#define PCI_DEVICE_ID_JNX_PTX5K_MTRCB_CBC 0x0071
-
-/* Other Vendors' devices */
-#define PCI_DEVICE_ID_IDT_PES12NT3_TRANS_AB 0x8058
-#define PCI_DEVICE_ID_IDT_PES12NT3_TRANS_C 0x8059
-#define PCI_DEVICE_ID_IDT_PES12NT3_INT_NTB_C 0x805a
-#define PCI_DEVICE_ID_IDT_48H12G2 0x807a
-#define PCI_DEVICE_ID_IDT_PES24NT24G2 0x808e
-#define PCI_DEVICE_ID_IDT_PES16NT16G2 0x8090
-
-#define PCI_DEVICE_ID_PLX_8614 0x8614
-#define PCI_DEVICE_ID_PLX_8618 0x8618
-#define PCI_DEVICE_ID_PLX_8713 0x8713
-#define PCI_DEVICE_ID_PLX_8725 0x8725
-#define PCI_DEVICE_ID_PLX_8749 0x8749
-#define PCI_DEVICE_ID_PLX_8796 0x8796
-#define PCI_DEVICE_ID_PLX_8608 0x8608
-
-/*
- * Juniper CBD FPGA Device ID(s)
- */
-#define JNX_CBD_FPGA_DID_09B3 0x004D
-#define JNX_CBD_FPGA_DID_0BA8 0x005A
-
-/*
- * Juniper Brackla FPGA Device IDs
- * - UBAM, MBAM, PBAM, QBAM
- */
-#define PCI_DEVICE_ID_JNX_UBAM 0x00A7
-#define PCI_DEVICE_ID_JNX_PBAM 0x00A8
-#define PCI_DEVICE_ID_JNX_MBAM 0x00A9
-#define PCI_DEVICE_ID_JNX_QBAM 0x00AA
-
-/*
- * Juniper MPC11E Supercon and WAN FPGA IDs
- */
-#define PCI_DEVICE_ID_JNX_MPC11CON 0x00A1
-#define PCI_DEVICE_ID_JNX_MPC11WAN 0x00C4
-
-/*
- * Juniper Attella TMC and Supercon FPGA IDs
- */
-#define PCI_DEVICE_ID_JNX_ARGUS 0x00B0
-#define PCI_DEVICE_ID_JNX_ATIC 0x00C0
-#define PCI_DEVICE_ID_JNX_ATMC_CHD 0x00C1
-#define PCI_DEVICE_ID_JNX_ATMC_PFE 0x00C2
-#define PCI_DEVICE_ID_JNX_AOHIO 0x00C3
-
-/*
- * Juniper TMC FPGA Device IDs
- */
-#define PCI_DEVICE_ID_JNX_TMC_CHD 0x007B
-#define PCI_DEVICE_ID_JNX_TMC_PFE 0x007C
-
-#define PCI_DEVICE_ID_XILINX_1588_FPGA 0x0505
-
-/*
- * Juniper Scapa SIB/LC Supercon FPGA IDs
- */
-#define PCI_DEVICE_ID_JNX_SCAPA_SIB_CTRL 0x00BA
-#define PCI_DEVICE_ID_JNX_SDLC_CTRL 0x00BE
-#define PCI_DEVICE_ID_JNX_LLC_CTRL 0x00C8
-
-/*
- * Deanston WANIO FPGA
- */
-#define PCI_DEVICE_ID_JNX_DEANSTON_WAN 0x00C6
-
-/*
- * Juniper Ardbeg Supercon FPGA IDs
- */
-#define PCI_DEVICE_ID_JNX_ARDBEG_CTRL 0x00C5
-
-/*
- * Ericsson CCM FPGA ID used in Bolan (ACX753)
- */
-#define PCI_DEVICE_ID_ERIC_CCM_FPGA 0x0020
-
-/*
- * Ericsson OAM FPGA ID used in Bolan (ACX753)
- */
-#define PCI_DEVICE_ID_ERIC_OAM_FPGA 0x7021
-
-#endif /* __JNX_PCI_IDS_H__ */
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/service/qfx5200-platform-init.service b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/service/qfx5200-platform-init.service
old mode 100755
new mode 100644
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/setup.py b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/setup.py
deleted file mode 100755
index a847e4d8f6..0000000000
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/setup.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env python
-
-import os
-from setuptools import setup
-os.listdir
-
-setup(
- name='sonic_platform',
- version='1.0',
- description='Module to initialize Juniper QFX5200-32C-S platforms',
-
- packages=['sonic_platform'],
- package_dir={'sonic_platform': 'qfx5200/sonic_platform'},
-)
-
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-juniper/qfx5200/sonic_platform/chassis.py
deleted file mode 100755
index 39b6f81c9f..0000000000
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/sonic_platform/chassis.py
+++ /dev/null
@@ -1,260 +0,0 @@
-#!/usr/bin/env python
-#
-# Name: chassis.py, version: 1.0
-#
-# Description: Module contains the definitions of SONiC platform APIs
-# which provide the chassis specific details
-#
-# Copyright (c) 2020, Juniper Networks, Inc.
-# All rights reserved.
-#
-# Notice and Disclaimer: This code is licensed to you under the GNU General
-# Public License as published by the Free Software Foundation, version 3 or
-# any later version. This code is not an official Juniper product. You can
-# obtain a copy of the License at
-#
-# OSS License:
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-#
-# Third-Party Code: This code may depend on other components under separate
-# copyright notice and license terms. Your use of the source code for those
-# components is subject to the terms and conditions of the respective license
-# as noted in the Third-Party source code file.
-#
-
-try:
- import commands
- import time
- from sonic_platform_base.chassis_base import ChassisBase
-except ImportError as e:
- raise ImportError(str(e) + "- required module not found")
-
-
-class Chassis(ChassisBase):
- """
- JUNIPER QFX5200 Platform-specific Chassis class
- """
-
- def __init__(self):
- ChassisBase.__init__(self)
-
- def get_qfx5200_parameter_value(self,parameter_name):
- try:
- with open("/var/run/eeprom", "r") as file:
- for item in file:
- content = item.split('=')
- if content[0] == parameter_name:
- return content[1:]
- return "False"
- except IOError:
- print "Error: File not found"
- return "False"
-
- def get_product_name(self):
- product_name_list = self.get_qfx5200_parameter_value('Product Name')
- if product_name_list:
- product_name = ''.join(product_name_list)
- return product_name
- else:
- return False
-
-
- def get_part_number(self):
- part_number_list = self.get_qfx5200_parameter_value('Part Number')
- if part_number_list:
- part_number = ''.join(part_number_list)
- return part_number
- else:
- return False
-
-
- def get_serial_number(self):
- serial_number_list = self.get_qfx5200_parameter_value('Serial Number')
- if serial_number_list:
- serial_number = ''.join(serial_number_list)
- return serial_number
- else:
- return False
-
-
- def get_base_mac(self):
- mac_list = self.get_qfx5200_parameter_value('MAC Address')
- if mac_list:
- mac = ''.join(mac_list)
- return mac
- else:
- return False
-
-
- def get_mfg_date(self):
- mfgdate_list = self.get_qfx5200_parameter_value('Manufacture Date')
- if mfgdate_list:
- mfgdate = ''.join(mfgdate_list)
- return mfgdate
- else:
- return False
-
-
- def get_platform_name(self):
- platform_name_list = self.get_qfx5200_parameter_value('Platform Name')
- if platform_name_list:
- platform_name = ''.join(platform_name_list)
- return platform_name
- else:
- return False
-
-
- def get_MACnumber_name(self):
- MACnumber_name_list = self.get_qfx5200_parameter_value('Number of MAC Addresses')
- if MACnumber_name_list:
- MACnumber_name = ''.join(MACnumber_name_list)
- return MACnumber_name
- else:
- return False
-
-
- def get_vendor_name(self):
- vendor_name_list = self.get_qfx5200_parameter_value('Vendor Name')
- if vendor_name_list:
- vendor_name = ''.join(vendor_name_list)
- return vendor_name
- else:
- return False
-
- def get_mfg_name(self):
- mfg_name_list = self.get_qfx5200_parameter_value('Manufacture Name')
- if mfg_name_list:
- mfg_name = ''.join(mfg_name_list)
- return mfg_name
- else:
- return False
-
- def get_vendorext_name(self):
- vendorext_list = self.get_qfx5200_parameter_value('Vendor Extension')
- if vendorext_list:
- vendorext = ''.join(vendorext_list)
- return vendorext
- else:
- return False
-
- def get_vendorextIANA_name(self):
- vendorext_list = self.get_qfx5200_parameter_value('IANA')
- if vendorext_list:
- vendorext = ''.join(vendorext_list)
- return vendorext
- else:
- return False
-
- def get_vendorextASMREV_name(self):
- vendorext_list = self.get_qfx5200_parameter_value('Assembly Part Number Revision')
- if vendorext_list:
- vendorext = ''.join(vendorext_list)
- return vendorext
- else:
- return False
-
- def get_vendorextASMPartNum_name(self):
- vendorext_list = self.get_qfx5200_parameter_value('Assembly Part Number')
- if vendorext_list:
- vendorext = ''.join(vendorext_list)
- return vendorext
- else:
- return False
-
- def get_vendorextASMID_name(self):
- vendorext_list = self.get_qfx5200_parameter_value('Assembly ID')
- if vendorext_list:
- vendorext = ''.join(vendorext_list)
- return vendorext
- else:
- return False
-
- def get_vendorextASMMajNum_name(self):
- vendorext_list = self.get_qfx5200_parameter_value('Assembly Major Revision')
- if vendorext_list:
- vendorext = ''.join(vendorext_list)
- return vendorext
- else:
- return False
-
- def get_vendorextASMMinNum_name(self):
- vendorext_list = self.get_qfx5200_parameter_value('Assembly Minor Revision')
- if vendorext_list:
- vendorext = ''.join(vendorext_list)
- return vendorext
- else:
- return False
-
- def get_vendorextCLEI_name(self):
- vendorext_list = self.get_qfx5200_parameter_value('CLEI code')
- if vendorext_list:
- vendorext = ''.join(vendorext_list)
- return vendorext
- else:
- return False
-
- def get_onieversion_name(self):
- onieversion_name_list = self.get_qfx5200_parameter_value('ONIE Version')
- if onieversion_name_list:
- onieversion_name = ''.join(onieversion_name_list)
- return onieversion_name
- else:
- return False
-
- def get_crc_name(self):
- crc_list = self.get_qfx5200_parameter_value('CRC')
- if crc_list:
- crc_name = ''.join(crc_list)
- return crc_name
- else:
- return False
-
- def get_fan_type(self):
- fantype_list = self.get_qfx5200_parameter_value('Fan Type')
- if fantype_list:
- fantype_name = ''.join(fantype_list)
- return fantype_name
- else:
- return False
-
- def get_reboot_cause(self):
- """
- Retrieves the cause of the previous reboot
- """
- status, last_reboot_reason = commands.getstatusoutput("busybox devmem 0xFED50004 8")
- if (status == 0):
- if last_reboot_reason == "0x80":
- return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)
- elif last_reboot_reason == "0x40" or last_reboot_reason == "0x08":
- return (ChassisBase.REBOOT_CAUSE_WATCHDOG, None)
- elif last_reboot_reason == "0x20":
- return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None)
- elif last_reboot_reason == "0x10":
- return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Swizzle Reset")
- else:
- return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Unknown reason")
- else:
- time.sleep(3)
- status, last_reboot_reason = commands.getstatusoutput("busybox devmem 0xFED50004 8")
- if last_reboot_reason == "0x80":
- return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)
- elif last_reboot_reason == "0x40" or last_reboot_reason == "0x08":
- return (ChassisBase.REBOOT_CAUSE_WATCHDOG, None)
- elif last_reboot_reason == "0x20":
- return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None)
- elif last_reboot_reason == "0x10":
- return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Swizzle Reset")
- else:
- return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Unknown reason")
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/juniper_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/juniper_i2c_cpld.c
deleted file mode 120000
index 843ce05a43..0000000000
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/juniper_i2c_cpld.c
+++ /dev/null
@@ -1 +0,0 @@
-../../common/modules/juniper_i2c_cpld.c
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/juniper_i2c_cpld.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/juniper_i2c_cpld.c
new file mode 100644
index 0000000000..25860a6ac1
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/juniper_i2c_cpld.c
@@ -0,0 +1,892 @@
+/*
+ * A hwmon driver for the juniper_i2c_cpld
+ *
+ * Tested and validated on Juniper QFX5210
+ * Ciju Rajan K
+ *
+ * Copyright (C) 2013 Accton Technology Corporation.
+ * Brandon Chuang
+ *
+ * Based on ad7414.c
+ * Copyright 2006 Stefan Roese , DENX Software Engineering
+ *
+ * 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
+#include
+#include
+#include
+#include
+
+
+#define MAX_PORT_NUM 64
+#define I2C_RW_RETRY_COUNT 10
+#define I2C_RW_RETRY_INTERVAL 60 /* ms */
+
+#define I2C_ADDR_CPLD1 0x60
+#define I2C_ADDR_CPLD2 0x62
+#define I2C_ADDR_CPLD3 0x64
+#define CPLD_ADDRS {I2C_ADDR_CPLD1, I2C_ADDR_CPLD2, I2C_ADDR_CPLD3}
+
+
+/*
+ * Number of additional attribute pointers to allocate
+ * with each call to krealloc
+ */
+#define ATTR_ALLOC_SIZE 1 /*For last attribute which is NUll.*/
+
+#define NAME_SIZE 24
+#define MAX_RESP_LENGTH 48
+
+typedef ssize_t (*show_func)( struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+typedef ssize_t (*store_func)(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+enum models {
+ AS7712_32X,
+ AS7716_32X,
+ qfx5210_64X,
+ AS7312_54X,
+ PLAIN_CPLD, /*No attribute but add i2c addr to the list.*/
+ NUM_MODEL
+};
+
+enum sfp_func {
+ HAS_SFP = 1<<0 ,
+ HAS_QSFP = 1<<1 ,
+};
+
+enum common_attrs {
+ CMN_VERSION,
+ CMN_ACCESS,
+ CMN_PRESENT_ALL,
+ NUM_COMMON_ATTR
+};
+
+enum sfp_attrs {
+ SFP_PRESENT,
+ SFP_RESET,
+ SFP_LP_MODE,
+ NUM_SFP_ATTR
+};
+
+struct cpld_sensor {
+ struct cpld_sensor *next;
+ char name[NAME_SIZE+1]; /* sysfs sensor name */
+ struct device_attribute attribute;
+ bool update; /* runtime sensor update needed */
+ int data; /* Sensor data. Negative if there was a read error */
+
+ u8 reg; /* register */
+ u8 mask; /* bit mask */
+ bool invert; /* inverted value*/
+
+};
+
+#define to_cpld_sensor(_attr) \
+ container_of(_attr, struct cpld_sensor, attribute)
+
+struct cpld_data {
+ struct device *dev;
+ struct device *hwmon_dev;
+
+ int num_attributes;
+ struct attribute_group group;
+
+ enum models model;
+ struct cpld_sensor *sensors;
+ struct mutex update_lock;
+ bool valid;
+ unsigned long last_updated; /* in jiffies */
+
+ int attr_index;
+ u16 sfp_num;
+ u8 sfp_types;
+ struct model_attrs *cmn_attr;
+};
+
+struct cpld_client_node {
+ struct i2c_client *client;
+ struct list_head list;
+};
+
+
+struct base_attrs {
+ const char *name;
+ umode_t mode;
+ show_func get;
+ store_func set;
+};
+
+struct attrs {
+ int reg;
+ bool invert;
+ struct base_attrs *base;
+};
+
+struct model_attrs {
+ struct attrs **cmn;
+ struct attrs **portly;
+};
+
+
+static ssize_t show_bit(struct device *dev,
+ struct device_attribute *devattr, char *buf);
+static ssize_t show_presnet_all(struct device *dev,
+ struct device_attribute *devattr, char *buf);
+static ssize_t set_1bit(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count);
+static ssize_t set_byte(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count);
+static ssize_t access(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count);
+
+int juniper_i2c_cpld_read(u8 cpld_addr, u8 reg);
+int juniper_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
+
+
+struct base_attrs common_attrs[NUM_COMMON_ATTR] =
+{
+ [CMN_VERSION] = {"version", S_IRUGO, show_bit, NULL},
+ [CMN_ACCESS] = {"access", S_IWUSR, NULL, set_byte},
+ [CMN_PRESENT_ALL] = {"module_present_all", S_IRUGO, show_presnet_all, NULL},
+};
+
+struct attrs as7712_common[] = {
+ [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]},
+ [CMN_ACCESS] = {0x00, false, &common_attrs[CMN_ACCESS]},
+ [CMN_PRESENT_ALL] = {0x30, false, &common_attrs[CMN_PRESENT_ALL]},
+};
+struct attrs qfx5210_common[] = {
+ [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]},
+ [CMN_ACCESS] = {0x00, false, &common_attrs[CMN_ACCESS]},
+ [CMN_PRESENT_ALL] = {0x30, false, &common_attrs[CMN_PRESENT_ALL]},
+};
+struct attrs as7312_common[] = {
+ [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]},
+ [CMN_ACCESS] = {0x00, false, &common_attrs[CMN_ACCESS]},
+ [CMN_PRESENT_ALL] = {-1, false, &common_attrs[CMN_PRESENT_ALL]},
+};
+struct attrs plain_common[] = {
+ [CMN_VERSION] = {0x01, false, &common_attrs[CMN_VERSION]},
+};
+
+struct base_attrs portly_attrs[] =
+{
+ [SFP_PRESENT] = {"module_present", S_IRUGO, show_bit, NULL},
+ // Only root user will have the privilege to write to sysfs
+ // [SFP_RESET] = {"module_reset", S_IRUGO|S_IWUGO, show_bit, set_1bit},
+ [SFP_RESET] = {"module_reset", S_IRUGO|S_IWUSR, show_bit, set_1bit},
+};
+
+struct attrs as7712_port[] = {
+ {0x30, true, &portly_attrs[SFP_PRESENT]},
+ {0x04, true, &portly_attrs[SFP_RESET]},
+};
+
+struct attrs qfx5210_port[] = {
+ {0x70, true, &portly_attrs[SFP_PRESENT]},
+ {0x40, true, &portly_attrs[SFP_RESET]},
+};
+
+struct attrs *as7712_cmn_list[] = {
+ &as7712_common[CMN_VERSION],
+ &as7712_common[CMN_ACCESS],
+ &as7712_common[CMN_PRESENT_ALL],
+ NULL
+};
+
+struct attrs *qfx5210_cmn_list[] = {
+ &qfx5210_common[CMN_VERSION],
+ &qfx5210_common[CMN_ACCESS],
+ &qfx5210_common[CMN_PRESENT_ALL],
+ NULL
+};
+
+struct attrs *as7312_cmn_list[] = {
+ &as7312_common[CMN_VERSION],
+ &as7312_common[CMN_ACCESS],
+ &as7312_common[CMN_PRESENT_ALL],
+ NULL
+};
+
+struct attrs *plain_cmn_list[] = {
+ &plain_common[CMN_VERSION],
+ NULL
+};
+
+struct attrs *as7712_port_list[] = {
+ &as7712_port[SFP_PRESENT],
+ &as7712_port[SFP_RESET],
+ NULL
+};
+struct attrs *qfx5210_port_list[] = {
+ &qfx5210_port[SFP_PRESENT],
+ &qfx5210_port[SFP_RESET],
+ NULL
+};
+
+struct model_attrs models_attr[NUM_MODEL] = {
+ {.cmn = as7712_cmn_list, .portly=as7712_port_list},
+ {.cmn = as7712_cmn_list, .portly=as7712_port_list}, /*7716's as 7712*/
+ {.cmn = qfx5210_cmn_list, .portly=qfx5210_port_list},
+ {.cmn = as7312_cmn_list, .portly=qfx5210_port_list},
+ {.cmn = plain_cmn_list, .portly=NULL},
+};
+
+static LIST_HEAD(cpld_client_list);
+static struct mutex list_lock;
+/* Addresses scanned for juniper_i2c_cpld
+ */
+static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int get_sfp_spec(int model, u16 *num, u8 *types)
+{
+ switch (model) {
+ case AS7712_32X:
+ case AS7716_32X:
+ *num = 32;
+ *types = HAS_QSFP;
+ break;
+ case qfx5210_64X:
+ *num = 64;
+ *types = HAS_QSFP;
+ break;
+ case AS7312_54X:
+ *num = 54;
+ *types = HAS_QSFP|HAS_SFP;
+ default:
+ *types = 0;
+ *num = 0;
+ break;
+ }
+
+ return 0;
+}
+
+static int get_present_reg(int model, u8 port, u8 *cpld_addr, u8 *reg, u8 *num)
+{
+ u8 cpld_address[] = CPLD_ADDRS;
+
+ switch (model) {
+ case AS7312_54X:
+ if (port < 48) {
+ *cpld_addr = cpld_address[1 + port/24];
+ *reg = 0x09 + (port%24)/8;
+ *num = 8;
+ }
+ else
+ {
+ *reg = 0x18;
+ *num = 4;
+ *cpld_addr = ( port < 52)? cpld_address[1]: cpld_address[2];
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+}
+
+
+/*Assume the bits for ports are listed in-a-row.*/
+static int get_reg_bit(u8 reg_start, int port,
+ u8 *reg ,u8 *mask)
+{
+ *reg = reg_start + ((port)/8);
+ *mask = 1 << ((port)%8);
+
+ return 0;
+}
+
+static int cpld_write_internal(
+ struct i2c_client *client, u8 reg, u8 value)
+{
+ int status = 0, retry = I2C_RW_RETRY_COUNT;
+
+ while (retry) {
+ status = i2c_smbus_write_byte_data(client, reg, value);
+ if (unlikely(status < 0)) {
+ msleep(I2C_RW_RETRY_INTERVAL);
+ retry--;
+ continue;
+ }
+
+ break;
+ }
+
+ return status;
+}
+
+static int cpld_read_internal(struct i2c_client *client, u8 reg)
+{
+ int status = 0, retry = I2C_RW_RETRY_COUNT;
+
+ while (retry) {
+ status = i2c_smbus_read_byte_data(client, reg);
+ if (unlikely(status < 0)) {
+ msleep(I2C_RW_RETRY_INTERVAL);
+ retry--;
+ continue;
+ }
+
+ break;
+ }
+
+ return status;
+}
+
+
+/*Turn a numberic array into string with " " between each element.
+ * e.g., {0x11, 0x33, 0xff, 0xf1} => "11 33 ff f1"
+ */
+static ssize_t array_stringify(char *buf, u8 *input, size_t size) {
+
+ int i;
+ char t[MAX_RESP_LENGTH+1];
+
+ buf[0] = '\0';
+ for (i = 0; i < size; i++) {
+ snprintf(t, MAX_RESP_LENGTH, "%x ", input[i]);
+ strncat(buf, t, MAX_RESP_LENGTH);
+ }
+
+ if (strlen(buf) > 0)
+ buf[strlen(buf)-1] = '\0'; /*Remove tailing blank*/
+
+ return snprintf(buf, MAX_RESP_LENGTH, "%s\n", buf);
+}
+
+static ssize_t show_presnet_all_distinct(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+ u8 i, value, reg;
+ u8 cpld_addr, num;
+ u8 _value[8];
+ u64 *values = (u64 *)_value;
+
+ values = 0;
+ mutex_lock(&data->update_lock);
+ while(i < data->sfp_num)
+ {
+ get_present_reg(data->model, i, &cpld_addr, ®, &num);
+ if(cpld_addr == client->addr)
+ value = cpld_read_internal(client, reg);
+ else
+ value = juniper_i2c_cpld_read(cpld_addr, reg);
+
+ if (unlikely(value < 0)) {
+ goto exit;
+ }
+
+ *values |= (value&((1<<(num))-1)) << i;
+ i += num;
+ }
+ mutex_unlock(&data->update_lock);
+
+ *values = cpu_to_le64(*values);
+ return array_stringify(buf, _value, i);
+exit:
+ mutex_unlock(&data->update_lock);
+ return value;
+}
+
+static ssize_t show_presnet_all(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+ struct cpld_sensor *sensor = to_cpld_sensor(devattr);
+ u8 i, values[MAX_RESP_LENGTH/8];
+
+ if (sensor->reg < 0) {
+ return show_presnet_all_distinct(dev, devattr, buf);
+ }
+
+ mutex_lock(&data->update_lock);
+ for (i = 0; i < ((data->sfp_num+7)/8); i++) {
+ values[i] = cpld_read_internal(client, sensor->reg + i);
+ if (unlikely(values[i] < 0)) {
+ goto exit;
+ }
+ }
+ mutex_unlock(&data->update_lock);
+ return array_stringify(buf, values, i);
+
+exit:
+ mutex_unlock(&data->update_lock);
+ return values[i];
+}
+
+static ssize_t show_bit(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ int value;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+ struct cpld_sensor *sensor = to_cpld_sensor(devattr);
+
+ mutex_lock(&data->update_lock);
+ value = cpld_read_internal(client, sensor->reg);
+ value = value & sensor->mask;
+ if (sensor->invert)
+ value = !value;
+ mutex_unlock(&data->update_lock);
+
+ return snprintf(buf, PAGE_SIZE, "%x\n", value);
+}
+
+static ssize_t set_1bit(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ long is_reset;
+ int value, status;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+ struct cpld_sensor *sensor = to_cpld_sensor(devattr);
+ u8 cpld_bit, reg;
+
+ status = kstrtol(buf, 10, &is_reset);
+ if (status) {
+ return status;
+ }
+ reg = sensor->reg;
+ cpld_bit = sensor->mask;
+ mutex_lock(&data->update_lock);
+ value = cpld_read_internal(client, reg);
+ if (unlikely(status < 0)) {
+ goto exit;
+ }
+
+ if (sensor->invert)
+ is_reset = !is_reset;
+
+ if (is_reset) {
+ value |= cpld_bit;
+ }
+ else {
+ value &= ~cpld_bit;
+ }
+
+ status = cpld_write_internal(client, reg, value);
+ if (unlikely(status < 0)) {
+ goto exit;
+ }
+ mutex_unlock(&data->update_lock);
+ return count;
+
+exit:
+ mutex_unlock(&data->update_lock);
+ return status;
+}
+
+static ssize_t set_byte(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count)
+{
+ return access(dev, da, buf, count);
+}
+
+static ssize_t access(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count)
+{
+ int status;
+ u32 addr, val;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct cpld_data *data = i2c_get_clientdata(client);
+
+ if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) {
+ return -EINVAL;
+ }
+
+ if (addr > 0xFF || val > 0xFF) {
+ return -EINVAL;
+ }
+
+ mutex_lock(&data->update_lock);
+ status = cpld_write_internal(client, addr, val);
+ if (unlikely(status < 0)) {
+ goto exit;
+ }
+ mutex_unlock(&data->update_lock);
+ return count;
+
+exit:
+ mutex_unlock(&data->update_lock);
+ return status;
+}
+
+static void juniper_i2c_cpld_add_client(struct i2c_client *client)
+{
+ struct cpld_client_node *node =
+ kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL);
+
+ if (!node) {
+ dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n",
+ client->addr);
+ return;
+ }
+ node->client = client;
+
+ mutex_lock(&list_lock);
+ list_add(&node->list, &cpld_client_list);
+ mutex_unlock(&list_lock);
+}
+
+static void juniper_i2c_cpld_remove_client(struct i2c_client *client)
+{
+ struct list_head *list_node = NULL;
+ struct cpld_client_node *cpld_node = NULL;
+ int found = 0;
+
+ mutex_lock(&list_lock);
+
+ list_for_each(list_node, &cpld_client_list)
+ {
+ cpld_node = list_entry(list_node, struct cpld_client_node, list);
+
+ if (cpld_node->client == client) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (found) {
+ list_del(list_node);
+ kfree(cpld_node);
+ }
+
+ mutex_unlock(&list_lock);
+}
+
+static int cpld_add_attribute(struct cpld_data *data, struct attribute *attr)
+{
+ int new_max_attrs = ++data->num_attributes + ATTR_ALLOC_SIZE;
+ void *new_attrs = krealloc(data->group.attrs,
+ new_max_attrs * sizeof(void *),
+ GFP_KERNEL);
+ if (!new_attrs)
+ return -ENOMEM;
+ data->group.attrs = new_attrs;
+
+
+ data->group.attrs[data->num_attributes-1] = attr;
+ data->group.attrs[data->num_attributes] = NULL;
+
+ return 0;
+}
+
+static void cpld_dev_attr_init(struct device_attribute *dev_attr,
+ const char *name, umode_t mode,
+ show_func show, store_func store)
+{
+ sysfs_attr_init(&dev_attr->attr);
+ dev_attr->attr.name = name;
+ dev_attr->attr.mode = mode;
+ dev_attr->show = show;
+ dev_attr->store = store;
+}
+
+static struct cpld_sensor * add_sensor(struct cpld_data *data,
+ const char *name,
+ u8 reg, u8 mask, bool invert,
+ bool update, umode_t mode,
+ show_func get, store_func set)
+{
+ struct cpld_sensor *sensor;
+ struct device_attribute *a;
+
+ sensor = devm_kzalloc(data->dev, sizeof(*sensor), GFP_KERNEL);
+ if (!sensor)
+ return NULL;
+ a = &sensor->attribute;
+
+ snprintf(sensor->name, sizeof(sensor->name), name);
+ sensor->reg = reg;
+ sensor->mask = mask;
+ sensor->update = update;
+ sensor->invert = invert;
+ cpld_dev_attr_init(a, sensor->name,
+ mode,
+ get, set);
+
+ if (cpld_add_attribute(data, &a->attr))
+ return NULL;
+
+ sensor->next = data->sensors;
+ data->sensors = sensor;
+
+ return sensor;
+}
+
+static int add_attributes_cmn(struct cpld_data *data, struct attrs **cmn)
+{
+ u8 reg, i ;
+ bool invert;
+ struct attrs *a;
+ struct base_attrs *b;
+
+ if (NULL == cmn)
+ return -1;
+
+ for (i = 0; cmn[i]; i++)
+ {
+ a = cmn[i];
+
+ reg = a->reg;
+ invert = a->invert;
+
+ b = a->base;
+ if (NULL == b)
+ break;
+
+ if (add_sensor(data, b->name,
+ reg, 0xff, invert,
+ true, b->mode,
+ b->get, b->set) == NULL)
+ {
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+
+static int add_attributes_portly(struct cpld_data *data, struct attrs **pa)
+{
+ char name[NAME_SIZE+1];
+ int i, j;
+ u8 reg, mask, invert;
+ struct attrs *a;
+ struct base_attrs *b;
+
+ if (NULL == pa)
+ return -1;
+
+
+ for (i = 0; pa[i]; i++) {
+ a = pa[i];
+
+ invert = a->invert;
+ b = a->base;
+ if (b == NULL)
+ break;
+
+ for (j = 0; j < data->sfp_num; j++)
+ {
+ snprintf(name, NAME_SIZE, "%s_%d", b->name, j+1);
+ get_reg_bit(a->reg, j, ®, &mask);
+
+ if (add_sensor(data, name, reg, mask, invert,
+ true, b->mode, b->get, b->set) == NULL)
+ {
+ return -ENOMEM;
+ }
+ }
+ }
+ return 0;
+}
+
+static int add_attributes(struct i2c_client *client,
+ struct cpld_data *data)
+{
+ struct model_attrs *m = data->cmn_attr;
+
+ if (m == NULL)
+ return -EINVAL;
+
+ /* Common attributes.*/
+ add_attributes_cmn(data, m->cmn);
+
+ /* Port-wise attributes.*/
+ add_attributes_portly(data, m->portly);
+
+ return 0;
+}
+
+static int juniper_i2c_cpld_probe(struct i2c_client *client,
+ const struct i2c_device_id *dev_id)
+{
+ int status;
+ struct cpld_data *data = NULL;
+ struct device *dev = &client->dev;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+ dev_dbg(dev, "i2c_check_functionality failed (0x%x)\n", client->addr);
+ return -EIO;
+ }
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ return -ENOMEM;
+ }
+
+ data->model = dev_id->driver_data;
+ data->cmn_attr = &models_attr[data->model];
+ get_sfp_spec(data->model, &data->sfp_num, &data->sfp_types);
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+ data->dev = dev;
+ dev_info(dev, "chip found\n");
+
+ status = add_attributes(client, data);
+ if (status)
+ goto out_kfree;
+
+ /*
+ * If there are no attributes, something is wrong.
+ * Bail out instead of trying to register nothing.
+ */
+ if (!data->num_attributes) {
+ dev_err(dev, "No attributes found\n");
+ status = -ENODEV;
+ goto out_kfree;
+ }
+
+ /* Register sysfs hooks */
+ status = sysfs_create_group(&client->dev.kobj, &data->group);
+ if (status) {
+ goto out_kfree;
+ }
+
+ data->hwmon_dev = hwmon_device_register(&client->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ status = PTR_ERR(data->hwmon_dev);
+ goto exit_remove;
+ }
+
+ juniper_i2c_cpld_add_client(client);
+ dev_info(dev, "%s: cpld '%s'\n",
+ dev_name(data->hwmon_dev), client->name);
+
+ return 0;
+exit_remove:
+ sysfs_remove_group(&client->dev.kobj, &data->group);
+out_kfree:
+ kfree(data->group.attrs);
+ return status;
+
+}
+
+static int juniper_i2c_cpld_remove(struct i2c_client *client)
+{
+ struct cpld_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &data->group);
+ kfree(data->group.attrs);
+ juniper_i2c_cpld_remove_client(client);
+ return 0;
+}
+
+int juniper_i2c_cpld_read(u8 cpld_addr, u8 reg)
+{
+ struct list_head *list_node = NULL;
+ struct cpld_client_node *cpld_node = NULL;
+ int ret = -EPERM;
+
+ mutex_lock(&list_lock);
+
+ list_for_each(list_node, &cpld_client_list)
+ {
+ cpld_node = list_entry(list_node, struct cpld_client_node, list);
+
+ if (cpld_node->client->addr == cpld_addr) {
+ ret = i2c_smbus_read_byte_data(cpld_node->client, reg);
+ break;
+ }
+ }
+
+ mutex_unlock(&list_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(juniper_i2c_cpld_read);
+
+int juniper_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value)
+{
+ struct list_head *list_node = NULL;
+ struct cpld_client_node *cpld_node = NULL;
+ int ret = -EIO;
+
+ mutex_lock(&list_lock);
+
+ list_for_each(list_node, &cpld_client_list)
+ {
+ cpld_node = list_entry(list_node, struct cpld_client_node, list);
+
+ if (cpld_node->client->addr == cpld_addr) {
+ ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value);
+ break;
+ }
+ }
+
+ mutex_unlock(&list_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(juniper_i2c_cpld_write);
+
+
+static const struct i2c_device_id juniper_i2c_cpld_id[] = {
+ { "cpld_as7712", AS7712_32X},
+ { "cpld_as7716", AS7716_32X},
+ { "cpld_qfx5210", qfx5210_64X},
+ { "cpld_as7312", AS7312_54X},
+ { "cpld_plain", PLAIN_CPLD},
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, juniper_i2c_cpld_id);
+
+static struct i2c_driver juniper_i2c_cpld_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "juniper_i2c_cpld",
+ },
+ .probe = juniper_i2c_cpld_probe,
+ .remove = juniper_i2c_cpld_remove,
+ .id_table = juniper_i2c_cpld_id,
+ .address_list = normal_i2c,
+};
+
+
+static int __init juniper_i2c_cpld_init(void)
+{
+ mutex_init(&list_lock);
+ return i2c_add_driver(&juniper_i2c_cpld_driver);
+}
+
+static void __exit juniper_i2c_cpld_exit(void)
+{
+ i2c_del_driver(&juniper_i2c_cpld_driver);
+}
+
+module_init(juniper_i2c_cpld_init);
+module_exit(juniper_i2c_cpld_exit);
+
+MODULE_AUTHOR("Brandon Chuang ");
+MODULE_DESCRIPTION("juniper_i2c_cpld driver");
+MODULE_LICENSE("GPL");
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/ym2651y.c
deleted file mode 120000
index f4d67640cc..0000000000
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/ym2651y.c
+++ /dev/null
@@ -1 +0,0 @@
-../../common/modules/ym2651y.c
\ No newline at end of file
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/ym2651y.c b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/ym2651y.c
new file mode 100644
index 0000000000..3ade568410
--- /dev/null
+++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/modules/ym2651y.c
@@ -0,0 +1,622 @@
+/*
+ * An hwmon driver for the 3Y Power YM-2651Y Power Module
+ *
+ * Tested and validated on Juniper QFX5210
+ * Ciju Rajan K
+ *
+ * Copyright (C) 2014 Accton Technology Corporation.
+ * Brandon Chuang
+ *
+ * Based on ad7414.c
+ * Copyright 2006 Stefan Roese , DENX Software Engineering
+ *
+ * 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
+#include
+
+#define MAX_FAN_DUTY_CYCLE 100
+
+/* Addresses scanned
+ */
+static const unsigned short normal_i2c[] = { 0x58, 0x5b, I2C_CLIENT_END };
+
+enum chips {
+ YM2651,
+ YM2401,
+ YM2851,
+};
+
+/* Each client has this additional data
+ */
+struct ym2651y_data {
+ struct device *hwmon_dev;
+ struct mutex update_lock;
+ char valid; /* !=0 if registers are valid */
+ unsigned long last_updated; /* In jiffies */
+ u8 capability; /* Register value */
+ u16 status_word; /* Register value */
+ u8 fan_fault; /* Register value */
+ u8 over_temp; /* Register value */
+ u16 v_out; /* Register value */
+ u16 i_out; /* Register value */
+ u16 p_out; /* Register value */
+ u16 temp; /* Register value */
+ u16 fan_speed; /* Register value */
+ u16 fan_duty_cycle[2]; /* Register value */
+ u8 fan_dir[4]; /* Register value */
+ u8 pmbus_revision; /* Register value */
+ u8 mfr_id[10]; /* Register value */
+ u8 mfr_model[10]; /* Register value */
+ u8 mfr_revsion[3]; /* Register value */
+ u16 mfr_vin_min; /* Register value */
+ u16 mfr_vin_max; /* Register value */
+ u16 mfr_iin_max; /* Register value */
+ u16 mfr_iout_max; /* Register value */
+ u16 mfr_pin_max; /* Register value */
+ u16 mfr_pout_max; /* Register value */
+ u16 mfr_vout_min; /* Register value */
+ u16 mfr_vout_max; /* Register value */
+};
+
+static ssize_t show_byte(struct device *dev, struct device_attribute *da,
+ char *buf);
+static ssize_t show_word(struct device *dev, struct device_attribute *da,
+ char *buf);
+static ssize_t show_linear(struct device *dev, struct device_attribute *da,
+ char *buf);
+static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da,
+ char *buf);
+static ssize_t show_over_temp(struct device *dev, struct device_attribute *da,
+ char *buf);
+static ssize_t show_ascii(struct device *dev, struct device_attribute *da,
+ char *buf);
+static struct ym2651y_data *ym2651y_update_device(struct device *dev);
+static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count);
+static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value);
+
+enum ym2651y_sysfs_attributes {
+ PSU_POWER_ON = 0,
+ PSU_TEMP_FAULT,
+ PSU_POWER_GOOD,
+ PSU_FAN1_FAULT,
+ PSU_FAN_DIRECTION,
+ PSU_OVER_TEMP,
+ PSU_V_OUT,
+ PSU_I_OUT,
+ PSU_P_OUT,
+ PSU_P_OUT_UV, /*In Unit of microVolt, instead of mini.*/
+ PSU_TEMP1_INPUT,
+ PSU_FAN1_SPEED,
+ PSU_FAN1_DUTY_CYCLE,
+ PSU_PMBUS_REVISION,
+ PSU_MFR_ID,
+ PSU_MFR_MODEL,
+ PSU_MFR_REVISION,
+ PSU_MFR_VIN_MIN,
+ PSU_MFR_VIN_MAX,
+ PSU_MFR_VOUT_MIN,
+ PSU_MFR_VOUT_MAX,
+ PSU_MFR_IIN_MAX,
+ PSU_MFR_IOUT_MAX,
+ PSU_MFR_PIN_MAX,
+ PSU_MFR_POUT_MAX
+};
+
+/* sysfs attributes for hwmon
+ */
+static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON);
+static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT);
+static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD);
+static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT);
+static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP);
+static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_linear, NULL, PSU_V_OUT);
+static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT);
+static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT);
+static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT);
+static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED);
+static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE);
+static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION);
+static SENSOR_DEVICE_ATTR(psu_pmbus_revision, S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION);
+static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID);
+static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL);
+static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION);
+static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN);
+static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX);
+static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN);
+static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX);
+static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX);
+static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX);
+static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX);
+static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX);
+
+/*Duplicate nodes for lm-sensors.*/
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_linear, NULL, PSU_V_OUT);
+static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_linear, NULL, PSU_I_OUT);
+static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_linear, NULL, PSU_P_OUT_UV);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT);
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED);
+static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT);
+
+static struct attribute *ym2651y_attributes[] = {
+ &sensor_dev_attr_psu_power_on.dev_attr.attr,
+ &sensor_dev_attr_psu_temp_fault.dev_attr.attr,
+ &sensor_dev_attr_psu_power_good.dev_attr.attr,
+ &sensor_dev_attr_psu_fan1_fault.dev_attr.attr,
+ &sensor_dev_attr_psu_over_temp.dev_attr.attr,
+ &sensor_dev_attr_psu_v_out.dev_attr.attr,
+ &sensor_dev_attr_psu_i_out.dev_attr.attr,
+ &sensor_dev_attr_psu_p_out.dev_attr.attr,
+ &sensor_dev_attr_psu_temp1_input.dev_attr.attr,
+ &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr,
+ &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr,
+ &sensor_dev_attr_psu_fan_dir.dev_attr.attr,
+ &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_id.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_model.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_revision.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr,
+ &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr,
+ /*Duplicate nodes for lm-sensors.*/
+ &sensor_dev_attr_curr2_input.dev_attr.attr,
+ &sensor_dev_attr_in3_input.dev_attr.attr,
+ &sensor_dev_attr_power2_input.dev_attr.attr,
+ &sensor_dev_attr_temp1_input.dev_attr.attr,
+ &sensor_dev_attr_fan1_input.dev_attr.attr,
+ &sensor_dev_attr_temp1_fault.dev_attr.attr,
+ NULL
+};
+
+static ssize_t show_byte(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct ym2651y_data *data = ym2651y_update_device(dev);
+
+ return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) :
+ sprintf(buf, "0\n");
+}
+
+static ssize_t show_word(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct ym2651y_data *data = ym2651y_update_device(dev);
+ u16 status = 0;
+
+ switch (attr->index) {
+ case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */
+ status = (data->status_word & 0x40) ? 0 : 1;
+ break;
+ case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */
+ status = (data->status_word & 0x4) >> 2;
+ break;
+ case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */
+ status = (data->status_word & 0x800) ? 0 : 1;
+ break;
+ }
+
+ return sprintf(buf, "%d\n", status);
+}
+
+static int two_complement_to_int(u16 data, u8 valid_bit, int mask)
+{
+ u16 valid_data = data & mask;
+ bool is_negative = valid_data >> (valid_bit - 1);
+
+ return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data;
+}
+
+static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct ym2651y_data *data = i2c_get_clientdata(client);
+ int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1;
+ long speed;
+ int error;
+
+ error = kstrtol(buf, 10, &speed);
+ if (error)
+ return error;
+
+ if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ data->fan_duty_cycle[nr] = speed;
+ ym2651y_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t show_linear(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct ym2651y_data *data = ym2651y_update_device(dev);
+
+ u16 value = 0;
+ int exponent, mantissa;
+ int multiplier = 1000;
+
+ switch (attr->index) {
+ case PSU_V_OUT:
+ value = data->v_out;
+ break;
+ case PSU_I_OUT:
+ value = data->i_out;
+ break;
+ case PSU_P_OUT_UV:
+ multiplier = 1000000; /*For lm-sensors, unit is micro-Volt.*/
+ /*Passing through*/
+ case PSU_P_OUT:
+ value = data->p_out;
+ break;
+ case PSU_TEMP1_INPUT:
+ value = data->temp;
+ break;
+ case PSU_FAN1_SPEED:
+ value = data->fan_speed;
+ multiplier = 1;
+ break;
+ case PSU_FAN1_DUTY_CYCLE:
+ value = data->fan_duty_cycle[0];
+ multiplier = 1;
+ break;
+ case PSU_MFR_VIN_MIN:
+ value = data->mfr_vin_min;
+ break;
+ case PSU_MFR_VIN_MAX:
+ value = data->mfr_vin_max;
+ break;
+ case PSU_MFR_VOUT_MIN:
+ value = data->mfr_vout_min;
+ break;
+ case PSU_MFR_VOUT_MAX:
+ value = data->mfr_vout_max;
+ break;
+ case PSU_MFR_PIN_MAX:
+ value = data->mfr_pin_max;
+ break;
+ case PSU_MFR_POUT_MAX:
+ value = data->mfr_pout_max;
+ break;
+ case PSU_MFR_IOUT_MAX:
+ value = data->mfr_iout_max;
+ break;
+ case PSU_MFR_IIN_MAX:
+ value = data->mfr_iin_max;
+ break;
+ }
+
+ exponent = two_complement_to_int(value >> 11, 5, 0x1f);
+ mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff);
+ return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) :
+ sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent));
+}
+
+static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct ym2651y_data *data = ym2651y_update_device(dev);
+
+ u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6;
+
+ return sprintf(buf, "%d\n", data->fan_fault >> shift);
+}
+
+static ssize_t show_over_temp(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct ym2651y_data *data = ym2651y_update_device(dev);
+
+ return sprintf(buf, "%d\n", data->over_temp >> 7);
+}
+
+static ssize_t show_ascii(struct device *dev, struct device_attribute *da,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+ struct ym2651y_data *data = ym2651y_update_device(dev);
+ u8 *ptr = NULL;
+
+ switch (attr->index) {
+ case PSU_FAN_DIRECTION: /* psu_fan_dir */
+ ptr = data->fan_dir;
+ break;
+ case PSU_MFR_ID: /* psu_mfr_id */
+ ptr = data->mfr_id;
+ break;
+ case PSU_MFR_MODEL: /* psu_mfr_model */
+ ptr = data->mfr_model;
+ break;
+ case PSU_MFR_REVISION: /* psu_mfr_revision */
+ ptr = data->mfr_revsion;
+ break;
+ default:
+ return 0;
+ }
+
+ return sprintf(buf, "%s\n", ptr);
+}
+
+static const struct attribute_group ym2651y_group = {
+ .attrs = ym2651y_attributes,
+};
+
+static int ym2651y_probe(struct i2c_client *client,
+ const struct i2c_device_id *dev_id)
+{
+ struct ym2651y_data *data;
+ int status;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK)) {
+ status = -EIO;
+ goto exit;
+ }
+
+ data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL);
+ if (!data) {
+ status = -ENOMEM;
+ goto exit;
+ }
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+
+ dev_info(&client->dev, "chip found\n");
+
+ /* Register sysfs hooks */
+ status = sysfs_create_group(&client->dev.kobj, &ym2651y_group);
+ if (status) {
+ goto exit_free;
+ }
+
+ data->hwmon_dev = hwmon_device_register(&client->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ status = PTR_ERR(data->hwmon_dev);
+ goto exit_remove;
+ }
+
+ dev_info(&client->dev, "%s: psu '%s'\n",
+ dev_name(data->hwmon_dev), client->name);
+
+ return 0;
+
+exit_remove:
+ sysfs_remove_group(&client->dev.kobj, &ym2651y_group);
+exit_free:
+ kfree(data);
+exit:
+
+ return status;
+}
+
+static int ym2651y_remove(struct i2c_client *client)
+{
+ struct ym2651y_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &ym2651y_group);
+ kfree(data);
+
+ return 0;
+}
+
+static const struct i2c_device_id ym2651y_id[] = {
+ { "ym2651", YM2651 },
+ { "ym2401", YM2401 },
+ { "ym2851", YM2851 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, ym2651y_id);
+
+static struct i2c_driver ym2651y_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "ym2651",
+ },
+ .probe = ym2651y_probe,
+ .remove = ym2651y_remove,
+ .id_table = ym2651y_id,
+ .address_list = normal_i2c,
+};
+
+static int ym2651y_read_byte(struct i2c_client *client, u8 reg)
+{
+ return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int ym2651y_read_word(struct i2c_client *client, u8 reg)
+{
+ return i2c_smbus_read_word_data(client, reg);
+}
+
+static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value)
+{
+ return i2c_smbus_write_word_data(client, reg, value);
+}
+
+static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data,
+ int data_len)
+{
+ int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data);
+
+ if (unlikely(result < 0))
+ goto abort;
+ if (unlikely(result != data_len)) {
+ result = -EIO;
+ goto abort;
+ }
+
+ result = 0;
+
+abort:
+ return result;
+}
+
+struct reg_data_byte {
+ u8 reg;
+ u8 *value;
+};
+
+struct reg_data_word {
+ u8 reg;
+ u16 *value;
+};
+
+static struct ym2651y_data *ym2651y_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct ym2651y_data *data = i2c_get_clientdata(client);
+
+ mutex_lock(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+ || !data->valid) {
+ int i, status;
+ u8 command;
+ u8 fan_dir[5] = {0};
+ struct reg_data_byte regs_byte[] = { {0x19, &data->capability},
+ {0x7d, &data->over_temp},
+ {0x81, &data->fan_fault},
+ {0x98, &data->pmbus_revision}
+ };
+ struct reg_data_word regs_word[] = { {0x79, &data->status_word},
+ {0x8b, &data->v_out},
+ {0x8c, &data->i_out},
+ {0x96, &data->p_out},
+ {0x8d, &data->temp},
+ {0x3b, &(data->fan_duty_cycle[0])},
+ {0x3c, &(data->fan_duty_cycle[1])},
+ {0x90, &data->fan_speed},
+ {0xa0, &data->mfr_vin_min},
+ {0xa1, &data->mfr_vin_max},
+ {0xa2, &data->mfr_iin_max},
+ {0xa3, &data->mfr_pin_max},
+ {0xa4, &data->mfr_vout_min},
+ {0xa5, &data->mfr_vout_max},
+ {0xa6, &data->mfr_iout_max},
+ {0xa7, &data->mfr_pout_max}
+ };
+
+ dev_dbg(&client->dev, "Starting ym2651 update\n");
+
+ /* Read byte data */
+ for (i = 0; i < ARRAY_SIZE(regs_byte); i++) {
+ status = ym2651y_read_byte(client, regs_byte[i].reg);
+
+ if (status < 0)
+ {
+ dev_dbg(&client->dev, "reg %d, err %d\n",
+ regs_byte[i].reg, status);
+ *(regs_byte[i].value) = 0;
+ }
+ else {
+ *(regs_byte[i].value) = status;
+ }
+ }
+
+ /* Read word data */
+ for (i = 0; i < ARRAY_SIZE(regs_word); i++) {
+ status = ym2651y_read_word(client, regs_word[i].reg);
+
+ if (status < 0)
+ {
+ dev_dbg(&client->dev, "reg %d, err %d\n",
+ regs_word[i].reg, status);
+ *(regs_word[i].value) = 0;
+ }
+ else {
+ *(regs_word[i].value) = status;
+ }
+ }
+
+ /* Read fan_direction */
+ command = 0xC3;
+ status = ym2651y_read_block(client, command, fan_dir, ARRAY_SIZE(fan_dir)-1);
+
+ if (status < 0) {
+ dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
+ }
+
+ strncpy(data->fan_dir, fan_dir+1, ARRAY_SIZE(data->fan_dir)-1);
+ data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0';
+
+ /* Read mfr_id */
+ command = 0x99;
+ status = ym2651y_read_block(client, command, data->mfr_id,
+ ARRAY_SIZE(data->mfr_id)-1);
+ data->mfr_id[ARRAY_SIZE(data->mfr_id)-1] = '\0';
+
+ if (status < 0)
+ dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
+
+ /* Read mfr_model */
+ command = 0x9a;
+ status = ym2651y_read_block(client, command, data->mfr_model,
+ ARRAY_SIZE(data->mfr_model)-1);
+ data->mfr_model[ARRAY_SIZE(data->mfr_model)-1] = '\0';
+
+ if (status < 0)
+ dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
+
+ /* Read mfr_revsion */
+ command = 0x9b;
+ status = ym2651y_read_block(client, command, data->mfr_revsion,
+ ARRAY_SIZE(data->mfr_revsion)-1);
+ data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0';
+
+ if (status < 0)
+ dev_dbg(&client->dev, "reg %d, err %d\n", command, status);
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
+
+module_i2c_driver(ym2651y_driver);
+
+MODULE_AUTHOR("Brandon Chuang ");
+MODULE_DESCRIPTION("3Y Power YM-2651Y driver");
+MODULE_LICENSE("GPL");
+
+
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/service/qfx5210-platform-init.service b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/service/qfx5210-platform-init.service
old mode 100755
new mode 100644
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/sonic_platform/__init__.py
deleted file mode 100755
index 9e1b2e56b1..0000000000
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/sonic_platform/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-import platform
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/sonic_platform/platform.py
deleted file mode 100755
index 5620fec54f..0000000000
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/sonic_platform/platform.py
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/usr/bin/env python
-#
-# Name: platform.py, version: 1.0
-#
-# Description: Module contains the definitions of SONiC platform APIs
-# which provide the platform specific details
-#
-# Copyright (c) 2019, Juniper Networks, Inc.
-# All rights reserved.
-#
-# Notice and Disclaimer: This code is licensed to you under the GNU General
-# Public License as published by the Free Software Foundation, version 3 or
-# any later version. This code is not an official Juniper product. You can
-# obtain a copy of the License at
-#
-# OSS License:
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-#
-# Third-Party Code: This code may depend on other components under separate
-# copyright notice and license terms. Your use of the source code for those
-# components is subject to the terms and conditions of the respective license
-# as noted in the Third-Party source code file.
-#
-
-
-import sys
-
-try:
- from sonic_platform_base.platform_base import PlatformBase
-except ImportError as e:
- raise ImportError("%s - required module not found" % e)
-
-platformDict = {'platform':'QFX5210-64C'}
-
-class Platform(PlatformBase):
- def __init__(self):
- self.platform = self.getPlatform()
-
- def getPlatformDict(self):
- global platformDict
- if platformDict:
- return platformDict
-
- def readPlatformName(self):
- return self.getPlatformDict().get('platform')
-
- def getPlatform(self):
- platformCls = self.readPlatformName()
- return platformCls
-
- def get_chassis(self):
- from chassis import Chassis
- chassis = Chassis()
- return chassis
-
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_monitor.py b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_monitor.py
index dbf0b83124..77eac52342 100755
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_monitor.py
+++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_monitor.py
@@ -35,20 +35,12 @@
try:
import os
import commands
- import sys, getopt
import subprocess
- import click
- import imp
import logging
import logging.config
import logging.handlers
- import types
import time
- import traceback
import glob
- import collections
- import StringIO
- from tabulate import tabulate
except ImportError as e:
raise ImportError('%s - required module not found' % str(e))
@@ -58,17 +50,16 @@ FUNCTION_NAME = '/var/log/juniper_qfx5210_monitor'
verbose = False
DEBUG = False
-global log_file
-global log_level
+log_file = '%s.log' % FUNCTION_NAME
+log_level = logging.DEBUG
-
-global isPlatformAFI
-global is80PerFlag
-global is60PerFlag
-global isFireThresholdReached
-global isFireThresholdPrint
-global PrevASICValue
-global FireThresholdSecsRemaining
+isPlatformAFI = False
+is80PerFlag = True
+is60PerFlag = True
+isFireThresholdReached = False
+isFireThresholdPrint = True
+PrevASICValue = 0
+FireThresholdSecsRemaining = 120
temp_policy_AFI = {
0: [[70, 0, 48000], [70, 48000, 53000], [80, 53000, 0], [80, 53000, 58000], [100, 58000, 0], ['Yellow Alarm', 64000, 70000], ['Red Alarm', 70000, 75000], ['Fire Shut Alarm', 75000, 0]],
@@ -201,7 +192,7 @@ class QFX5210_ThermalUtil(object):
try:
val_file.close()
- except:
+ except IOError as e:
logging.debug('get_sensor_node_val: unable to close file. device_path:%s', device_path)
return None
@@ -227,8 +218,8 @@ class QFX5210_ThermalUtil(object):
return None
try:
- val_file.close()
- except:
+ val_file.close()
+ except IOError as e:
logging.debug('get_coretemp_node_val: unable to close file. device_path:%s', device_path)
return None
@@ -326,7 +317,7 @@ class QFX5210_ThermalUtil(object):
isFireThresholdReached == False
time.sleep(20)
cmd = "poweroff"
- returned_value = os.system(cmd)
+ os.system(cmd)
for x in range(self.SENSOR_CORETEMP_NUM_ON_MAIN_BOARD):
if x < self.SENSOR_NUM_ON_MAIN_BOARD:
@@ -340,7 +331,7 @@ class QFX5210_ThermalUtil(object):
proc = subprocess.Popen("bcmcmd \"show temp\" | grep \"maximum peak temperature\" | awk '{ print $5 }' > /var/log/asic_value 2>&1 & ",shell=True)
time.sleep(2)
cmd = "kill -9 %s"%(proc.pid)
- status, cmd_out = commands.getstatusoutput(cmd)
+ commands.getstatusoutput(cmd)
if os.stat("/var/log/asic_value").st_size == 0:
value = PrevASICValue
@@ -531,13 +522,6 @@ class device_monitor(object):
def __init__(self, log_file, log_level):
global DEBUG
- global isPlatformAFI
- global isFireThresholdReached
- global is80PerFlag
- global is60PerFlag
- global isFireThresholdPrint
- global PrevASICValue
- global FireThresholdSecsRemaining
MASTER_LED_PATH = '/sys/class/leds/master/brightness'
SYSTEM_LED_PATH = '/sys/class/leds/system/brightness'
FANTYPE_PATH = '/sys/bus/i2c/devices/17-0068/fan1_direction'
@@ -561,27 +545,26 @@ class device_monitor(object):
console.setFormatter(formatter)
logging.getLogger('').addHandler(console)
- import sonic_platform
- platform = sonic_platform.platform.Platform()
- chassis = platform.get_chassis()
- fan_type = chassis.get_fan_type(FANTYPE_PATH)
+ try:
+ fan_type_file = open(FANTYPE_PATH)
+ except IOError as e:
+ print "Error: unable to open file: %s" % str(e)
+ fan_type = -1
+ else:
+ fan_type = fan_type_file.read()
+ fan_type_file.close()
+
# the return value of get_fan_type is AFO = 0, AFI = 1 and for error condition it is -1
# In the error condition also, we are making default platform as AFO, to continue with Energy Monitoring
if (int(fan_type) == -1 or int(fan_type) == 0):
+ logging.debug('FANTYPE_PATH. fan_type %d', int(fan_type))
if (int(fan_type) == -1):
logging.error('device_monitor: unable to open sys file for fan handling, defaulting it to AFO')
isPlatformAFI = False
else:
isPlatformAFI = True
- isFireThresholdReached = False
- is80PerFlag = True
- is60PerFlag = True
- isFireThresholdPrint = True
- FireThresholdSecsRemaining = 120
- PrevASICValue = 0
-
master_led_value = 1
try:
masterLED_file = open(MASTER_LED_PATH, 'r+')
@@ -605,9 +588,7 @@ class device_monitor(object):
thermal.getSensorTemp()
def main():
- log_file = '%s.log' % FUNCTION_NAME
- log_level = logging.DEBUG
-
+
#Introducing sleep of 150 seconds to wait for all the docker containers to start before starting the EM policy.
time.sleep(150)
monitor = device_monitor(log_file, log_level)
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_util.py b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_util.py
index b3f130af41..26eed74c94 100755
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_util.py
+++ b/platform/broadcom/sonic-platform-modules-juniper/qfx5210/utils/juniper_qfx5210_util.py
@@ -39,11 +39,7 @@ import commands
import sys, getopt
import binascii
import logging
-import re
import time
-import random
-import optparse
-from collections import namedtuple
@@ -138,145 +134,16 @@ def main():
except OSError:
print 'Error: Execution of "%s" failed', DisableWatchDogCmd
return False
-
-
- CPUeepromFileCmd = 'cat /sys/devices/pci0000:00/0000:00:1f.3/i2c-0/0-0056/eeprom > /etc/init.d/eeprom_qfx5210_ascii'
- # Write the contents of CPU EEPROM to file
+
+ time.sleep(1)
+ # Invoking the script which retrieves the data from Board EEPROM and storing in file
+ EEPROMDataCmd = 'python /usr/share/sonic/device/x86_64-juniper_qfx5210-r0/plugins/qfx5210_eeprom_data.py'
try:
- os.system(CPUeepromFileCmd)
+ os.system(EEPROMDataCmd)
except OSError:
- print 'Error: Execution of "%s" failed', CPUeepromFileCmd
+ print 'Error: Execution of "%s" failed', EEPROMDataCmd
return False
- eeprom_ascii = '/etc/init.d/eeprom_qfx5210_ascii'
- # Read file contents in Hex format
- with open(eeprom_ascii, 'rb') as Hexformat:
- content = Hexformat.read()
- Hexformatoutput = binascii.hexlify(content)
-
- eeprom_hex = '/etc/init.d/eeprom_qfx5210_hex'
- #Write contents of CPU EEPROM to new file in hexa format
- with open(eeprom_hex, 'wb+') as Hexfile:
- Hexfile.write(Hexformatoutput)
-
- # Read from EEPROM Hex file and extract the different fields like Product name,
- # Part Number, Serial Number MAC Address, Mfg Date ... etc and store in /var/run/eeprom file
- with open(eeprom_hex, 'rb') as eeprom_hexfile:
- # moving the file pointer to required position where product name is stored in EEPROM file and reading the required bytes from this position
-
- product_position = eeprom_hexfile.seek(26, 0)
- product_read = eeprom_hexfile.read(36)
- product_name = binascii.unhexlify(product_read)
-
- # creating the "/var/run/eeprom" file and storing all the values of different fields in this file.
- eeprom_file = open ("/var/run/eeprom", "a+")
- eeprom_file.write("Product Name=%s\r\n" % str(product_name))
-
- # like wise we are moving the file pointer to respective position where other fields are stored and extract these fields and store in /var/run/eeprom file
- partnumber_position = eeprom_hexfile.seek(66, 0)
- partnumber_read = eeprom_hexfile.read(20)
- partnumber_name = binascii.unhexlify(partnumber_read)
- eeprom_file.write("Part Number=%s\r\n" % str(partnumber_name))
-
- serialnumber_position = eeprom_hexfile.seek(90, 0)
- serialnumber_read = eeprom_hexfile.read(24)
- serialnumber_name = binascii.unhexlify(serialnumber_read)
- eeprom_file.write("Serial Number=%s\r\n" % str(serialnumber_name))
-
- macaddress_position = eeprom_hexfile.seek(118, 0)
- macaddress_read = eeprom_hexfile.read(12)
- macaddress_name=""
- for i in range(0,12,2):
- macaddress_name += macaddress_read[i:i+2] + ":"
- macaddress_name=macaddress_name[:-1]
- eeprom_file.write("MAC Address=%s\r\n" % str(macaddress_name))
-
- mfgdate_position = eeprom_hexfile.seek(132, 0)
- mfgdate_read = eeprom_hexfile.read(40)
- mfgdate_name = binascii.unhexlify(mfgdate_read)
- eeprom_file.write("Manufacture Date=%s\r\n" % str(mfgdate_name))
-
- devversion_position = eeprom_hexfile.seek(176, 0)
- devversion_read = eeprom_hexfile.read(2)
- eeprom_file.write("Device Version=%s\r\n" % str(devversion_read))
-
- platform_position = eeprom_hexfile.seek(182, 0)
- platform_read = eeprom_hexfile.read(68)
- platform_name = binascii.unhexlify(platform_read)
- eeprom_file.write("Platform Name=%s\r\n" % str(platform_name))
-
- MACnumber_position = eeprom_hexfile.seek(254, 0)
- MACnumber_read = eeprom_hexfile.read(4)
- MACnumber = int(MACnumber_read, 16)
- eeprom_file.write("Number of MAC Addresses=%s\r\n" % str(MACnumber))
-
- vendorName_position = eeprom_hexfile.seek(262, 0)
- vendorName_read = eeprom_hexfile.read(40)
- vendorName = binascii.unhexlify(vendorName_read)
- eeprom_file.write("Vendor Name=%s\r\n" % str(vendorName))
-
- mfgname_position = eeprom_hexfile.seek(306, 0)
- mfgname_read = eeprom_hexfile.read(40)
- mfgname = binascii.unhexlify(mfgname_read)
- eeprom_file.write("Manufacture Name=%s\r\n" % str(mfgname))
-
- vendorext_position = eeprom_hexfile.seek(350, 0)
- vendorext_read = eeprom_hexfile.read(124)
- vendorext=""
- vendorext += "0x" + vendorext_read[0:2]
- for i in range(2,124,2):
- vendorext += " 0x" + vendorext_read[i:i+2]
- eeprom_file.write("Vendor Extension=%s\r\n" % str(vendorext))
-
- IANA_position = eeprom_hexfile.seek(350, 0)
- IANA_read = eeprom_hexfile.read(8)
- IANAName = binascii.unhexlify(IANA_read)
- eeprom_file.write("IANA=%s\r\n" % str(IANAName))
-
- ASMpartrev_position = eeprom_hexfile.seek(358, 0)
- ASMpartrev_read = eeprom_hexfile.read(4)
- ASMpartrev = binascii.unhexlify(ASMpartrev_read)
- eeprom_file.write("Assembly Part Number Rev=%s\r\n" % str(ASMpartrev))
-
- ASMpartnum_position = eeprom_hexfile.seek(374, 0)
- ASMpartnum_read = eeprom_hexfile.read(20)
- ASMpartnum_read = binascii.unhexlify(ASMpartnum_read)
- eeprom_file.write("Assembly Part Number=%s\r\n" % str(ASMpartnum_read))
-
- ASMID_position = eeprom_hexfile.seek(402, 0)
- ASMID_read = eeprom_hexfile.read(4)
- ASMID_read_upper = ASMID_read.upper()
- eeprom_file.write("Assembly ID=0x%s\r\n" % str(ASMID_read_upper))
-
- ASMHWMajRev_position = eeprom_hexfile.seek(410, 0)
- ASMHWMajRev_read = eeprom_hexfile.read(2)
- eeprom_file.write("Assembly Major Revision=0x%s\r\n" % str(ASMHWMajRev_read))
-
- ASMHWMinRev_position = eeprom_hexfile.seek(416, 0)
- ASMHWMinRev_read = eeprom_hexfile.read(2)
- eeprom_file.write("Assembly Minor Revision=0x%s\r\n" % str(ASMHWMinRev_read))
-
- Deviation_position = eeprom_hexfile.seek(422, 0)
- Deviation_read = eeprom_hexfile.read(28)
- Deviation_read_upper = Deviation_read.upper()
- eeprom_file.write("Deviation=0x%s\r\n" % str(Deviation_read_upper))
-
- CLEI_position = eeprom_hexfile.seek(450, 0)
- CLEI_read = eeprom_hexfile.read(20)
- CLEI_name = binascii.unhexlify(CLEI_read)
- eeprom_file.write("CLEI code=%s\r\n" % str(CLEI_name))
-
- ONIEversion_position = eeprom_hexfile.seek(478, 0)
- ONIEversion_read = eeprom_hexfile.read(22)
- ONIEversion = binascii.unhexlify(ONIEversion_read)
- eeprom_file.write("ONIE Version=%s\r\n" % str(ONIEversion))
-
- CRC_position = eeprom_hexfile.seek(504, 0)
- CRC = eeprom_hexfile.read(8)
- eeprom_file.write("CRC=%s\r\n" % str(CRC))
-
- eeprom_file.close()
-
return True
def show_help():
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/setup.py b/platform/broadcom/sonic-platform-modules-juniper/setup.py
similarity index 57%
rename from platform/broadcom/sonic-platform-modules-juniper/qfx5210/setup.py
rename to platform/broadcom/sonic-platform-modules-juniper/setup.py
index 536f814a35..283c00d386 100755
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/setup.py
+++ b/platform/broadcom/sonic-platform-modules-juniper/setup.py
@@ -8,9 +8,9 @@ os.listdir
setup(
name='sonic_platform',
version='1.0',
- description='Module to initialize Juniper QFX5210-64X platforms',
+ description='Module to initialize Juniper platforms',
packages=['sonic_platform'],
- package_dir={'sonic_platform': 'qfx5210/sonic_platform'},
+ package_dir={'sonic_platform': 'sonic_platform'},
)
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/sonic_platform/__init__.py b/platform/broadcom/sonic-platform-modules-juniper/sonic_platform/__init__.py
similarity index 100%
rename from platform/broadcom/sonic-platform-modules-juniper/qfx5200/sonic_platform/__init__.py
rename to platform/broadcom/sonic-platform-modules-juniper/sonic_platform/__init__.py
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-juniper/sonic_platform/chassis.py
similarity index 54%
rename from platform/broadcom/sonic-platform-modules-juniper/qfx5210/sonic_platform/chassis.py
rename to platform/broadcom/sonic-platform-modules-juniper/sonic_platform/chassis.py
index 674d9184df..0e3d43fa07 100755
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5210/sonic_platform/chassis.py
+++ b/platform/broadcom/sonic-platform-modules-juniper/sonic_platform/chassis.py
@@ -5,7 +5,7 @@
# Description: Module contains the definitions of SONiC platform APIs
# which provide the chassis specific details
#
-# Copyright (c) 2019, Juniper Networks, Inc.
+# Copyright (c) 2020, Juniper Networks, Inc.
# All rights reserved.
#
# Notice and Disclaimer: This code is licensed to you under the GNU General
@@ -39,26 +39,24 @@ try:
import commands
import sys
import time
+ import syslog
from sonic_platform_base.chassis_base import ChassisBase
except ImportError as e:
raise ImportError(str(e) + "- required module not found")
+SYSLOG_IDENTIFIER = "Juniper-Chassis"
+
+def log_info(msg):
+ syslog.openlog(SYSLOG_IDENTIFIER)
+ syslog.syslog(syslog.LOG_INFO, msg)
+ syslog.closelog()
class Chassis(ChassisBase):
- """
- JUNIPER QFX5210 Platform-specific Chassis class
- """
-
- # Find the last reboot reason out of following
- # CPLD_WATCHDOG_RESET 0x08
- # POWER_ON_RESET 0x20
- # CPU_WATCHDOG_RESET 0x40
- # SOFTWARE_RESET 0x80
def __init__(self):
ChassisBase.__init__(self)
- def get_qfx5210_parameter_value(self,parameter_name):
+ def get_parameter_value(self,parameter_name):
try:
with open("/var/run/eeprom", "r") as file:
for item in file:
@@ -71,7 +69,7 @@ class Chassis(ChassisBase):
return "False"
def get_product_name(self):
- product_name_list = self.get_qfx5210_parameter_value('Product Name')
+ product_name_list = self.get_parameter_value('Product Name')
if product_name_list:
product_name = ''.join(product_name_list)
return product_name
@@ -80,7 +78,7 @@ class Chassis(ChassisBase):
def get_part_number(self):
- part_number_list = self.get_qfx5210_parameter_value('Part Number')
+ part_number_list = self.get_parameter_value('Part Number')
if part_number_list:
part_number = ''.join(part_number_list)
return part_number
@@ -89,7 +87,7 @@ class Chassis(ChassisBase):
def get_serial_number(self):
- serial_number_list = self.get_qfx5210_parameter_value('Serial Number')
+ serial_number_list = self.get_parameter_value('Serial Number')
if serial_number_list:
serial_number = ''.join(serial_number_list)
return serial_number
@@ -98,7 +96,7 @@ class Chassis(ChassisBase):
def get_base_mac(self):
- mac_list = self.get_qfx5210_parameter_value('MAC')
+ mac_list = self.get_parameter_value('MAC')
if mac_list:
mac = ''.join(mac_list)
return mac
@@ -107,7 +105,7 @@ class Chassis(ChassisBase):
def get_mfg_date(self):
- mfgdate_list = self.get_qfx5210_parameter_value('Manufacture Date')
+ mfgdate_list = self.get_parameter_value('Manufacture Date')
if mfgdate_list:
mfgdate = ''.join(mfgdate_list)
return mfgdate
@@ -115,7 +113,7 @@ class Chassis(ChassisBase):
return False
def get_deviceversion_name(self):
- device_version_list = self.get_qfx5210_parameter_value('Device Version')
+ device_version_list = self.get_parameter_value('Device Version')
if device_version_list:
deviceversion_name = ''.join(device_version_list)
return deviceversion_name
@@ -123,7 +121,7 @@ class Chassis(ChassisBase):
return False
def get_platform_name(self):
- platform_name_list = self.get_qfx5210_parameter_value('Platform Name')
+ platform_name_list = self.get_parameter_value('Platform Name')
if platform_name_list:
platform_name = ''.join(platform_name_list)
return platform_name
@@ -131,7 +129,7 @@ class Chassis(ChassisBase):
return False
def get_MACnumber_name(self):
- MACnumber_name_list = self.get_qfx5210_parameter_value('Number of MAC Addresses')
+ MACnumber_name_list = self.get_parameter_value('Number of MAC Addresses')
if MACnumber_name_list:
MACnumber_name = ''.join(MACnumber_name_list)
return MACnumber_name
@@ -139,7 +137,7 @@ class Chassis(ChassisBase):
return False
def get_vendor_name(self):
- vendor_name_list = self.get_qfx5210_parameter_value('Vendor Name')
+ vendor_name_list = self.get_parameter_value('Vendor Name')
if vendor_name_list:
vendor_name = ''.join(vendor_name_list)
return vendor_name
@@ -147,7 +145,7 @@ class Chassis(ChassisBase):
return False
def get_mfg_name(self):
- mfg_name_list = self.get_qfx5210_parameter_value('Manufacture Name')
+ mfg_name_list = self.get_parameter_value('Manufacture Name')
if mfg_name_list:
mfg_name = ''.join(mfg_name_list)
return mfg_name
@@ -155,7 +153,7 @@ class Chassis(ChassisBase):
return False
def get_vendorext_name(self):
- vendorext_list = self.get_qfx5210_parameter_value('Vendor Extension')
+ vendorext_list = self.get_parameter_value('Vendor Extension')
if vendorext_list:
vendorext = ''.join(vendorext_list)
return vendorext
@@ -163,7 +161,7 @@ class Chassis(ChassisBase):
return False
def get_vendorextIANA_name(self):
- vendorext_list = self.get_qfx5210_parameter_value('IANA')
+ vendorext_list = self.get_parameter_value('IANA')
if vendorext_list:
vendorext = ''.join(vendorext_list)
return vendorext
@@ -171,7 +169,7 @@ class Chassis(ChassisBase):
return False
def get_vendorextASMREV_name(self):
- vendorext_list = self.get_qfx5210_parameter_value('Assembly Part Number Rev')
+ vendorext_list = self.get_parameter_value('Assembly Part Number Rev')
if vendorext_list:
vendorext = ''.join(vendorext_list)
return vendorext
@@ -179,7 +177,7 @@ class Chassis(ChassisBase):
return False
def get_vendorextASMPartNum_name(self):
- vendorext_list = self.get_qfx5210_parameter_value('Assembly Part Number')
+ vendorext_list = self.get_parameter_value('Assembly Part Number')
if vendorext_list:
vendorext = ''.join(vendorext_list)
return vendorext
@@ -187,7 +185,7 @@ class Chassis(ChassisBase):
return False
def get_vendorextASMID_name(self):
- vendorext_list = self.get_qfx5210_parameter_value('Assembly ID')
+ vendorext_list = self.get_parameter_value('Assembly ID')
if vendorext_list:
vendorext = ''.join(vendorext_list)
return vendorext
@@ -195,7 +193,7 @@ class Chassis(ChassisBase):
return False
def get_vendorextASMMajNum_name(self):
- vendorext_list = self.get_qfx5210_parameter_value('Assembly Major Revision')
+ vendorext_list = self.get_parameter_value('Assembly Major Revision')
if vendorext_list:
vendorext = ''.join(vendorext_list)
return vendorext
@@ -203,7 +201,7 @@ class Chassis(ChassisBase):
return False
def get_vendorextASMMinNum_name(self):
- vendorext_list = self.get_qfx5210_parameter_value('Assembly Minor Revision')
+ vendorext_list = self.get_parameter_value('Assembly Minor Revision')
if vendorext_list:
vendorext = ''.join(vendorext_list)
return vendorext
@@ -211,7 +209,7 @@ class Chassis(ChassisBase):
return False
def get_vendorextCLEI_name(self):
- vendorext_list = self.get_qfx5210_parameter_value('CLEI code')
+ vendorext_list = self.get_parameter_value('CLEI code')
if vendorext_list:
vendorext = ''.join(vendorext_list)
return vendorext
@@ -219,7 +217,7 @@ class Chassis(ChassisBase):
return False
def get_onieversion_name(self):
- onieversion_name_list = self.get_qfx5210_parameter_value('ONIE Version')
+ onieversion_name_list = self.get_parameter_value('ONIE Version')
if onieversion_name_list:
onieversion_name = ''.join(onieversion_name_list)
return onieversion_name
@@ -227,51 +225,75 @@ class Chassis(ChassisBase):
return False
def get_crc_name(self):
- crc_list = self.get_qfx5210_parameter_value('CRC')
+ crc_list = self.get_parameter_value('CRC')
if crc_list:
crc_name = ''.join(crc_list)
return crc_name
else:
return False
- def get_fan_type(self, fantype_path):
- try:
- fan_type_file = open(fantype_path)
- except IOError as e:
- print "Error: unable to open file: %s" % str(e)
- return "-1"
- else:
- fan_type = fan_type_file.read()
- fan_type_file.close()
- return str(fan_type)
-
-
def get_reboot_cause(self):
"""
Retrieves the cause of the previous reboot
"""
- status, last_reboot_reason = commands.getstatusoutput("i2cget -y 0 0x65 0x24")
- if (status == 0):
- if last_reboot_reason == "0x80":
- return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)
- elif last_reboot_reason == "0x40" or last_reboot_reason == "0x08":
- return (ChassisBase.REBOOT_CAUSE_WATCHDOG, None)
- elif last_reboot_reason == "0x20":
- return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None)
- elif last_reboot_reason == "0x10":
- return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Swizzle Reset")
+ platform_name = self.get_platform_name()
+ platform_name = platform_name.replace("\r","")
+ platform_name = platform_name.replace("\n","")
+ log_info("Juniper Platform name: {} and {}".format(self.get_platform_name(), platform_name))
+ if str(platform_name) == "x86_64-juniper_networks_qfx5210-r0":
+ log_info("Juniper Platform QFX5210 ")
+ status, last_reboot_reason = commands.getstatusoutput("i2cget -f -y 0 0x65 0x24")
+ if (status == 0):
+ if last_reboot_reason == "0x80":
+ return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)
+ elif last_reboot_reason == "0x40" or last_reboot_reason == "0x08":
+ return (ChassisBase.REBOOT_CAUSE_WATCHDOG, None)
+ elif last_reboot_reason == "0x20":
+ return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None)
+ elif last_reboot_reason == "0x10":
+ return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Swizzle Reset")
+ else:
+ return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Unknown reason")
else:
- return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Unknown reason")
+ time.sleep(3)
+ status, last_reboot_reason = commands.getstatusoutput("i2cget -f -y 0 0x65 0x24")
+ if last_reboot_reason == "0x80":
+ return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)
+ elif last_reboot_reason == "0x40" or last_reboot_reason == "0x08":
+ return (ChassisBase.REBOOT_CAUSE_WATCHDOG, None)
+ elif last_reboot_reason == "0x20":
+ return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None)
+ elif last_reboot_reason == "0x10":
+ return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Swizzle Reset")
+ else:
+ return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Unknown reason")
+
+ elif str(platform_name) == "x86_64-juniper_networks_qfx5200-r0" :
+ log_info("Juniper Platform QFX5200 ")
+ status, last_reboot_reason = commands.getstatusoutput("busybox devmem 0xFED50004 8")
+ if (status == 0):
+ if last_reboot_reason == "0x80":
+ return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)
+ elif last_reboot_reason == "0x40" or last_reboot_reason == "0x08":
+ return (ChassisBase.REBOOT_CAUSE_WATCHDOG, None)
+ elif last_reboot_reason == "0x20":
+ return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None)
+ elif last_reboot_reason == "0x10":
+ return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Swizzle Reset")
+ else:
+ return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Unknown reason")
+ else:
+ time.sleep(3)
+ status, last_reboot_reason = commands.getstatusoutput("busybox devmem 0xFED50004 8")
+ if last_reboot_reason == "0x80":
+ return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)
+ elif last_reboot_reason == "0x40" or last_reboot_reason == "0x08":
+ return (ChassisBase.REBOOT_CAUSE_WATCHDOG, None)
+ elif last_reboot_reason == "0x20":
+ return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None)
+ elif last_reboot_reason == "0x10":
+ return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Swizzle Reset")
+ else:
+ return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Unknown reason")
else:
- time.sleep(3)
- status, last_reboot_reason = commands.getstatusoutput("i2cget -y 0 0x65 0x24")
- if last_reboot_reason == "0x80":
- return (ChassisBase.REBOOT_CAUSE_NON_HARDWARE, None)
- elif last_reboot_reason == "0x40" or last_reboot_reason == "0x08":
- return (ChassisBase.REBOOT_CAUSE_WATCHDOG, None)
- elif last_reboot_reason == "0x20":
- return (ChassisBase.REBOOT_CAUSE_POWER_LOSS, None)
- elif last_reboot_reason == "0x10":
- return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Swizzle Reset")
- else:
- return (ChassisBase.REBOOT_CAUSE_HARDWARE_OTHER, "Unknown reason")
+ log_info("Juniper QFX5200 and QFX5210 platforms are supported")
diff --git a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/sonic_platform/platform.py b/platform/broadcom/sonic-platform-modules-juniper/sonic_platform/platform.py
similarity index 73%
rename from platform/broadcom/sonic-platform-modules-juniper/qfx5200/sonic_platform/platform.py
rename to platform/broadcom/sonic-platform-modules-juniper/sonic_platform/platform.py
index a9e70c7251..c3a596111d 100755
--- a/platform/broadcom/sonic-platform-modules-juniper/qfx5200/sonic_platform/platform.py
+++ b/platform/broadcom/sonic-platform-modules-juniper/sonic_platform/platform.py
@@ -2,7 +2,7 @@
#
# Name: platform.py, version: 1.0
#
-# Description: Module contains the definitions of SONiC platform APIs
+# Description: Module contains the definition of SONiC platform API
# which provide the platform specific details
#
# Copyright (c) 2020, Juniper Networks, Inc.
@@ -35,31 +35,18 @@
#
+import sys
+
try:
from sonic_platform_base.platform_base import PlatformBase
+ from sonic_platform.chassis import Chassis
except ImportError as e:
raise ImportError("%s - required module not found" % e)
-platformDict = {'platform':'QFX5200-32C'}
-
class Platform(PlatformBase):
+ """
+ Juniper Platform-specific class
+ """
def __init__(self):
- self.platform = self.getPlatform()
-
- def getPlatformDict(self):
- global platformDict
- if platformDict:
- return platformDict
-
- def readPlatformName(self):
- return self.getPlatformDict().get('platform')
-
- def getPlatform(self):
- platformCls = self.readPlatformName()
- return platformCls
-
- def get_chassis(self):
- from chassis import Chassis
- chassis = Chassis()
- return chassis
-
+ PlatformBase.__init__(self)
+ self._chassis = Chassis()