diff --git a/packages/base/all/vendor-config-onl/src/python/onl/install/ShellApp.py b/packages/base/all/vendor-config-onl/src/python/onl/install/ShellApp.py index fcf7f93d..4b363e73 100644 --- a/packages/base/all/vendor-config-onl/src/python/onl/install/ShellApp.py +++ b/packages/base/all/vendor-config-onl/src/python/onl/install/ShellApp.py @@ -242,8 +242,9 @@ class OnieSysinfoApp(SubprocessMixin, object): with InitrdContext(initrd=initrd, log=self.log) as ctx: cmd = ['onie-sysinfo',] cmd.extend(self.args) + cmd = 'IFS=;' + " ".join(cmd) cmd = ('chroot', ctx.dir, - '/bin/sh', '-c', 'IFS=;' + " ".join(cmd)) + '/bin/sh', '-c', cmd,) try: self.output = self.check_output(cmd) ret = 0 diff --git a/packages/base/all/vendor-config-onl/src/python/onl/pki/__init__.py b/packages/base/all/vendor-config-onl/src/python/onl/pki/__init__.py index eec0f7fc..35c891bc 100755 --- a/packages/base/all/vendor-config-onl/src/python/onl/pki/__init__.py +++ b/packages/base/all/vendor-config-onl/src/python/onl/pki/__init__.py @@ -8,11 +8,8 @@ import sys import os import argparse import logging -import tempfile import shutil -import subprocess import tempfile -import yaml from onl.mounts import OnlMountManager, OnlMountContextReadOnly, OnlMountContextReadWrite from onl.sysconfig import sysconfig from onl.util import * @@ -50,39 +47,70 @@ class OnlPki(OnlServiceMixin): self.init_cert(force=force) def init_key(self, force=False): - with OnlPkiContextReadOnly(self.logger): - if not os.path.exists(self.kpath) or force: - self.logger.info("Generating private key...") - cmd = "openssl genrsa -out %s %s" % (self.kpath, sysconfig.pki.key.len) - with OnlPkiContextReadWrite(self.logger): - if not os.path.isdir(self.CONFIG_PKI_DIR): - os.makedirs(self.CONFIG_PKI_DIR) - self._execute(cmd) - self.init_cert(force=True) - else: - self.logger.info("Using existing private key.") + need_key = False + need_cert = False + + if force: + need_key = True + else: + with OnlPkiContextReadOnly(self.logger): + if not os.path.exists(self.kpath): + need_key = True + + if need_key: + self.logger.info("Generating private key...") + cmd = ('openssl', 'genrsa', + '-out', self.kpath, + str(sysconfig.pki.key.len),) + with OnlPkiContextReadWrite(self.logger): + if not os.path.isdir(self.CONFIG_PKI_DIR): + os.makedirs(self.CONFIG_PKI_DIR) + self._execute(cmd, logLevel=logging.INFO) + need_cert = True + else: + self.logger.info("Using existing private key.") + + if need_cert: + self.init_cert(force=True) def init_cert(self, force=False): - with OnlPkiContextReadOnly(self.logger): - if not os.path.exists(self.cpath) or force: - self.logger.info("Generating self-signed certificate...") - csr = tempfile.NamedTemporaryFile(prefix="pki-", suffix=".csr", delete=False) - csr.close() - fields = [ "%s=%s" % (k, v) for k,v in sysconfig.pki.cert.csr.fields.iteritems() ] - subject = "/" + "/".join(fields) - self.logger.debug("Subject: '%s'", subject) - self.logger.debug("CSR: %s", csr.name) - with OnlPkiContextReadWrite(self.logger): - if not os.path.isdir(self.CONFIG_PKI_DIR): - os.makedirs(self.CONFIG_PKI_DIR) - self._execute("""openssl req -new -batch -subj "%s" -key %s -out %s""" % ( - subject, self.kpath, csr.name)) - self._execute("""openssl x509 -req -days %s -sha256 -in %s -signkey %s -out %s""" % ( - sysconfig.pki.cert.csr.cdays, - csr.name, self.kpath, self.cpath)) - os.unlink(csr.name) - else: - self.logger.info("Using existing certificate.") + need_cert = False + + if force: + need_cert = True + else: + with OnlPkiContextReadOnly(self.logger): + if not os.path.exists(self.cpath): + need_cert = True + + if need_cert: + self.logger.info("Generating self-signed certificate...") + csr = tempfile.NamedTemporaryFile(prefix="pki-", suffix=".csr", delete=False) + csr.close() + fields = [ "%s=%s" % (k, v) for k,v in sysconfig.pki.cert.csr.fields.iteritems() ] + subject = "/" + "/".join(fields) + self.logger.debug("Subject: '%s'", subject) + self.logger.debug("CSR: %s", csr.name) + with OnlPkiContextReadWrite(self.logger): + if not os.path.isdir(self.CONFIG_PKI_DIR): + os.makedirs(self.CONFIG_PKI_DIR) + self._execute(('openssl', 'req', + '-new', '-batch', + '-subj', subject, + '-key', self.kpath, + '-out', csr.name,), + logLevel=logging.INFO) + self._execute(('openssl', 'x509', + '-req', + '-days', str(sysconfig.pki.cert.csr.cdays), + '-sha256', + '-in', csr.name, + '-signkey', self.kpath, + '-out', self.cpath,), + logLevel=logging.INFO) + os.unlink(csr.name) + else: + self.logger.info("Using existing certificate.") @staticmethod def main(): diff --git a/packages/base/all/vendor-config-onl/src/python/onl/util/__init__.py b/packages/base/all/vendor-config-onl/src/python/onl/util/__init__.py index c085b3f2..f625f2b5 100644 --- a/packages/base/all/vendor-config-onl/src/python/onl/util/__init__.py +++ b/packages/base/all/vendor-config-onl/src/python/onl/util/__init__.py @@ -1,18 +1,49 @@ import subprocess +import logging class OnlServiceMixin(object): - def _execute(self, cmd, root=False, ex=True): - self.logger.debug("Executing: %s" % cmd) + + def _execute(self, cmd, + root=False, ex=True, + logLevel=logging.DEBUG): + self.logger.log(logLevel, "Executing: %s", cmd) + + if isinstance(cmd, basestring): + shell = True + else: + shell = False + if root is True and os.getuid() != 0: - cmd = "sudo " + cmd + if isinstance(cmd, basestring): + cmd = "sudo " + cmd + else: + cmd = ['sudo',] + list(cmd) + try: - subprocess.check_call(cmd, shell=True) - except Exception, e: + pipe = subprocess.Popen(cmd, shell=shell, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + except OSError as e: if ex: - self.logger.error("Command failed: %s" % e) + self.logger.error("Command did not start: %s (%s)", + str(e), str(e.child_traceback),) raise else: - return e.returncode + return -1 + + out, _ = pipe.communicate() + code = pipe.wait() + + lvl = logging.WARN if code else logLevel + out = (out or "").rstrip() + for line in out.splitlines(False): + self.logger.log(lvl, ">>> %s", line) + + if ex and code: + self.logger.error("Command failed with code %s", code) + raise subprocess.CalledProcessError(code, cmd) + + return code def _raise(self, msg, klass): self.logger.critical(msg) diff --git a/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/arm-iproc-all.config b/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/arm-iproc-all.config index e70dd3b3..6d420e0f 100644 --- a/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/arm-iproc-all.config +++ b/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/arm-iproc-all.config @@ -868,7 +868,7 @@ CONFIG_EEPROM_AT25=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_EEPROM_93XX46 is not set # CONFIG_EEPROM_SFF_8436 is not set -CONFIG_EEPROM_ACCTON_AS4610_SFP=y +CONFIG_EEPROM_OPTOE=y # CONFIG_CB710_CORE is not set # CONFIG_IWMC3200TOP is not set @@ -1497,7 +1497,7 @@ CONFIG_SENSORS_W83781D=y # CONFIG_SENSORS_W83L786NG is not set # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set -CONFIG_SENSORS_ACCTON_I2C_CPLD=y +CONFIG_SENSORS_ACCTON_AS4610_CPLD=y CONFIG_SENSORS_ACCTON_AS4610_FAN=y CONFIG_SENSORS_ACCTON_AS4610_PSU=y CONFIG_SENSORS_YM2651Y=y diff --git a/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/patches/arch_arm_boot_dts_accton_as4610_54.dts.patch b/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/patches/arch_arm_boot_dts_accton_as4610_54.dts.patch index 7737f9ef..5d5e0485 100644 --- a/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/patches/arch_arm_boot_dts_accton_as4610_54.dts.patch +++ b/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/patches/arch_arm_boot_dts_accton_as4610_54.dts.patch @@ -1,6 +1,6 @@ --- /dev/null +++ b/arch/arm/boot/dts/accton_as4610_54.dts -@@ -0,0 +1,250 @@ +@@ -0,0 +1,256 @@ +/* + * Accton AS4610 54 Device Tree Source + * @@ -117,7 +117,7 @@ + cpld@1,0 { + #address-cells = <1>; + #size-cells = <1>; -+ compatible = "accton,as4610-54-cpld"; ++ compatible = "accton,as4610_54_cpld"; + label = "cpld"; + reg = <0x30>; + }; @@ -142,8 +142,8 @@ + #address-cells = <1>; + #size-cells = <0>; + reg = <0>; -+ sfp_eeprom@50 { -+ compatible = "at,24c04"; ++ optoe@50 { ++ compatible = "optoe2"; + reg = <0x50>; + label = "port49"; + }; @@ -154,8 +154,8 @@ + #address-cells = <1>; + #size-cells = <0>; + reg = <1>; -+ sfp_eeprom@50 { -+ compatible = "at,24c04"; ++ optoe@50 { ++ compatible = "optoe2"; + reg = <0x50>; + label = "port50"; + }; @@ -166,8 +166,8 @@ + #address-cells = <1>; + #size-cells = <0>; + reg = <2>; -+ sfp_eeprom@50 { -+ compatible = "at,24c04"; ++ optoe@50 { ++ compatible = "optoe2"; + reg = <0x50>; + label = "port51"; + }; @@ -178,8 +178,8 @@ + #address-cells = <1>; + #size-cells = <0>; + reg = <3>; -+ sfp_eeprom@50 { -+ compatible = "at,24c04"; ++ optoe@50 { ++ compatible = "optoe2"; + reg = <0x50>; + label = "port52"; + }; @@ -190,9 +190,10 @@ + #address-cells = <1>; + #size-cells = <0>; + reg = <4>; -+ sfp_eeprom@50 { -+ compatible = "at,24c04"; ++ optoe@50 { ++ compatible = "optoe1"; + reg = <0x50>; ++ label = "port53"; + }; + }; + @@ -201,9 +202,10 @@ + #address-cells = <1>; + #size-cells = <0>; + reg = <5>; -+ sfp_eeprom@50 { -+ compatible = "at,24c04"; ++ optoe@50 { ++ compatible = "optoe1"; + reg = <0x50>; ++ label = "port54"; + }; + }; + @@ -212,17 +214,21 @@ + #address-cells = <1>; + #size-cells = <0>; + reg = <6>; -+ psu_eeprom@50 { -+ compatible = "at,24c02"; ++ psu1_eeprom@50 { ++ compatible = "accton,as4610_psu1"; + reg = <0x50>; -+ label = "psu1_eeprom"; -+ read-only; + }; -+ psu_eeprom@51 { -+ compatible = "at,24c02"; ++ psu1_pmbus@58 { ++ compatible = "3y-power,ym1921"; ++ reg = <0x58>; ++ }; ++ psu2_eeprom@51 { ++ compatible = "accton,as4610_psu2"; + reg = <0x51>; -+ label = "psu2_eeprom"; -+ read-only; ++ }; ++ psu2_pmbus@59 { ++ compatible = "3y-power,ym1921"; ++ reg = <0x59>; + }; + }; + diff --git a/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/patches/platform-accton-as4610-device-drivers.patch b/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/patches/platform-accton-as4610-device-drivers.patch index 66ba4882..3964bfac 100644 --- a/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/patches/platform-accton-as4610-device-drivers.patch +++ b/packages/base/any/kernels/3.2-lts/configs/arm-iproc-all/patches/platform-accton-as4610-device-drivers.patch @@ -1,162 +1,5 @@ Device driver patches for accton as4610 54 (fan/psu/cpld/led/sfp) -diff --git a/arch/arm/boot/dts/accton_as4610_54.dts b/arch/arm/boot/dts/accton_as4610_54.dts -index 9276c0a..8848f8c 100644 ---- a/arch/arm/boot/dts/accton_as4610_54.dts -+++ b/arch/arm/boot/dts/accton_as4610_54.dts -@@ -105,46 +105,46 @@ - }; - - i2c0: i2c@18038000 { -- compatible = "iproc-smb"; -- reg = <0x18038000 0x1000>; -+ compatible = "iproc-smb"; -+ reg = <0x18038000 0x1000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ interrupts = < 127 >; -+ clock-frequency = <400000>; -+ cpld@1,0 { - #address-cells = <1>; -- #size-cells = <0>; -- interrupts = < 127 >; -- clock-frequency = <400000>; -- cpld@1,0 { -- #address-cells = <1>; -- #size-cells = <1>; -- compatible = "accton,as4610-54-cpld"; -- label = "cpld"; -- reg = <0x30>; -- }; -+ #size-cells = <1>; -+ compatible = "accton,as4610_54_cpld"; -+ label = "cpld"; -+ reg = <0x30>; -+ }; - }; - - i2c1: i2c@1803b000 { -- compatible = "iproc-smb"; -- reg = <0x1803b000 0x1000>; -+ compatible = "iproc-smb"; -+ reg = <0x1803b000 0x1000>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ interrupts = < 128 >; -+ clock-frequency = <100000>; -+ mux@70 { -+ compatible = "ti,pca9548"; -+ reg = <0x70>; - #address-cells = <1>; - #size-cells = <0>; -- interrupts = < 128 >; -- clock-frequency = <100000>; -- mux@70 { -- compatible = "ti,pca9548"; -- reg = <0x70>; -+ deselect-on-exit; -+ -+ // SFP+ 1 -+ i2c@0 { - #address-cells = <1>; - #size-cells = <0>; -- deselect-on-exit; -- -- // SFP+ 1 -- i2c@0 { -- #address-cells = <1>; -- #size-cells = <0>; -- reg = <0>; -- sfp_eeprom@50 { -- compatible = "at,24c04"; -- reg = <0x50>; -- label = "port49"; -- }; -+ reg = <0>; -+ sfp_eeprom@50 { -+ compatible = "at,as4610_sfp1"; -+ reg = <0x50>; -+ label = "port49"; - }; -+ }; - - // SFP+ 2 - i2c@1 { -@@ -152,7 +152,7 @@ - #size-cells = <0>; - reg = <1>; - sfp_eeprom@50 { -- compatible = "at,24c04"; -+ compatible = "accton,as4610_sfp2"; - reg = <0x50>; - label = "port50"; - }; -@@ -164,7 +164,7 @@ - #size-cells = <0>; - reg = <2>; - sfp_eeprom@50 { -- compatible = "at,24c04"; -+ compatible = "accton,as4610_sfp3"; - reg = <0x50>; - label = "port51"; - }; -@@ -176,7 +176,7 @@ - #size-cells = <0>; - reg = <3>; - sfp_eeprom@50 { -- compatible = "at,24c04"; -+ compatible = "accton,as4610_sfp4"; - reg = <0x50>; - label = "port52"; - }; -@@ -188,7 +188,7 @@ - #size-cells = <0>; - reg = <4>; - sfp_eeprom@50 { -- compatible = "at,24c04"; -+ compatible = "accton,as4610_sfp5"; - reg = <0x50>; - }; - }; -@@ -199,7 +199,7 @@ - #size-cells = <0>; - reg = <5>; - sfp_eeprom@50 { -- compatible = "at,24c04"; -+ compatible = "accton,as4610_sfp6"; - reg = <0x50>; - }; - }; -@@ -209,17 +209,21 @@ - #address-cells = <1>; - #size-cells = <0>; - reg = <6>; -- psu_eeprom@50 { -- compatible = "at,24c02"; -+ psu1_eeprom@50 { -+ compatible = "accton,as4610_psu1"; - reg = <0x50>; -- label = "psu1_eeprom"; -- read-only; - }; -- psu_eeprom@51 { -- compatible = "at,24c02"; -+ psu1_pmbus@58 { -+ compatible = "3y-power,ym1921"; -+ reg = <0x58>; -+ }; -+ psu2_eeprom@51 { -+ compatible = "accton,as4610_psu2"; - reg = <0x51>; -- label = "psu2_eeprom"; -- read-only; -+ }; -+ psu2_pmbus@59 { -+ compatible = "3y-power,ym1921"; -+ reg = <0x59>; - }; - }; - diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 5c984a6..df89e25 100644 --- a/drivers/hwmon/Kconfig @@ -165,18 +8,18 @@ index 5c984a6..df89e25 100644 help Support for the A/D converter on MC13783 PMIC. -+config SENSORS_ACCTON_I2C_CPLD -+ tristate "Accton i2c cpld" ++config SENSORS_ACCTON_AS4610_CPLD ++ tristate "Accton as4610 cpld" + depends on I2C + help -+ If you say yes here you get support for Accton i2c cpld. ++ If you say yes here you get support for Accton as4610 cpld. + + This driver can also be built as a module. If so, the module will -+ be called accton_i2c_cpld. ++ be called accton_as4610_cpld. + +config SENSORS_ACCTON_AS4610_FAN + tristate "Accton as4610 fan" -+ depends on I2C && SENSORS_ACCTON_I2C_CPLD ++ depends on I2C && SENSORS_ACCTON_AS4610_CPLD + help + If you say yes here you get support for Accton as4610 fan. + @@ -185,7 +28,7 @@ index 5c984a6..df89e25 100644 + +config SENSORS_ACCTON_AS4610_PSU + tristate "Accton as4610 psu" -+ depends on I2C && SENSORS_ACCTON_I2C_CPLD ++ depends on I2C && SENSORS_ACCTON_AS4610_CPLD + help + If you say yes here you get support for Accton as4610 psu. + @@ -213,7 +56,7 @@ index ff3a18e..39c9888 100644 obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o -+obj-$(CONFIG_SENSORS_ACCTON_I2C_CPLD) += accton_i2c_cpld.o ++obj-$(CONFIG_SENSORS_ACCTON_AS4610_CPLD) += accton_as4610_cpld.o +obj-$(CONFIG_SENSORS_ACCTON_AS4610_FAN) += accton_as4610_fan.o +obj-$(CONFIG_SENSORS_ACCTON_AS4610_PSU) += accton_as4610_psu.o obj-$(CONFIG_SENSORS_AD7314) += ad7314.o @@ -227,12 +70,616 @@ index ff3a18e..39c9888 100644 obj-$(CONFIG_PMBUS) += pmbus/ +diff --git a/drivers/hwmon/accton_as4610_cpld.c b/drivers/hwmon/accton_as4610_cpld.c +new file mode 100644 +index 0000000..26b3ae5 +--- /dev/null ++++ b/drivers/hwmon/accton_as4610_cpld.c +@@ -0,0 +1,598 @@ ++/* ++ * Copyright (C) Brandon Chuang ++ * ++ * This module supports the accton cpld that hold the channel select ++ * mechanism for other i2c slave devices, such as SFP. ++ * This includes the: ++ * Accton as4610_54 CPLD ++ * ++ * Based on: ++ * pca954x.c from Kumar Gala ++ * Copyright (C) 2006 ++ * ++ * Based on: ++ * pca954x.c from Ken Harrenstien ++ * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) ++ * ++ * Based on: ++ * i2c-virtual_cb.c from Brian Kuschak ++ * and ++ * pca9540.c from Jean Delvare . ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define I2C_RW_RETRY_COUNT 10 ++#define I2C_RW_RETRY_INTERVAL 60 /* ms */ ++ ++static LIST_HEAD(cpld_client_list); ++static struct mutex list_lock; ++ ++struct cpld_client_node { ++ struct i2c_client *client; ++ struct list_head list; ++}; ++ ++enum cpld_type { ++ as4610_54_cpld ++}; ++ ++struct as4610_54_cpld_data { ++ enum cpld_type type; ++ struct device *hwmon_dev; ++ struct mutex update_lock; ++}; ++ ++static const struct i2c_device_id as4610_54_cpld_id[] = { ++ { "as4610_54_cpld", as4610_54_cpld }, ++ { } ++}; ++MODULE_DEVICE_TABLE(i2c, as4610_54_cpld_id); ++ ++#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index ++#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index ++#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index ++#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index ++ ++enum as4610_54_cpld1_sysfs_attributes { ++ CPLD_VERSION, ++ PRODUCT_ID, ++ ACCESS, ++ MODULE_PRESENT_ALL, ++ MODULE_RXLOS_ALL, ++ /* transceiver attributes */ ++ TRANSCEIVER_PRESENT_ATTR_ID(1), ++ TRANSCEIVER_PRESENT_ATTR_ID(2), ++ TRANSCEIVER_PRESENT_ATTR_ID(3), ++ TRANSCEIVER_PRESENT_ATTR_ID(4), ++ TRANSCEIVER_PRESENT_ATTR_ID(5), ++ TRANSCEIVER_PRESENT_ATTR_ID(6), ++ TRANSCEIVER_TXDISABLE_ATTR_ID(1), ++ TRANSCEIVER_TXDISABLE_ATTR_ID(2), ++ TRANSCEIVER_TXDISABLE_ATTR_ID(3), ++ TRANSCEIVER_TXDISABLE_ATTR_ID(4), ++ TRANSCEIVER_RXLOS_ATTR_ID(1), ++ TRANSCEIVER_RXLOS_ATTR_ID(2), ++ TRANSCEIVER_RXLOS_ATTR_ID(3), ++ TRANSCEIVER_RXLOS_ATTR_ID(4), ++ TRANSCEIVER_TXFAULT_ATTR_ID(1), ++ TRANSCEIVER_TXFAULT_ATTR_ID(2), ++ TRANSCEIVER_TXFAULT_ATTR_ID(3), ++ TRANSCEIVER_TXFAULT_ATTR_ID(4), ++}; ++ ++/* sysfs attributes for hwmon ++ */ ++static ssize_t show_status(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_present_all(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t access(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count); ++static ssize_t show_version(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_product_id(struct device *dev, struct device_attribute *attr, ++ char *buf); ++static int as4610_54_cpld_read_internal(struct i2c_client *client, u8 reg); ++static int as4610_54_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); ++ ++/* transceiver attributes */ ++#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ ++ static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) ++#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr ++ ++#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ ++ static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ ++ static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_TXFAULT_##index) ++ ++#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ ++ &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ ++ &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr ++ ++static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); ++static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); ++static SENSOR_DEVICE_ATTR(product_id, S_IRUGO, show_product_id, NULL, PRODUCT_ID); ++/* transceiver attributes */ ++static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); ++static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, MODULE_RXLOS_ALL); ++DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); ++DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); ++DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); ++DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); ++DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); ++DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); ++ ++DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); ++DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); ++DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); ++DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); ++ ++static struct attribute *as4610_54_cpld_attributes[] = { ++ &sensor_dev_attr_version.dev_attr.attr, ++ &sensor_dev_attr_access.dev_attr.attr, ++ /* transceiver attributes */ ++ &sensor_dev_attr_module_present_all.dev_attr.attr, ++ &sensor_dev_attr_module_rx_los_all.dev_attr.attr, ++ DECLARE_TRANSCEIVER_PRESENT_ATTR(1), ++ DECLARE_TRANSCEIVER_PRESENT_ATTR(2), ++ DECLARE_TRANSCEIVER_PRESENT_ATTR(3), ++ DECLARE_TRANSCEIVER_PRESENT_ATTR(4), ++ DECLARE_TRANSCEIVER_PRESENT_ATTR(5), ++ DECLARE_TRANSCEIVER_PRESENT_ATTR(6), ++ DECLARE_SFP_TRANSCEIVER_ATTR(1), ++ DECLARE_SFP_TRANSCEIVER_ATTR(2), ++ DECLARE_SFP_TRANSCEIVER_ATTR(3), ++ DECLARE_SFP_TRANSCEIVER_ATTR(4), ++ NULL ++}; ++ ++static const struct attribute_group as4610_54_cpld_group = { ++ .attrs = as4610_54_cpld_attributes, ++}; ++ ++static ssize_t show_present_all(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ int i, status, present = 0; ++ u8 values[3] = {0}; ++ u8 regs[] = {0x2, 0x3, 0x21}; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct as4610_54_cpld_data *data = i2c_get_clientdata(client); ++ ++ mutex_lock(&data->update_lock); ++ ++ for (i = 0; i < ARRAY_SIZE(regs); i++) { ++ status = as4610_54_cpld_read_internal(client, regs[i]); ++ ++ if (status < 0) { ++ goto exit; ++ } ++ ++ switch (i) { ++ case 0: ++ present |= (status & BIT(6)) >> 6; /* port 25/49 */ ++ present |= (status & BIT(2)) >> 1; /* port 26/50 */ ++ break; ++ case 1: ++ present |= (status & BIT(6)) >> 4; /* port 27/51 */ ++ present |= (status & BIT(2)) << 1; /* port 28/52 */ ++ break; ++ case 2: ++ present |= (status & BIT(0)) << 4; /* port 29/53 */ ++ present |= (status & BIT(4)) << 1; /* port 30/54 */ ++ break; ++ default: ++ break; ++ } ++ } ++ ++ mutex_unlock(&data->update_lock); ++ ++ return sprintf(buf, "%.2x\n", present); ++ ++exit: ++ mutex_unlock(&data->update_lock); ++ return status; ++} ++ ++static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ int i, status, rx_los = 0; ++ u8 values[2] = {0}; ++ u8 regs[] = {0x2, 0x3}; ++ struct i2c_client *client = to_i2c_client(dev); ++ struct as4610_54_cpld_data *data = i2c_get_clientdata(client); ++ ++ mutex_lock(&data->update_lock); ++ ++ for (i = 0; i < ARRAY_SIZE(regs); i++) { ++ status = as4610_54_cpld_read_internal(client, regs[i]); ++ ++ if (status < 0) { ++ goto exit; ++ } ++ switch (i) { ++ case 0: ++ rx_los |= (status & BIT(4)) >> 4; /* port 25/49 rx_los */ ++ rx_los |= (status & BIT(0)) << 1; /* port 26/50 rx_los */ ++ break; ++ case 1: ++ rx_los |= (status & BIT(4)) >> 2; /* port 27/51 rx_los */ ++ rx_los |= (status & BIT(0)) << 3; /* port 28/52 rx_los */ ++ break; ++ default: ++ break; ++ } ++ } ++ ++ mutex_unlock(&data->update_lock); ++ ++ /* Return values 25/49 -> 28/52 in order */ ++ return sprintf(buf, "%.2x\n", rx_los); ++ ++exit: ++ mutex_unlock(&data->update_lock); ++ return status; ++} ++ ++static ssize_t show_status(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct as4610_54_cpld_data *data = i2c_get_clientdata(client); ++ int status = 0; ++ u8 reg = 0, mask = 0, revert = 0; ++ ++ switch (attr->index) { ++ case MODULE_PRESENT_1: ++ reg = 0x2; ++ mask = 0x40; ++ break; ++ case MODULE_PRESENT_2: ++ reg = 0x2; ++ mask = 0x4; ++ break; ++ case MODULE_PRESENT_3: ++ reg = 0x3; ++ mask = 0x40; ++ break; ++ case MODULE_PRESENT_4: ++ reg = 0x3; ++ mask = 0x4; ++ break; ++ case MODULE_PRESENT_5: ++ reg = 0x21; ++ mask = 0x1; ++ break; ++ case MODULE_PRESENT_6: ++ reg = 0x21; ++ mask = 0x10; ++ break; ++ case MODULE_TXFAULT_1: ++ reg = 0x2; ++ mask = 0x20; ++ break; ++ case MODULE_TXFAULT_2: ++ reg = 0x2; ++ mask = 0x2; ++ break; ++ case MODULE_TXFAULT_3: ++ reg = 0x3; ++ mask = 0x20; ++ break; ++ case MODULE_TXFAULT_4: ++ reg = 0x3; ++ mask = 0x2; ++ break; ++ case MODULE_RXLOS_1: ++ reg = 0x2; ++ mask = 0x10; ++ break; ++ case MODULE_RXLOS_2: ++ reg = 0x2; ++ mask = 0x1; ++ break; ++ case MODULE_RXLOS_3: ++ reg = 0x3; ++ mask = 0x10; ++ break; ++ case MODULE_RXLOS_4: ++ reg = 0x3; ++ mask = 0x1; ++ break; ++ default: ++ return 0; ++ } ++ ++ mutex_lock(&data->update_lock); ++ status = as4610_54_cpld_read_internal(client, reg); ++ if (unlikely(status < 0)) { ++ goto exit; ++ } ++ mutex_unlock(&data->update_lock); ++ ++ return sprintf(buf, "%d\n", !!(status & mask)); ++ ++exit: ++ mutex_unlock(&data->update_lock); ++ return status; ++} ++ ++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 as4610_54_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 = as4610_54_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 as4610_54_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 as4610_54_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 ssize_t show_product_id(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ int val = 0; ++ struct i2c_client *client = to_i2c_client(dev); ++ ++ val = i2c_smbus_read_byte_data(client, 0x1); ++ if (val < 0) { ++ dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); ++ } ++ ++ return sprintf(buf, "%d\n", (val & 0xF)); ++} ++ ++static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ int val = 0; ++ struct i2c_client *client = to_i2c_client(dev); ++ ++ val = i2c_smbus_read_byte_data(client, 0xB); ++ ++ if (val < 0) { ++ dev_dbg(&client->dev, "cpld(0x%x) reg(0xB) err %d\n", client->addr, val); ++ } ++ ++ return sprintf(buf, "%d", val); ++} ++ ++/* I2C init/probing/exit functions */ ++static int as4610_54_cpld_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); ++ struct as4610_54_cpld_data *data; ++ int ret = -ENODEV; ++ const struct attribute_group *group = NULL; ++ ++ if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) ++ goto exit; ++ ++ data = kzalloc(sizeof(struct as4610_54_cpld_data), GFP_KERNEL); ++ if (!data) { ++ ret = -ENOMEM; ++ goto exit; ++ } ++ ++ i2c_set_clientdata(client, data); ++ mutex_init(&data->update_lock); ++ data->type = id->driver_data; ++ /* Bring QSFPs out of reset */ ++ as4610_54_cpld_write_internal(client, 0x2A, 0); ++ ++ ret = sysfs_create_group(&client->dev.kobj, &as4610_54_cpld_group); ++ if (ret) { ++ goto exit_free; ++ } ++ ++ as4610_54_cpld_add_client(client); ++ return 0; ++ ++exit_free: ++ kfree(data); ++exit: ++ return ret; ++} ++ ++static int as4610_54_cpld_remove(struct i2c_client *client) ++{ ++ struct as4610_54_cpld_data *data = i2c_get_clientdata(client); ++ const struct attribute_group *group = NULL; ++ ++ as4610_54_cpld_remove_client(client); ++ ++ /* Remove sysfs hooks */ ++ sysfs_remove_group(&client->dev.kobj, &as4610_54_cpld_group); ++ kfree(data); ++ ++ return 0; ++} ++ ++static int as4610_54_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; ++} ++ ++static int as4610_54_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; ++} ++ ++int as4610_54_cpld_read(unsigned short 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 = as4610_54_cpld_read_internal(cpld_node->client, reg); ++ break; ++ } ++ } ++ ++ mutex_unlock(&list_lock); ++ ++ return ret; ++} ++EXPORT_SYMBOL(as4610_54_cpld_read); ++ ++int as4610_54_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 = as4610_54_cpld_write_internal(cpld_node->client, reg, value); ++ break; ++ } ++ } ++ ++ mutex_unlock(&list_lock); ++ ++ return ret; ++} ++EXPORT_SYMBOL(as4610_54_cpld_write); ++ ++static struct i2c_driver as4610_54_cpld_driver = { ++ .driver = { ++ .name = "as4610_54_cpld", ++ .owner = THIS_MODULE, ++ }, ++ .probe = as4610_54_cpld_probe, ++ .remove = as4610_54_cpld_remove, ++ .id_table = as4610_54_cpld_id, ++}; ++ ++static int __init as4610_54_cpld_init(void) ++{ ++ mutex_init(&list_lock); ++ return i2c_add_driver(&as4610_54_cpld_driver); ++} ++ ++static void __exit as4610_54_cpld_exit(void) ++{ ++ i2c_del_driver(&as4610_54_cpld_driver); ++} ++ ++MODULE_AUTHOR("Brandon Chuang "); ++MODULE_DESCRIPTION("Accton I2C CPLD driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(as4610_54_cpld_init); ++module_exit(as4610_54_cpld_exit); ++ diff --git a/drivers/hwmon/accton_as4610_fan.c b/drivers/hwmon/accton_as4610_fan.c new file mode 100644 -index 0000000..3934bcd +index 0000000..612d5df --- /dev/null +++ b/drivers/hwmon/accton_as4610_fan.c -@@ -0,0 +1,344 @@ +@@ -0,0 +1,345 @@ +/* + * A hwmon driver for the Accton as4610 fan + * @@ -272,9 +719,10 @@ index 0000000..3934bcd +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); ++extern int as4610_54_cpld_read(unsigned short cpld_addr, u8 reg); ++extern int as4610_54_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + -+/* fan related data, the index should match sysfs_fan_attributes -+ */ ++/* fan related data, the index should match sysfs_fan_attributes */ +static const u8 fan_reg[] = { + 0x2B, /* fan PWM(for all fan) */ + 0x2D, /* fan 1 speed(rpm) */ @@ -347,91 +795,91 @@ index 0000000..3934bcd + +static int as4610_fan_read_value(u8 reg) +{ -+ return accton_i2c_cpld_read(AS4610_CPLD_SLAVE_ADDR, reg); ++ return as4610_54_cpld_read(AS4610_CPLD_SLAVE_ADDR, reg); +} + +static int as4610_fan_write_value(u8 reg, u8 value) +{ -+ return accton_i2c_cpld_write(AS4610_CPLD_SLAVE_ADDR, reg, value); ++ return as4610_54_cpld_write(AS4610_CPLD_SLAVE_ADDR, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ -+ reg_val &= FAN_DUTY_CYCLE_REG_MASK; -+ return (u32)((reg_val * 125 + 5)/10); ++ reg_val &= FAN_DUTY_CYCLE_REG_MASK; ++ return (u32)((reg_val * 125 + 5)/10); +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ -+ return ((u32)duty_cycle * 10 / 125); ++ return ((u32)duty_cycle * 10 / 125); +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ -+ /* Count Frequency is 1.515KHz= 0.66ms -+ * Count Period = 400 cycle = 400*0.66ms = 264ms -+ * R.P.M value = read value x3.79*60/2 -+ * 3.79 = 1000ms/264ms -+ * 60 = 1min =60s -+ * 2 = 1 rotation of fan has two pulses. -+ */ -+ return (u32)reg_val * 379 * 60 / 2 / 100; ++ /* Count Frequency is 1.515KHz= 0.66ms ++ * Count Period = 400 cycle = 400*0.66ms = 264ms ++ * R.P.M value = read value x3.79*60/2 ++ * 3.79 = 1000ms/264ms ++ * 60 = 1min =60s ++ * 2 = 1 rotation of fan has two pulses. ++ */ ++ return (u32)reg_val * 379 * 60 / 2 / 100; +} + +static u8 is_fan_fault(struct as4610_fan_data *data, enum fan_id id) +{ -+ u8 mask = (id == FAN1_ID) ? 0x20 : 0x10; ++ u8 mask = (id == FAN1_ID) ? 0x20 : 0x10; + -+ return !(data->reg_val[FAN_FAULT] & mask); ++ return !(data->reg_val[FAN_FAULT] & mask); +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ -+ int error, value; ++ int error, value; + -+ error = kstrtoint(buf, 10, &value); -+ if (error) -+ return error; ++ error = kstrtoint(buf, 10, &value); ++ if (error) ++ return error; + -+ if (value < 0 || value > FAN_MAX_DUTY_CYCLE) -+ return -EINVAL; ++ if (value < 0 || value > FAN_MAX_DUTY_CYCLE) ++ return -EINVAL; + -+ as4610_fan_write_value(fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); -+ return count; ++ as4610_fan_write_value(fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value)); ++ return count; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ -+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); -+ struct as4610_fan_data *data = as4610_fan_update_device(dev); -+ ssize_t ret = 0; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct as4610_fan_data *data = as4610_fan_update_device(dev); ++ ssize_t ret = 0; + -+ if (data->valid) { -+ switch (attr->index) { -+ case FAN_DUTY_CYCLE_PERCENTAGE: -+ { -+ u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[attr->index]); -+ ret = sprintf(buf, "%u\n", duty_cycle); -+ break; -+ } -+ case FAN1_SPEED_RPM: -+ case FAN2_SPEED_RPM: -+ ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); -+ break; -+ case FAN1_FAULT: -+ case FAN2_FAULT: -+ ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); -+ break; -+ default: -+ break; -+ } -+ } ++ if (data->valid) { ++ switch (attr->index) { ++ case FAN_DUTY_CYCLE_PERCENTAGE: ++ { ++ u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[attr->index]); ++ ret = sprintf(buf, "%u\n", duty_cycle); ++ break; ++ } ++ case FAN1_SPEED_RPM: ++ case FAN2_SPEED_RPM: ++ ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index])); ++ break; ++ case FAN1_FAULT: ++ case FAN2_FAULT: ++ ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT)); ++ break; ++ default: ++ break; ++ } ++ } + -+ return ret; ++ return ret; +} + +static const struct attribute_group as4610_fan_group = { @@ -440,73 +888,73 @@ index 0000000..3934bcd + +static struct as4610_fan_data *as4610_fan_update_device(struct device *dev) +{ -+ mutex_lock(&fan_data->update_lock); ++ mutex_lock(&fan_data->update_lock); + -+ if (time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) || -+ !fan_data->valid) { -+ int i; ++ if (time_after(jiffies, fan_data->last_updated + HZ + HZ / 2) || ++ !fan_data->valid) { ++ int i; + -+ dev_dbg(fan_data->hwmon_dev, "Starting as4610_fan update\n"); -+ fan_data->valid = 0; ++ dev_dbg(fan_data->hwmon_dev, "Starting as4610_fan update\n"); ++ fan_data->valid = 0; + -+ /* Update fan data -+ */ -+ for (i = 0; i < ARRAY_SIZE(fan_data->reg_val); i++) { -+ int status = as4610_fan_read_value(fan_reg[i]); ++ /* Update fan data ++ */ ++ for (i = 0; i < ARRAY_SIZE(fan_data->reg_val); i++) { ++ int status = as4610_fan_read_value(fan_reg[i]); + -+ if (status < 0) { -+ fan_data->valid = 0; -+ mutex_unlock(&fan_data->update_lock); -+ dev_dbg(fan_data->hwmon_dev, "reg %d, err %d\n", fan_reg[i], status); -+ return fan_data; -+ } -+ else { -+ fan_data->reg_val[i] = status; -+ } -+ } ++ if (status < 0) { ++ fan_data->valid = 0; ++ mutex_unlock(&fan_data->update_lock); ++ dev_dbg(fan_data->hwmon_dev, "reg %d, err %d\n", fan_reg[i], status); ++ return fan_data; ++ } ++ else { ++ fan_data->reg_val[i] = status; ++ } ++ } + -+ fan_data->last_updated = jiffies; -+ fan_data->valid = 1; -+ } ++ fan_data->last_updated = jiffies; ++ fan_data->valid = 1; ++ } + -+ mutex_unlock(&fan_data->update_lock); ++ mutex_unlock(&fan_data->update_lock); + -+ return fan_data; ++ return fan_data; +} + +static int as4610_fan_probe(struct platform_device *pdev) +{ -+ int status = -1; ++ int status = -1; + -+ /* Register sysfs hooks */ -+ status = sysfs_create_group(&pdev->dev.kobj, &as4610_fan_group); -+ if (status) { -+ goto exit; ++ /* Register sysfs hooks */ ++ status = sysfs_create_group(&pdev->dev.kobj, &as4610_fan_group); ++ if (status) { ++ goto exit; + -+ } ++ } + -+ fan_data->hwmon_dev = hwmon_device_register(&pdev->dev); -+ if (IS_ERR(fan_data->hwmon_dev)) { -+ status = PTR_ERR(fan_data->hwmon_dev); -+ goto exit_remove; -+ } ++ fan_data->hwmon_dev = hwmon_device_register(&pdev->dev); ++ if (IS_ERR(fan_data->hwmon_dev)) { ++ status = PTR_ERR(fan_data->hwmon_dev); ++ goto exit_remove; ++ } + -+ dev_info(&pdev->dev, "accton_as4610_fan\n"); ++ dev_info(&pdev->dev, "accton_as4610_fan\n"); + -+ return 0; ++ return 0; + +exit_remove: -+ sysfs_remove_group(&pdev->dev.kobj, &as4610_fan_group); ++ sysfs_remove_group(&pdev->dev.kobj, &as4610_fan_group); +exit: -+ return status; ++ return status; +} + +static int as4610_fan_remove(struct platform_device *pdev) +{ -+ hwmon_device_unregister(fan_data->hwmon_dev); -+ sysfs_remove_group(&pdev->dev.kobj, &as4610_fan_group); ++ hwmon_device_unregister(fan_data->hwmon_dev); ++ sysfs_remove_group(&pdev->dev.kobj, &as4610_fan_group); + -+ return 0; ++ return 0; +} + +static const struct i2c_device_id as4610_fan_id[] = { @@ -526,48 +974,48 @@ index 0000000..3934bcd + +static int __init as4610_fan_init(void) +{ -+ int ret; ++ int ret; + -+ if (as4610_number_of_system_fan() == 0) { -+ return -ENODEV; -+ } ++ if (as4610_number_of_system_fan() == 0) { ++ return -ENODEV; ++ } + -+ ret = platform_driver_register(&as4610_fan_driver); -+ if (ret < 0) { -+ goto exit; -+ } ++ ret = platform_driver_register(&as4610_fan_driver); ++ if (ret < 0) { ++ goto exit; ++ } + -+ fan_data = kzalloc(sizeof(struct as4610_fan_data), GFP_KERNEL); -+ if (!fan_data) { -+ ret = -ENOMEM; -+ platform_driver_unregister(&as4610_fan_driver); -+ goto exit; -+ } ++ fan_data = kzalloc(sizeof(struct as4610_fan_data), GFP_KERNEL); ++ if (!fan_data) { ++ ret = -ENOMEM; ++ platform_driver_unregister(&as4610_fan_driver); ++ goto exit; ++ } + -+ mutex_init(&fan_data->update_lock); -+ fan_data->valid = 0; ++ mutex_init(&fan_data->update_lock); ++ fan_data->valid = 0; + -+ fan_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); -+ if (IS_ERR(fan_data->pdev)) { -+ ret = PTR_ERR(fan_data->pdev); -+ platform_driver_unregister(&as4610_fan_driver); -+ kfree(fan_data); -+ goto exit; -+ } ++ fan_data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); ++ if (IS_ERR(fan_data->pdev)) { ++ ret = PTR_ERR(fan_data->pdev); ++ platform_driver_unregister(&as4610_fan_driver); ++ kfree(fan_data); ++ goto exit; ++ } + +exit: -+ return ret; ++ return ret; +} + +static void __exit as4610_fan_exit(void) +{ -+ if (!fan_data) { -+ return; -+ } ++ if (!fan_data) { ++ return; ++ } + -+ platform_device_unregister(fan_data->pdev); -+ platform_driver_unregister(&as4610_fan_driver); -+ kfree(fan_data); ++ platform_device_unregister(fan_data->pdev); ++ platform_driver_unregister(&as4610_fan_driver); ++ kfree(fan_data); +} + +late_initcall(as4610_fan_init); @@ -579,7 +1027,7 @@ index 0000000..3934bcd + diff --git a/drivers/hwmon/accton_as4610_psu.c b/drivers/hwmon/accton_as4610_psu.c new file mode 100644 -index 0000000..1f0d79d +index 0000000..68f0348 --- /dev/null +++ b/drivers/hwmon/accton_as4610_psu.c @@ -0,0 +1,286 @@ @@ -622,7 +1070,7 @@ index 0000000..1f0d79d +static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); +static int as4610_psu_read_data(struct i2c_client *client, u8 command, u8 *data,int data_len); -+extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); ++extern int as4610_54_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ @@ -655,100 +1103,100 @@ index 0000000..1f0d79d +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD); + +static struct attribute *as4610_psu_attributes[] = { -+ &sensor_dev_attr_psu_present.dev_attr.attr, -+ &sensor_dev_attr_psu_model_name.dev_attr.attr, -+ &sensor_dev_attr_psu_power_good.dev_attr.attr, -+ NULL ++ &sensor_dev_attr_psu_present.dev_attr.attr, ++ &sensor_dev_attr_psu_model_name.dev_attr.attr, ++ &sensor_dev_attr_psu_power_good.dev_attr.attr, ++ NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ -+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); -+ struct as4610_psu_data *data = as4610_psu_update_device(dev); -+ u8 status = 0; ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct as4610_psu_data *data = as4610_psu_update_device(dev); ++ u8 status = 0; + -+ if (attr->index == PSU_PRESENT) { -+ status = (data->status >> (data->index*2) & 0x1); -+ } -+ else { /* PSU_POWER_GOOD */ -+ status = (data->status >> (data->index*2 + 1) & 0x1); -+ } ++ if (attr->index == PSU_PRESENT) { ++ status = (data->status >> (data->index*2) & 0x1); ++ } ++ else { /* PSU_POWER_GOOD */ ++ status = (data->status >> (data->index*2 + 1) & 0x1); ++ } + -+ return sprintf(buf, "%d\n", status); ++ return sprintf(buf, "%d\n", status); +} + +static ssize_t show_model_name(struct device *dev, struct device_attribute *da, -+ char *buf) ++ char *buf) +{ -+ struct as4610_psu_data *data = as4610_psu_update_device(dev); ++ struct as4610_psu_data *data = as4610_psu_update_device(dev); + -+ return sprintf(buf, "%s\n", data->model_name); ++ return sprintf(buf, "%s\n", data->model_name); +} + +static const struct attribute_group as4610_psu_group = { -+ .attrs = as4610_psu_attributes, ++ .attrs = as4610_psu_attributes, +}; + +static int as4610_psu_probe(struct i2c_client *client, -+ const struct i2c_device_id *dev_id) ++ const struct i2c_device_id *dev_id) +{ -+ struct as4610_psu_data *data; -+ int status; ++ struct as4610_psu_data *data; ++ int status; + -+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { -+ status = -EIO; -+ goto exit; -+ } ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { ++ status = -EIO; ++ goto exit; ++ } + -+ data = kzalloc(sizeof(struct as4610_psu_data), GFP_KERNEL); -+ if (!data) { -+ status = -ENOMEM; -+ goto exit; -+ } ++ data = kzalloc(sizeof(struct as4610_psu_data), GFP_KERNEL); ++ if (!data) { ++ status = -ENOMEM; ++ goto exit; ++ } + -+ i2c_set_clientdata(client, data); -+ data->valid = 0; -+ data->index = dev_id->driver_data; -+ mutex_init(&data->update_lock); ++ i2c_set_clientdata(client, data); ++ data->valid = 0; ++ data->index = dev_id->driver_data; ++ mutex_init(&data->update_lock); + -+ dev_info(&client->dev, "chip found\n"); ++ dev_info(&client->dev, "chip found\n"); + -+ /* Register sysfs hooks */ -+ status = sysfs_create_group(&client->dev.kobj, &as4610_psu_group); -+ if (status) { -+ goto exit_free; -+ } ++ /* Register sysfs hooks */ ++ status = sysfs_create_group(&client->dev.kobj, &as4610_psu_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; -+ } ++ 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); ++ dev_info(&client->dev, "%s: psu '%s'\n", ++ dev_name(data->hwmon_dev), client->name); + -+ return 0; ++ return 0; + +exit_remove: -+ sysfs_remove_group(&client->dev.kobj, &as4610_psu_group); ++ sysfs_remove_group(&client->dev.kobj, &as4610_psu_group); +exit_free: -+ kfree(data); ++ kfree(data); +exit: + -+ return status; ++ return status; +} + +static int as4610_psu_remove(struct i2c_client *client) +{ -+ struct as4610_psu_data *data = i2c_get_clientdata(client); ++ struct as4610_psu_data *data = i2c_get_clientdata(client); + -+ hwmon_device_unregister(data->hwmon_dev); -+ sysfs_remove_group(&client->dev.kobj, &as4610_psu_group); -+ kfree(data); ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &as4610_psu_group); ++ kfree(data); + -+ return 0; ++ return 0; +} + +enum psu_index @@ -778,88 +1226,88 @@ index 0000000..1f0d79d +static int as4610_psu_read_data(struct i2c_client *client, u8 command, u8 *data, + int count) +{ -+ int status = 0; ++ int status = 0; + -+ while (count) { -+ status = i2c_smbus_read_byte_data(client, command); -+ if (unlikely(status < 0)) { -+ break; -+ } ++ while (count) { ++ status = i2c_smbus_read_byte_data(client, command); ++ if (unlikely(status < 0)) { ++ break; ++ } + -+ *data = (u8)status; -+ data += 1; -+ command += 1; -+ count -= 1; -+ } ++ *data = (u8)status; ++ data += 1; ++ command += 1; ++ count -= 1; ++ } + -+ return status; ++ return status; +} + +static struct as4610_psu_data *as4610_psu_update_device(struct device *dev) +{ -+ struct i2c_client *client = to_i2c_client(dev); -+ struct as4610_psu_data *data = i2c_get_clientdata(client); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct as4610_psu_data *data = i2c_get_clientdata(client); + -+ mutex_lock(&data->update_lock); ++ mutex_lock(&data->update_lock); + -+ if (time_after(jiffies, data->last_updated + HZ + HZ / 2) -+ || !data->valid) { -+ int status; -+ int present = 0; ++ if (time_after(jiffies, data->last_updated + HZ + HZ / 2) ++ || !data->valid) { ++ int status; ++ int present = 0; + -+ data->valid = 0; -+ data->status = 0; -+ dev_dbg(&client->dev, "Starting as4610 update\n"); ++ data->valid = 0; ++ data->status = 0; ++ dev_dbg(&client->dev, "Starting as4610 update\n"); + -+ /* Read psu status */ -+ status = accton_i2c_cpld_read(0x30, 0x11); ++ /* Read psu status */ ++ status = as4610_54_cpld_read(0x30, 0x11); + -+ if (status < 0) { -+ dev_dbg(&client->dev, "cpld reg 0x30 err %d\n", status); -+ goto exit; -+ } -+ else { -+ data->status = status; -+ } ++ if (status < 0) { ++ dev_dbg(&client->dev, "cpld reg 0x30 err %d\n", status); ++ goto exit; ++ } ++ else { ++ data->status = status; ++ } + -+ /* Read model name */ -+ memset(data->model_name, 0, sizeof(data->model_name)); -+ present = (data->status >> (data->index*2) & 0x1); ++ /* Read model name */ ++ memset(data->model_name, 0, sizeof(data->model_name)); ++ present = (data->status >> (data->index*2) & 0x1); + -+ if (present) { -+ int len = ARRAY_SIZE(data->model_name)-1; ++ if (present) { ++ int len = ARRAY_SIZE(data->model_name)-1; + -+ status = as4610_psu_read_data(client, 0x20, data->model_name, -+ ARRAY_SIZE(data->model_name)-1); ++ status = as4610_psu_read_data(client, 0x20, data->model_name, ++ ARRAY_SIZE(data->model_name)-1); + -+ if (status < 0) { -+ data->model_name[0] = '\0'; -+ dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); -+ goto exit; -+ } -+ else { -+ data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; -+ } -+ } ++ if (status < 0) { ++ data->model_name[0] = '\0'; ++ dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); ++ goto exit; ++ } ++ else { ++ data->model_name[ARRAY_SIZE(data->model_name)-1] = '\0'; ++ } ++ } + -+ data->last_updated = jiffies; -+ data->valid = 1; -+ } ++ data->last_updated = jiffies; ++ data->valid = 1; ++ } + +exit: -+ mutex_unlock(&data->update_lock); ++ mutex_unlock(&data->update_lock); + -+ return data; ++ return data; +} + +static int __init as4610_psu_init(void) +{ -+ return i2c_add_driver(&as4610_psu_driver); ++ return i2c_add_driver(&as4610_psu_driver); +} + +static void __exit as4610_psu_exit(void) +{ -+ i2c_del_driver(&as4610_psu_driver); ++ i2c_del_driver(&as4610_psu_driver); +} + +module_init(as4610_psu_init); @@ -869,297 +1317,6 @@ index 0000000..1f0d79d +MODULE_DESCRIPTION("as4610_psu driver"); +MODULE_LICENSE("GPL"); + -diff --git a/drivers/hwmon/accton_i2c_cpld.c b/drivers/hwmon/accton_i2c_cpld.c -new file mode 100644 -index 0000000..0b9762e ---- /dev/null -+++ b/drivers/hwmon/accton_i2c_cpld.c -@@ -0,0 +1,285 @@ -+/* -+ * A hwmon driver for the accton_i2c_cpld -+ * -+ * 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 -+ -+static LIST_HEAD(cpld_client_list); -+static struct mutex list_lock; -+ -+enum cpld_device_id { -+ as4610_30_cpld, -+ as4610_54_cpld -+}; -+ -+struct cpld_data { -+ enum cpld_device_id id; -+}; -+ -+struct cpld_client_node { -+ struct i2c_client *client; -+ struct list_head list; -+}; -+ -+/* Addresses scanned for accton_i2c_cpld -+ */ -+static const unsigned short normal_i2c[] = { 0x31, 0x35, 0x60, 0x61, 0x62, I2C_CLIENT_END }; -+ -+static u8 cpld_product_id_offset(enum cpld_device_id id) -+{ -+ switch (id) { -+ case as4610_30_cpld: -+ case as4610_54_cpld: -+ return 0x1; -+ } -+ -+ return 0; -+} -+ -+static int cpld_has_product_id(const struct i2c_device_id *dev_id) -+{ -+ return (dev_id->driver_data == as4610_30_cpld) || -+ (dev_id->driver_data == as4610_54_cpld); -+} -+ -+static ssize_t show_cpld_product_id(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ int val = 0; -+ struct i2c_client *client = to_i2c_client(dev); -+ struct cpld_data *data = i2c_get_clientdata(client); -+ -+ val = i2c_smbus_read_byte_data(client, cpld_product_id_offset(data->id)); -+ if (val < 0) { -+ dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", client->addr, cpld_product_id_offset(data->id), val); -+ } -+ -+ return sprintf(buf, "%d\n", (val & 0xF)); -+} -+ -+static u8 cpld_version_offset(enum cpld_device_id id) -+{ -+ switch (id) { -+ case as4610_30_cpld: -+ case as4610_54_cpld: -+ return 0xB; -+ } -+ -+ return 0; -+} -+ -+static ssize_t show_cpld_version(struct device *dev, struct device_attribute *attr, char *buf) -+{ -+ int val = 0; -+ struct i2c_client *client = to_i2c_client(dev); -+ struct cpld_data *data = i2c_get_clientdata(client); -+ -+ val = i2c_smbus_read_byte_data(client, cpld_version_offset(data->id)); -+ if (val < 0) { -+ dev_dbg(&client->dev, "cpld(0x%x) reg(0xB) err %d\n", client->addr, val); -+ } -+ -+ return sprintf(buf, "%d\n", val); -+} -+ -+static void accton_i2c_cpld_add_client(struct i2c_client *client, enum cpld_device_id id) -+{ -+ struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); -+ struct cpld_data *data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL); -+ -+ if (!node) { -+ dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); -+ return; -+ } -+ -+ if (!data) { -+ dev_dbg(&client->dev, "Can't allocate cpld_client_data (0x%x)\n", client->addr); -+ return; -+ } -+ -+ data->id = id; -+ i2c_set_clientdata(client, data); -+ node->client = client; -+ -+ mutex_lock(&list_lock); -+ list_add(&node->list, &cpld_client_list); -+ mutex_unlock(&list_lock); -+} -+ -+static void accton_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 struct device_attribute ver = __ATTR(version, 0600, show_cpld_version, NULL); -+static struct device_attribute pid = __ATTR(product_id, 0600, show_cpld_product_id, NULL); -+ -+static int accton_i2c_cpld_probe(struct i2c_client *client, -+ const struct i2c_device_id *dev_id) -+{ -+ int status; -+ -+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { -+ dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr); -+ status = -EIO; -+ goto exit; -+ } -+ -+ status = sysfs_create_file(&client->dev.kobj, &ver.attr); -+ if (status) { -+ goto exit; -+ } -+ -+ if (cpld_has_product_id(dev_id)) { -+ status = sysfs_create_file(&client->dev.kobj, &pid.attr); -+ if (status) { -+ goto exit; -+ } -+ } -+ -+ dev_info(&client->dev, "chip found\n"); -+ accton_i2c_cpld_add_client(client, (enum cpld_device_id)dev_id->driver_data); -+ -+ return 0; -+ -+exit: -+ return status; -+} -+ -+static int accton_i2c_cpld_remove(struct i2c_client *client) -+{ -+ sysfs_remove_file(&client->dev.kobj, &ver.attr); -+ accton_i2c_cpld_remove_client(client); -+ -+ return 0; -+} -+ -+static const struct i2c_device_id accton_i2c_cpld_id[] = { -+ { "as4610_30_cpld", as4610_30_cpld }, -+ { "as4610_54_cpld", as4610_54_cpld }, -+ { /* LIST END */} -+}; -+MODULE_DEVICE_TABLE(i2c, accton_i2c_cpld_id); -+ -+static struct i2c_driver accton_i2c_cpld_driver = { -+ .class = I2C_CLASS_HWMON, -+ .driver = { -+ .name = "accton_i2c_cpld", -+ }, -+ .probe = accton_i2c_cpld_probe, -+ .remove = accton_i2c_cpld_remove, -+ .id_table = accton_i2c_cpld_id, -+ .address_list = normal_i2c, -+}; -+ -+int accton_i2c_cpld_read(unsigned short 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(accton_i2c_cpld_read); -+ -+int accton_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(accton_i2c_cpld_write); -+ -+static int __init accton_i2c_cpld_init(void) -+{ -+ mutex_init(&list_lock); -+ return i2c_add_driver(&accton_i2c_cpld_driver); -+} -+ -+static void __exit accton_i2c_cpld_exit(void) -+{ -+ i2c_del_driver(&accton_i2c_cpld_driver); -+} -+ -+MODULE_AUTHOR("Brandon Chuang "); -+MODULE_DESCRIPTION("accton_i2c_cpld driver"); -+MODULE_LICENSE("GPL"); -+ -+module_init(accton_i2c_cpld_init); -+module_exit(accton_i2c_cpld_exit); -+ diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index 8dfc678..b9eafcf 100644 --- a/drivers/hwmon/lm77.c @@ -1840,7 +1997,7 @@ index ff203a4..97d4d54 100644 +config LEDS_ACCTON_AS4610 + tristate "LED support for the Accton as4610" -+ depends on LEDS_CLASS && SENSORS_ACCTON_I2C_CPLD ++ depends on LEDS_CLASS && SENSORS_ACCTON_AS4610_CPLD + help + This option enables support for the LEDs on the Accton as4610. + Say Y to enable LEDs on the Accton as4610. @@ -1862,7 +2019,7 @@ index e4f6bf5..db2dab8 100644 obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o diff --git a/drivers/leds/leds-accton_as4610.c b/drivers/leds/leds-accton_as4610.c new file mode 100644 -index 0000000..0c4b535 +index 0000000..7a8bf34 --- /dev/null +++ b/drivers/leds/leds-accton_as4610.c @@ -0,0 +1,678 @@ @@ -1899,8 +2056,8 @@ index 0000000..0c4b535 +#include +#include + -+extern int accton_i2c_cpld_read (unsigned short cpld_addr, u8 reg); -+extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); ++extern int as4610_54_cpld_read (unsigned short cpld_addr, u8 reg); ++extern int as4610_54_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +extern void led_classdev_unregister(struct led_classdev *led_cdev); +extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); @@ -2016,12 +2173,12 @@ index 0000000..0c4b535 + +static int as4610_led_read_value(u8 reg) +{ -+ return accton_i2c_cpld_read(0x30, reg); ++ return as4610_54_cpld_read(0x30, reg); +} + +static int as4610_led_write_value(u8 reg, u8 value) +{ -+ return accton_i2c_cpld_write(0x30, reg, value); ++ return as4610_54_cpld_write(0x30, reg, value); +} + +static void as4610_led_update(void) @@ -2553,14 +2710,14 @@ index 7c7b208..1c62b33 100644 This driver can also be built as a module. If so, the module will be called sff_8436. + -+config EEPROM_ACCTON_AS4610_SFP -+ tristate "Accton as4610 sfp" -+ depends on I2C && SENSORS_ACCTON_I2C_CPLD ++config EEPROM_OPTOE ++ tristate "Optoe driver" ++ depends on I2C + help -+ If you say yes here you get support for Accton as4610 sfp. ++ If you say yes here you get support for Optoe. + + This driver can also be built as a module. If so, the module will -+ be called accton_as4610_sfp. ++ be called optoe. endmenu diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile @@ -2571,1290 +2728,1167 @@ index 9edd559..12f7cae 100644 obj-$(CONFIG_EEPROM_93XX46) += eeprom_93xx46.o obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o obj-$(CONFIG_EEPROM_SFF_8436) += sff_8436_eeprom.o -+obj-$(CONFIG_EEPROM_ACCTON_AS4610_SFP) += accton_as4610_sfp.o -diff --git a/drivers/misc/eeprom/accton_as4610_sfp.c b/drivers/misc/eeprom/accton_as4610_sfp.c ++obj-$(CONFIG_EEPROM_OPTOE) += optoe.o +diff --git a/drivers/misc/eeprom/optoe.c b/drivers/misc/eeprom/optoe.c new file mode 100644 -index 0000000..39c17ec +index 0000000..b3064f0 --- /dev/null -+++ b/drivers/misc/eeprom/accton_as4610_sfp.c -@@ -0,0 +1,1269 @@ ++++ b/drivers/misc/eeprom/optoe.c +@@ -0,0 +1,1146 @@ +/* -+ * SFP driver for accton as4610 sfp ++ * optoe.c - A driver to read and write the EEPROM on optical transceivers ++ * (SFP, QSFP and similar I2C based devices) + * -+ * Copyright (C) Brandon Chuang -+ * -+ * Based on ad7414.c -+ * Copyright 2006 Stefan Roese , DENX Software Engineering ++ * Copyright (C) 2014 Cumulus networks Inc. ++ * Copyright (C) 2017 Finisar Corp. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or ++ * the Freeoftware 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 -+ -+#define DRIVER_NAME "as4610_sfp" /* Platform dependent */ -+ -+#define DEBUG_MODE 0 -+ -+#if (DEBUG_MODE == 1) -+ #define DEBUG_PRINT(fmt, args...) \ -+ printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) -+#else -+ #define DEBUG_PRINT(fmt, args...) -+#endif -+ -+#define NUM_OF_SFP_PORT 32 -+#define EEPROM_NAME "sfp_eeprom" -+#define EEPROM_SIZE 256 /* 256 byte eeprom */ -+#define BIT_INDEX(i) (1ULL << (i)) -+#define USE_I2C_BLOCK_READ 0 /* Platform dependent */ -+#define I2C_RW_RETRY_COUNT 3 -+#define I2C_RW_RETRY_INTERVAL 100 /* ms */ -+ -+#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) -+#define SFP_EEPROM_A2_I2C_ADDR (0xA2 >> 1) -+ -+#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 -+#define SFF8024_DEVICE_ID_SFP 0x3 -+#define SFF8024_DEVICE_ID_QSFP 0xC -+#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD -+#define SFF8024_DEVICE_ID_QSFP28 0x11 -+ -+#define SFF8472_DIAG_MON_TYPE_ADDR 92 -+#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 -+#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 -+#define SFF8472_10G_BASE_MASK 0xF0 -+ -+#define SFF8436_RX_LOS_ADDR 3 -+#define SFF8436_TX_FAULT_ADDR 4 -+#define SFF8436_TX_DISABLE_ADDR 86 -+ -+static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); -+static ssize_t show_port_type(struct device *dev, struct device_attribute *da, char *buf); -+static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); -+static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); -+static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); -+static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -+static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; -+static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, char *buf); -+static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); -+static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); -+extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); -+extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); -+ -+enum sfp_sysfs_attributes { -+ PRESENT, -+ PRESENT_ALL, -+ PORT_NUMBER, -+ PORT_TYPE, -+ DDM_IMPLEMENTED, -+ TX_FAULT, -+ TX_FAULT1, -+ TX_FAULT2, -+ TX_FAULT3, -+ TX_FAULT4, -+ TX_DISABLE, -+ TX_DISABLE1, -+ TX_DISABLE2, -+ TX_DISABLE3, -+ TX_DISABLE4, -+ RX_LOS, -+ RX_LOS1, -+ RX_LOS2, -+ RX_LOS3, -+ RX_LOS4, -+ RX_LOS_ALL -+}; -+ -+/* SFP/QSFP common attributes for sysfs */ -+static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); -+static SENSOR_DEVICE_ATTR(sfp_port_type, S_IRUGO, show_port_type, NULL, PORT_TYPE); -+static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); -+static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); -+static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS); -+static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, TX_DISABLE); -+static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, TX_FAULT); -+ -+/* QSFP attributes for sysfs */ -+static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); -+static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); -+static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); -+static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); -+static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); -+static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); -+static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); -+static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); -+static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); -+static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); -+static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); -+static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); -+static struct attribute *qsfp_attributes[] = { -+ &sensor_dev_attr_sfp_port_number.dev_attr.attr, -+ &sensor_dev_attr_sfp_port_type.dev_attr.attr, -+ &sensor_dev_attr_sfp_is_present.dev_attr.attr, -+ &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, -+ &sensor_dev_attr_sfp_rx_los.dev_attr.attr, -+ &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, -+ &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, -+ &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, -+ &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, -+ &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, -+ &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, -+ &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, -+ &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, -+ &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, -+ &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, -+ &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, -+ &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, -+ &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, -+ &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, -+ NULL -+}; -+ -+/* SFP msa attributes for sysfs */ -+static SENSOR_DEVICE_ATTR(sfp_ddm_implemented, S_IRUGO, sfp_show_ddm_implemented, NULL, DDM_IMPLEMENTED); -+static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS_ALL); -+static struct attribute *sfp_msa_attributes[] = { -+ &sensor_dev_attr_sfp_port_number.dev_attr.attr, -+ &sensor_dev_attr_sfp_port_type.dev_attr.attr, -+ &sensor_dev_attr_sfp_is_present.dev_attr.attr, -+ &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, -+ &sensor_dev_attr_sfp_ddm_implemented.dev_attr.attr, -+ &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, -+ &sensor_dev_attr_sfp_rx_los.dev_attr.attr, -+ &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, -+ &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, -+ NULL -+}; -+ -+/* SFP ddm attributes for sysfs */ -+static struct attribute *sfp_ddm_attributes[] = { -+ NULL -+}; -+ -+/* Platform dependent +++ */ -+enum port_numbers { -+as4610_sfp1, /* Port 25 for as4610_30, Port 49 for as4610_54 */ -+as4610_sfp2, /* Port 26 for as4610_30, Port 50 for as4610_54 */ -+as4610_sfp3, /* Port 27 for as4610_30, Port 51 for as4610_54 */ -+as4610_sfp4, /* Port 28 for as4610_30, Port 52 for as4610_54 */ -+as4610_sfp5, /* Port 29 for as4610_30, Port 53 for as4610_54 */ -+as4610_sfp6, /* Port 30 for as4610_30, Port 54 for as4610_54 */ -+}; -+ -+static const struct i2c_device_id sfp_device_id[] = { -+{"as4610_sfp1", as4610_sfp1}, -+{"as4610_sfp2", as4610_sfp2}, -+{"as4610_sfp3", as4610_sfp3}, -+{"as4610_sfp4", as4610_sfp4}, -+{"as4610_sfp5", as4610_sfp5}, -+{"as4610_sfp6", as4610_sfp6}, -+{ /* LIST END */ } -+}; -+MODULE_DEVICE_TABLE(i2c, sfp_device_id); -+/* Platform dependent --- */ -+ +/* -+ * list of valid port types -+ * note OOM_PORT_TYPE_NOT_PRESENT to indicate no -+ * module is present in this port -+ */ -+typedef enum oom_driver_port_type_e { -+ OOM_DRIVER_PORT_TYPE_INVALID, -+ OOM_DRIVER_PORT_TYPE_NOT_PRESENT, -+ OOM_DRIVER_PORT_TYPE_SFP, -+ OOM_DRIVER_PORT_TYPE_SFP_PLUS, -+ OOM_DRIVER_PORT_TYPE_QSFP, -+ OOM_DRIVER_PORT_TYPE_QSFP_PLUS, -+ OOM_DRIVER_PORT_TYPE_QSFP28 -+} oom_driver_port_type_t; -+ -+enum driver_type_e { -+ DRIVER_TYPE_SFP_MSA, -+ DRIVER_TYPE_SFP_DDM, -+ DRIVER_TYPE_QSFP -+}; -+ -+/* Each client has this additional data -+ */ -+struct eeprom_data { -+ char valid; /* !=0 if registers are valid */ -+ unsigned long last_updated; /* In jiffies */ -+ struct bin_attribute bin; /* eeprom data */ -+}; -+ -+struct sfp_msa_data { -+ char valid; /* !=0 if registers are valid */ -+ unsigned long last_updated; /* In jiffies */ -+ u64 status[6]; /* bit0:port0, bit1:port1 and so on */ -+ /* index 0 => tx_fail -+ 1 => tx_disable -+ 2 => rx_loss -+ 3 => device id -+ 4 => 10G Ethernet Compliance Codes -+ to distinguish SFP or SFP+ -+ 5 => DIAGNOSTIC MONITORING TYPE */ -+ struct eeprom_data eeprom; -+}; -+ -+struct sfp_ddm_data { -+ struct eeprom_data eeprom; -+}; -+ -+struct qsfp_data { -+ char valid; /* !=0 if registers are valid */ -+ unsigned long last_updated; /* In jiffies */ -+ u8 status[3]; /* bit0:port0, bit1:port1 and so on */ -+ /* index 0 => tx_fail -+ 1 => tx_disable -+ 2 => rx_loss */ -+ -+ u8 device_id; -+ struct eeprom_data eeprom; -+}; -+ -+struct sfp_port_data { -+ struct mutex update_lock; -+ enum driver_type_e driver_type; -+ int port; /* CPLD port index */ -+ oom_driver_port_type_t port_type; -+ u64 present; /* present status, bit0:port0, bit1:port1 and so on */ -+ -+ struct sfp_msa_data *msa; -+ struct sfp_ddm_data *ddm; -+ struct qsfp_data *qsfp; -+ -+ struct i2c_client *client; -+}; -+ -+static ssize_t show_port_number(struct device *dev, struct device_attribute *da, -+ char *buf) -+{ -+ struct i2c_client *client = to_i2c_client(dev); -+ struct sfp_port_data *data = i2c_get_clientdata(client); -+ -+ return sprintf(buf, "sfp %d\n", data->port); -+} -+ -+/* Platform dependent +++ */ -+static struct sfp_port_data *sfp_update_present(struct i2c_client *client) -+{ -+ struct sfp_port_data *data = i2c_get_clientdata(client); -+ int i = 0; -+ int status = -1; -+ u8 regs[] = {0x2, 0x3, 0x21}; -+ -+ DEBUG_PRINT("Starting sfp present status update"); -+ mutex_lock(&data->update_lock); -+ -+ /* Read present status of port 49~54 */ -+ data->present = 0; -+ -+ for (i = 0; i < ARRAY_SIZE(regs); i++) { -+ status = accton_i2c_cpld_read(0x30, regs[i]); -+ -+ if (status < 0) { -+ DEBUG_PRINT("cpld(0x30) reg(0x%x) err %d", regs[i], status); -+ goto exit; -+ } -+ -+ DEBUG_PRINT("Present status = 0x%lx", data->present); -+ switch (i) { -+ case 0: -+ data->present |= (status & BIT_INDEX(6)) >> 6; /* port 25/49 */ -+ data->present |= (status & BIT_INDEX(2)) >> 1; /* port 26/50 */ -+ break; -+ case 1: -+ data->present |= (status & BIT_INDEX(6)) >> 4; /* port 27/51 */ -+ data->present |= (status & BIT_INDEX(2)) << 1; /* port 28/52 */ -+ break; -+ case 2: -+ data->present |= (status & BIT_INDEX(0)) << 4; /* port 29/53 */ -+ data->present |= (status & BIT_INDEX(4)) << 1; /* port 30/54 */ -+ break; -+ default: -+ break; -+ } -+ } -+ -+ DEBUG_PRINT("Present status = 0x%lx", data->present); -+exit: -+ mutex_unlock(&data->update_lock); -+ return (status < 0) ? ERR_PTR(status) : data; -+} -+ -+static struct sfp_port_data *sfp_update_tx_rx_status(struct device *dev) -+{ -+ struct i2c_client *client = to_i2c_client(dev); -+ struct sfp_port_data *data = i2c_get_clientdata(client); -+ int i = 0; -+ int status = -1; -+ u8 regs[] = {0x2, 0x3, 0x21}; -+ -+ if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { -+ return data; -+ } -+ -+ DEBUG_PRINT("Starting as4610 sfp tx rx status update"); -+ mutex_lock(&data->update_lock); -+ data->msa->valid = 0; -+ memset(data->msa->status, 0, sizeof(data->msa->status)); -+ -+ /* Read status of port 49~52(SFP port) */ -+ for (i = 0; i < ARRAY_SIZE(regs); i++) { -+ status = accton_i2c_cpld_read(0x30, regs[i]); -+ -+ if (status < 0) { -+ DEBUG_PRINT("cpld(0x30) reg(0x%x) err %d", regs[i], status); -+ goto exit; -+ } -+ -+ DEBUG_PRINT("TX_FAULT = 0x%lx, TX_DISABLE = 0x%lx, TX_FAULT = 0x%lx", -+ data->msa->status[0], data->msa->status[1], data->msa->status[2]); -+ switch (i) { -+ case 0: -+ /* port 25/49 */ -+ data->msa->status[0] |= (status & BIT_INDEX(5)) >> 5; /* tx_fail */ -+ data->msa->status[2] |= (status & BIT_INDEX(4)) >> 4; /* rx_los */ -+ /* port 26/50 */ -+ data->msa->status[0] |= (status & BIT_INDEX(1)) << 0; /* tx_fail */ -+ data->msa->status[2] |= (status & BIT_INDEX(0)) << 1; /* rx_los */ -+ break; -+ case 1: -+ /* port 27/51 */ -+ data->msa->status[0] |= (status & BIT_INDEX(5)) >> 3; /* tx_fail */ -+ data->msa->status[2] |= (status & BIT_INDEX(4)) >> 2; /* rx_los */ -+ /* port 28/52 */ -+ data->msa->status[0] |= (status & BIT_INDEX(1)) << 1; /* tx_fail */ -+ data->msa->status[2] |= (status & BIT_INDEX(0)) << 2; /* rx_los */ -+ break; -+ default: -+ break; -+ } -+ } -+ -+ DEBUG_PRINT("TX_FAULT = 0x%lx, TX_DISABLE = 0x%lx, TX_FAULT = 0x%lx", -+ data->msa->status[0], data->msa->status[1], data->msa->status[2]); -+ data->msa->valid = 1; -+ data->msa->last_updated = jiffies; -+ -+exit: -+ mutex_unlock(&data->update_lock); -+ return data; -+} -+/* Platform dependent --- */ -+ -+static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, -+ const char *buf, size_t count) -+{ -+ struct i2c_client *client = to_i2c_client(dev); -+ struct sfp_port_data *data = i2c_get_clientdata(client); -+ -+ if (data->driver_type == DRIVER_TYPE_QSFP) { -+ return qsfp_set_tx_disable(dev, da, buf, count); -+ } -+ -+ return 0; -+} -+ -+static int sfp_is_port_present(struct i2c_client *client, int port) -+{ -+ struct sfp_port_data *data = i2c_get_clientdata(client); -+ -+ data = sfp_update_present(client); -+ if (IS_ERR(data)) { -+ return PTR_ERR(data); -+ } -+ -+ return (data->present & BIT_INDEX(data->port)) ? 1 : 0; /* Platform dependent */ -+} -+ -+/* Platform dependent +++ */ -+static ssize_t show_present(struct device *dev, struct device_attribute *da, -+ char *buf) -+{ -+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); -+ struct i2c_client *client = to_i2c_client(dev); -+ -+ if (PRESENT_ALL == attr->index) { -+ struct sfp_port_data *data = sfp_update_present(client); -+ -+ if (IS_ERR(data)) { -+ return PTR_ERR(data); -+ } -+ -+ /* Return values 25/49 -> 30/54 in order */ -+ return sprintf(buf, "%.2x\n", (u8)(data->present)); -+ } -+ else { -+ struct sfp_port_data *data = i2c_get_clientdata(client); -+ int present = sfp_is_port_present(client, data->port); -+ -+ if (IS_ERR_VALUE(present)) { -+ return present; -+ } -+ -+ /* PRESENT */ -+ return sprintf(buf, "%d\n", present); -+ } -+} -+/* Platform dependent --- */ -+ -+static struct sfp_port_data *sfp_update_port_type(struct device *dev) -+{ -+ struct i2c_client *client = to_i2c_client(dev); -+ struct sfp_port_data *data = i2c_get_clientdata(client); -+ u8 buf = 0; -+ int status; -+ -+ mutex_lock(&data->update_lock); -+ -+ switch (data->driver_type) { -+ case DRIVER_TYPE_SFP_MSA: -+ { -+ status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); -+ if (unlikely(status < 0)) { -+ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; -+ break; -+ } -+ -+ if (buf != SFF8024_DEVICE_ID_SFP) { -+ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; -+ break; -+ } -+ -+ status = sfp_eeprom_read(client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); -+ if (unlikely(status < 0)) { -+ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; -+ break; -+ } -+ -+ DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); -+ data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; -+ break; -+ } -+ case DRIVER_TYPE_QSFP: -+ { -+ status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); -+ if (unlikely(status < 0)) { -+ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; -+ break; -+ } -+ -+ DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); -+ switch (buf) { -+ case SFF8024_DEVICE_ID_QSFP: -+ data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; -+ break; -+ case SFF8024_DEVICE_ID_QSFP_PLUS: -+ data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; -+ break; -+ case SFF8024_DEVICE_ID_QSFP28: -+ data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; -+ break; -+ default: -+ data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; -+ break; -+ } -+ -+ break; -+ } -+ default: -+ break; -+ } -+ -+ mutex_unlock(&data->update_lock); -+ return data; -+} -+ -+static ssize_t show_port_type(struct device *dev, struct device_attribute *da, -+ char *buf) -+{ -+ struct i2c_client *client = to_i2c_client(dev); -+ struct sfp_port_data *data = i2c_get_clientdata(client); -+ int present = sfp_is_port_present(client, data->port); -+ -+ if (IS_ERR_VALUE(present)) { -+ return present; -+ } -+ -+ if (!present) { -+ return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); -+ } -+ -+ sfp_update_port_type(dev); -+ return sprintf(buf, "%d\n", data->port_type); -+} -+ -+static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) -+{ -+ struct i2c_client *client = to_i2c_client(dev); -+ struct sfp_port_data *data = i2c_get_clientdata(client); -+ int i, status = -1; -+ u8 buf = 0; -+ u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; -+ -+ if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { -+ return data; -+ } -+ -+ DEBUG_PRINT("Starting sfp tx rx status update"); -+ mutex_lock(&data->update_lock); -+ data->qsfp->valid = 0; -+ memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); -+ -+ /* Notify device to update tx fault/ tx disable/ rx los status */ -+ for (i = 0; i < ARRAY_SIZE(reg); i++) { -+ status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); -+ if (unlikely(status < 0)) { -+ goto exit; -+ } -+ } -+ msleep(200); -+ -+ /* Read actual tx fault/ tx disable/ rx los status */ -+ for (i = 0; i < ARRAY_SIZE(reg); i++) { -+ status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); -+ if (unlikely(status < 0)) { -+ goto exit; -+ } -+ -+ DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); -+ data->qsfp->status[i] = (buf & 0xF); -+ } -+ -+ data->qsfp->valid = 1; -+ data->qsfp->last_updated = jiffies; -+ -+exit: -+ mutex_unlock(&data->update_lock); -+ return (status < 0) ? ERR_PTR(status) : data; -+} -+ -+static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, -+ char *buf) -+{ -+ int present; -+ u8 val = 0; -+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); -+ struct i2c_client *client = to_i2c_client(dev); -+ struct sfp_port_data *data = i2c_get_clientdata(client); -+ -+ present = sfp_is_port_present(client, data->port); -+ if (IS_ERR_VALUE(present)) { -+ return present; -+ } -+ -+ if (present == 0) { -+ /* port is not present */ -+ return -ENXIO; -+ } -+ -+ data = qsfp_update_tx_rx_status(dev); -+ if (IS_ERR(data)) { -+ return PTR_ERR(data); -+ } -+ -+ switch (attr->index) { -+ case TX_FAULT: -+ val = !!(data->qsfp->status[2] & 0xF); -+ break; -+ case TX_FAULT1: -+ case TX_FAULT2: -+ case TX_FAULT3: -+ case TX_FAULT4: -+ val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); -+ break; -+ case TX_DISABLE: -+ val = data->qsfp->status[1] & 0xF; -+ break; -+ case TX_DISABLE1: -+ case TX_DISABLE2: -+ case TX_DISABLE3: -+ case TX_DISABLE4: -+ val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); -+ break; -+ case RX_LOS: -+ val = !!(data->qsfp->status[0] & 0xF); -+ break; -+ case RX_LOS1: -+ case RX_LOS2: -+ case RX_LOS3: -+ case RX_LOS4: -+ val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); -+ break; -+ default: -+ break; -+ } -+ -+ return sprintf(buf, "%d\n", val); -+} -+ -+static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, -+ const char *buf, size_t count) -+{ -+ long disable; -+ int status; -+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); -+ struct i2c_client *client = to_i2c_client(dev); -+ struct sfp_port_data *data = i2c_get_clientdata(client); -+ -+ status = sfp_is_port_present(client, data->port); -+ if (IS_ERR_VALUE(status)) { -+ return status; -+ } -+ -+ if (!status) { -+ /* port is not present */ -+ return -ENXIO; -+ } -+ -+ status = kstrtol(buf, 10, &disable); -+ if (status) { -+ return status; -+ } -+ -+ data = qsfp_update_tx_rx_status(dev); -+ if (IS_ERR(data)) { -+ return PTR_ERR(data); -+ } -+ -+ mutex_lock(&data->update_lock); -+ -+ if (attr->index == TX_DISABLE) { -+ data->qsfp->status[1] = disable & 0xF; -+ } -+ else {/* TX_DISABLE1 ~ TX_DISABLE4*/ -+ if (disable) { -+ data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); -+ } -+ else { -+ data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); -+ } -+ } -+ -+ DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); -+ status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); -+ if (unlikely(status < 0)) { -+ count = status; -+ } -+ -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, -+ char *buf) -+{ -+ int status; -+ char ddm; -+ struct i2c_client *client = to_i2c_client(dev); -+ struct sfp_port_data *data = i2c_get_clientdata(client); -+ -+ status = sfp_is_port_present(client, data->port); -+ if (IS_ERR_VALUE(status)) { -+ return status; -+ } -+ -+ if (status == 0) { -+ /* port is not present */ -+ return -ENODEV; -+ } -+ -+ status = sfp_eeprom_read(client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); -+ if (unlikely(status < 0)) { -+ return status; -+ } -+ -+ return sprintf(buf, "%d\n", !!(ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK)); -+} -+ -+/* Platform dependent +++ */ -+static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, -+ char *buf) -+{ -+ u8 val = 0, index = 0; -+ struct i2c_client *client = to_i2c_client(dev); -+ struct sfp_port_data *data = i2c_get_clientdata(client); -+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); -+ -+ if (data->driver_type == DRIVER_TYPE_QSFP) { -+ return qsfp_show_tx_rx_status(dev, da, buf); -+ } -+ -+ data = sfp_update_tx_rx_status(dev); -+ if (IS_ERR(data)) { -+ return PTR_ERR(data); -+ } -+ -+ if(attr->index == RX_LOS_ALL) { -+ /** Return values 25/49 -> 28/52 in order */ -+ return sprintf(buf, "%.2x\n", (u8)(data->msa->status[2])); -+ } -+ -+ switch (attr->index) { -+ case TX_FAULT: -+ index = 0; -+ break; -+ case TX_DISABLE: -+ index = 1; -+ break; -+ case RX_LOS: -+ index = 2; -+ break; -+ default: -+ return 0; -+ } -+ -+ val = (data->msa->status[index] & BIT_INDEX(data->port)) ? 1 : 0; -+ return sprintf(buf, "%d\n", val); -+} -+/* Platform dependent --- */ -+static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, -+ int data_len) -+{ -+#if USE_I2C_BLOCK_READ -+ int status, retry = I2C_RW_RETRY_COUNT; -+ -+ if (data_len > I2C_SMBUS_BLOCK_MAX) { -+ data_len = I2C_SMBUS_BLOCK_MAX; -+ } -+ -+ while (retry) { -+ status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); -+ if (unlikely(status < 0)) { -+ msleep(I2C_RW_RETRY_INTERVAL); -+ retry--; -+ continue; -+ } -+ -+ break; -+ } -+ -+ if (unlikely(status < 0)) { -+ return status; -+ } -+ -+ return data_len; -+#else -+ int status, retry = I2C_RW_RETRY_COUNT; -+ -+ while (retry) { -+ status = i2c_smbus_write_byte_data(client, command, *data); -+ if (unlikely(status < 0)) { -+ msleep(I2C_RW_RETRY_INTERVAL); -+ retry--; -+ continue; -+ } -+ -+ break; -+ } -+ -+ if (unlikely(status < 0)) { -+ return status; -+ } -+ -+ return 1; ++ * Description: ++ * a) Optical transceiver EEPROM read/write transactions are just like ++ * the at24 eeproms managed by the at24.c i2c driver ++ * b) The register/memory layout is up to 256 128 byte pages defined by ++ * a "pages valid" register and switched via a "page select" ++ * register as explained in below diagram. ++ * c) 256 bytes are mapped at a time. 'Lower page 00h' is the first 128 ++ * bytes of address space, and always references the same ++ * location, independent of the page select register. ++ * All mapped pages are mapped into the upper 128 bytes ++ * (offset 128-255) of the i2c address. ++ * d) Devices with one I2C address (eg QSFP) use I2C address 0x50 ++ * (A0h in the spec), and map all pages in the upper 128 bytes ++ * of that address. ++ * e) Devices with two I2C addresses (eg SFP) have 256 bytes of data ++ * at I2C address 0x50, and 256 bytes of data at I2C address ++ * 0x51 (A2h in the spec). Page selection and paged access ++ * only apply to this second I2C address (0x51). ++ * e) The address space is presented, by the driver, as a linear ++ * address space. For devices with one I2C client at address ++ * 0x50 (eg QSFP), offset 0-127 are in the lower ++ * half of address 50/A0h/client[0]. Offset 128-255 are in ++ * page 0, 256-383 are page 1, etc. More generally, offset ++ * 'n' resides in page (n/128)-1. ('page -1' is the lower ++ * half, offset 0-127). ++ * f) For devices with two I2C clients at address 0x50 and 0x51 (eg SFP), ++ * the address space places offset 0-127 in the lower ++ * half of 50/A0/client[0], offset 128-255 in the upper ++ * half. Offset 256-383 is in the lower half of 51/A2/client[1]. ++ * Offset 384-511 is in page 0, in the upper half of 51/A2/... ++ * Offset 512-639 is in page 1, in the upper half of 51/A2/... ++ * Offset 'n' is in page (n/128)-3 (for n > 383) ++ * ++ * One I2c addressed (eg QSFP) Memory Map ++ * ++ * 2-Wire Serial Address: 1010000x ++ * ++ * Lower Page 00h (128 bytes) ++ * ===================== ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * | | ++ * |Page Select Byte(127)| ++ * ===================== ++ * | ++ * | ++ * | ++ * | ++ * V ++ * ------------------------------------------------------------ ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * | | | | ++ * V V V V ++ * ------------ -------------- --------------- -------------- ++ * | | | | | | | | ++ * | Upper | | Upper | | Upper | | Upper | ++ * | Page 00h | | Page 01h | | Page 02h | | Page 03h | ++ * | | | (Optional) | | (Optional) | | (Optional | ++ * | | | | | | | for Cable | ++ * | | | | | | | Assemblies) | ++ * | ID | | AST | | User | | | ++ * | Fields | | Table | | EEPROM Data | | | ++ * | | | | | | | | ++ * | | | | | | | | ++ * | | | | | | | | ++ * ------------ -------------- --------------- -------------- ++ * ++ * The SFF 8436 (QSFP) spec only defines the 4 pages described above. ++ * In anticipation of future applications and devices, this driver ++ * supports access to the full architected range, 256 pages. ++ * ++ **/ ++ ++/* #define DEBUG 1 */ ++ ++#undef EEPROM_CLASS ++#ifdef CONFIG_EEPROM_CLASS ++#define EEPROM_CLASS ++#endif ++#ifdef CONFIG_EEPROM_CLASS_MODULE ++#define EEPROM_CLASS +#endif + ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+} ++#ifdef EEPROM_CLASS ++#include ++#endif + -+static ssize_t sfp_port_write(struct sfp_port_data *data, -+ const char *buf, loff_t off, size_t count) ++#include ++ ++/* The maximum length of a port name */ ++#define MAX_PORT_NAME_LEN 20 ++ ++struct optoe_platform_data { ++ u32 byte_len; /* size (sum of all addr) */ ++ u16 page_size; /* for writes */ ++ u8 flags; ++ void *dummy1; /* backward compatibility */ ++ void *dummy2; /* backward compatibility */ ++ ++#ifdef EEPROM_CLASS ++ struct eeprom_platform_data *eeprom_data; ++#endif ++ char port_name[MAX_PORT_NAME_LEN]; ++}; ++ ++/* fundamental unit of addressing for EEPROM */ ++#define OPTOE_PAGE_SIZE 128 ++/* ++ * Single address devices (eg QSFP) have 256 pages, plus the unpaged ++ * low 128 bytes. If the device does not support paging, it is ++ * only 2 'pages' long. ++ */ ++#define OPTOE_ARCH_PAGES 256 ++#define ONE_ADDR_EEPROM_SIZE ((1 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE) ++#define ONE_ADDR_EEPROM_UNPAGED_SIZE (2 * OPTOE_PAGE_SIZE) ++/* ++ * Dual address devices (eg SFP) have 256 pages, plus the unpaged ++ * low 128 bytes, plus 256 bytes at 0x50. If the device does not ++ * support paging, it is 4 'pages' long. ++ */ ++#define TWO_ADDR_EEPROM_SIZE ((3 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE) ++#define TWO_ADDR_EEPROM_UNPAGED_SIZE (4 * OPTOE_PAGE_SIZE) ++#define TWO_ADDR_NO_0X51_SIZE (2 * OPTOE_PAGE_SIZE) ++ ++/* a few constants to find our way around the EEPROM */ ++#define OPTOE_PAGE_SELECT_REG 0x7F ++#define ONE_ADDR_PAGEABLE_REG 0x02 ++#define ONE_ADDR_NOT_PAGEABLE (1<<2) ++#define TWO_ADDR_PAGEABLE_REG 0x40 ++#define TWO_ADDR_PAGEABLE (1<<4) ++#define TWO_ADDR_0X51_REG 92 ++#define TWO_ADDR_0X51_SUPP (1<<6) ++#define OPTOE_ID_REG 0 ++#define OPTOE_READ_OP 0 ++#define OPTOE_WRITE_OP 1 ++#define OPTOE_EOF 0 /* used for access beyond end of device */ ++ ++struct optoe_data { ++ struct optoe_platform_data chip; ++ int use_smbus; ++ char port_name[MAX_PORT_NAME_LEN]; ++ ++ /* ++ * Lock protects against activities from other Linux tasks, ++ * but not from changes by other I2C masters. ++ */ ++ struct mutex lock; ++ struct bin_attribute bin; ++ struct attribute_group attr_group; ++ ++ u8 *writebuf; ++ unsigned int write_max; ++ ++ unsigned int num_addresses; ++ ++#ifdef EEPROM_CLASS ++ struct eeprom_device *eeprom_dev; ++#endif ++ ++ /* dev_class: ONE_ADDR (QSFP) or TWO_ADDR (SFP) */ ++ int dev_class; ++ ++ struct i2c_client *client[]; ++}; ++ ++ ++/* ++ * This parameter is to help this driver avoid blocking other drivers out ++ * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C ++ * clock, one 256 byte read takes about 1/43 second which is excessive; ++ * but the 1/170 second it takes at 400 kHz may be quite reasonable; and ++ * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. ++ * ++ * This value is forced to be a power of two so that writes align on pages. ++ */ ++static unsigned int io_limit = OPTOE_PAGE_SIZE; ++ ++/* ++ * specs often allow 5 msec for a page write, sometimes 20 msec; ++ * it's important to recover from write timeouts. ++ */ ++static unsigned int write_timeout = 25; ++ ++/* ++ * flags to distinguish one-address (QSFP family) from two-address (SFP family) ++ * If the family is not known, figure it out when the device is accessed ++ */ ++#define ONE_ADDR 1 ++#define TWO_ADDR 2 ++ ++static const struct i2c_device_id optoe_ids[] = { ++ { "optoe1", ONE_ADDR }, ++ { "optoe2", TWO_ADDR }, ++ { "sff8436", ONE_ADDR }, ++ { "24c04", TWO_ADDR }, ++ { /* END OF LIST */ } ++}; ++MODULE_DEVICE_TABLE(i2c, optoe_ids); ++ ++/*-------------------------------------------------------------------------*/ ++/* ++ * This routine computes the addressing information to be used for ++ * a given r/w request. ++ * ++ * Task is to calculate the client (0 = i2c addr 50, 1 = i2c addr 51), ++ * the page, and the offset. ++ * ++ * Handles both single address (eg QSFP) and two address (eg SFP). ++ * For SFP, offset 0-255 are on client[0], >255 is on client[1] ++ * Offset 256-383 are on the lower half of client[1] ++ * Pages are accessible on the upper half of client[1]. ++ * Offset >383 are in 128 byte pages mapped into the upper half ++ * ++ * For QSFP, all offsets are on client[0] ++ * offset 0-127 are on the lower half of client[0] (no paging) ++ * Pages are accessible on the upper half of client[1]. ++ * Offset >127 are in 128 byte pages mapped into the upper half ++ * ++ * Callers must not read/write beyond the end of a client or a page ++ * without recomputing the client/page. Hence offset (within page) ++ * plus length must be less than or equal to 128. (Note that this ++ * routine does not have access to the length of the call, hence ++ * cannot do the validity check.) ++ * ++ * Offset within Lower Page 00h and Upper Page 00h are not recomputed ++ */ ++ ++static uint8_t optoe_translate_offset(struct optoe_data *optoe, ++ loff_t *offset, struct i2c_client **client) +{ -+ ssize_t retval = 0; ++ unsigned int page = 0; + -+ if (unlikely(!count)) { -+ return count; ++ *client = optoe->client[0]; ++ ++ /* if SFP style, offset > 255, shift to i2c addr 0x51 */ ++ if (optoe->dev_class == TWO_ADDR) { ++ if (*offset > 255) { ++ /* like QSFP, but shifted to client[1] */ ++ *client = optoe->client[1]; ++ *offset -= 256; ++ } + } + + /* -+ * Write data to chip, protecting against concurrent updates -+ * from this host, but not from other I2C masters. ++ * if offset is in the range 0-128... ++ * page doesn't matter (using lower half), return 0. ++ * offset is already correct (don't add 128 to get to paged area) + */ -+ mutex_lock(&data->update_lock); ++ if (*offset < OPTOE_PAGE_SIZE) ++ return page; ++ ++ /* note, page will always be positive since *offset >= 128 */ ++ page = (*offset >> 7)-1; ++ /* 0x80 places the offset in the top half, offset is last 7 bits */ ++ *offset = OPTOE_PAGE_SIZE + (*offset & 0x7f); ++ ++ return page; /* note also returning client and offset */ ++} ++ ++static ssize_t optoe_eeprom_read(struct optoe_data *optoe, ++ struct i2c_client *client, ++ char *buf, unsigned int offset, size_t count) ++{ ++ struct i2c_msg msg[2]; ++ u8 msgbuf[2]; ++ unsigned long timeout, read_time; ++ int status, i; ++ ++ memset(msg, 0, sizeof(msg)); ++ ++ switch (optoe->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ /*smaller eeproms can work given some SMBus extension calls */ ++ if (count > I2C_SMBUS_BLOCK_MAX) ++ count = I2C_SMBUS_BLOCK_MAX; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ /* Check for odd length transaction */ ++ count = (count == 1) ? 1 : 2; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ count = 1; ++ break; ++ default: ++ /* ++ * When we have a better choice than SMBus calls, use a ++ * combined I2C message. Write address; then read up to ++ * io_limit data bytes. msgbuf is u8 and will cast to our ++ * needs. ++ */ ++ i = 0; ++ msgbuf[i++] = offset; ++ ++ msg[0].addr = client->addr; ++ msg[0].buf = msgbuf; ++ msg[0].len = i; ++ ++ msg[1].addr = client->addr; ++ msg[1].flags = I2C_M_RD; ++ msg[1].buf = buf; ++ msg[1].len = count; ++ } ++ ++ /* ++ * Reads fail if the previous write didn't complete yet. We may ++ * loop a few times until this one succeeds, waiting at least ++ * long enough for one entire page write to work. ++ */ ++ timeout = jiffies + msecs_to_jiffies(write_timeout); ++ do { ++ read_time = jiffies; ++ ++ switch (optoe->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ status = i2c_smbus_read_i2c_block_data(client, offset, ++ count, buf); ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ status = i2c_smbus_read_word_data(client, offset); ++ if (status >= 0) { ++ buf[0] = status & 0xff; ++ if (count == 2) ++ buf[1] = status >> 8; ++ status = count; ++ } ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ status = i2c_smbus_read_byte_data(client, offset); ++ if (status >= 0) { ++ buf[0] = status; ++ status = count; ++ } ++ break; ++ default: ++ status = i2c_transfer(client->adapter, msg, 2); ++ if (status == 2) ++ status = count; ++ } ++ ++ dev_dbg(&client->dev, "eeprom read %zu@%d --> %d (%ld)\n", ++ count, offset, status, jiffies); ++ ++ if (status == count) /* happy path */ ++ return count; ++ ++ if (status == -ENXIO) /* no module present */ ++ return status; ++ ++ /* REVISIT: at HZ=100, this is sloooow */ ++ usleep_range(1000, 2000); ++ } while (time_before(read_time, timeout)); ++ ++ return -ETIMEDOUT; ++} ++ ++static ssize_t optoe_eeprom_write(struct optoe_data *optoe, ++ struct i2c_client *client, ++ const char *buf, ++ unsigned int offset, size_t count) ++{ ++ struct i2c_msg msg; ++ ssize_t status; ++ unsigned long timeout, write_time; ++ unsigned int next_page_start; ++ int i = 0; ++ ++ /* write max is at most a page ++ * (In this driver, write_max is actually one byte!) ++ */ ++ if (count > optoe->write_max) ++ count = optoe->write_max; ++ ++ /* shorten count if necessary to avoid crossing page boundary */ ++ next_page_start = roundup(offset + 1, OPTOE_PAGE_SIZE); ++ if (offset + count > next_page_start) ++ count = next_page_start - offset; ++ ++ switch (optoe->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ /*smaller eeproms can work given some SMBus extension calls */ ++ if (count > I2C_SMBUS_BLOCK_MAX) ++ count = I2C_SMBUS_BLOCK_MAX; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ /* Check for odd length transaction */ ++ count = (count == 1) ? 1 : 2; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ count = 1; ++ break; ++ default: ++ /* If we'll use I2C calls for I/O, set up the message */ ++ msg.addr = client->addr; ++ msg.flags = 0; ++ ++ /* msg.buf is u8 and casts will mask the values */ ++ msg.buf = optoe->writebuf; ++ ++ msg.buf[i++] = offset; ++ memcpy(&msg.buf[i], buf, count); ++ msg.len = i + count; ++ break; ++ } ++ ++ /* ++ * Reads fail if the previous write didn't complete yet. We may ++ * loop a few times until this one succeeds, waiting at least ++ * long enough for one entire page write to work. ++ */ ++ timeout = jiffies + msecs_to_jiffies(write_timeout); ++ do { ++ write_time = jiffies; ++ ++ switch (optoe->use_smbus) { ++ case I2C_SMBUS_I2C_BLOCK_DATA: ++ status = i2c_smbus_write_i2c_block_data(client, ++ offset, count, buf); ++ if (status == 0) ++ status = count; ++ break; ++ case I2C_SMBUS_WORD_DATA: ++ if (count == 2) { ++ status = i2c_smbus_write_word_data(client, ++ offset, (u16)((buf[0])|(buf[1] << 8))); ++ } else { ++ /* count = 1 */ ++ status = i2c_smbus_write_byte_data(client, ++ offset, buf[0]); ++ } ++ if (status == 0) ++ status = count; ++ break; ++ case I2C_SMBUS_BYTE_DATA: ++ status = i2c_smbus_write_byte_data(client, offset, ++ buf[0]); ++ if (status == 0) ++ status = count; ++ break; ++ default: ++ status = i2c_transfer(client->adapter, &msg, 1); ++ if (status == 1) ++ status = count; ++ break; ++ } ++ ++ dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", ++ count, offset, (long int) status, jiffies); ++ ++ if (status == count) ++ return count; ++ ++ /* REVISIT: at HZ=100, this is sloooow */ ++ usleep_range(1000, 2000); ++ } while (time_before(write_time, timeout)); ++ ++ return -ETIMEDOUT; ++} ++ ++ ++static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, ++ char *buf, loff_t off, ++ size_t count, int opcode) ++{ ++ struct i2c_client *client; ++ ssize_t retval = 0; ++ uint8_t page = 0; ++ loff_t phy_offset = off; ++ int ret = 0; ++ ++ page = optoe_translate_offset(optoe, &phy_offset, &client); ++ dev_dbg(&client->dev, ++ "%s off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", ++ __func__, off, page, phy_offset, (long int) count, opcode); ++ if (page > 0) { ++ ret = optoe_eeprom_write(optoe, client, &page, ++ OPTOE_PAGE_SELECT_REG, 1); ++ if (ret < 0) { ++ dev_dbg(&client->dev, ++ "Write page register for page %d failed ret:%d!\n", ++ page, ret); ++ return ret; ++ } ++ } + + while (count) { -+ ssize_t status; ++ ssize_t status; + -+ status = sfp_eeprom_write(data->client, off, buf, count); ++ if (opcode == OPTOE_READ_OP) { ++ status = optoe_eeprom_read(optoe, client, ++ buf, phy_offset, count); ++ } else { ++ status = optoe_eeprom_write(optoe, client, ++ buf, phy_offset, count); ++ } + if (status <= 0) { -+ if (retval == 0) { ++ if (retval == 0) + retval = status; -+ } + break; + } + buf += status; -+ off += status; ++ phy_offset += status; + count -= status; + retval += status; + } + -+ mutex_unlock(&data->update_lock); ++ ++ if (page > 0) { ++ /* return the page register to page 0 (why?) */ ++ page = 0; ++ ret = optoe_eeprom_write(optoe, client, &page, ++ OPTOE_PAGE_SELECT_REG, 1); ++ if (ret < 0) { ++ dev_err(&client->dev, ++ "Restore page register to 0 failed:%d!\n", ret); ++ /* error only if nothing has been transferred */ ++ if (retval == 0) ++ retval = ret; ++ } ++ } + return retval; +} + -+ -+static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, -+ struct bin_attribute *attr, -+ char *buf, loff_t off, size_t count) ++/* ++ * Figure out if this access is within the range of supported pages. ++ * Note this is called on every access because we don't know if the ++ * module has been replaced since the last call. ++ * If/when modules support more pages, this is the routine to update ++ * to validate and allow access to additional pages. ++ * ++ * Returns updated len for this access: ++ * - entire access is legal, original len is returned. ++ * - access begins legal but is too long, len is truncated to fit. ++ * - initial offset exceeds supported pages, return OPTOE_EOF (zero) ++ */ ++static ssize_t optoe_page_legal(struct optoe_data *optoe, ++ loff_t off, size_t len) +{ -+ int present; -+ struct sfp_port_data *data; -+ DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); -+ data = dev_get_drvdata(container_of(kobj, struct device, kobj)); ++ struct i2c_client *client = optoe->client[0]; ++ u8 regval; ++ int status; ++ size_t maxlen; + -+ present = sfp_is_port_present(data->client, data->port); -+ if (IS_ERR_VALUE(present)) { -+ return present; ++ if (off < 0) ++ return -EINVAL; ++ if (optoe->dev_class == TWO_ADDR) { ++ /* SFP case */ ++ /* if only using addr 0x50 (first 256 bytes) we're good */ ++ if ((off + len) <= TWO_ADDR_NO_0X51_SIZE) ++ return len; ++ /* if offset exceeds possible pages, we're not good */ ++ if (off >= TWO_ADDR_EEPROM_SIZE) ++ return OPTOE_EOF; ++ /* in between, are pages supported? */ ++ status = optoe_eeprom_read(optoe, client, ®val, ++ TWO_ADDR_PAGEABLE_REG, 1); ++ if (status < 0) ++ return status; /* error out (no module?) */ ++ if (regval & TWO_ADDR_PAGEABLE) { ++ /* Pages supported, trim len to the end of pages */ ++ maxlen = TWO_ADDR_EEPROM_SIZE - off; ++ } else { ++ /* pages not supported, trim len to unpaged size */ ++ if (off >= TWO_ADDR_EEPROM_UNPAGED_SIZE) ++ return OPTOE_EOF; ++ ++ /* will be accessing addr 0x51, is that supported? */ ++ /* byte 92, bit 6 implies DDM support, 0x51 support */ ++ status = optoe_eeprom_read(optoe, client, ®val, ++ TWO_ADDR_0X51_REG, 1); ++ if (status < 0) ++ return status; ++ if (regval & TWO_ADDR_0X51_SUPP) { ++ /* addr 0x51 is OK */ ++ maxlen = TWO_ADDR_EEPROM_UNPAGED_SIZE - off; ++ } else { ++ /* addr 0x51 NOT supported, trim to 256 max */ ++ if (off >= TWO_ADDR_NO_0X51_SIZE) ++ return OPTOE_EOF; ++ maxlen = TWO_ADDR_NO_0X51_SIZE - off; ++ } ++ } ++ len = (len > maxlen) ? maxlen : len; ++ dev_dbg(&client->dev, ++ "page_legal, SFP, off %lld len %ld\n", ++ off, (long int) len); ++ } else { ++ /* QSFP case */ ++ /* if no pages needed, we're good */ ++ if ((off + len) <= ONE_ADDR_EEPROM_UNPAGED_SIZE) ++ return len; ++ /* if offset exceeds possible pages, we're not good */ ++ if (off >= ONE_ADDR_EEPROM_SIZE) ++ return OPTOE_EOF; ++ /* in between, are pages supported? */ ++ status = optoe_eeprom_read(optoe, client, ®val, ++ ONE_ADDR_PAGEABLE_REG, 1); ++ if (status < 0) ++ return status; /* error out (no module?) */ ++ if (regval & ONE_ADDR_NOT_PAGEABLE) { ++ /* pages not supported, trim len to unpaged size */ ++ if (off >= ONE_ADDR_EEPROM_UNPAGED_SIZE) ++ return OPTOE_EOF; ++ maxlen = ONE_ADDR_EEPROM_UNPAGED_SIZE - off; ++ } else { ++ /* Pages supported, trim len to the end of pages */ ++ maxlen = ONE_ADDR_EEPROM_SIZE - off; ++ } ++ len = (len > maxlen) ? maxlen : len; ++ dev_dbg(&client->dev, ++ "page_legal, QSFP, off %lld len %ld\n", ++ off, (long int) len); + } -+ -+ if (present == 0) { -+ /* port is not present */ -+ return -ENODEV; -+ } -+ -+ return sfp_port_write(data, buf, off, count); ++ return len; +} + -+static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, -+ int data_len) ++static ssize_t optoe_read_write(struct optoe_data *optoe, ++ char *buf, loff_t off, size_t len, int opcode) +{ -+#if USE_I2C_BLOCK_READ -+ int status, retry = I2C_RW_RETRY_COUNT; ++ struct i2c_client *client = optoe->client[0]; ++ int chunk; ++ int status = 0; ++ ssize_t retval; ++ size_t pending_len = 0, chunk_len = 0; ++ loff_t chunk_offset = 0, chunk_start_offset = 0; + -+ if (data_len > I2C_SMBUS_BLOCK_MAX) { -+ data_len = I2C_SMBUS_BLOCK_MAX; -+ } -+ -+ while (retry) { -+ status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); -+ if (unlikely(status < 0)) { -+ msleep(I2C_RW_RETRY_INTERVAL); -+ retry--; -+ continue; -+ } -+ -+ break; -+ } -+ -+ if (unlikely(status < 0)) { -+ goto abort; -+ } -+ if (unlikely(status != data_len)) { -+ status = -EIO; -+ goto abort; -+ } -+ -+ //result = data_len; -+ -+abort: -+ return status; -+#else -+ int status, retry = I2C_RW_RETRY_COUNT; -+ -+ while (retry) { -+ status = i2c_smbus_read_byte_data(client, command); -+ if (unlikely(status < 0)) { -+ msleep(I2C_RW_RETRY_INTERVAL); -+ retry--; -+ continue; -+ } -+ -+ break; -+ } -+ -+ if (unlikely(status < 0)) { -+ dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); -+ goto abort; -+ } -+ -+ *data = (u8)status; -+ status = 1; -+ -+abort: -+ return status; -+#endif -+} -+ -+static ssize_t sfp_port_read(struct sfp_port_data *data, -+ char *buf, loff_t off, size_t count) -+{ -+ ssize_t retval = 0; -+ -+ if (unlikely(!count)) { -+ DEBUG_PRINT("Count = 0, return"); -+ return count; -+ } ++ dev_dbg(&client->dev, ++ "%s: off %lld len:%ld, opcode:%s\n", ++ __func__, off, (long int) len, ++ (opcode == OPTOE_READ_OP) ? "r" : "w"); ++ if (unlikely(!len)) ++ return len; + + /* + * Read data from chip, protecting against concurrent updates + * from this host, but not from other I2C masters. + */ -+ mutex_lock(&data->update_lock); ++ mutex_lock(&optoe->lock); + -+ while (count) { -+ ssize_t status; ++ /* ++ * Confirm this access fits within the device suppored addr range ++ */ ++ status = optoe_page_legal(optoe, off, len); ++ if ((status == OPTOE_EOF) || (status < 0)) { ++ mutex_unlock(&optoe->lock); ++ return status; ++ } ++ len = status; + -+ status = sfp_eeprom_read(data->client, off, buf, count); -+ if (status <= 0) { -+ if (retval == 0) { -+ retval = status; -+ } -+ break; ++ /* ++ * For each (128 byte) chunk involved in this request, issue a ++ * separate call to sff_eeprom_update_client(), to ++ * ensure that each access recalculates the client/page ++ * and writes the page register as needed. ++ * Note that chunk to page mapping is confusing, is different for ++ * QSFP and SFP, and never needs to be done. Don't try! ++ */ ++ pending_len = len; /* amount remaining to transfer */ ++ retval = 0; /* amount transferred */ ++ for (chunk = off >> 7; chunk <= (off + len - 1) >> 7; chunk++) { ++ ++ /* ++ * Compute the offset and number of bytes to be read/write ++ * ++ * 1. start at offset 0 (within the chunk), and read/write ++ * the entire chunk ++ * 2. start at offset 0 (within the chunk) and read/write less ++ * than entire chunk ++ * 3. start at an offset not equal to 0 and read/write the rest ++ * of the chunk ++ * 4. start at an offset not equal to 0 and read/write less than ++ * (end of chunk - offset) ++ */ ++ chunk_start_offset = chunk * OPTOE_PAGE_SIZE; ++ ++ if (chunk_start_offset < off) { ++ chunk_offset = off; ++ if ((off + pending_len) < (chunk_start_offset + ++ OPTOE_PAGE_SIZE)) ++ chunk_len = pending_len; ++ else ++ chunk_len = OPTOE_PAGE_SIZE - off; ++ } else { ++ chunk_offset = chunk_start_offset; ++ if (pending_len > OPTOE_PAGE_SIZE) ++ chunk_len = OPTOE_PAGE_SIZE; ++ else ++ chunk_len = pending_len; + } + ++ dev_dbg(&client->dev, ++ "sff_r/w: off %lld, len %ld, chunk_start_offset %lld, chunk_offset %lld, chunk_len %ld, pending_len %ld\n", ++ off, (long int) len, chunk_start_offset, chunk_offset, ++ (long int) chunk_len, (long int) pending_len); ++ ++ /* ++ * note: chunk_offset is from the start of the EEPROM, ++ * not the start of the chunk ++ */ ++ status = optoe_eeprom_update_client(optoe, buf, ++ chunk_offset, chunk_len, opcode); ++ if (status != chunk_len) { ++ /* This is another 'no device present' path */ ++ dev_dbg(&client->dev, ++ "o_u_c: chunk %d c_offset %lld c_len %ld failed %d!\n", ++ chunk, chunk_offset, (long int) chunk_len, status); ++ if (status > 0) ++ retval += status; ++ if (retval == 0) ++ retval = status; ++ break; ++ } + buf += status; -+ off += status; -+ count -= status; ++ pending_len -= status; + retval += status; + } ++ mutex_unlock(&optoe->lock); + -+ mutex_unlock(&data->update_lock); + return retval; -+ +} + -+static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, ++static ssize_t optoe_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ -+ int present; -+ struct sfp_port_data *data; -+ DEBUG_PRINT("offset = (%d), count = (%d)", off, count); -+ data = dev_get_drvdata(container_of(kobj, struct device, kobj)); ++ struct i2c_client *client = to_i2c_client(container_of(kobj, ++ struct device, kobj)); ++ struct optoe_data *optoe = i2c_get_clientdata(client); + -+ present = sfp_is_port_present(data->client, data->port); -+ if (IS_ERR_VALUE(present)) { -+ return present; -+ } -+ -+ if (present == 0) { -+ /* port is not present */ -+ return -ENODEV; -+ } -+ -+ return sfp_port_read(data, buf, off, count); ++ return optoe_read_write(optoe, buf, off, count, OPTOE_READ_OP); +} + -+static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) ++ ++static ssize_t optoe_bin_write(struct file *filp, struct kobject *kobj, ++ struct bin_attribute *attr, ++ char *buf, loff_t off, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(container_of(kobj, ++ struct device, kobj)); ++ struct optoe_data *optoe = i2c_get_clientdata(client); ++ ++ return optoe_read_write(optoe, buf, off, count, OPTOE_WRITE_OP); ++} ++ ++static int optoe_remove(struct i2c_client *client) ++{ ++ struct optoe_data *optoe; ++ int i; ++ ++ optoe = i2c_get_clientdata(client); ++ sysfs_remove_group(&client->dev.kobj, &optoe->attr_group); ++ sysfs_remove_bin_file(&client->dev.kobj, &optoe->bin); ++ ++ for (i = 1; i < optoe->num_addresses; i++) ++ i2c_unregister_device(optoe->client[i]); ++ ++#ifdef EEPROM_CLASS ++ eeprom_device_unregister(optoe->eeprom_dev); ++#endif ++ ++ kfree(optoe->writebuf); ++ kfree(optoe); ++ return 0; ++} ++ ++static ssize_t show_dev_class(struct device *dev, ++ struct device_attribute *dattr, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct optoe_data *optoe = i2c_get_clientdata(client); ++ ssize_t count; ++ ++ mutex_lock(&optoe->lock); ++ count = sprintf(buf, "%d\n", optoe->dev_class); ++ mutex_unlock(&optoe->lock); ++ ++ return count; ++} ++ ++static ssize_t set_dev_class(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct optoe_data *optoe = i2c_get_clientdata(client); ++ int dev_class; ++ ++ /* ++ * dev_class is actually the number of i2c addresses used, thus ++ * legal values are "1" (QSFP class) and "2" (SFP class) ++ */ ++ ++ if (kstrtoint(buf, 0, &dev_class) != 0 || ++ dev_class < 1 || dev_class > 2) ++ return -EINVAL; ++ ++ mutex_lock(&optoe->lock); ++ optoe->dev_class = dev_class; ++ mutex_unlock(&optoe->lock); ++ ++ return count; ++} ++ ++/* ++ * if using the EEPROM CLASS driver, we don't report a port_name, ++ * the EEPROM CLASS drive handles that. Hence all this code is ++ * only compiled if we are NOT using the EEPROM CLASS driver. ++ */ ++#ifndef EEPROM_CLASS ++ ++static ssize_t show_port_name(struct device *dev, ++ struct device_attribute *dattr, char *buf) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct optoe_data *optoe = i2c_get_clientdata(client); ++ ssize_t count; ++ ++ mutex_lock(&optoe->lock); ++ count = sprintf(buf, "%s\n", optoe->port_name); ++ mutex_unlock(&optoe->lock); ++ ++ return count; ++} ++ ++static ssize_t set_port_name(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct optoe_data *optoe = i2c_get_clientdata(client); ++ char port_name[MAX_PORT_NAME_LEN]; ++ ++ /* no checking, this value is not used except by show_port_name */ ++ ++ if (sscanf(buf, "%19s", port_name) != 1) ++ return -EINVAL; ++ ++ mutex_lock(&optoe->lock); ++ strcpy(optoe->port_name, port_name); ++ mutex_unlock(&optoe->lock); ++ ++ return count; ++} ++ ++static DEVICE_ATTR(port_name, 0644, show_port_name, set_port_name); ++#endif /* if NOT defined EEPROM_CLASS, the common case */ ++ ++static DEVICE_ATTR(dev_class, 0644, show_dev_class, set_dev_class); ++ ++static struct attribute *optoe_attrs[] = { ++#ifndef EEPROM_CLASS ++ &dev_attr_port_name.attr, ++#endif ++ &dev_attr_dev_class.attr, ++ NULL, ++}; ++ ++static struct attribute_group optoe_attr_group = { ++ .attrs = optoe_attrs, ++}; ++ ++static int optoe_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) +{ + int err; ++ int use_smbus = 0; ++ struct optoe_platform_data chip; ++ struct optoe_data *optoe; ++ int num_addresses = 0; ++ char port_name[MAX_PORT_NAME_LEN]; + -+ sysfs_bin_attr_init(eeprom); -+ eeprom->attr.name = EEPROM_NAME; -+ eeprom->attr.mode = S_IWUSR | S_IRUGO; -+ eeprom->read = sfp_bin_read; -+ eeprom->write = sfp_bin_write; -+ eeprom->size = EEPROM_SIZE; -+ -+ /* Create eeprom file */ -+ err = sysfs_create_bin_file(kobj, eeprom); -+ if (err) { -+ return err; ++ if (client->addr != 0x50) { ++ dev_dbg(&client->dev, "probe, bad i2c addr: 0x%x\n", ++ client->addr); ++ err = -EINVAL; ++ goto exit; + } + -+ return 0; -+} -+ -+static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) -+{ -+ sysfs_remove_bin_file(kobj, eeprom); -+ return 0; -+} -+ -+static const struct attribute_group sfp_msa_group = { -+ .attrs = sfp_msa_attributes, -+}; -+ -+static int sfp_i2c_check_functionality(struct i2c_client *client) -+{ -+#if USE_I2C_BLOCK_READ -+ return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); ++ if (client->dev.platform_data) { ++ chip = *(struct optoe_platform_data *)client->dev.platform_data; ++ /* take the port name from the supplied platform data */ ++#ifdef EEPROM_CLASS ++ strncpy(port_name, chip.eeprom_data->label, MAX_PORT_NAME_LEN); +#else -+ return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); ++ memcpy(port_name, chip.port_name, MAX_PORT_NAME_LEN); +#endif -+} -+ -+static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, -+ struct sfp_msa_data **data) -+{ -+ int status; -+ struct sfp_msa_data *msa; -+ -+ if (!sfp_i2c_check_functionality(client)) { -+ status = -EIO; -+ goto exit; -+ } -+ -+ msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); -+ if (!msa) { -+ status = -ENOMEM; -+ goto exit; -+ } -+ -+ /* Register sysfs hooks */ -+ status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); -+ if (status) { -+ goto exit_free; -+ } -+ -+ /* init eeprom */ -+ status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); -+ if (status) { -+ goto exit_remove; -+ } -+ -+ *data = msa; -+ dev_info(&client->dev, "sfp msa '%s'\n", client->name); -+ -+ return 0; -+ -+exit_remove: -+ sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); -+exit_free: -+ kfree(msa); -+exit: -+ -+ return status; -+} -+ -+static const struct attribute_group sfp_ddm_group = { -+ .attrs = sfp_ddm_attributes, -+}; -+ -+static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, -+ struct sfp_ddm_data **data) -+{ -+ int status; -+ struct sfp_ddm_data *ddm; -+ -+ if (!sfp_i2c_check_functionality(client)) { -+ status = -EIO; -+ goto exit; -+ } -+ -+ ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); -+ if (!ddm) { -+ status = -ENOMEM; -+ goto exit; -+ } -+ -+ /* Register sysfs hooks */ -+ status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); -+ if (status) { -+ goto exit_free; -+ } -+ -+ /* init eeprom */ -+ status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); -+ if (status) { -+ goto exit_remove; -+ } -+ -+ *data = ddm; -+ dev_info(&client->dev, "sfp ddm '%s'\n", client->name); -+ -+ return 0; -+ -+exit_remove: -+ sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); -+exit_free: -+ kfree(ddm); -+exit: -+ -+ return status; -+} -+ -+static const struct attribute_group qsfp_group = { -+ .attrs = qsfp_attributes, -+}; -+ -+static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, -+ struct qsfp_data **data) -+{ -+ int status; -+ struct qsfp_data *qsfp; -+ -+ if (!sfp_i2c_check_functionality(client)) { -+ status = -EIO; -+ goto exit; -+ } -+ -+ qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); -+ if (!qsfp) { -+ status = -ENOMEM; -+ goto exit; -+ } -+ -+ /* Register sysfs hooks */ -+ status = sysfs_create_group(&client->dev.kobj, &qsfp_group); -+ if (status) { -+ goto exit_free; -+ } -+ -+ /* init eeprom */ -+ status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); -+ if (status) { -+ goto exit_remove; -+ } -+ -+ *data = qsfp; -+ dev_info(&client->dev, "qsfp '%s'\n", client->name); -+ -+ return 0; -+ -+exit_remove: -+ sysfs_remove_group(&client->dev.kobj, &qsfp_group); -+exit_free: -+ kfree(qsfp); -+exit: -+ -+ return status; -+} -+ -+/* Platform dependent +++ */ -+static int sfp_device_probe(struct i2c_client *client, -+ const struct i2c_device_id *dev_id) -+{ -+ struct sfp_port_data *data = NULL; -+ -+ data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); -+ if (!data) { -+ return -ENOMEM; -+ } -+ -+ i2c_set_clientdata(client, data); -+ mutex_init(&data->update_lock); -+ data->port = dev_id->driver_data; -+ data->client = client; -+ -+ if (client->addr != SFP_EEPROM_A0_I2C_ADDR && -+ client->addr != SFP_EEPROM_A2_I2C_ADDR ) { -+ return -ENODEV; -+ } -+ -+ if (dev_id->driver_data >= as4610_sfp1 && dev_id->driver_data <= as4610_sfp4) { -+ if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { -+ data->driver_type = DRIVER_TYPE_SFP_MSA; -+ return sfp_msa_probe(client, dev_id, &data->msa); -+ } -+ else if (client->addr == SFP_EEPROM_A2_I2C_ADDR) { -+ data->driver_type = DRIVER_TYPE_SFP_DDM; -+ return sfp_ddm_probe(client, dev_id, &data->ddm); ++ dev_dbg(&client->dev, ++ "probe, chip provided, flags:0x%x; name: %s\n", ++ chip.flags, client->name); ++ } else { ++ if (!id->driver_data) { ++ err = -ENODEV; ++ goto exit; + } ++ dev_dbg(&client->dev, "probe, building chip\n"); ++ strcpy(port_name, "unitialized"); ++ chip.flags = 0; ++#ifdef EEPROM_CLASS ++ chip.eeprom_data = NULL; ++#endif + } -+ else if (dev_id->driver_data >= as4610_sfp5 && dev_id->driver_data <= as4610_sfp6) { -+ if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { -+ data->driver_type = DRIVER_TYPE_QSFP; -+ return qsfp_probe(client, dev_id, &data->qsfp); ++ ++ /* Use I2C operations unless we're stuck with SMBus extensions. */ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { ++ if (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { ++ use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; ++ } else if (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_WORD_DATA)) { ++ use_smbus = I2C_SMBUS_WORD_DATA; ++ } else if (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_READ_BYTE_DATA)) { ++ use_smbus = I2C_SMBUS_BYTE_DATA; ++ } else { ++ err = -EPFNOSUPPORT; ++ goto exit; + } + } + -+ return -ENODEV; -+} -+/* Platform dependent --- */ + -+static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) -+{ -+ sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); -+ sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); -+ kfree(data); -+ return 0; -+} ++ /* ++ * Make room for two i2c clients ++ */ ++ num_addresses = 2; + -+static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) -+{ -+ sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); -+ sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); -+ kfree(data); -+ return 0; -+} ++ optoe = kzalloc(sizeof(struct optoe_data) + ++ num_addresses * sizeof(struct i2c_client *), ++ GFP_KERNEL); ++ if (!optoe) { ++ err = -ENOMEM; ++ goto exit; ++ } + -+static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) -+{ -+ sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); -+ sysfs_remove_group(&client->dev.kobj, &qsfp_group); -+ kfree(data); -+ return 0; -+} ++ mutex_init(&optoe->lock); + -+static int sfp_device_remove(struct i2c_client *client) -+{ -+ struct sfp_port_data *data = i2c_get_clientdata(client); ++ /* determine whether this is a one-address or two-address module */ ++ if ((strcmp(client->name, "optoe1") == 0) || ++ (strcmp(client->name, "sff8436") == 0)) { ++ /* one-address (eg QSFP) family */ ++ optoe->dev_class = ONE_ADDR; ++ chip.byte_len = ONE_ADDR_EEPROM_SIZE; ++ num_addresses = 1; ++ } else if ((strcmp(client->name, "optoe2") == 0) || ++ (strcmp(client->name, "24c04") == 0)) { ++ /* SFP family */ ++ optoe->dev_class = TWO_ADDR; ++ chip.byte_len = TWO_ADDR_EEPROM_SIZE; ++ } else { /* those were the only two choices */ ++ err = -EINVAL; ++ goto exit; ++ } + -+ switch (data->driver_type) { -+ case DRIVER_TYPE_SFP_MSA: -+ return sfp_msa_remove(client, data->msa); -+ case DRIVER_TYPE_SFP_DDM: -+ return sfp_ddm_remove(client, data->ddm); -+ case DRIVER_TYPE_QSFP: -+ return qfp_remove(client, data->qsfp); ++ dev_dbg(&client->dev, "dev_class: %d\n", optoe->dev_class); ++ optoe->use_smbus = use_smbus; ++ optoe->chip = chip; ++ optoe->num_addresses = num_addresses; ++ memcpy(optoe->port_name, port_name, MAX_PORT_NAME_LEN); ++ ++ /* ++ * Export the EEPROM bytes through sysfs, since that's convenient. ++ * By default, only root should see the data (maybe passwords etc) ++ */ ++ sysfs_bin_attr_init(&optoe->bin); ++ optoe->bin.attr.name = "eeprom"; ++ optoe->bin.attr.mode = 0444; ++ optoe->bin.read = optoe_bin_read; ++ optoe->bin.size = chip.byte_len; ++ ++ if (!use_smbus || ++ (i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || ++ i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_WORD_DATA) || ++ i2c_check_functionality(client->adapter, ++ I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { ++ /* ++ * NOTE: AN-2079 ++ * Finisar recommends that the host implement 1 byte writes ++ * only since this module only supports 32 byte page boundaries. ++ * 2 byte writes are acceptable for PE and Vout changes per ++ * Application Note AN-2071. ++ */ ++ unsigned int write_max = 1; ++ ++ optoe->bin.write = optoe_bin_write; ++ optoe->bin.attr.mode |= 0200; ++ ++ if (write_max > io_limit) ++ write_max = io_limit; ++ if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) ++ write_max = I2C_SMBUS_BLOCK_MAX; ++ optoe->write_max = write_max; ++ ++ /* buffer (data + address at the beginning) */ ++ optoe->writebuf = kmalloc(write_max + 2, GFP_KERNEL); ++ if (!optoe->writebuf) { ++ err = -ENOMEM; ++ goto exit_kfree; ++ } ++ } else { ++ dev_warn(&client->dev, ++ "cannot write due to controller restrictions."); ++ } ++ ++ optoe->client[0] = client; ++ ++ /* SFF-8472 spec requires that the second I2C address be 0x51 */ ++ if (num_addresses == 2) { ++ optoe->client[1] = i2c_new_dummy(client->adapter, 0x51); ++ if (!optoe->client[1]) { ++ dev_err(&client->dev, "address 0x51 unavailable\n"); ++ err = -EADDRINUSE; ++ goto err_struct; ++ } ++ } ++ ++ /* create the sysfs eeprom file */ ++ err = sysfs_create_bin_file(&client->dev.kobj, &optoe->bin); ++ if (err) ++ goto err_struct; ++ ++ optoe->attr_group = optoe_attr_group; ++ ++ err = sysfs_create_group(&client->dev.kobj, &optoe->attr_group); ++ if (err) { ++ dev_err(&client->dev, "failed to create sysfs attribute group.\n"); ++ goto err_struct; ++ } ++ ++#ifdef EEPROM_CLASS ++ optoe->eeprom_dev = eeprom_device_register(&client->dev, ++ chip.eeprom_data); ++ if (IS_ERR(optoe->eeprom_dev)) { ++ dev_err(&client->dev, "error registering eeprom device.\n"); ++ err = PTR_ERR(optoe->eeprom_dev); ++ goto err_sysfs_cleanup; ++ } ++#endif ++ ++ i2c_set_clientdata(client, optoe); ++ ++ dev_info(&client->dev, "%zu byte %s EEPROM, %s\n", ++ optoe->bin.size, client->name, ++ optoe->bin.write ? "read/write" : "read-only"); ++ ++ if (use_smbus == I2C_SMBUS_WORD_DATA || ++ use_smbus == I2C_SMBUS_BYTE_DATA) { ++ dev_notice(&client->dev, ++ "Falling back to %s reads, performance will suffer\n", ++ use_smbus == I2C_SMBUS_WORD_DATA ? "word" : "byte"); + } + + return 0; ++ ++#ifdef EEPROM_CLASS ++err_sysfs_cleanup: ++ sysfs_remove_group(&client->dev.kobj, &optoe->attr_group); ++ sysfs_remove_bin_file(&client->dev.kobj, &optoe->bin); ++#endif ++ ++err_struct: ++ if (num_addresses == 2) { ++ if (optoe->client[1]) ++ i2c_unregister_device(optoe->client[1]); ++ } ++ ++ kfree(optoe->writebuf); ++exit_kfree: ++ kfree(optoe); ++exit: ++ dev_dbg(&client->dev, "probe error %d\n", err); ++ ++ return err; +} + -+/* Addresses scanned -+ */ -+static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; ++/*-------------------------------------------------------------------------*/ + -+static struct i2c_driver sfp_driver = { ++static struct i2c_driver optoe_driver = { + .driver = { -+ .name = DRIVER_NAME, ++ .name = "optoe", ++ .owner = THIS_MODULE, + }, -+ .probe = sfp_device_probe, -+ .remove = sfp_device_remove, -+ .id_table = sfp_device_id, -+ .address_list = normal_i2c, ++ .probe = optoe_probe, ++ .remove = optoe_remove, ++ .id_table = optoe_ids, +}; + -+static int __init sfp_init(void) ++static int __init optoe_init(void) +{ -+ return i2c_add_driver(&sfp_driver); -+} + -+static void __exit sfp_exit(void) ++ if (!io_limit) { ++ pr_err("optoe: io_limit must not be 0!\n"); ++ return -EINVAL; ++ } ++ ++ io_limit = rounddown_pow_of_two(io_limit); ++ return i2c_add_driver(&optoe_driver); ++} ++module_init(optoe_init); ++ ++static void __exit optoe_exit(void) +{ -+ i2c_del_driver(&sfp_driver); ++ i2c_del_driver(&optoe_driver); +} ++module_exit(optoe_exit); + -+MODULE_AUTHOR("Brandon Chuang "); -+MODULE_DESCRIPTION("accton as4610_sfp driver"); ++MODULE_DESCRIPTION("Driver for optical transceiver (SFP, QSFP, ...) EEPROMs"); ++MODULE_AUTHOR("DON BOLLINGER "); +MODULE_LICENSE("GPL"); -+ -+late_initcall(sfp_init); -+module_exit(sfp_exit); -+ diff --git a/include/linux/accton_i2c_cpld.h b/include/linux/accton_i2c_cpld.h new file mode 100644 index 0000000..9b75abd --- /dev/null -+++ b/include/linux/accton_i2c_cpld.h ++++ b/include/linux/accton_as4610_cpld.h @@ -0,0 +1,76 @@ +/* -+ * A hwmon driver for the accton_i2c_cpld ++ * A hwmon driver for the accton as4610 cpld + * + * Copyright (C) 2016 Accton Technology Corporation. + * Brandon Chuang @@ -3874,8 +3908,8 @@ index 0000000..9b75abd + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + -+extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); -+extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); ++extern int as4610_54_cpld_read(unsigned short cpld_addr, u8 reg); ++extern int as4610_54_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +#define AS4610_CPLD_SLAVE_ADDR 0x30 +#define AS4610_CPLD_PID_OFFSET 0x01 /* Product ID offset */ @@ -3892,7 +3926,7 @@ index 0000000..9b75abd + +static inline int as4610_product_id(void) +{ -+ int pid = accton_i2c_cpld_read(AS4610_CPLD_SLAVE_ADDR, AS4610_CPLD_PID_OFFSET); ++ int pid = as4610_54_cpld_read(AS4610_CPLD_SLAVE_ADDR, AS4610_CPLD_PID_OFFSET); + pid &= 0xF; + + if (pid < PID_AS4610_30T || pid > PID_AS4610_54T_B || pid == PID_RESERVED) { @@ -3929,4 +3963,3 @@ index 0000000..9b75abd + return nFan; +} + - diff --git a/packages/base/any/kernels/4.14-lts/configs/x86_64-all/x86_64-all.config b/packages/base/any/kernels/4.14-lts/configs/x86_64-all/x86_64-all.config index ad3795fc..8aa3ce13 100755 --- a/packages/base/any/kernels/4.14-lts/configs/x86_64-all/x86_64-all.config +++ b/packages/base/any/kernels/4.14-lts/configs/x86_64-all/x86_64-all.config @@ -37,6 +37,7 @@ CONFIG_ZONE_DMA32=y CONFIG_AUDIT_ARCH=y CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_HAVE_INTEL_TXT=y CONFIG_X86_64_SMP=y CONFIG_ARCH_SUPPORTS_UPROBES=y CONFIG_FIX_EARLYCON_MEM=y @@ -557,6 +558,7 @@ CONFIG_ARCH_ENABLE_THP_MIGRATION=y CONFIG_PHYS_ADDR_T_64BIT=y CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y +CONFIG_MMU_NOTIFIER=y CONFIG_KSM=y CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y @@ -1708,10 +1710,10 @@ CONFIG_MD=y CONFIG_BLK_DEV_MD=y # CONFIG_MD_AUTODETECT is not set # CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID10 is not set -# CONFIG_MD_RAID456 is not set +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +CONFIG_MD_RAID10=y +CONFIG_MD_RAID456=y # CONFIG_MD_MULTIPATH is not set # CONFIG_MD_FAULTY is not set # CONFIG_BCACHE is not set @@ -1719,19 +1721,25 @@ CONFIG_BLK_DEV_DM_BUILTIN=y CONFIG_BLK_DEV_DM=y # CONFIG_DM_MQ_DEFAULT is not set # CONFIG_DM_DEBUG is not set +CONFIG_DM_BUFIO=y +# CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING is not set +CONFIG_DM_BIO_PRISON=y +CONFIG_DM_PERSISTENT_DATA=y CONFIG_DM_CRYPT=y -# CONFIG_DM_SNAPSHOT is not set -# CONFIG_DM_THIN_PROVISIONING is not set +CONFIG_DM_SNAPSHOT=y +CONFIG_DM_THIN_PROVISIONING=y # CONFIG_DM_CACHE is not set # CONFIG_DM_ERA is not set -# CONFIG_DM_MIRROR is not set -# CONFIG_DM_RAID is not set +CONFIG_DM_MIRROR=y +# CONFIG_DM_LOG_USERSPACE is not set +CONFIG_DM_RAID=y # CONFIG_DM_ZERO is not set # CONFIG_DM_MULTIPATH is not set # CONFIG_DM_DELAY is not set -# CONFIG_DM_UEVENT is not set +CONFIG_DM_UEVENT=y # CONFIG_DM_FLAKEY is not set -# CONFIG_DM_VERITY is not set +CONFIG_DM_VERITY=y +# CONFIG_DM_VERITY_FEC is not set # CONFIG_DM_SWITCH is not set # CONFIG_DM_LOG_WRITES is not set # CONFIG_DM_INTEGRITY is not set @@ -2270,7 +2278,7 @@ CONFIG_DEVPORT=y # I2C support # CONFIG_I2C=y -# CONFIG_ACPI_I2C_OPREGION is not set +CONFIG_ACPI_I2C_OPREGION=y CONFIG_I2C_BOARDINFO=y CONFIG_I2C_COMPAT=y CONFIG_I2C_CHARDEV=y @@ -2327,11 +2335,11 @@ CONFIG_I2C_PIIX4=y # CONFIG_I2C_DESIGNWARE_PCI is not set # CONFIG_I2C_EMEV2 is not set # CONFIG_I2C_GPIO is not set -# CONFIG_I2C_OCORES is not set +CONFIG_I2C_OCORES=y CONFIG_I2C_PCA_PLATFORM=y # CONFIG_I2C_PXA_PCI is not set # CONFIG_I2C_SIMTEC is not set -# CONFIG_I2C_XILINX is not set +CONFIG_I2C_XILINX=y # # External I2C/SMBus adapter drivers @@ -2804,6 +2812,7 @@ CONFIG_MFD_CORE=y CONFIG_LPC_ICH=y CONFIG_LPC_SCH=y # CONFIG_INTEL_SOC_PMIC is not set +# CONFIG_INTEL_SOC_PMIC_BXTWC is not set # CONFIG_INTEL_SOC_PMIC_CHTWC is not set CONFIG_MFD_INTEL_LPSS=y CONFIG_MFD_INTEL_LPSS_ACPI=y @@ -3411,15 +3420,16 @@ CONFIG_SYNC_FILE=y # CONFIG_SW_SYNC is not set # CONFIG_AUXDISPLAY is not set CONFIG_UIO=y -# CONFIG_UIO_CIF is not set -# CONFIG_UIO_PDRV_GENIRQ is not set -# CONFIG_UIO_DMEM_GENIRQ is not set +CONFIG_UIO_CIF=y +CONFIG_UIO_PDRV_GENIRQ=y +CONFIG_UIO_DMEM_GENIRQ=y # CONFIG_UIO_AEC is not set # CONFIG_UIO_SERCOS3 is not set -# CONFIG_UIO_PCI_GENERIC is not set +CONFIG_UIO_PCI_GENERIC=y # CONFIG_UIO_NETX is not set # CONFIG_UIO_PRUSS is not set # CONFIG_UIO_MF624 is not set +# CONFIG_VFIO is not set CONFIG_VIRT_DRIVERS=y CONFIG_VIRTIO=y @@ -3463,9 +3473,10 @@ CONFIG_X86_PLATFORM_DEVICES=y # CONFIG_INTEL_RST is not set # CONFIG_INTEL_SMARTCONNECT is not set # CONFIG_PVPANIC is not set -# CONFIG_INTEL_PMC_IPC is not set +CONFIG_INTEL_PMC_IPC=y # CONFIG_SURFACE_PRO3_BUTTON is not set -# CONFIG_INTEL_PUNIT_IPC is not set +CONFIG_INTEL_PUNIT_IPC=y +CONFIG_INTEL_TELEMETRY=y # CONFIG_MLX_PLATFORM is not set # CONFIG_MLX_CPLD_PLATFORM is not set # CONFIG_INTEL_TURBO_MAX_3 is not set @@ -3500,14 +3511,21 @@ CONFIG_CLKBLD_I8253=y CONFIG_MAILBOX=y CONFIG_PCC=y # CONFIG_ALTERA_MBOX is not set +CONFIG_IOMMU_API=y CONFIG_IOMMU_SUPPORT=y # # Generic IOMMU Pagetable Support # -# CONFIG_AMD_IOMMU is not set -# CONFIG_INTEL_IOMMU is not set -# CONFIG_IRQ_REMAP is not set +CONFIG_IOMMU_IOVA=y +CONFIG_AMD_IOMMU=y +CONFIG_AMD_IOMMU_V2=y +CONFIG_DMAR_TABLE=y +CONFIG_INTEL_IOMMU=y +# CONFIG_INTEL_IOMMU_SVM is not set +# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set +CONFIG_INTEL_IOMMU_FLOPPY_WA=y +CONFIG_IRQ_REMAP=y # # Remoteproc drivers @@ -4017,6 +4035,7 @@ CONFIG_PROVIDE_OHCI1394_DMA_INIT=y # CONFIG_INTERVAL_TREE_TEST is not set # CONFIG_PERCPU_TEST is not set # CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_ASYNC_RAID6_TEST is not set # CONFIG_TEST_HEXDUMP is not set # CONFIG_TEST_STRING_HELPERS is not set # CONFIG_TEST_KSTRTOX is not set @@ -4095,6 +4114,7 @@ CONFIG_SECURITY_NETWORK=y CONFIG_PAGE_TABLE_ISOLATION=y # CONFIG_SECURITY_NETWORK_XFRM is not set # CONFIG_SECURITY_PATH is not set +# CONFIG_INTEL_TXT is not set CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y # CONFIG_HARDENED_USERCOPY is not set # CONFIG_FORTIFY_SOURCE is not set @@ -4112,6 +4132,12 @@ CONFIG_INTEGRITY_AUDIT=y # CONFIG_EVM is not set CONFIG_DEFAULT_SECURITY_DAC=y CONFIG_DEFAULT_SECURITY="" +CONFIG_XOR_BLOCKS=y +CONFIG_ASYNC_CORE=y +CONFIG_ASYNC_MEMCPY=y +CONFIG_ASYNC_XOR=y +CONFIG_ASYNC_PQ=y +CONFIG_ASYNC_RAID6_RECOV=y CONFIG_CRYPTO=y # @@ -4301,6 +4327,7 @@ CONFIG_BINARY_PRINTF=y # # Library routines # +CONFIG_RAID6_PQ=y CONFIG_BITREVERSE=y # CONFIG_HAVE_ARCH_BITREVERSE is not set CONFIG_RATIONAL=y diff --git a/packages/base/any/kernels/4.9-lts/configs/x86_64-all/x86_64-all.config b/packages/base/any/kernels/4.9-lts/configs/x86_64-all/x86_64-all.config index 423e0d63..db1ad67e 100644 --- a/packages/base/any/kernels/4.9-lts/configs/x86_64-all/x86_64-all.config +++ b/packages/base/any/kernels/4.9-lts/configs/x86_64-all/x86_64-all.config @@ -2435,6 +2435,7 @@ CONFIG_SENSORS_MAX6620=y # CONFIG_SENSORS_MAX6697 is not set # CONFIG_SENSORS_MAX31790 is not set # CONFIG_SENSORS_MCP3021 is not set +CONFIG_SENSORS_MLXREG_FAN=y # CONFIG_SENSORS_ADCXX is not set # CONFIG_SENSORS_LM63 is not set # CONFIG_SENSORS_LM70 is not set diff --git a/packages/base/any/kernels/4.9-lts/patches/0013-Mellanox-backport-patchwork-from-kernels-4.17-4.19.patch b/packages/base/any/kernels/4.9-lts/patches/0013-Mellanox-backport-patchwork-from-kernels-4.17-4.19.patch new file mode 100644 index 00000000..5c0c5d91 --- /dev/null +++ b/packages/base/any/kernels/4.9-lts/patches/0013-Mellanox-backport-patchwork-from-kernels-4.17-4.19.patch @@ -0,0 +1,3063 @@ +From 54f7d08c9337a82e79142fcdab2b6fa5bcf5843e Mon Sep 17 00:00:00 2001 +From: Vadim Pasternak +Date: Wed, 18 Jul 2018 16:27:08 +0000 +Subject: [patch bacport patchwork 1/1] Mellanox backport patchwork from + kerenls 4.17-4.19 + +Signed-off-by: Vadim Pasternak +--- + drivers/hwmon/Kconfig | 12 + + drivers/hwmon/Makefile | 1 + + drivers/hwmon/mlxreg-fan.c | 489 ++++++++++++ + drivers/platform/mellanox/Kconfig | 9 +- + drivers/platform/mellanox/Makefile | 7 +- + drivers/platform/mellanox/mlxreg-hotplug.c | 306 ++++---- + drivers/platform/mellanox/mlxreg-io.c | 118 +-- + drivers/platform/x86/mlx-platform.c | 1106 +++++++++++++++++++--------- + 8 files changed, 1482 insertions(+), 566 deletions(-) + create mode 100644 drivers/hwmon/mlxreg-fan.c + +diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig +index 45cef3d..9014151 100644 +--- a/drivers/hwmon/Kconfig ++++ b/drivers/hwmon/Kconfig +@@ -907,6 +907,18 @@ config SENSORS_MCP3021 + This driver can also be built as a module. If so, the module + will be called mcp3021. + ++config SENSORS_MLXREG_FAN ++ tristate "Mellanox Mellanox FAN driver" ++ depends on MELLANOX_PLATFORM ++ select THERMAL ++ select REGMAP ++ help ++ This option enables support for the FAN control on the Mellanox ++ Ethernet and InfiniBand switches. The driver can be activated by the ++ platform device add call. Say Y to enable these. To compile this ++ driver as a module, choose 'M' here: the module will be called ++ mlxreg-fan. ++ + config SENSORS_MENF21BMC_HWMON + tristate "MEN 14F021P00 BMC Hardware Monitoring" + depends on MFD_MENF21BMC +diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile +index aecf4ba..4ff1b63 100644 +--- a/drivers/hwmon/Makefile ++++ b/drivers/hwmon/Makefile +@@ -122,6 +122,7 @@ obj-$(CONFIG_SENSORS_MAX6697) += max6697.o + obj-$(CONFIG_SENSORS_MAX31790) += max31790.o + obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o + obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o ++obj-$(CONFIG_SENSORS_MLXREG_FAN) += mlxreg-fan.o + obj-$(CONFIG_SENSORS_MENF21BMC_HWMON) += menf21bmc_hwmon.o + obj-$(CONFIG_SENSORS_NCT6683) += nct6683.o + obj-$(CONFIG_SENSORS_NCT6775) += nct6775.o +diff --git a/drivers/hwmon/mlxreg-fan.c b/drivers/hwmon/mlxreg-fan.c +new file mode 100644 +index 0000000..de46577 +--- /dev/null ++++ b/drivers/hwmon/mlxreg-fan.c +@@ -0,0 +1,489 @@ ++// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) ++// ++// Copyright (c) 2018 Mellanox Technologies. All rights reserved. ++// Copyright (c) 2018 Vadim Pasternak ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define MLXREG_FAN_MAX_TACHO 12 ++#define MLXREG_FAN_MAX_STATE 10 ++#define MLXREG_FAN_MIN_DUTY 51 /* 20% */ ++#define MLXREG_FAN_MAX_DUTY 255 /* 100% */ ++/* ++ * Minimum and maximum FAN allowed speed in percent: from 20% to 100%. Values ++ * MLXREG_FAN_MAX_STATE + x, where x is between 2 and 10 are used for ++ * setting FAN speed dynamic minimum. For example, if value is set to 14 (40%) ++ * cooling levels vector will be set to 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10 to ++ * introduce PWM speed in percent: 40, 40, 40, 40, 40, 50, 60. 70, 80, 90, 100. ++ */ ++#define MLXREG_FAN_SPEED_MIN (MLXREG_FAN_MAX_STATE + 2) ++#define MLXREG_FAN_SPEED_MAX (MLXREG_FAN_MAX_STATE * 2) ++#define MLXREG_FAN_SPEED_MIN_LEVEL 2 /* 20 percent */ ++#define MLXREG_FAN_TACHO_SAMPLES_PER_PULSE_DEF 44 ++#define MLXREG_FAN_TACHO_DIVIDER_DEF 1132 ++/* ++ * FAN datasheet defines the formula for RPM calculations as RPM = 15/t-high. ++ * The logic in a programmable device measures the time t-high by sampling the ++ * tachometer every t-sample (with the default value 11.32 uS) and increment ++ * a counter (N) as long as the pulse has not change: ++ * RPM = 15 / (t-sample * (K + Regval)), where: ++ * Regval: is the value read from the programmable device register; ++ * - 0xff - represents tachometer fault; ++ * - 0xfe - represents tachometer minimum value , which is 4444 RPM; ++ * - 0x00 - represents tachometer maximum value , which is 300000 RPM; ++ * K: is 44 and it represents the minimum allowed samples per pulse; ++ * N: is equal K + Regval; ++ * In order to calculate RPM from the register value the following formula is ++ * used: RPM = 15 / ((Regval + K) * 11.32) * 10^(-6)), which in the ++ * default case is modified to: ++ * RPM = 15000000 * 100 / ((Regval + 44) * 1132); ++ * - for Regval 0x00, RPM will be 15000000 * 100 / (44 * 1132) = 30115; ++ * - for Regval 0xfe, RPM will be 15000000 * 100 / ((254 + 44) * 1132) = 4446; ++ * In common case the formula is modified to: ++ * RPM = 15000000 * 100 / ((Regval + samples) * divider). ++ */ ++#define MLXREG_FAN_GET_RPM(rval, d, s) (DIV_ROUND_CLOSEST(15000000 * 100, \ ++ ((rval) + (s)) * (d))) ++#define MLXREG_FAN_GET_FAULT(val, mask) (!!((val) ^ (mask))) ++#define MLXREG_FAN_PWM_DUTY2STATE(duty) (DIV_ROUND_CLOSEST((duty) * \ ++ MLXREG_FAN_MAX_STATE, \ ++ MLXREG_FAN_MAX_DUTY)) ++#define MLXREG_FAN_PWM_STATE2DUTY(stat) (DIV_ROUND_CLOSEST((stat) * \ ++ MLXREG_FAN_MAX_DUTY, \ ++ MLXREG_FAN_MAX_STATE)) ++ ++/* ++ * struct mlxreg_fan_tacho - tachometer data (internal use): ++ * ++ * @connected: indicates if tachometer is connected; ++ * @reg: register offset; ++ * @mask: fault mask; ++ */ ++struct mlxreg_fan_tacho { ++ bool connected; ++ u32 reg; ++ u32 mask; ++}; ++ ++/* ++ * struct mlxreg_fan_pwm - PWM data (internal use): ++ * ++ * @connected: indicates if PWM is connected; ++ * @reg: register offset; ++ */ ++struct mlxreg_fan_pwm { ++ bool connected; ++ u32 reg; ++}; ++ ++/* ++ * struct mlxreg_fan - private data (internal use): ++ * ++ * @dev: basic device; ++ * @regmap: register map of parent device; ++ * @tacho: tachometer data; ++ * @pwm: PWM data; ++ * @samples: minimum allowed samples per pulse; ++ * @divider: divider value for tachometer RPM calculation; ++ * @cooling: cooling device levels; ++ * @cdev: cooling device; ++ */ ++struct mlxreg_fan { ++ struct device *dev; ++ void *regmap; ++ struct mlxreg_core_platform_data *pdata; ++ struct mlxreg_fan_tacho tacho[MLXREG_FAN_MAX_TACHO]; ++ struct mlxreg_fan_pwm pwm; ++ int samples; ++ int divider; ++ u8 cooling_levels[MLXREG_FAN_MAX_STATE + 1]; ++ struct thermal_cooling_device *cdev; ++}; ++ ++static int ++mlxreg_fan_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, ++ int channel, long *val) ++{ ++ struct mlxreg_fan *fan = dev_get_drvdata(dev); ++ struct mlxreg_fan_tacho *tacho; ++ u32 regval; ++ int err; ++ ++ switch (type) { ++ case hwmon_fan: ++ tacho = &fan->tacho[channel]; ++ switch (attr) { ++ case hwmon_fan_input: ++ err = regmap_read(fan->regmap, tacho->reg, ®val); ++ if (err) ++ return err; ++ ++ *val = MLXREG_FAN_GET_RPM(regval, fan->divider, ++ fan->samples); ++ break; ++ ++ case hwmon_fan_fault: ++ err = regmap_read(fan->regmap, tacho->reg, ®val); ++ if (err) ++ return err; ++ ++ *val = MLXREG_FAN_GET_FAULT(regval, tacho->mask); ++ break; ++ ++ default: ++ return -EOPNOTSUPP; ++ } ++ break; ++ ++ case hwmon_pwm: ++ switch (attr) { ++ case hwmon_pwm_input: ++ err = regmap_read(fan->regmap, fan->pwm.reg, ®val); ++ if (err) ++ return err; ++ ++ *val = regval; ++ break; ++ ++ default: ++ return -EOPNOTSUPP; ++ } ++ break; ++ ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return 0; ++} ++ ++static int ++mlxreg_fan_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, ++ int channel, long val) ++{ ++ struct mlxreg_fan *fan = dev_get_drvdata(dev); ++ ++ switch (type) { ++ case hwmon_pwm: ++ switch (attr) { ++ case hwmon_pwm_input: ++ if (val < MLXREG_FAN_MIN_DUTY || ++ val > MLXREG_FAN_MAX_DUTY) ++ return -EINVAL; ++ return regmap_write(fan->regmap, fan->pwm.reg, val); ++ default: ++ return -EOPNOTSUPP; ++ } ++ break; ++ ++ default: ++ return -EOPNOTSUPP; ++ } ++ ++ return -EOPNOTSUPP; ++} ++ ++static umode_t ++mlxreg_fan_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, ++ int channel) ++{ ++ switch (type) { ++ case hwmon_fan: ++ if (!(((struct mlxreg_fan *)data)->tacho[channel].connected)) ++ return 0; ++ ++ switch (attr) { ++ case hwmon_fan_input: ++ case hwmon_fan_fault: ++ return 0444; ++ default: ++ break; ++ } ++ break; ++ ++ case hwmon_pwm: ++ if (!(((struct mlxreg_fan *)data)->pwm.connected)) ++ return 0; ++ ++ switch (attr) { ++ case hwmon_pwm_input: ++ return 0644; ++ default: ++ break; ++ } ++ break; ++ ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static const u32 mlxreg_fan_hwmon_fan_config[] = { ++ HWMON_F_INPUT | HWMON_F_FAULT, ++ HWMON_F_INPUT | HWMON_F_FAULT, ++ HWMON_F_INPUT | HWMON_F_FAULT, ++ HWMON_F_INPUT | HWMON_F_FAULT, ++ HWMON_F_INPUT | HWMON_F_FAULT, ++ HWMON_F_INPUT | HWMON_F_FAULT, ++ HWMON_F_INPUT | HWMON_F_FAULT, ++ HWMON_F_INPUT | HWMON_F_FAULT, ++ HWMON_F_INPUT | HWMON_F_FAULT, ++ HWMON_F_INPUT | HWMON_F_FAULT, ++ HWMON_F_INPUT | HWMON_F_FAULT, ++ HWMON_F_INPUT | HWMON_F_FAULT, ++ 0 ++}; ++ ++static const struct hwmon_channel_info mlxreg_fan_hwmon_fan = { ++ .type = hwmon_fan, ++ .config = mlxreg_fan_hwmon_fan_config, ++}; ++ ++static const u32 mlxreg_fan_hwmon_pwm_config[] = { ++ HWMON_PWM_INPUT, ++ 0 ++}; ++ ++static const struct hwmon_channel_info mlxreg_fan_hwmon_pwm = { ++ .type = hwmon_pwm, ++ .config = mlxreg_fan_hwmon_pwm_config, ++}; ++ ++static const struct hwmon_channel_info *mlxreg_fan_hwmon_info[] = { ++ &mlxreg_fan_hwmon_fan, ++ &mlxreg_fan_hwmon_pwm, ++ NULL ++}; ++ ++static const struct hwmon_ops mlxreg_fan_hwmon_hwmon_ops = { ++ .is_visible = mlxreg_fan_is_visible, ++ .read = mlxreg_fan_read, ++ .write = mlxreg_fan_write, ++}; ++ ++static const struct hwmon_chip_info mlxreg_fan_hwmon_chip_info = { ++ .ops = &mlxreg_fan_hwmon_hwmon_ops, ++ .info = mlxreg_fan_hwmon_info, ++}; ++ ++static int mlxreg_fan_get_max_state(struct thermal_cooling_device *cdev, ++ unsigned long *state) ++{ ++ *state = MLXREG_FAN_MAX_STATE; ++ return 0; ++} ++ ++static int mlxreg_fan_get_cur_state(struct thermal_cooling_device *cdev, ++ unsigned long *state) ++ ++{ ++ struct mlxreg_fan *fan = cdev->devdata; ++ u32 regval; ++ int err; ++ ++ err = regmap_read(fan->regmap, fan->pwm.reg, ®val); ++ if (err) { ++ dev_err(fan->dev, "Failed to query PWM duty\n"); ++ return err; ++ } ++ ++ *state = MLXREG_FAN_PWM_DUTY2STATE(regval); ++ ++ return 0; ++} ++ ++static int mlxreg_fan_set_cur_state(struct thermal_cooling_device *cdev, ++ unsigned long state) ++ ++{ ++ struct mlxreg_fan *fan = cdev->devdata; ++ unsigned long cur_state; ++ u32 regval; ++ int i; ++ int err; ++ ++ /* ++ * Verify if this request is for changing allowed FAN dynamical ++ * minimum. If it is - update cooling levels accordingly and update ++ * state, if current state is below the newly requested minimum state. ++ * For example, if current state is 5, and minimal state is to be ++ * changed from 4 to 6, fan->cooling_levels[0 to 5] will be changed all ++ * from 4 to 6. And state 5 (fan->cooling_levels[4]) should be ++ * overwritten. ++ */ ++ if (state >= MLXREG_FAN_SPEED_MIN && state <= MLXREG_FAN_SPEED_MAX) { ++ state -= MLXREG_FAN_MAX_STATE; ++ for (i = 0; i < state; i++) ++ fan->cooling_levels[i] = state; ++ for (i = state; i <= MLXREG_FAN_MAX_STATE; i++) ++ fan->cooling_levels[i] = i; ++ ++ err = regmap_read(fan->regmap, fan->pwm.reg, ®val); ++ if (err) { ++ dev_err(fan->dev, "Failed to query PWM duty\n"); ++ return err; ++ } ++ ++ cur_state = MLXREG_FAN_PWM_DUTY2STATE(regval); ++ if (state < cur_state) ++ return 0; ++ ++ state = cur_state; ++ } ++ ++ if (state > MLXREG_FAN_MAX_STATE) ++ return -EINVAL; ++ ++ /* Normalize the state to the valid speed range. */ ++ state = fan->cooling_levels[state]; ++ err = regmap_write(fan->regmap, fan->pwm.reg, ++ MLXREG_FAN_PWM_STATE2DUTY(state)); ++ if (err) { ++ dev_err(fan->dev, "Failed to write PWM duty\n"); ++ return err; ++ } ++ return 0; ++} ++ ++static const struct thermal_cooling_device_ops mlxreg_fan_cooling_ops = { ++ .get_max_state = mlxreg_fan_get_max_state, ++ .get_cur_state = mlxreg_fan_get_cur_state, ++ .set_cur_state = mlxreg_fan_set_cur_state, ++}; ++ ++static int mlxreg_fan_config(struct mlxreg_fan *fan, ++ struct mlxreg_core_platform_data *pdata) ++{ ++ struct mlxreg_core_data *data = pdata->data; ++ bool configured = false; ++ int tacho_num = 0, i; ++ ++ fan->samples = MLXREG_FAN_TACHO_SAMPLES_PER_PULSE_DEF; ++ fan->divider = MLXREG_FAN_TACHO_DIVIDER_DEF; ++ for (i = 0; i < pdata->counter; i++, data++) { ++ if (strnstr(data->label, "tacho", sizeof(data->label))) { ++ if (tacho_num == MLXREG_FAN_MAX_TACHO) { ++ dev_err(fan->dev, "too many tacho entries: %s\n", ++ data->label); ++ return -EINVAL; ++ } ++ fan->tacho[tacho_num].reg = data->reg; ++ fan->tacho[tacho_num].mask = data->mask; ++ fan->tacho[tacho_num++].connected = true; ++ } else if (strnstr(data->label, "pwm", sizeof(data->label))) { ++ if (fan->pwm.connected) { ++ dev_err(fan->dev, "duplicate pwm entry: %s\n", ++ data->label); ++ return -EINVAL; ++ } ++ fan->pwm.reg = data->reg; ++ fan->pwm.connected = true; ++ } else if (strnstr(data->label, "conf", sizeof(data->label))) { ++ if (configured) { ++ dev_err(fan->dev, "duplicate conf entry: %s\n", ++ data->label); ++ return -EINVAL; ++ } ++ /* Validate that conf parameters are not zeros. */ ++ if (!data->mask || !data->bit) { ++ dev_err(fan->dev, "invalid conf entry params: %s\n", ++ data->label); ++ return -EINVAL; ++ } ++ fan->samples = data->mask; ++ fan->divider = data->bit; ++ configured = true; ++ } else { ++ dev_err(fan->dev, "invalid label: %s\n", data->label); ++ return -EINVAL; ++ } ++ } ++ ++ /* Init cooling levels per PWM state. */ ++ for (i = 0; i < MLXREG_FAN_SPEED_MIN_LEVEL; i++) ++ fan->cooling_levels[i] = MLXREG_FAN_SPEED_MIN_LEVEL; ++ for (i = MLXREG_FAN_SPEED_MIN_LEVEL; i <= MLXREG_FAN_MAX_STATE; i++) ++ fan->cooling_levels[i] = i; ++ ++ return 0; ++} ++ ++static int mlxreg_fan_probe(struct platform_device *pdev) ++{ ++ struct mlxreg_core_platform_data *pdata; ++ struct mlxreg_fan *fan; ++ struct device *hwm; ++ int err; ++ ++ pdata = dev_get_platdata(&pdev->dev); ++ if (!pdata) { ++ dev_err(&pdev->dev, "Failed to get platform data.\n"); ++ return -EINVAL; ++ } ++ ++ fan = devm_kzalloc(&pdev->dev, sizeof(*fan), GFP_KERNEL); ++ if (!fan) ++ return -ENOMEM; ++ ++ fan->dev = &pdev->dev; ++ fan->regmap = pdata->regmap; ++ platform_set_drvdata(pdev, fan); ++ ++ err = mlxreg_fan_config(fan, pdata); ++ if (err) ++ return err; ++ ++ hwm = devm_hwmon_device_register_with_info(&pdev->dev, "mlxreg_fan", ++ fan, ++ &mlxreg_fan_hwmon_chip_info, ++ NULL); ++ if (IS_ERR(hwm)) { ++ dev_err(&pdev->dev, "Failed to register hwmon device\n"); ++ return PTR_ERR(hwm); ++ } ++ ++ if (IS_REACHABLE(CONFIG_THERMAL)) { ++ fan->cdev = thermal_cooling_device_register("mlxreg_fan", fan, ++ &mlxreg_fan_cooling_ops); ++ if (IS_ERR(fan->cdev)) { ++ dev_err(&pdev->dev, "Failed to register cooling device\n"); ++ return PTR_ERR(fan->cdev); ++ } ++ } ++ ++ return 0; ++} ++ ++static int mlxreg_fan_remove(struct platform_device *pdev) ++{ ++ struct mlxreg_fan *fan = platform_get_drvdata(pdev); ++ ++ if (IS_REACHABLE(CONFIG_THERMAL)) ++ thermal_cooling_device_unregister(fan->cdev); ++ ++ return 0; ++} ++ ++static struct platform_driver mlxreg_fan_driver = { ++ .driver = { ++ .name = "mlxreg-fan", ++ }, ++ .probe = mlxreg_fan_probe, ++ .remove = mlxreg_fan_remove, ++}; ++ ++module_platform_driver(mlxreg_fan_driver); ++ ++MODULE_AUTHOR("Vadim Pasternak "); ++MODULE_DESCRIPTION("Mellanox FAN driver"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:mlxreg-fan"); +diff --git a/drivers/platform/mellanox/Kconfig b/drivers/platform/mellanox/Kconfig +index 5c6dc29..cd8a908 100644 +--- a/drivers/platform/mellanox/Kconfig ++++ b/drivers/platform/mellanox/Kconfig +@@ -1,3 +1,4 @@ ++# SPDX-License-Identifier: GPL-2.0 + # + # Platform support for Mellanox hardware + # +@@ -23,13 +24,13 @@ config MLXREG_HOTPLUG + cables and fans on the wide range Mellanox IB and Ethernet systems. + + config MLXREG_IO +- tristate "Mellanox platform register driver support" ++ tristate "Mellanox platform register access driver support" + depends on REGMAP + depends on HWMON +- ---help--- ++ help + This driver allows access to Mellanox programmable device register +- space trough sysfs interface. The set of registers for sysfs access +- are defined per system type bases and includes the registers related ++ space through sysfs interface. The sets of registers for sysfs access ++ are defined per system type bases and include the registers related + to system resets operation, system reset causes monitoring and some + kinds of mux selection. + +diff --git a/drivers/platform/mellanox/Makefile b/drivers/platform/mellanox/Makefile +index b9a2692..57074d9c 100644 +--- a/drivers/platform/mellanox/Makefile ++++ b/drivers/platform/mellanox/Makefile +@@ -1,2 +1,7 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Makefile for linux/drivers/platform/mellanox ++# Mellanox Platform-Specific Drivers ++# + obj-$(CONFIG_MLXREG_HOTPLUG) += mlxreg-hotplug.o +-obj-$(CONFIG_MLXREG_IO) += mlxreg-io.o ++obj-$(CONFIG_MLXREG_IO) += mlxreg-io.o +diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c +index 5c13591..4761211 100644 +--- a/drivers/platform/mellanox/mlxreg-hotplug.c ++++ b/drivers/platform/mellanox/mlxreg-hotplug.c +@@ -1,6 +1,6 @@ + /* +- * Copyright (c) 2017 Mellanox Technologies. All rights reserved. +- * Copyright (c) 2017 Vadim Pasternak ++ * Copyright (c) 2016-2018 Mellanox Technologies. All rights reserved. ++ * Copyright (c) 2016-2018 Vadim Pasternak + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -50,12 +51,9 @@ + #define MLXREG_HOTPLUG_AGGR_MASK_OFF 1 + + /* ASIC health parameters. */ ++#define MLXREG_HOTPLUG_DOWN_MASK 0x00 + #define MLXREG_HOTPLUG_HEALTH_MASK 0x02 +-#define MLXREG_HOTPLUG_RST_CNTR 3 +- +-#define MLXREG_HOTPLUG_PROP_OKAY "okay" +-#define MLXREG_HOTPLUG_PROP_DISABLED "disabled" +-#define MLXREG_HOTPLUG_PROP_STATUS "status" ++#define MLXREG_HOTPLUG_RST_CNTR 2 + + #define MLXREG_HOTPLUG_ATTRS_MAX 24 + #define MLXREG_HOTPLUG_NOT_ASSERT 3 +@@ -63,11 +61,14 @@ + /** + * struct mlxreg_hotplug_priv_data - platform private data: + * @irq: platform device interrupt number; ++ * @dev: basic device; + * @pdev: platform device; + * @plat: platform data; +- * @dwork: delayed work template; ++ * @regmap: register map handle; ++ * @dwork_irq: delayed work template; + * @lock: spin lock; + * @hwmon: hwmon device; ++ * @kobj: hwmon kobject for notification; + * @mlxreg_hotplug_attr: sysfs attributes array; + * @mlxreg_hotplug_dev_attr: sysfs sensor device attribute array; + * @group: sysfs attribute group; +@@ -75,6 +76,7 @@ + * @cell: location of top aggregation interrupt register; + * @mask: top aggregation interrupt common mask; + * @aggr_cache: last value of aggregation register status; ++ * @after_probe: flag indication probing completion; + * @not_asserted: number of entries in workqueue with no signal assertion; + */ + struct mlxreg_hotplug_priv_data { +@@ -84,9 +86,9 @@ struct mlxreg_hotplug_priv_data { + struct mlxreg_hotplug_platform_data *plat; + struct regmap *regmap; + struct delayed_work dwork_irq; +- struct delayed_work dwork; + spinlock_t lock; /* sync with interrupt */ + struct device *hwmon; ++ struct kobject *kobj; + struct attribute *mlxreg_hotplug_attr[MLXREG_HOTPLUG_ATTRS_MAX + 1]; + struct sensor_device_attribute_2 + mlxreg_hotplug_dev_attr[MLXREG_HOTPLUG_ATTRS_MAX]; +@@ -99,70 +101,37 @@ struct mlxreg_hotplug_priv_data { + u8 not_asserted; + }; + +-#if defined(CONFIG_OF_DYNAMIC) +-/** +- * struct mlxreg_hotplug_device_en - Open Firmware property for enabling device +- * +- * @name - property name; +- * @value - property value string; +- * @length - length of proprty value string; +- * +- * The structure is used for the devices, which require some dynamic +- * selection operation allowing access to them. +- */ +-static struct property mlxreg_hotplug_device_en = { +- .name = MLXREG_HOTPLUG_PROP_STATUS, +- .value = MLXREG_HOTPLUG_PROP_OKAY, +- .length = sizeof(MLXREG_HOTPLUG_PROP_OKAY), +-}; +- +-/** +- * struct mlxreg_hotplug_device_dis - Open Firmware property for disabling +- * device +- * +- * @name - property name; +- * @value - property value string; +- * @length - length of proprty value string; +- * +- * The structure is used for the devices, which require some dynamic +- * selection operation disallowing access to them. +- */ +-static struct property mlxreg_hotplug_device_dis = { +- .name = MLXREG_HOTPLUG_PROP_STATUS, +- .value = MLXREG_HOTPLUG_PROP_DISABLED, +- .length = sizeof(MLXREG_HOTPLUG_PROP_DISABLED), +-}; +- +-static int mlxreg_hotplug_of_device_create(struct mlxreg_core_data *data) ++static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv, ++ struct mlxreg_core_data *data) + { +- return of_update_property(data->np, &mlxreg_hotplug_device_en); +-} ++ struct mlxreg_core_hotplug_platform_data *pdata; + +-static void mlxreg_hotplug_of_device_destroy(struct mlxreg_core_data *data) +-{ +- of_update_property(data->np, &mlxreg_hotplug_device_dis); +- of_node_clear_flag(data->np, OF_POPULATED); +-} +-#else +-static int mlxreg_hotplug_of_device_create(struct mlxreg_core_data *data) +-{ +- return 0; +-} ++ /* Notify user by sending hwmon uevent. */ ++ kobject_uevent(priv->kobj, KOBJ_CHANGE); + +-static void mlxreg_hotplug_of_device_destroy(struct mlxreg_core_data *data) +-{ +-} +-#endif ++ /* ++ * Return if adapter number is negative. It could be in case hotplug ++ * event is not associated with hotplug device. ++ */ ++ if (data->hpdev.nr < 0) ++ return 0; + +-static int mlxreg_hotplug_device_create(struct mlxreg_core_data *data) +-{ +- data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr); +- if (!data->hpdev.adapter) ++ pdata = dev_get_platdata(&priv->pdev->dev); ++ data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr + ++ pdata->shift_nr); ++ if (!data->hpdev.adapter) { ++ dev_err(priv->dev, "Failed to get adapter for bus %d\n", ++ data->hpdev.nr + pdata->shift_nr); + return -EFAULT; ++ } + + data->hpdev.client = i2c_new_device(data->hpdev.adapter, + data->hpdev.brdinfo); + if (!data->hpdev.client) { ++ dev_err(priv->dev, "Failed to create client %s at bus %d at addr 0x%02x\n", ++ data->hpdev.brdinfo->type, data->hpdev.nr + ++ pdata->shift_nr, data->hpdev.brdinfo->addr); ++ + i2c_put_adapter(data->hpdev.adapter); + data->hpdev.adapter = NULL; + return -EFAULT; +@@ -171,8 +140,13 @@ static int mlxreg_hotplug_device_create(struct mlxreg_core_data *data) + return 0; + } + +-static void mlxreg_hotplug_device_destroy(struct mlxreg_core_data *data) ++static void ++mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_priv_data *priv, ++ struct mlxreg_core_data *data) + { ++ /* Notify user by sending hwmon uevent. */ ++ kobject_uevent(priv->kobj, KOBJ_CHANGE); ++ + if (data->hpdev.client) { + i2c_unregister_device(data->hpdev.client); + data->hpdev.client = NULL; +@@ -184,28 +158,6 @@ static void mlxreg_hotplug_device_destroy(struct mlxreg_core_data *data) + } + } + +-static int mlxreg_hotplug_dev_enable(struct mlxreg_core_data *data) +-{ +- int err; +- +- /* Enable and create device. */ +- if (data->np) +- err = mlxreg_hotplug_of_device_create(data); +- else +- err = mlxreg_hotplug_device_create(data); +- +- return err; +-} +- +-static void mlxreg_hotplug_dev_disable(struct mlxreg_core_data *data) +-{ +- /* Disable and unregister platform device. */ +- if (data->np) +- mlxreg_hotplug_of_device_destroy(data); +- else +- mlxreg_hotplug_device_destroy(data); +-} +- + static ssize_t mlxreg_hotplug_attr_show(struct device *dev, + struct device_attribute *attr, + char *buf) +@@ -281,7 +233,8 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv) + } + } + +- priv->group.attrs = devm_kzalloc(&priv->pdev->dev, num_attrs * ++ priv->group.attrs = devm_kcalloc(&priv->pdev->dev, ++ num_attrs, + sizeof(struct attribute *), + GFP_KERNEL); + if (!priv->group.attrs) +@@ -320,12 +273,12 @@ mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv, + ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_MASK_OFF, + 0); + if (ret) +- goto access_error; ++ goto out; + + /* Read status. */ + ret = regmap_read(priv->regmap, item->reg, ®val); + if (ret) +- goto access_error; ++ goto out; + + /* Set asserted bits and save last status. */ + regval &= item->mask; +@@ -336,14 +289,14 @@ mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv, + data = item->data + bit; + if (regval & BIT(bit)) { + if (item->inversed) +- mlxreg_hotplug_dev_disable(data); ++ mlxreg_hotplug_device_destroy(priv, data); + else +- mlxreg_hotplug_dev_enable(data); ++ mlxreg_hotplug_device_create(priv, data); + } else { + if (item->inversed) +- mlxreg_hotplug_dev_enable(data); ++ mlxreg_hotplug_device_create(priv, data); + else +- mlxreg_hotplug_dev_disable(data); ++ mlxreg_hotplug_device_destroy(priv, data); + } + } + +@@ -351,18 +304,15 @@ mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv, + ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_EVENT_OFF, + 0); + if (ret) +- goto access_error; ++ goto out; + + /* Unmask event. */ + ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_MASK_OFF, + item->mask); +- if (ret) +- goto access_error; + +- return; +- +-access_error: +- dev_err(priv->dev, "Failed to complete workqueue.\n"); ++ out: ++ if (ret) ++ dev_err(priv->dev, "Failed to complete workqueue.\n"); + } + + static void +@@ -371,53 +321,83 @@ mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv, + { + struct mlxreg_core_data *data = item->data; + u32 regval; +- int i, ret; ++ int i, ret = 0; + + for (i = 0; i < item->count; i++, data++) { + /* Mask event. */ + ret = regmap_write(priv->regmap, data->reg + + MLXREG_HOTPLUG_MASK_OFF, 0); + if (ret) +- goto access_error; ++ goto out; + + /* Read status. */ + ret = regmap_read(priv->regmap, data->reg, ®val); + if (ret) +- goto access_error; ++ goto out; + + regval &= data->mask; +- item->cache = regval; ++ /* ++ * ASIC health indication is provided through two bits. Bits ++ * value 0x2 indicates that ASIC reached the good health, value ++ * 0x0 indicates ASIC the bad health or dormant state and value ++ * 0x2 indicates the booting state. During ASIC reset it should ++ * pass the following states: dormant -> booting -> good. ++ * The transition from dormant to booting state and from ++ * booting to good state are indicated by ASIC twice, so actual ++ * sequence for getting to the steady state after reset is: ++ * dormant -> booting -> booting -> good -> good. It is ++ * possible that due to some hardware noise, the transition ++ * sequence will look like: dormant -> booting -> [ booting -> ++ * good -> dormant -> booting ] -> good -> good. ++ */ + if (regval == MLXREG_HOTPLUG_HEALTH_MASK) { +- if ((data->health_cntr++ == MLXREG_HOTPLUG_RST_CNTR) || ++ if ((++data->health_cntr == MLXREG_HOTPLUG_RST_CNTR) || + !priv->after_probe) { +- mlxreg_hotplug_dev_enable(data); ++ /* ++ * ASIC is in steady state. Connect associated ++ * device, if configured. ++ */ ++ mlxreg_hotplug_device_create(priv, data); + data->attached = true; + } + } else { + if (data->attached) { +- mlxreg_hotplug_dev_disable(data); ++ /* ++ * ASIC health is dropped after ASIC has been ++ * in steady state. Disconnect associated ++ * device, if it has been connected. ++ */ ++ mlxreg_hotplug_device_destroy(priv, data); + data->attached = false; + data->health_cntr = 0; ++ } else if (regval == MLXREG_HOTPLUG_DOWN_MASK && ++ item->cache == MLXREG_HOTPLUG_HEALTH_MASK) { ++ /* ++ * Decrease counter, if health has been dropped ++ * before ASIC reaches the steady state, like: ++ * good -> dormant -> booting. ++ */ ++ data->health_cntr--; + } + } ++ item->cache = regval; + + /* Acknowledge event. */ + ret = regmap_write(priv->regmap, data->reg + + MLXREG_HOTPLUG_EVENT_OFF, 0); + if (ret) +- goto access_error; ++ goto out; + + /* Unmask event. */ + ret = regmap_write(priv->regmap, data->reg + + MLXREG_HOTPLUG_MASK_OFF, data->mask); + if (ret) +- goto access_error; ++ goto out; + } + +- return; +- +-access_error: +- dev_err(priv->dev, "Failed to complete workqueue.\n"); ++ out: ++ if (ret) ++ dev_err(priv->dev, "Failed to complete workqueue.\n"); + } + + /* +@@ -449,32 +429,38 @@ mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv, + */ + static void mlxreg_hotplug_work_handler(struct work_struct *work) + { +- struct mlxreg_hotplug_priv_data *priv = container_of(work, +- struct mlxreg_hotplug_priv_data, dwork_irq.work); + struct mlxreg_core_hotplug_platform_data *pdata; ++ struct mlxreg_hotplug_priv_data *priv; + struct mlxreg_core_item *item; +- unsigned long flags; + u32 regval, aggr_asserted; +- int i; +- int ret; ++ unsigned long flags; ++ int i, ret; + ++ priv = container_of(work, struct mlxreg_hotplug_priv_data, ++ dwork_irq.work); + pdata = dev_get_platdata(&priv->pdev->dev); + item = pdata->items; ++ + /* Mask aggregation event. */ + ret = regmap_write(priv->regmap, pdata->cell + + MLXREG_HOTPLUG_AGGR_MASK_OFF, 0); + if (ret < 0) +- goto access_error; ++ goto out; + + /* Read aggregation status. */ + ret = regmap_read(priv->regmap, pdata->cell, ®val); + if (ret) +- goto access_error; ++ goto out; + + regval &= pdata->mask; + aggr_asserted = priv->aggr_cache ^ regval; + priv->aggr_cache = regval; + ++ /* ++ * Handler is invoked, but no assertion is detected at top aggregation ++ * status level. Set aggr_asserted to mask value to allow handler extra ++ * run over all relevant signals to recover any missed signal. ++ */ + if (priv->not_asserted == MLXREG_HOTPLUG_NOT_ASSERT) { + priv->not_asserted = 0; + aggr_asserted = pdata->mask; +@@ -492,47 +478,40 @@ static void mlxreg_hotplug_work_handler(struct work_struct *work) + } + } + +- if (aggr_asserted) { +- spin_lock_irqsave(&priv->lock, flags); ++ spin_lock_irqsave(&priv->lock, flags); + +- /* +- * It is possible, that some signals have been inserted, while +- * interrupt has been masked by mlxreg_hotplug_work_handler. +- * In this case such signals will be missed. In order to handle +- * these signals delayed work is canceled and work task +- * re-scheduled for immediate execution. It allows to handle +- * missed signals, if any. In other case work handler just +- * validates that no new signals have been received during +- * masking. +- */ +- cancel_delayed_work(&priv->dwork_irq); +- schedule_delayed_work(&priv->dwork_irq, 0); ++ /* ++ * It is possible, that some signals have been inserted, while ++ * interrupt has been masked by mlxreg_hotplug_work_handler. In this ++ * case such signals will be missed. In order to handle these signals ++ * delayed work is canceled and work task re-scheduled for immediate ++ * execution. It allows to handle missed signals, if any. In other case ++ * work handler just validates that no new signals have been received ++ * during masking. ++ */ ++ cancel_delayed_work(&priv->dwork_irq); ++ schedule_delayed_work(&priv->dwork_irq, 0); + +- spin_unlock_irqrestore(&priv->lock, flags); ++ spin_unlock_irqrestore(&priv->lock, flags); + +- return; +- } ++ return; + + unmask_event: + priv->not_asserted++; + /* Unmask aggregation event (no need acknowledge). */ + ret = regmap_write(priv->regmap, pdata->cell + + MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask); +- if (ret) +- goto access_error; + +- return; +- +-access_error: +- dev_err(priv->dev, "Failed to complete workqueue.\n"); ++ out: ++ if (ret) ++ dev_err(priv->dev, "Failed to complete workqueue.\n"); + } + + static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv) + { + struct mlxreg_core_hotplug_platform_data *pdata; + struct mlxreg_core_item *item; +- int i; +- int ret; ++ int i, ret; + + pdata = dev_get_platdata(&priv->pdev->dev); + item = pdata->items; +@@ -542,7 +521,7 @@ static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv) + ret = regmap_write(priv->regmap, item->reg + + MLXREG_HOTPLUG_EVENT_OFF, 0); + if (ret) +- goto access_error; ++ goto out; + + /* Set group initial status as mask and unmask group event. */ + if (item->inversed) { +@@ -551,7 +530,7 @@ static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv) + MLXREG_HOTPLUG_MASK_OFF, + item->mask); + if (ret) +- goto access_error; ++ goto out; + } + } + +@@ -559,7 +538,7 @@ static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv) + ret = regmap_write(priv->regmap, pdata->cell + + MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask); + if (ret) +- goto access_error; ++ goto out; + + /* Keep low aggregation initial status as zero and unmask events. */ + if (pdata->cell_low) { +@@ -567,21 +546,16 @@ static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv) + MLXREG_HOTPLUG_AGGR_MASK_OFF, + pdata->mask_low); + if (ret) +- goto access_error; ++ goto out; + } + + /* Invoke work handler for initializing hot plug devices setting. */ + mlxreg_hotplug_work_handler(&priv->dwork_irq.work); + ++ out: ++ if (ret) ++ dev_err(priv->dev, "Failed to set interrupts.\n"); + enable_irq(priv->irq); +- +- return 0; +- +-access_error: +- dev_err(priv->dev, "Failed to set interrupts.\n"); +- +- enable_irq(priv->irq); +- + return ret; + } + +@@ -619,14 +593,15 @@ static void mlxreg_hotplug_unset_irq(struct mlxreg_hotplug_priv_data *priv) + /* Remove all the attached devices in group. */ + count = item->count; + for (j = 0; j < count; j++, data++) +- mlxreg_hotplug_dev_disable(data); ++ mlxreg_hotplug_device_destroy(priv, data); + } + } + + static irqreturn_t mlxreg_hotplug_irq_handler(int irq, void *dev) + { +- struct mlxreg_hotplug_priv_data *priv = +- (struct mlxreg_hotplug_priv_data *)dev; ++ struct mlxreg_hotplug_priv_data *priv; ++ ++ priv = (struct mlxreg_hotplug_priv_data *)dev; + + /* Schedule work task for immediate execution.*/ + schedule_delayed_work(&priv->dwork_irq, 0); +@@ -683,10 +658,6 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev) + disable_irq(priv->irq); + spin_lock_init(&priv->lock); + INIT_DELAYED_WORK(&priv->dwork_irq, mlxreg_hotplug_work_handler); +- /* Perform initial interrupts setup. */ +- mlxreg_hotplug_set_irq(priv); +- +- priv->after_probe = true; + dev_set_drvdata(&pdev->dev, priv); + + err = mlxreg_hotplug_attr_init(priv); +@@ -703,6 +674,11 @@ static int mlxreg_hotplug_probe(struct platform_device *pdev) + PTR_ERR(priv->hwmon)); + return PTR_ERR(priv->hwmon); + } ++ priv->kobj = &priv->hwmon->kobj; ++ ++ /* Perform initial interrupts setup. */ ++ mlxreg_hotplug_set_irq(priv); ++ priv->after_probe = true; + + return 0; + } +diff --git a/drivers/platform/mellanox/mlxreg-io.c b/drivers/platform/mellanox/mlxreg-io.c +index f7434ca..c192dfe 100644 +--- a/drivers/platform/mellanox/mlxreg-io.c ++++ b/drivers/platform/mellanox/mlxreg-io.c +@@ -1,3 +1,11 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Mellanox register access driver ++ * ++ * Copyright (C) 2018 Mellanox Technologies ++ * Copyright (C) 2018 Vadim Pasternak ++ */ ++ + #include + #include + #include +@@ -33,6 +41,54 @@ struct mlxreg_io_priv_data { + const struct attribute_group *groups[2]; + }; + ++static int ++mlxreg_io_get_reg(void *regmap, struct mlxreg_core_data *data, u32 in_val, ++ bool rw_flag, u32 *regval) ++{ ++ int ret; ++ ++ ret = regmap_read(regmap, data->reg, regval); ++ if (ret) ++ goto access_error; ++ ++ /* ++ * There are three kinds of attributes: single bit, full register's ++ * bits and bit sequence. For the first kind field mask indicates which ++ * bits are not related and field bit is set zero. For the second kind ++ * field mask is set to zero and field bit is set with all bits one. ++ * No special handling for such kind of attributes - pass value as is. ++ * For the third kind, field mask indicates which bits are related and ++ * field bit is set to the first bit number (from 1 to 32) is the bit ++ * sequence. ++ */ ++ if (!data->bit) { ++ /* Single bit. */ ++ if (rw_flag) { ++ /* For show: expose effective bit value as 0 or 1. */ ++ *regval = !!(*regval & ~data->mask); ++ } else { ++ /* For store: set effective bit value. */ ++ *regval &= data->mask; ++ if (in_val) ++ *regval |= ~data->mask; ++ } ++ } else if (data->mask) { ++ /* Bit sequence. */ ++ if (rw_flag) { ++ /* For show: mask and shift right. */ ++ *regval = ror32(*regval & data->mask, (data->bit - 1)); ++ } else { ++ /* For store: shift to the position and mask. */ ++ in_val = rol32(in_val, data->bit - 1) & data->mask; ++ /* Clear relevant bits and set them to new value. */ ++ *regval = (*regval & ~data->mask) | in_val; ++ } ++ } ++ ++access_error: ++ return ret; ++} ++ + static ssize_t + mlxreg_io_attr_show(struct device *dev, struct device_attribute *attr, + char *buf) +@@ -43,13 +99,10 @@ mlxreg_io_attr_show(struct device *dev, struct device_attribute *attr, + u32 regval = 0; + int ret; + +- ret = regmap_read(priv->pdata->regmap, data->reg, ®val); ++ ret = mlxreg_io_get_reg(priv->pdata->regmap, data, 0, true, ®val); + if (ret) + goto access_error; + +- if (!data->bit) +- regval = !!(regval & ~data->mask); +- + return sprintf(buf, "%u\n", regval); + + access_error: +@@ -63,25 +116,22 @@ mlxreg_io_attr_store(struct device *dev, struct device_attribute *attr, + struct mlxreg_io_priv_data *priv = dev_get_drvdata(dev); + int index = to_sensor_dev_attr(attr)->index; + struct mlxreg_core_data *data = priv->pdata->data + index; +- u32 val, regval; ++ u32 input_val, regval; + int ret; + +- ret = kstrtou32(buf, MLXREG_IO_ATT_SIZE, &val); ++ if (len > MLXREG_IO_ATT_SIZE) ++ return -EINVAL; ++ ++ /* Convert buffer to input value. */ ++ ret = kstrtou32(buf, len, &input_val); + if (ret) + return ret; + +- ret = regmap_read(priv->pdata->regmap, data->reg, ®val); ++ ret = mlxreg_io_get_reg(priv->pdata->regmap, data, input_val, false, ++ ®val); + if (ret) + goto access_error; + +- regval &= data->mask; +- +- val = !!val; +- if (val) +- regval |= ~data->mask; +- else +- regval &= data->mask; +- + ret = regmap_write(priv->pdata->regmap, data->reg, regval); + if (ret) + goto access_error; +@@ -93,6 +143,11 @@ mlxreg_io_attr_store(struct device *dev, struct device_attribute *attr, + return ret; + } + ++static struct device_attribute mlxreg_io_devattr_rw = { ++ .show = mlxreg_io_attr_show, ++ .store = mlxreg_io_attr_store, ++}; ++ + static int mlxreg_io_attr_init(struct mlxreg_io_priv_data *priv) + { + int i; +@@ -107,6 +162,8 @@ static int mlxreg_io_attr_init(struct mlxreg_io_priv_data *priv) + for (i = 0; i < priv->pdata->counter; i++) { + priv->mlxreg_io_attr[i] = + &priv->mlxreg_io_dev_attr[i].dev_attr.attr; ++ memcpy(&priv->mlxreg_io_dev_attr[i].dev_attr, ++ &mlxreg_io_devattr_rw, sizeof(struct device_attribute)); + + /* Set attribute name as a label. */ + priv->mlxreg_io_attr[i]->name = +@@ -121,31 +178,6 @@ static int mlxreg_io_attr_init(struct mlxreg_io_priv_data *priv) + + priv->mlxreg_io_dev_attr[i].dev_attr.attr.mode = + priv->pdata->data[i].mode; +- switch (priv->pdata->data[i].mode) { +- case 0200: +- priv->mlxreg_io_dev_attr[i].dev_attr.store = +- mlxreg_io_attr_store; +- break; +- +- case 0444: +- priv->mlxreg_io_dev_attr[i].dev_attr.show = +- mlxreg_io_attr_show; +- break; +- +- case 0644: +- priv->mlxreg_io_dev_attr[i].dev_attr.show = +- mlxreg_io_attr_show; +- priv->mlxreg_io_dev_attr[i].dev_attr.store = +- mlxreg_io_attr_store; +- break; +- +- default: +- dev_err(&priv->pdev->dev, "Bad access mode %u for attribute %s.\n", +- priv->pdata->data[i].mode, +- priv->mlxreg_io_attr[i]->name); +- return -EINVAL; +- } +- + priv->mlxreg_io_dev_attr[i].dev_attr.attr.name = + priv->mlxreg_io_attr[i]->name; + priv->mlxreg_io_dev_attr[i].index = i; +@@ -184,7 +216,9 @@ static int mlxreg_io_probe(struct platform_device *pdev) + } + + priv->hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, +- "mlxreg_io", priv, priv->groups); ++ "mlxreg_io", ++ priv, ++ priv->groups); + if (IS_ERR(priv->hwmon)) { + dev_err(&pdev->dev, "Failed to register hwmon device %ld\n", + PTR_ERR(priv->hwmon)); +@@ -207,5 +241,5 @@ module_platform_driver(mlxreg_io_driver); + + MODULE_AUTHOR("Vadim Pasternak "); + MODULE_DESCRIPTION("Mellanox regmap I/O access driver"); +-MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_LICENSE("GPL"); + MODULE_ALIAS("platform:mlxreg-io"); +diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c +index e03f03f..e1f9fce 100644 +--- a/drivers/platform/x86/mlx-platform.c ++++ b/drivers/platform/x86/mlx-platform.c +@@ -47,34 +47,52 @@ + /* LPC bus IO offsets */ + #define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000 + #define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500 +-#define MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFF 0x00 +-#define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFF 0x01 +-#define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF 0x1d +-#define MLXPLAT_CPLD_LPC_REG_LED1_OFF 0x20 +-#define MLXPLAT_CPLD_LPC_REG_LED2_OFF 0x21 +-#define MLXPLAT_CPLD_LPC_REG_LED3_OFF 0x22 +-#define MLXPLAT_CPLD_LPC_REG_LED4_OFF 0x23 +-#define MLXPLAT_CPLD_LPC_REG_LED5_OFF 0x24 +-#define MLXPLAT_CPLD_LPC_REG_GP1_OFF 0x30 +-#define MLXPLAT_CPLD_LPC_REG_WP1_OFF 0x31 +-#define MLXPLAT_CPLD_LPC_REG_GP2_OFF 0x32 +-#define MLXPLAT_CPLD_LPC_REG_WP2_OFF 0x33 +-#define MLXPLAT_CPLD_LPC_REG_AGGR_OFF 0x3a +-#define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFF 0x3b +-#define MLXPLAT_CPLD_LPC_REG_AGGR_LOW_OFF 0x40 +-#define MLXPLAT_CPLD_LPC_REG_AGGR_LOW_MASK_OFF 0x41 +-#define MLXPLAT_CPLD_LPC_REG_PSU_OFF 0x58 +-#define MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFF 0x59 +-#define MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFF 0x5a +-#define MLXPLAT_CPLD_LPC_REG_PWR_OFF 0x64 +-#define MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFF 0x65 +-#define MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFF 0x66 +-#define MLXPLAT_CPLD_LPC_REG_FAN_OFF 0x88 +-#define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFF 0x89 +-#define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFF 0x8a ++#define MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET 0x00 ++#define MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET 0x01 ++#define MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET 0x1d ++#define MLXPLAT_CPLD_LPC_REG_LED1_OFFSET 0x20 ++#define MLXPLAT_CPLD_LPC_REG_LED2_OFFSET 0x21 ++#define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET 0x22 ++#define MLXPLAT_CPLD_LPC_REG_LED4_OFFSET 0x23 ++#define MLXPLAT_CPLD_LPC_REG_LED5_OFFSET 0x24 ++#define MLXPLAT_CPLD_LPC_REG_GP1_OFFSET 0x30 ++#define MLXPLAT_CPLD_LPC_REG_WP1_OFFSET 0x31 ++#define MLXPLAT_CPLD_LPC_REG_GP2_OFFSET 0x32 ++#define MLXPLAT_CPLD_LPC_REG_WP2_OFFSET 0x33 ++#define MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET 0x37 ++#define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a ++#define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET 0x3b ++#define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40 ++#define MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET 0x41 ++#define MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET 0x50 ++#define MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET 0x51 ++#define MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET 0x52 ++#define MLXPLAT_CPLD_LPC_REG_PSU_OFFSET 0x58 ++#define MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET 0x59 ++#define MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET 0x5a ++#define MLXPLAT_CPLD_LPC_REG_PWR_OFFSET 0x64 ++#define MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET 0x65 ++#define MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET 0x66 ++#define MLXPLAT_CPLD_LPC_REG_FAN_OFFSET 0x88 ++#define MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET 0x89 ++#define MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET 0x8a ++#define MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET 0xe3 ++#define MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET 0xe4 ++#define MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET 0xe5 ++#define MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET 0xe6 ++#define MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET 0xe7 ++#define MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET 0xe8 ++#define MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET 0xe9 ++#define MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET 0xea ++#define MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET 0xeb ++#define MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET 0xec ++#define MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET 0xed ++#define MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET 0xee ++#define MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET 0xef + #define MLXPLAT_CPLD_LPC_IO_RANGE 0x100 + #define MLXPLAT_CPLD_LPC_I2C_CH1_OFF 0xdb + #define MLXPLAT_CPLD_LPC_I2C_CH2_OFF 0xda ++ + #define MLXPLAT_CPLD_LPC_PIO_OFFSET 0x10000UL + #define MLXPLAT_CPLD_LPC_REG1 ((MLXPLAT_CPLD_LPC_REG_BASE_ADRR + \ + MLXPLAT_CPLD_LPC_I2C_CH1_OFF) | \ +@@ -84,17 +102,20 @@ + MLXPLAT_CPLD_LPC_PIO_OFFSET) + + /* Masks for aggregation, psu, pwr and fan event in CPLD related registers. */ ++#define MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF 0x04 + #define MLXPLAT_CPLD_AGGR_PSU_MASK_DEF 0x08 + #define MLXPLAT_CPLD_AGGR_PWR_MASK_DEF 0x08 + #define MLXPLAT_CPLD_AGGR_FAN_MASK_DEF 0x40 +-#define MLXPLAT_CPLD_AGGR_MASK_DEF (MLXPLAT_CPLD_AGGR_PSU_MASK_DEF | \ ++#define MLXPLAT_CPLD_AGGR_MASK_DEF (MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF | \ ++ MLXPLAT_CPLD_AGGR_PSU_MASK_DEF | \ + MLXPLAT_CPLD_AGGR_FAN_MASK_DEF) ++#define MLXPLAT_CPLD_AGGR_ASIC_MASK_NG 0x01 + #define MLXPLAT_CPLD_AGGR_MASK_NG_DEF 0x04 +-#define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc0 +-#define MLXPLAT_CPLD_AGGR_MASK_MSN21XX 0x04 ++#define MLXPLAT_CPLD_LOW_AGGR_MASK_LOW 0xc1 + #define MLXPLAT_CPLD_PSU_MASK GENMASK(1, 0) + #define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0) + #define MLXPLAT_CPLD_FAN_MASK GENMASK(3, 0) ++#define MLXPLAT_CPLD_ASIC_MASK GENMASK(1, 0) + #define MLXPLAT_CPLD_FAN_NG_MASK GENMASK(5, 0) + #define MLXPLAT_CPLD_LED_LO_NIBBLE_MASK GENMASK(7, 4) + #define MLXPLAT_CPLD_LED_HI_NIBBLE_MASK GENMASK(3, 0) +@@ -119,6 +140,10 @@ + #define MLXPLAT_CPLD_NR_NONE -1 + #define MLXPLAT_CPLD_PSU_DEFAULT_NR 10 + #define MLXPLAT_CPLD_PSU_MSNXXXX_NR 4 ++#define MLXPLAT_CPLD_FAN1_DEFAULT_NR 11 ++#define MLXPLAT_CPLD_FAN2_DEFAULT_NR 12 ++#define MLXPLAT_CPLD_FAN3_DEFAULT_NR 13 ++#define MLXPLAT_CPLD_FAN4_DEFAULT_NR 14 + + /* mlxplat_priv - platform private data + * @pdev_i2c - i2c controller platform device +@@ -126,6 +151,7 @@ + * @pdev_hotplug - hotplug platform devices + * @pdev_led - led platform devices + * @pdev_io_regs - register access platform devices ++ * @pdev_fan - FAN platform devices + */ + struct mlxplat_priv { + struct platform_device *pdev_i2c; +@@ -133,6 +159,7 @@ struct mlxplat_priv { + struct platform_device *pdev_hotplug; + struct platform_device *pdev_led; + struct platform_device *pdev_io_regs; ++ struct platform_device *pdev_fan; + }; + + /* Regions for LPC I2C controller and LPC base register space */ +@@ -194,6 +221,15 @@ static struct i2c_board_info mlxplat_mlxcpld_psu[] = { + }, + }; + ++static struct i2c_board_info mlxplat_mlxcpld_ng_psu[] = { ++ { ++ I2C_BOARD_INFO("24c32", 0x51), ++ }, ++ { ++ I2C_BOARD_INFO("24c32", 0x50), ++ }, ++}; ++ + static struct i2c_board_info mlxplat_mlxcpld_pwr[] = { + { + I2C_BOARD_INFO("dps460", 0x59), +@@ -222,14 +258,14 @@ static struct i2c_board_info mlxplat_mlxcpld_fan[] = { + static struct mlxreg_core_data mlxplat_mlxcpld_default_psu_items_data[] = { + { + .label = "psu1", +- .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, + .mask = BIT(0), + .hpdev.brdinfo = &mlxplat_mlxcpld_psu[0], + .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR, + }, + { + .label = "psu2", +- .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, + .mask = BIT(1), + .hpdev.brdinfo = &mlxplat_mlxcpld_psu[1], + .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR, +@@ -239,14 +275,14 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_psu_items_data[] = { + static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_items_data[] = { + { + .label = "pwr1", +- .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, + .mask = BIT(0), + .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0], + .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR, + }, + { + .label = "pwr2", +- .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, + .mask = BIT(1), + .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1], + .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR, +@@ -256,31 +292,40 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_pwr_items_data[] = { + static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_items_data[] = { + { + .label = "fan1", +- .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, + .mask = BIT(0), + .hpdev.brdinfo = &mlxplat_mlxcpld_fan[0], +- .hpdev.nr = 11, ++ .hpdev.nr = MLXPLAT_CPLD_FAN1_DEFAULT_NR, + }, + { + .label = "fan2", +- .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, + .mask = BIT(1), + .hpdev.brdinfo = &mlxplat_mlxcpld_fan[1], +- .hpdev.nr = 12, ++ .hpdev.nr = MLXPLAT_CPLD_FAN2_DEFAULT_NR, + }, + { + .label = "fan3", +- .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, + .mask = BIT(2), + .hpdev.brdinfo = &mlxplat_mlxcpld_fan[2], +- .hpdev.nr = 13, ++ .hpdev.nr = MLXPLAT_CPLD_FAN3_DEFAULT_NR, + }, + { + .label = "fan4", +- .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, + .mask = BIT(3), + .hpdev.brdinfo = &mlxplat_mlxcpld_fan[3], +- .hpdev.nr = 14, ++ .hpdev.nr = MLXPLAT_CPLD_FAN4_DEFAULT_NR, ++ }, ++}; ++ ++static struct mlxreg_core_data mlxplat_mlxcpld_default_asic_items_data[] = { ++ { ++ .label = "asic1", ++ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, ++ .mask = MLXPLAT_CPLD_ASIC_MASK, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, + }, + }; + +@@ -288,7 +333,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = { + { + .data = mlxplat_mlxcpld_default_psu_items_data, + .aggr_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF, +- .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, + .mask = MLXPLAT_CPLD_PSU_MASK, + .count = ARRAY_SIZE(mlxplat_mlxcpld_psu), + .inversed = 1, +@@ -297,7 +342,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = { + { + .data = mlxplat_mlxcpld_default_pwr_items_data, + .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF, +- .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, + .mask = MLXPLAT_CPLD_PWR_MASK, + .count = ARRAY_SIZE(mlxplat_mlxcpld_pwr), + .inversed = 0, +@@ -306,127 +351,92 @@ static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = { + { + .data = mlxplat_mlxcpld_default_fan_items_data, + .aggr_mask = MLXPLAT_CPLD_AGGR_FAN_MASK_DEF, +- .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, + .mask = MLXPLAT_CPLD_FAN_MASK, + .count = ARRAY_SIZE(mlxplat_mlxcpld_fan), + .inversed = 1, + .health = false, + }, ++ { ++ .data = mlxplat_mlxcpld_default_asic_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, ++ .mask = MLXPLAT_CPLD_ASIC_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), ++ .inversed = 0, ++ .health = true, ++ }, + }; + + static + struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_data = { + .items = mlxplat_mlxcpld_default_items, + .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_items), +- .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFF, ++ .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, + .mask = MLXPLAT_CPLD_AGGR_MASK_DEF, +-}; +- +-/* Platform hotplug MSN21xx system family data */ +-static struct i2c_board_info mlxplat_mlxcpld_msn21xx_pwr[] = { +- { +- I2C_BOARD_INFO("holder", 0x59), +- }, +- { +- I2C_BOARD_INFO("holder", 0x58), +- }, ++ .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, ++ .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, + }; + + static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_pwr_items_data[] = { + { + .label = "pwr1", +- .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, + .mask = BIT(0), +- .hpdev.brdinfo = &mlxplat_mlxcpld_msn21xx_pwr[0], +- .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, + }, + { + .label = "pwr2", +- .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, + .mask = BIT(1), +- .hpdev.brdinfo = &mlxplat_mlxcpld_msn21xx_pwr[1], +- .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, + }, + }; + ++/* Platform hotplug MSN21xx system family data */ + static struct mlxreg_core_item mlxplat_mlxcpld_msn21xx_items[] = { + { + .data = mlxplat_mlxcpld_msn21xx_pwr_items_data, + .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF, +- .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, + .mask = MLXPLAT_CPLD_PWR_MASK, + .count = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_pwr_items_data), + .inversed = 0, + .health = false, + }, +-}; +- +-static +-struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = { +- .items = mlxplat_mlxcpld_msn21xx_items, +- .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_items), +- .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFF, +- .mask = MLXPLAT_CPLD_AGGR_MASK_DEF, +- .cell_low = MLXPLAT_CPLD_LPC_REG_AGGR_LOW_OFF, +- .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, +-}; +- +-/* Platform hotplug MSN201x system family data */ +-static struct mlxreg_core_data mlxplat_mlxcpld_msn201x_pwr_items_data[] = { +- { +- .label = "pwr1", +- .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFF, +- .mask = BIT(0), +- .hpdev.brdinfo = &mlxplat_mlxcpld_msn21xx_pwr[0], +- .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, +- }, +- { +- .label = "pwr2", +- .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFF, +- .mask = BIT(1), +- .hpdev.brdinfo = &mlxplat_mlxcpld_msn21xx_pwr[1], +- .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, +- }, +-}; +- +-static struct mlxreg_core_item mlxplat_mlxcpld_msn201x_items[] = { + { +- .data = mlxplat_mlxcpld_msn201x_pwr_items_data, +- .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF, +- .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFF, +- .mask = MLXPLAT_CPLD_PWR_MASK, +- .count = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_pwr_items_data), ++ .data = mlxplat_mlxcpld_default_asic_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, ++ .mask = MLXPLAT_CPLD_ASIC_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), + .inversed = 0, +- .health = false, ++ .health = true, + }, + }; + + static +-struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn201x_data = { ++struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn21xx_data = { + .items = mlxplat_mlxcpld_msn21xx_items, +- .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_items), +- .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFF, ++ .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_items), ++ .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, + .mask = MLXPLAT_CPLD_AGGR_MASK_DEF, +- .cell_low = MLXPLAT_CPLD_LPC_REG_AGGR_LOW_OFF, ++ .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, + .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, + }; + +-/* Platform hotplug next generation system family data */ +-static struct i2c_board_info mlxplat_mlxcpld_ng_fan = { +- I2C_BOARD_INFO("holder", 0x50), +-}; +- +-static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_psu_items_data[] = { ++/* Platform hotplug msn274x system family data */ ++static struct mlxreg_core_data mlxplat_mlxcpld_msn274x_psu_items_data[] = { + { + .label = "psu1", +- .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, + .mask = BIT(0), + .hpdev.brdinfo = &mlxplat_mlxcpld_psu[0], + .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, + }, + { + .label = "psu2", +- .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, + .mask = BIT(1), + .hpdev.brdinfo = &mlxplat_mlxcpld_psu[1], + .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, +@@ -436,173 +446,246 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_psu_items_data[] = { + static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_pwr_items_data[] = { + { + .label = "pwr1", +- .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, + .mask = BIT(0), + .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[0], + .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, + }, + { + .label = "pwr2", +- .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, + .mask = BIT(1), + .hpdev.brdinfo = &mlxplat_mlxcpld_pwr[1], + .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, + }, + }; + +-static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_fan_items_data[] = { ++static struct mlxreg_core_data mlxplat_mlxcpld_msn274x_fan_items_data[] = { + { + .label = "fan1", +- .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, + .mask = BIT(0), +- .hpdev.brdinfo = &mlxplat_mlxcpld_ng_fan, +- .hpdev.nr = 11, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, + }, + { + .label = "fan2", +- .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, + .mask = BIT(1), +- .hpdev.brdinfo = &mlxplat_mlxcpld_ng_fan, +- .hpdev.nr = 12, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, + }, + { + .label = "fan3", +- .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, + .mask = BIT(2), +- .hpdev.brdinfo = &mlxplat_mlxcpld_ng_fan, +- .hpdev.nr = 13, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, + }, + { + .label = "fan4", +- .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, + .mask = BIT(3), +- .hpdev.brdinfo = &mlxplat_mlxcpld_ng_fan, +- .hpdev.nr = 14, +- }, +- { +- .label = "fan5", +- .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF, +- .mask = BIT(4), +- .hpdev.brdinfo = &mlxplat_mlxcpld_ng_fan, +- .hpdev.nr = 15, +- }, +- { +- .label = "fan6", +- .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF, +- .mask = BIT(5), +- .hpdev.brdinfo = &mlxplat_mlxcpld_ng_fan, +- .hpdev.nr = 16, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, + }, + }; + +-static struct mlxreg_core_item mlxplat_mlxcpld_default_ng_items[] = { ++static struct mlxreg_core_item mlxplat_mlxcpld_msn274x_items[] = { + { +- .data = mlxplat_mlxcpld_default_ng_psu_items_data, ++ .data = mlxplat_mlxcpld_msn274x_psu_items_data, + .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, +- .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, + .mask = MLXPLAT_CPLD_PSU_MASK, +- .count = ARRAY_SIZE(mlxplat_mlxcpld_psu), ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_psu_items_data), + .inversed = 1, + .health = false, + }, + { + .data = mlxplat_mlxcpld_default_ng_pwr_items_data, + .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, +- .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, + .mask = MLXPLAT_CPLD_PWR_MASK, +- .count = ARRAY_SIZE(mlxplat_mlxcpld_pwr), ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_pwr_items_data), + .inversed = 0, + .health = false, + }, + { +- .data = mlxplat_mlxcpld_default_ng_fan_items_data, ++ .data = mlxplat_mlxcpld_msn274x_fan_items_data, + .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, +- .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, + .mask = MLXPLAT_CPLD_FAN_MASK, +- .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data), ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_fan_items_data), + .inversed = 1, + .health = false, + }, ++ { ++ .data = mlxplat_mlxcpld_default_asic_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, ++ .mask = MLXPLAT_CPLD_ASIC_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), ++ .inversed = 0, ++ .health = true, ++ }, + }; + + static +-struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_ng_data = { +- .items = mlxplat_mlxcpld_default_ng_items, +- .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_items), +- .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFF, ++struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn274x_data = { ++ .items = mlxplat_mlxcpld_msn274x_items, ++ .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_items), ++ .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, + .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, +- .cell_low = MLXPLAT_CPLD_LPC_REG_AGGR_LOW_OFF, ++ .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, + .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, + }; + +-static struct mlxreg_core_data mlxplat_mlxcpld_msn274x_fan_items_data[] = { ++/* Platform hotplug MSN201x system family data */ ++static struct mlxreg_core_data mlxplat_mlxcpld_msn201x_pwr_items_data[] = { ++ { ++ .label = "pwr1", ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, ++ .mask = BIT(0), ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++ { ++ .label = "pwr2", ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, ++ .mask = BIT(1), ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++}; ++ ++static struct mlxreg_core_item mlxplat_mlxcpld_msn201x_items[] = { ++ { ++ .data = mlxplat_mlxcpld_msn201x_pwr_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, ++ .mask = MLXPLAT_CPLD_PWR_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_pwr_items_data), ++ .inversed = 0, ++ .health = false, ++ }, ++ { ++ .data = mlxplat_mlxcpld_default_asic_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_ASIC_MASK_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, ++ .mask = MLXPLAT_CPLD_ASIC_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), ++ .inversed = 0, ++ .health = true, ++ }, ++}; ++ ++static ++struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn201x_data = { ++ .items = mlxplat_mlxcpld_msn21xx_items, ++ .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn201x_items), ++ .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, ++ .mask = MLXPLAT_CPLD_AGGR_MASK_DEF, ++ .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, ++ .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, ++}; ++ ++/* Platform hotplug next generation system family data */ ++static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_psu_items_data[] = { ++ { ++ .label = "psu1", ++ .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, ++ .mask = BIT(0), ++ .hpdev.brdinfo = &mlxplat_mlxcpld_ng_psu[0], ++ .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, ++ }, ++ { ++ .label = "psu2", ++ .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, ++ .mask = BIT(1), ++ .hpdev.brdinfo = &mlxplat_mlxcpld_ng_psu[1], ++ .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, ++ }, ++}; ++ ++static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_fan_items_data[] = { + { + .label = "fan1", +- .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, + .mask = BIT(0), +- .hpdev.brdinfo = &mlxplat_mlxcpld_ng_fan, +- .hpdev.nr = 11, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, + }, + { + .label = "fan2", +- .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, + .mask = BIT(1), +- .hpdev.brdinfo = &mlxplat_mlxcpld_ng_fan, +- .hpdev.nr = 12, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, + }, + { + .label = "fan3", +- .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, + .mask = BIT(2), +- .hpdev.brdinfo = &mlxplat_mlxcpld_ng_fan, +- .hpdev.nr = 13, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, + }, + { + .label = "fan4", +- .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, + .mask = BIT(3), +- .hpdev.brdinfo = &mlxplat_mlxcpld_ng_fan, +- .hpdev.nr = 14, ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++ { ++ .label = "fan5", ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ .mask = BIT(4), ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, ++ }, ++ { ++ .label = "fan6", ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ .mask = BIT(5), ++ .hpdev.nr = MLXPLAT_CPLD_NR_NONE, + }, + }; + +-static struct mlxreg_core_item mlxplat_mlxcpld_msn274x_items[] = { ++static struct mlxreg_core_item mlxplat_mlxcpld_default_ng_items[] = { + { + .data = mlxplat_mlxcpld_default_ng_psu_items_data, + .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, +- .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, + .mask = MLXPLAT_CPLD_PSU_MASK, +- .count = ARRAY_SIZE(mlxplat_mlxcpld_psu), ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_psu_items_data), + .inversed = 1, + .health = false, + }, + { + .data = mlxplat_mlxcpld_default_ng_pwr_items_data, + .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, +- .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, + .mask = MLXPLAT_CPLD_PWR_MASK, +- .count = ARRAY_SIZE(mlxplat_mlxcpld_pwr), ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_pwr_items_data), + .inversed = 0, + .health = false, + }, + { +- .data = mlxplat_mlxcpld_msn274x_fan_items_data, ++ .data = mlxplat_mlxcpld_default_ng_fan_items_data, + .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, +- .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFF, +- .mask = MLXPLAT_CPLD_FAN_MASK, +- .count = ARRAY_SIZE(mlxplat_mlxcpld_msn274x_fan_items_data), ++ .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, ++ .mask = MLXPLAT_CPLD_FAN_NG_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_fan_items_data), + .inversed = 1, + .health = false, + }, ++ { ++ .data = mlxplat_mlxcpld_default_asic_items_data, ++ .aggr_mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, ++ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, ++ .mask = MLXPLAT_CPLD_ASIC_MASK, ++ .count = ARRAY_SIZE(mlxplat_mlxcpld_default_asic_items_data), ++ .inversed = 0, ++ .health = true, ++ }, + }; + + static +-struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn274x_data = { +- .items = mlxplat_mlxcpld_msn274x_items, ++struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_ng_data = { ++ .items = mlxplat_mlxcpld_default_ng_items, + .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_items), +- .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFF, ++ .cell = MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET, + .mask = MLXPLAT_CPLD_AGGR_MASK_NG_DEF, +- .cell_low = MLXPLAT_CPLD_LPC_REG_AGGR_LOW_OFF, ++ .cell_low = MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET, + .mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW, + }; + +@@ -610,62 +693,62 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_msn274x_data = { + static struct mlxreg_core_data mlxplat_mlxcpld_default_led_data[] = { + { + .label = "status:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + { + .label = "status:red", +- .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK + }, + { + .label = "psu:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, + .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, + }, + { + .label = "psu:red", +- .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, + .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, + }, + { + .label = "fan1:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + { + .label = "fan1:red", +- .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + { + .label = "fan2:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, + .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, + }, + { + .label = "fan2:red", +- .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, + .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, + }, + { + .label = "fan3:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + { + .label = "fan3:red", +- .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + { + .label = "fan4:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, + .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, + }, + { + .label = "fan4:red", +- .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, + .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, + }, + }; +@@ -679,47 +762,47 @@ static struct mlxreg_core_platform_data mlxplat_default_led_data = { + static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_led_data[] = { + { + .label = "status:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + { + .label = "status:red", +- .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK + }, + { + .label = "fan:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + { + .label = "fan:red", +- .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + { + .label = "psu1:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + { + .label = "psu1:red", +- .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + { + .label = "psu2:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, + .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, + }, + { + .label = "psu2:red", +- .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, + .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, + }, + { + .label = "uid:blue", +- .reg = MLXPLAT_CPLD_LPC_REG_LED5_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + }; +@@ -733,82 +816,82 @@ static struct mlxreg_core_platform_data mlxplat_msn21xx_led_data = { + static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_led_data[] = { + { + .label = "status:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + { + .label = "status:orange", +- .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK + }, + { + .label = "psu:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, + .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, + }, + { + .label = "psu:orange", +- .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET, + .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, + }, + { + .label = "fan1:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + { + .label = "fan1:orange", +- .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + { + .label = "fan2:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, + .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, + }, + { + .label = "fan2:orange", +- .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET, + .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, + }, + { + .label = "fan3:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + { + .label = "fan3:orange", +- .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + { + .label = "fan4:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, + .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, + }, + { + .label = "fan4:orange", +- .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET, + .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, + }, + { + .label = "fan5:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + { + .label = "fan5:orange", +- .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, + .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK, + }, + { + .label = "fan6:green", +- .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, + .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, + }, + { + .label = "fan6:orange", +- .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFF, ++ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET, + .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK, + }, + }; +@@ -818,26 +901,303 @@ static struct mlxreg_core_platform_data mlxplat_default_ng_led_data = { + .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_led_data), + }; + ++/* Platform register access default */ ++static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = { ++ { ++ .label = "cpld1_version", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld2_version", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_long_pb", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_short_pb", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_aux_pwr_or_ref", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_main_pwr_fail", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_sw_reset", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_fw_reset", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_hotswap_or_wd", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_asic_thermal", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(7), ++ .mode = 0444, ++ }, ++ { ++ .label = "psu1_on", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0200, ++ }, ++ { ++ .label = "psu2_on", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0200, ++ }, ++ { ++ .label = "pwr_cycle", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0200, ++ }, ++ { ++ .label = "pwr_down", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0200, ++ }, ++ { ++ .label = "select_iio", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP2_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0644, ++ }, ++ { ++ .label = "asic_health", ++ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, ++ .mask = MLXPLAT_CPLD_ASIC_MASK, ++ .bit = 1, ++ .mode = 0444, ++ }, ++}; ++ ++static struct mlxreg_core_platform_data mlxplat_default_regs_io_data = { ++ .data = mlxplat_mlxcpld_default_regs_io_data, ++ .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_regs_io_data), ++}; ++ ++/* Platform register access MSN21xx, MSN201x, MSN274x systems families data */ ++static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_regs_io_data[] = { ++ { ++ .label = "cpld1_version", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "cpld2_version", ++ .reg = MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET, ++ .bit = GENMASK(7, 0), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_long_pb", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_short_pb", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_aux_pwr_or_ref", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_sw_reset", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_main_pwr_fail", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(4), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_asic_thermal", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(5), ++ .mode = 0444, ++ }, ++ { ++ .label = "reset_hotswap_or_halt", ++ .reg = MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(6), ++ .mode = 0444, ++ }, ++ { ++ .label = "psu1_on", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(0), ++ .mode = 0200, ++ }, ++ { ++ .label = "psu2_on", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(1), ++ .mode = 0200, ++ }, ++ { ++ .label = "pwr_cycle", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(2), ++ .mode = 0200, ++ }, ++ { ++ .label = "pwr_down", ++ .reg = MLXPLAT_CPLD_LPC_REG_GP1_OFFSET, ++ .mask = GENMASK(7, 0) & ~BIT(3), ++ .mode = 0200, ++ }, ++ { ++ .label = "asic_health", ++ .reg = MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET, ++ .mask = MLXPLAT_CPLD_ASIC_MASK, ++ .bit = 1, ++ .mode = 0444, ++ }, ++}; ++ ++static struct mlxreg_core_platform_data mlxplat_msn21xx_regs_io_data = { ++ .data = mlxplat_mlxcpld_msn21xx_regs_io_data, ++ .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_regs_io_data), ++}; ++ ++/* Platform FAN default */ ++static struct mlxreg_core_data mlxplat_mlxcpld_default_fan_data[] = { ++ { ++ .label = "pwm1", ++ .reg = MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET, ++ }, ++ { ++ .label = "tacho1", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET, ++ .mask = GENMASK(7, 0), ++ }, ++ { ++ .label = "tacho2", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET, ++ .mask = GENMASK(7, 0), ++ }, ++ { ++ .label = "tacho3", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET, ++ .mask = GENMASK(7, 0), ++ }, ++ { ++ .label = "tacho4", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET, ++ .mask = GENMASK(7, 0), ++ }, ++ { ++ .label = "tacho5", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET, ++ .mask = GENMASK(7, 0), ++ }, ++ { ++ .label = "tacho6", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET, ++ .mask = GENMASK(7, 0), ++ }, ++ { ++ .label = "tacho7", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET, ++ .mask = GENMASK(7, 0), ++ }, ++ { ++ .label = "tacho8", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET, ++ .mask = GENMASK(7, 0), ++ }, ++ { ++ .label = "tacho9", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET, ++ .mask = GENMASK(7, 0), ++ }, ++ { ++ .label = "tacho10", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET, ++ .mask = GENMASK(7, 0), ++ }, ++ { ++ .label = "tacho11", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET, ++ .mask = GENMASK(7, 0), ++ }, ++ { ++ .label = "tacho12", ++ .reg = MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET, ++ .mask = GENMASK(7, 0), ++ }, ++}; ++ ++static struct mlxreg_core_platform_data mlxplat_default_fan_data = { ++ .data = mlxplat_mlxcpld_default_fan_data, ++ .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_data), ++}; ++ + static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) + { + switch (reg) { +- case MLXPLAT_CPLD_LPC_REG_LED1_OFF: +- case MLXPLAT_CPLD_LPC_REG_LED2_OFF: +- case MLXPLAT_CPLD_LPC_REG_LED3_OFF: +- case MLXPLAT_CPLD_LPC_REG_LED4_OFF: +- case MLXPLAT_CPLD_LPC_REG_LED5_OFF: +- case MLXPLAT_CPLD_LPC_REG_GP1_OFF: +- case MLXPLAT_CPLD_LPC_REG_WP1_OFF: +- case MLXPLAT_CPLD_LPC_REG_GP2_OFF: +- case MLXPLAT_CPLD_LPC_REG_WP2_OFF: +- case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFF: +- case MLXPLAT_CPLD_LPC_REG_AGGR_LOW_MASK_OFF: +- case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFF: +- case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFF: +- case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFF: +- case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFF: +- case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFF: +- case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFF: ++ case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET: + return true; + } + return false; +@@ -846,31 +1206,48 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg) + static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + { + switch (reg) { +- case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFF: +- case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFF: +- case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF: +- case MLXPLAT_CPLD_LPC_REG_LED1_OFF: +- case MLXPLAT_CPLD_LPC_REG_LED2_OFF: +- case MLXPLAT_CPLD_LPC_REG_LED3_OFF: +- case MLXPLAT_CPLD_LPC_REG_LED4_OFF: +- case MLXPLAT_CPLD_LPC_REG_LED5_OFF: +- case MLXPLAT_CPLD_LPC_REG_GP1_OFF: +- case MLXPLAT_CPLD_LPC_REG_WP1_OFF: +- case MLXPLAT_CPLD_LPC_REG_GP2_OFF: +- case MLXPLAT_CPLD_LPC_REG_WP2_OFF: +- case MLXPLAT_CPLD_LPC_REG_AGGR_OFF: +- case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFF: +- case MLXPLAT_CPLD_LPC_REG_AGGR_LOW_OFF: +- case MLXPLAT_CPLD_LPC_REG_AGGR_LOW_MASK_OFF: +- case MLXPLAT_CPLD_LPC_REG_PSU_OFF: +- case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFF: +- case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFF: +- case MLXPLAT_CPLD_LPC_REG_PWR_OFF: +- case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFF: +- case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFF: +- case MLXPLAT_CPLD_LPC_REG_FAN_OFF: +- case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFF: +- case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFF: ++ case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_WP1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_WP2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWR_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET: + return true; + } + return false; +@@ -879,54 +1256,82 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg) + static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg) + { + switch (reg) { +- case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFF: +- case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFF: +- case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF: +- case MLXPLAT_CPLD_LPC_REG_LED1_OFF: +- case MLXPLAT_CPLD_LPC_REG_LED2_OFF: +- case MLXPLAT_CPLD_LPC_REG_LED3_OFF: +- case MLXPLAT_CPLD_LPC_REG_LED4_OFF: +- case MLXPLAT_CPLD_LPC_REG_LED5_OFF: +- case MLXPLAT_CPLD_LPC_REG_GP1_OFF: +- case MLXPLAT_CPLD_LPC_REG_GP2_OFF: +- case MLXPLAT_CPLD_LPC_REG_AGGR_OFF: +- case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFF: +- case MLXPLAT_CPLD_LPC_REG_AGGR_LOW_OFF: +- case MLXPLAT_CPLD_LPC_REG_AGGR_LOW_MASK_OFF: +- case MLXPLAT_CPLD_LPC_REG_PSU_OFF: +- case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFF: +- case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFF: +- case MLXPLAT_CPLD_LPC_REG_PWR_OFF: +- case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFF: +- case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFF: +- case MLXPLAT_CPLD_LPC_REG_FAN_OFF: +- case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFF: +- case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFF: ++ case MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_GP1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_GP2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_ASIC_HEALTH_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_ASIC_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_ASIC_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PSU_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PSU_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWR_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWR_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWR_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_FAN_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_FAN_EVENT_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_FAN_MASK_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWM1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO1_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO2_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO3_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO4_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO5_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO6_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO7_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO8_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO9_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO10_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO11_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_TACHO12_OFFSET: ++ case MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET: + return true; + } + return false; + } + + static const struct reg_default mlxplat_mlxcpld_regmap_default[] = { +- { MLXPLAT_CPLD_LPC_REG_WP1_OFF, 0x00 }, +- { MLXPLAT_CPLD_LPC_REG_WP2_OFF, 0x00 }, ++ { MLXPLAT_CPLD_LPC_REG_WP1_OFFSET, 0x00 }, ++ { MLXPLAT_CPLD_LPC_REG_WP2_OFFSET, 0x00 }, ++ { MLXPLAT_CPLD_LPC_REG_PWM_CONTROL_OFFSET, 0x00 }, ++}; ++ ++struct mlxplat_mlxcpld_regmap_context { ++ void __iomem *base; + }; + ++static struct mlxplat_mlxcpld_regmap_context mlxplat_mlxcpld_regmap_ctx; ++ + static int + mlxplat_mlxcpld_reg_read(void *context, unsigned int reg, unsigned int *val) + { +- *val = ioread8(context + reg); ++ struct mlxplat_mlxcpld_regmap_context *ctx = context; ++ ++ *val = ioread8(ctx->base + reg); + return 0; + } + + static int + mlxplat_mlxcpld_reg_write(void *context, unsigned int reg, unsigned int val) + { +- iowrite8(val, context + reg); ++ struct mlxplat_mlxcpld_regmap_context *ctx = context; ++ ++ iowrite8(val, ctx->base + reg); + return 0; + } + +-const struct regmap_config mlxplat_mlxcpld_regmap_config = { ++static const struct regmap_config mlxplat_mlxcpld_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 255, +@@ -944,46 +1349,11 @@ static struct resource mlxplat_mlxcpld_resources[] = { + [0] = DEFINE_RES_IRQ_NAMED(17, "mlxreg-hotplug"), + }; + +-static struct mlxreg_core_data mlxplat_mlxcpld_default_regs_io_data[] = { +- { "cpld1_version", MLXPLAT_CPLD_LPC_REG_CPLD1_VER_OFF, 0x00, +- GENMASK(7, 0), 0444 }, +- { "cpld2_version", MLXPLAT_CPLD_LPC_REG_CPLD2_VER_OFF, 0x00, +- GENMASK(7, 0), 0444 }, +- { "cause_long_pb", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF, +- GENMASK(7, 0) & ~BIT(0), 0x00, 0444 }, +- { "cause_short_pb", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF, +- GENMASK(7, 0) & ~BIT(1), 0x00, 0444 }, +- { "cause_aux_pwr_or_refresh", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF, +- GENMASK(7, 0) & ~BIT(2), 0x00, 0444 }, +- { "cause_main_pwr_fail", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF, +- GENMASK(7, 0) & ~BIT(3), 0x00, 0444 }, +- { "cause_sw_reset", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF, +- GENMASK(7, 0) & ~BIT(4), 0x00, 0444 }, +- { "cause_fw_reset", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF, +- GENMASK(7, 0) & ~BIT(5), 0x00, 0444 }, +- { "cause_hotswap_or_wd", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF, +- GENMASK(7, 0) & ~BIT(6), 0x00, 0444 }, +- { "cause_asic_thermal", MLXPLAT_CPLD_LPC_REG_RESET_CAUSE_OFF, +- GENMASK(7, 0) & ~BIT(7), 0x00, 0444 }, +- { "psu1_on", MLXPLAT_CPLD_LPC_REG_GP1_OFF, GENMASK(7, 0) & ~BIT(0), +- 0x00, 0200 }, +- { "psu2_on", MLXPLAT_CPLD_LPC_REG_GP1_OFF, GENMASK(7, 0) & ~BIT(1), +- 0x00, 0200 }, +- { "pwr_cycle", MLXPLAT_CPLD_LPC_REG_GP1_OFF, GENMASK(7, 0) & ~BIT(2), +- 0x00, 0200 }, +- { "select_iio", MLXPLAT_CPLD_LPC_REG_GP2_OFF, GENMASK(7, 0) & ~BIT(6), +- 0x00, 0644 }, +-}; +- +-static struct mlxreg_core_platform_data mlxplat_default_regs_io_data = { +- .data = mlxplat_mlxcpld_default_regs_io_data, +- .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_regs_io_data), +-}; +- + static struct platform_device *mlxplat_dev; + static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug; + static struct mlxreg_core_platform_data *mlxplat_led; + static struct mlxreg_core_platform_data *mlxplat_regs_io; ++static struct mlxreg_core_platform_data *mlxplat_fan; + + static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi) + { +@@ -1016,7 +1386,7 @@ static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi) + mlxplat_hotplug->deferred_nr = + mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; + mlxplat_led = &mlxplat_msn21xx_led_data; +- mlxplat_regs_io = &mlxplat_default_regs_io_data; ++ mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data; + + return 1; + }; +@@ -1034,12 +1404,12 @@ static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi) + mlxplat_hotplug->deferred_nr = + mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; + mlxplat_led = &mlxplat_default_led_data; +- mlxplat_regs_io = &mlxplat_default_regs_io_data; ++ mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data; + + return 1; + }; + +-static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi) ++static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi) + { + int i; + +@@ -1048,16 +1418,16 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi) + mlxplat_mux_data[i].n_values = + ARRAY_SIZE(mlxplat_msn21xx_channels); + } +- mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data; ++ mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data; + mlxplat_hotplug->deferred_nr = + mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; + mlxplat_led = &mlxplat_default_ng_led_data; +- mlxplat_regs_io = &mlxplat_default_regs_io_data; ++ mlxplat_regs_io = &mlxplat_msn21xx_regs_io_data; + + return 1; + }; + +-static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi) ++static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi) + { + int i; + +@@ -1066,11 +1436,11 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi) + mlxplat_mux_data[i].n_values = + ARRAY_SIZE(mlxplat_msn21xx_channels); + } +- mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data; ++ mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data; + mlxplat_hotplug->deferred_nr = + mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1]; + mlxplat_led = &mlxplat_msn21xx_led_data; +- mlxplat_regs_io = &mlxplat_default_regs_io_data; ++ mlxplat_fan = &mlxplat_default_fan_data; + + return 1; + }; +@@ -1222,8 +1592,7 @@ static int mlxplat_mlxcpld_verify_bus_topology(int *nr) + static int __init mlxplat_init(void) + { + struct mlxplat_priv *priv; +- void __iomem *base; +- int i, j, nr, err = 0; ++ int i, j, nr, err; + + if (!dmi_check_system(mlxplat_dmi_table)) + return -ENODEV; +@@ -1267,29 +1636,21 @@ static int __init mlxplat_init(void) + } + } + +- base = devm_ioport_map(&mlxplat_dev->dev, ++ mlxplat_mlxcpld_regmap_ctx.base = devm_ioport_map(&mlxplat_dev->dev, + mlxplat_lpc_resources[1].start, 1); +- if (!base) { ++ if (!mlxplat_mlxcpld_regmap_ctx.base) { + err = -ENOMEM; + goto fail_platform_mux_register; + } + + mlxplat_hotplug->regmap = devm_regmap_init(&mlxplat_dev->dev, NULL, +- base, &mlxplat_mlxcpld_regmap_config); ++ &mlxplat_mlxcpld_regmap_ctx, ++ &mlxplat_mlxcpld_regmap_config); + if (IS_ERR(mlxplat_hotplug->regmap)) { + err = PTR_ERR(mlxplat_hotplug->regmap); + goto fail_platform_mux_register; + } + +- /* Set default registers. */ +- for (j = 0; j < mlxplat_mlxcpld_regmap_config.num_reg_defaults; j++) { +- err = regmap_write(mlxplat_hotplug->regmap, +- mlxplat_mlxcpld_regmap_default[j].reg, +- mlxplat_mlxcpld_regmap_default[j].def); +- if (err) +- goto fail_platform_mux_register; +- } +- + priv->pdev_hotplug = platform_device_register_resndata( + &mlxplat_dev->dev, "mlxreg-hotplug", + PLATFORM_DEVID_NONE, +@@ -1301,6 +1662,16 @@ static int __init mlxplat_init(void) + goto fail_platform_mux_register; + } + ++ /* Set default registers. */ ++ for (j = 0; j < mlxplat_mlxcpld_regmap_config.num_reg_defaults; j++) { ++ err = regmap_write(mlxplat_hotplug->regmap, ++ mlxplat_mlxcpld_regmap_default[j].reg, ++ mlxplat_mlxcpld_regmap_default[j].def); ++ if (err) ++ goto fail_platform_mux_register; ++ } ++ ++ /* Add LED driver. */ + mlxplat_led->regmap = mlxplat_hotplug->regmap; + priv->pdev_led = platform_device_register_resndata( + &mlxplat_dev->dev, "leds-mlxreg", +@@ -1311,24 +1682,48 @@ static int __init mlxplat_init(void) + goto fail_platform_hotplug_register; + } + +- mlxplat_regs_io->regmap = mlxplat_hotplug->regmap; +- priv->pdev_io_regs = platform_device_register_resndata( +- &mlxplat_dev->dev, "mlxreg-io", +- PLATFORM_DEVID_NONE, NULL, 0, +- mlxplat_regs_io, sizeof(*mlxplat_regs_io)); +- if (IS_ERR(priv->pdev_io_regs)) { +- err = PTR_ERR(priv->pdev_io_regs); +- goto fail_platform_led_register; ++ /* Add registers io access driver. */ ++ if (mlxplat_regs_io) { ++ mlxplat_regs_io->regmap = mlxplat_hotplug->regmap; ++ priv->pdev_io_regs = platform_device_register_resndata( ++ &mlxplat_dev->dev, "mlxreg-io", ++ PLATFORM_DEVID_NONE, NULL, 0, ++ mlxplat_regs_io, ++ sizeof(*mlxplat_regs_io)); ++ if (IS_ERR(priv->pdev_io_regs)) { ++ err = PTR_ERR(priv->pdev_io_regs); ++ goto fail_platform_led_register; ++ } ++ } ++ ++ /* Add FAN driver. */ ++ if (mlxplat_fan) { ++ mlxplat_fan->regmap = mlxplat_hotplug->regmap; ++ priv->pdev_fan = platform_device_register_resndata( ++ &mlxplat_dev->dev, "mlxreg-fan", ++ PLATFORM_DEVID_NONE, NULL, 0, ++ mlxplat_fan, ++ sizeof(*mlxplat_fan)); ++ if (IS_ERR(priv->pdev_io_regs)) { ++ err = PTR_ERR(priv->pdev_io_regs); ++ goto fail_platform_io_regs_register; ++ } + } + + /* Sync registers with hardware. */ + regcache_mark_dirty(mlxplat_hotplug->regmap); + err = regcache_sync(mlxplat_hotplug->regmap); + if (err) +- goto fail_platform_led_register; ++ goto fail_platform_fan_register; + + return 0; + ++fail_platform_fan_register: ++ if (mlxplat_fan) ++ platform_device_unregister(priv->pdev_fan); ++fail_platform_io_regs_register: ++ if (mlxplat_regs_io) ++ platform_device_unregister(priv->pdev_io_regs); + fail_platform_led_register: + platform_device_unregister(priv->pdev_led); + fail_platform_hotplug_register: +@@ -1349,7 +1744,10 @@ static void __exit mlxplat_exit(void) + struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev); + int i; + +- platform_device_unregister(priv->pdev_io_regs); ++ if (priv->pdev_fan) ++ platform_device_unregister(priv->pdev_fan); ++ if (priv->pdev_io_regs) ++ platform_device_unregister(priv->pdev_io_regs); + platform_device_unregister(priv->pdev_led); + platform_device_unregister(priv->pdev_hotplug); + +-- +2.1.4 + diff --git a/packages/base/any/kernels/4.9-lts/patches/series b/packages/base/any/kernels/4.9-lts/patches/series index 1d79cd29..bcbed8ca 100644 --- a/packages/base/any/kernels/4.9-lts/patches/series +++ b/packages/base/any/kernels/4.9-lts/patches/series @@ -13,3 +13,4 @@ driver-support-intel-igb-bcm5461-phy.patch 0012-i2c-busses-Add-capabilities-to-i2c-mlxcpld.patch driver-i2c-i2c-core.patch driver-add-the-support-max6620.patch +0013-Mellanox-backport-patchwork-from-kernels-4.17-4.19.patch diff --git a/packages/base/any/kernels/modules/optoe.c b/packages/base/any/kernels/modules/optoe.c index b3064f02..c22b92a2 100644 --- a/packages/base/any/kernels/modules/optoe.c +++ b/packages/base/any/kernels/modules/optoe.c @@ -660,6 +660,7 @@ static ssize_t optoe_read_write(struct optoe_data *optoe, ssize_t retval; size_t pending_len = 0, chunk_len = 0; loff_t chunk_offset = 0, chunk_start_offset = 0; + loff_t chunk_end_offset = 0; dev_dbg(&client->dev, "%s: off %lld len:%ld, opcode:%s\n", @@ -699,30 +700,30 @@ static ssize_t optoe_read_write(struct optoe_data *optoe, /* * Compute the offset and number of bytes to be read/write * - * 1. start at offset 0 (within the chunk), and read/write - * the entire chunk - * 2. start at offset 0 (within the chunk) and read/write less - * than entire chunk - * 3. start at an offset not equal to 0 and read/write the rest + * 1. start at an offset not equal to 0 (within the chunk) + * and read/write less than the rest of the chunk + * 2. start at an offset not equal to 0 and read/write the rest * of the chunk - * 4. start at an offset not equal to 0 and read/write less than - * (end of chunk - offset) + * 3. start at offset 0 (within the chunk) and read/write less + * than entire chunk + * 4. start at offset 0 (within the chunk), and read/write + * the entire chunk */ chunk_start_offset = chunk * OPTOE_PAGE_SIZE; + chunk_end_offset = chunk_start_offset + OPTOE_PAGE_SIZE; if (chunk_start_offset < off) { chunk_offset = off; - if ((off + pending_len) < (chunk_start_offset + - OPTOE_PAGE_SIZE)) + if ((off + pending_len) < chunk_end_offset) chunk_len = pending_len; else - chunk_len = OPTOE_PAGE_SIZE - off; + chunk_len = chunk_end_offset - off; } else { chunk_offset = chunk_start_offset; - if (pending_len > OPTOE_PAGE_SIZE) - chunk_len = OPTOE_PAGE_SIZE; - else + if (pending_len < OPTOE_PAGE_SIZE) chunk_len = pending_len; + else + chunk_len = OPTOE_PAGE_SIZE; } dev_dbg(&client->dev, diff --git a/packages/base/any/onlp/src/onlp/module/src/onlp_locks.h b/packages/base/any/onlp/src/onlp/module/src/onlp_locks.h index 7a3c92e1..66184704 100644 --- a/packages/base/any/onlp/src/onlp/module/src/onlp_locks.h +++ b/packages/base/any/onlp/src/onlp/module/src/onlp_locks.h @@ -206,7 +206,7 @@ void onlp_api_unlock(void); ONLP_API_T1(_name); \ ONLP_LOCKED_API_NAME(_name) (_v1, _v2, _v3); \ ONLP_API_UNLOCK(); \ - ONLP_API_T2_(name); \ + ONLP_API_T2(name); \ } #define ONLP_LOCKED_VAPI4(_name, _t1, _v1, _t2, _v2, _t3, _v3, _t4, _v4) \ diff --git a/packages/base/any/onlp/src/onlp/module/src/sfp.c b/packages/base/any/onlp/src/onlp/module/src/sfp.c index de7c64ff..33c176ca 100644 --- a/packages/base/any/onlp/src/onlp/module/src/sfp.c +++ b/packages/base/any/onlp/src/onlp/module/src/sfp.c @@ -110,6 +110,7 @@ ONLP_LOCKED_API1(onlp_sfp_is_present, int, port); static int onlp_sfp_presence_bitmap_get_locked__(onlp_sfp_bitmap_t* dst) { + onlp_sfp_bitmap_t_init(dst); int rv = onlp_sfpi_presence_bitmap_get(dst); if(rv == ONLP_STATUS_E_UNSUPPORTED) { diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/arm-accton-as4610-54-r0.dts b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/arm-accton-as4610-54-r0.dts index 0e7a33c0..3226b312 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/arm-accton-as4610-54-r0.dts +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/builds/dtb/arm-accton-as4610-54-r0.dts @@ -139,8 +139,8 @@ #address-cells = <1>; #size-cells = <0>; reg = <0>; - sfp_eeprom@50 { - compatible = "at,as4610_sfp1"; + optoe@50 { + compatible = "optoe2"; reg = <0x50>; label = "port49"; }; @@ -151,8 +151,8 @@ #address-cells = <1>; #size-cells = <0>; reg = <1>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp2"; + optoe@50 { + compatible = "optoe2"; reg = <0x50>; label = "port50"; }; @@ -163,8 +163,8 @@ #address-cells = <1>; #size-cells = <0>; reg = <2>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp3"; + optoe@50 { + compatible = "optoe2"; reg = <0x50>; label = "port51"; }; @@ -175,8 +175,8 @@ #address-cells = <1>; #size-cells = <0>; reg = <3>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp4"; + optoe@50 { + compatible = "optoe2"; reg = <0x50>; label = "port52"; }; @@ -187,9 +187,10 @@ #address-cells = <1>; #size-cells = <0>; reg = <4>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp5"; + optoe@50 { + compatible = "optoe1"; reg = <0x50>; + label = "port53"; }; }; @@ -198,9 +199,10 @@ #address-cells = <1>; #size-cells = <0>; reg = <5>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp6"; + optoe@50 { + compatible = "optoe1"; reg = <0x50>; + label = "port54"; }; }; diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/arm-accton-as4610-54-r0.dts b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/arm-accton-as4610-54-r0.dts index 0e7a33c0..3226b312 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/arm-accton-as4610-54-r0.dts +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/builds/dtb/arm-accton-as4610-54-r0.dts @@ -139,8 +139,8 @@ #address-cells = <1>; #size-cells = <0>; reg = <0>; - sfp_eeprom@50 { - compatible = "at,as4610_sfp1"; + optoe@50 { + compatible = "optoe2"; reg = <0x50>; label = "port49"; }; @@ -151,8 +151,8 @@ #address-cells = <1>; #size-cells = <0>; reg = <1>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp2"; + optoe@50 { + compatible = "optoe2"; reg = <0x50>; label = "port50"; }; @@ -163,8 +163,8 @@ #address-cells = <1>; #size-cells = <0>; reg = <2>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp3"; + optoe@50 { + compatible = "optoe2"; reg = <0x50>; label = "port51"; }; @@ -175,8 +175,8 @@ #address-cells = <1>; #size-cells = <0>; reg = <3>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp4"; + optoe@50 { + compatible = "optoe2"; reg = <0x50>; label = "port52"; }; @@ -187,9 +187,10 @@ #address-cells = <1>; #size-cells = <0>; reg = <4>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp5"; + optoe@50 { + compatible = "optoe1"; reg = <0x50>; + label = "port53"; }; }; @@ -198,9 +199,10 @@ #address-cells = <1>; #size-cells = <0>; reg = <5>; - sfp_eeprom@50 { - compatible = "accton,as4610_sfp6"; + optoe@50 { + compatible = "optoe1"; reg = <0x50>; + label = "port54"; }; }; diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/sfpi.c b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/sfpi.c index 7199a31a..41379f73 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/sfpi.c +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/sfpi.c @@ -24,50 +24,31 @@ * ***********************************************************/ #include +#include #include "platform_lib.h" #include #include "arm_accton_as4610_log.h" -#define MAX_SFP_PATH 64 -static char sfp_node_path[MAX_SFP_PATH] = {0}; -#define FRONT_PORT_MUX_INDEX(port) (port-46) +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" +#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/0-0030/module_present_%d" +#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/0-0030/module_rx_los_%d" +#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/0-0030/module_tx_fault_%d" +#define MODULE_PRESENT_ALL_ATTR_CPLD "/sys/bus/i2c/devices/0-0030/module_present_all" +#define MODULE_RXLOS_ALL_ATTR_CPLD "/sys/bus/i2c/devices/0-0030/module_rx_los_all" -static int -sfp_node_read_int(char *node_path, int *value, int data_len) +static int front_port_bus_index(int port) { - int ret = 0; - char buf[8]; - *value = 0; - - ret = deviceNodeReadString(node_path, buf, sizeof(buf), data_len); - - if (ret == 0) { - *value = atoi(buf); - } - - return ret; + return (platform_id == PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0) ? + (port - 22) : /* PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0 */ + (port - 46) ; /* PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0 */ } -static char* -sfp_get_port_path_addr(int port, int addr, char *node_name) +static int front_port_to_cpld_port(int port) { - int front_port_mux_id; - - if(platform_id == PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0) - front_port_mux_id = port - 22; - else /*PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0*/ - front_port_mux_id = port - 46; - - sprintf(sfp_node_path, "/sys/bus/i2c/devices/%d-00%d/%s", - front_port_mux_id, addr, node_name); - return sfp_node_path; -} - -static char* -sfp_get_port_path(int port, char *node_name) -{ - return sfp_get_port_path_addr(port, 50, node_name); + return (platform_id == PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0) ? + (port - 23) : /* PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0 */ + (port - 47) ; /* PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0 */ } /************************************************************ @@ -115,9 +96,9 @@ onlp_sfpi_is_present(int port) * Return < 0 if error. */ int present; - char* path = sfp_get_port_path(port, "sfp_is_present"); - - if (sfp_node_read_int(path, &present, 0) != 0) { + int cpld_port = front_port_to_cpld_port(port); + + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, cpld_port) < 0) { AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } @@ -129,7 +110,6 @@ int onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) { uint32_t byte; - char* path; FILE* fp; int port; @@ -140,18 +120,18 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) else /*PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0*/ port = 48; - path = sfp_get_port_path(port, "sfp_is_present_all"); - fp = fopen(path, "r"); - + /* Read present status of each port */ + fp = fopen(MODULE_PRESENT_ALL_ATTR_CPLD, "r"); if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file."); + AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD."); return ONLP_STATUS_E_INTERNAL; } + int count = fscanf(fp, "%x", &byte); fclose(fp); if(count != 1) { /* Likely a CPLD read timeout. */ - AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file."); + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD."); return ONLP_STATUS_E_INTERNAL; } @@ -173,7 +153,6 @@ int onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) { uint32_t byte; - char* path; FILE* fp; int port; @@ -182,16 +161,18 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) else /*PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0*/ port = 48; - path = sfp_get_port_path(port, "sfp_rx_los_all"); - fp = fopen(path, "r"); + /* Read present status of each port */ + fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD, "r"); if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the sfp_rx_los_all device file."); + AIM_LOG_ERROR("Unable to open the module_rx_los_all device file of CPLD."); return ONLP_STATUS_E_INTERNAL; } + int count = fscanf(fp, "%x", &byte); fclose(fp); if(count != 1) { - AIM_LOG_ERROR("Unable to read all fields from the sfp_rx_los_all device file."); + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_rx_los_all device file of CPLD."); return ONLP_STATUS_E_INTERNAL; } @@ -212,32 +193,51 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) int onlp_sfpi_eeprom_read(int port, uint8_t data[256]) { - char* path = sfp_get_port_path(port, "sfp_eeprom"); - /* * Read the SFP eeprom into data[] * * Return MISSING if SFP is missing. * Return OK if eeprom is read */ + int size = 0; memset(data, 0, 256); - if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) { + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, front_port_bus_index(port)) != ONLP_STATUS_OK) { AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + return ONLP_STATUS_OK; } int onlp_sfpi_dom_read(int port, uint8_t data[256]) { - char* path = sfp_get_port_path_addr(port, 51, "sfp_eeprom"); - memset(data, 0, 256); + FILE* fp; + char file[64] = {0}; + + sprintf(file, PORT_EEPROM_FORMAT, front_port_bus_index(port)); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } - if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) { - AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port); + if (fseek(fp, 256, SEEK_CUR) != 0) { + fclose(fp); + AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + int ret = fread(data, 1, 256, fp); + fclose(fp); + if (ret != 256) { + AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port); return ONLP_STATUS_E_INTERNAL; } @@ -247,45 +247,24 @@ onlp_sfpi_dom_read(int port, uint8_t data[256]) int onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) { - int rv; - - switch(control) - { - case ONLP_SFP_CONTROL_TX_DISABLE: - { - char* path = sfp_get_port_path(port, "sfp_tx_disable"); - - if (deviceNodeWriteInt(path, value, 0) != 0) { - AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port); - rv = ONLP_STATUS_E_INTERNAL; - } - else { - rv = ONLP_STATUS_OK; - } - break; - } - - default: - rv = ONLP_STATUS_E_UNSUPPORTED; - break; - } - - return rv; + return ONLP_STATUS_E_UNSUPPORTED; } int onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) { int rv; - char* path = NULL; + int cpld_port = front_port_to_cpld_port(port); + + if (cpld_port > 4) { + return ONLP_STATUS_E_UNSUPPORTED; + } switch(control) { case ONLP_SFP_CONTROL_RX_LOS: { - path = sfp_get_port_path(port, "sfp_rx_los"); - - if (sfp_node_read_int(path, value, 0) != 0) { + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, cpld_port) < 0) { AIM_LOG_ERROR("Unable to read rx_los status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -297,9 +276,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_FAULT: { - path = sfp_get_port_path(port, "sfp_tx_fault"); - - if (sfp_node_read_int(path, value, 0) != 0) { + if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, cpld_port) < 0) { AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -309,20 +286,6 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) break; } - case ONLP_SFP_CONTROL_TX_DISABLE: - { - path = sfp_get_port_path(port, "sfp_tx_disable"); - - if (sfp_node_read_int(path, value, 0) != 0) { - AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port); - rv = ONLP_STATUS_E_INTERNAL; - } - else { - rv = ONLP_STATUS_OK; - } - break; - } - default: rv = ONLP_STATUS_E_UNSUPPORTED; } @@ -330,9 +293,9 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) return rv; } - int onlp_sfpi_denit(void) { return ONLP_STATUS_OK; } + diff --git a/packages/platforms/accton/x86-64/modules/builds/optoe.c b/packages/platforms/accton/x86-64/modules/builds/optoe.c deleted file mode 100755 index b3064f02..00000000 --- a/packages/platforms/accton/x86-64/modules/builds/optoe.c +++ /dev/null @@ -1,1146 +0,0 @@ -/* - * optoe.c - A driver to read and write the EEPROM on optical transceivers - * (SFP, QSFP and similar I2C based devices) - * - * Copyright (C) 2014 Cumulus networks Inc. - * Copyright (C) 2017 Finisar Corp. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Freeoftware Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -/* - * Description: - * a) Optical transceiver EEPROM read/write transactions are just like - * the at24 eeproms managed by the at24.c i2c driver - * b) The register/memory layout is up to 256 128 byte pages defined by - * a "pages valid" register and switched via a "page select" - * register as explained in below diagram. - * c) 256 bytes are mapped at a time. 'Lower page 00h' is the first 128 - * bytes of address space, and always references the same - * location, independent of the page select register. - * All mapped pages are mapped into the upper 128 bytes - * (offset 128-255) of the i2c address. - * d) Devices with one I2C address (eg QSFP) use I2C address 0x50 - * (A0h in the spec), and map all pages in the upper 128 bytes - * of that address. - * e) Devices with two I2C addresses (eg SFP) have 256 bytes of data - * at I2C address 0x50, and 256 bytes of data at I2C address - * 0x51 (A2h in the spec). Page selection and paged access - * only apply to this second I2C address (0x51). - * e) The address space is presented, by the driver, as a linear - * address space. For devices with one I2C client at address - * 0x50 (eg QSFP), offset 0-127 are in the lower - * half of address 50/A0h/client[0]. Offset 128-255 are in - * page 0, 256-383 are page 1, etc. More generally, offset - * 'n' resides in page (n/128)-1. ('page -1' is the lower - * half, offset 0-127). - * f) For devices with two I2C clients at address 0x50 and 0x51 (eg SFP), - * the address space places offset 0-127 in the lower - * half of 50/A0/client[0], offset 128-255 in the upper - * half. Offset 256-383 is in the lower half of 51/A2/client[1]. - * Offset 384-511 is in page 0, in the upper half of 51/A2/... - * Offset 512-639 is in page 1, in the upper half of 51/A2/... - * Offset 'n' is in page (n/128)-3 (for n > 383) - * - * One I2c addressed (eg QSFP) Memory Map - * - * 2-Wire Serial Address: 1010000x - * - * Lower Page 00h (128 bytes) - * ===================== - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * |Page Select Byte(127)| - * ===================== - * | - * | - * | - * | - * V - * ------------------------------------------------------------ - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * V V V V - * ------------ -------------- --------------- -------------- - * | | | | | | | | - * | Upper | | Upper | | Upper | | Upper | - * | Page 00h | | Page 01h | | Page 02h | | Page 03h | - * | | | (Optional) | | (Optional) | | (Optional | - * | | | | | | | for Cable | - * | | | | | | | Assemblies) | - * | ID | | AST | | User | | | - * | Fields | | Table | | EEPROM Data | | | - * | | | | | | | | - * | | | | | | | | - * | | | | | | | | - * ------------ -------------- --------------- -------------- - * - * The SFF 8436 (QSFP) spec only defines the 4 pages described above. - * In anticipation of future applications and devices, this driver - * supports access to the full architected range, 256 pages. - * - **/ - -/* #define DEBUG 1 */ - -#undef EEPROM_CLASS -#ifdef CONFIG_EEPROM_CLASS -#define EEPROM_CLASS -#endif -#ifdef CONFIG_EEPROM_CLASS_MODULE -#define EEPROM_CLASS -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef EEPROM_CLASS -#include -#endif - -#include - -/* The maximum length of a port name */ -#define MAX_PORT_NAME_LEN 20 - -struct optoe_platform_data { - u32 byte_len; /* size (sum of all addr) */ - u16 page_size; /* for writes */ - u8 flags; - void *dummy1; /* backward compatibility */ - void *dummy2; /* backward compatibility */ - -#ifdef EEPROM_CLASS - struct eeprom_platform_data *eeprom_data; -#endif - char port_name[MAX_PORT_NAME_LEN]; -}; - -/* fundamental unit of addressing for EEPROM */ -#define OPTOE_PAGE_SIZE 128 -/* - * Single address devices (eg QSFP) have 256 pages, plus the unpaged - * low 128 bytes. If the device does not support paging, it is - * only 2 'pages' long. - */ -#define OPTOE_ARCH_PAGES 256 -#define ONE_ADDR_EEPROM_SIZE ((1 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE) -#define ONE_ADDR_EEPROM_UNPAGED_SIZE (2 * OPTOE_PAGE_SIZE) -/* - * Dual address devices (eg SFP) have 256 pages, plus the unpaged - * low 128 bytes, plus 256 bytes at 0x50. If the device does not - * support paging, it is 4 'pages' long. - */ -#define TWO_ADDR_EEPROM_SIZE ((3 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE) -#define TWO_ADDR_EEPROM_UNPAGED_SIZE (4 * OPTOE_PAGE_SIZE) -#define TWO_ADDR_NO_0X51_SIZE (2 * OPTOE_PAGE_SIZE) - -/* a few constants to find our way around the EEPROM */ -#define OPTOE_PAGE_SELECT_REG 0x7F -#define ONE_ADDR_PAGEABLE_REG 0x02 -#define ONE_ADDR_NOT_PAGEABLE (1<<2) -#define TWO_ADDR_PAGEABLE_REG 0x40 -#define TWO_ADDR_PAGEABLE (1<<4) -#define TWO_ADDR_0X51_REG 92 -#define TWO_ADDR_0X51_SUPP (1<<6) -#define OPTOE_ID_REG 0 -#define OPTOE_READ_OP 0 -#define OPTOE_WRITE_OP 1 -#define OPTOE_EOF 0 /* used for access beyond end of device */ - -struct optoe_data { - struct optoe_platform_data chip; - int use_smbus; - char port_name[MAX_PORT_NAME_LEN]; - - /* - * Lock protects against activities from other Linux tasks, - * but not from changes by other I2C masters. - */ - struct mutex lock; - struct bin_attribute bin; - struct attribute_group attr_group; - - u8 *writebuf; - unsigned int write_max; - - unsigned int num_addresses; - -#ifdef EEPROM_CLASS - struct eeprom_device *eeprom_dev; -#endif - - /* dev_class: ONE_ADDR (QSFP) or TWO_ADDR (SFP) */ - int dev_class; - - struct i2c_client *client[]; -}; - - -/* - * This parameter is to help this driver avoid blocking other drivers out - * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C - * clock, one 256 byte read takes about 1/43 second which is excessive; - * but the 1/170 second it takes at 400 kHz may be quite reasonable; and - * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. - * - * This value is forced to be a power of two so that writes align on pages. - */ -static unsigned int io_limit = OPTOE_PAGE_SIZE; - -/* - * specs often allow 5 msec for a page write, sometimes 20 msec; - * it's important to recover from write timeouts. - */ -static unsigned int write_timeout = 25; - -/* - * flags to distinguish one-address (QSFP family) from two-address (SFP family) - * If the family is not known, figure it out when the device is accessed - */ -#define ONE_ADDR 1 -#define TWO_ADDR 2 - -static const struct i2c_device_id optoe_ids[] = { - { "optoe1", ONE_ADDR }, - { "optoe2", TWO_ADDR }, - { "sff8436", ONE_ADDR }, - { "24c04", TWO_ADDR }, - { /* END OF LIST */ } -}; -MODULE_DEVICE_TABLE(i2c, optoe_ids); - -/*-------------------------------------------------------------------------*/ -/* - * This routine computes the addressing information to be used for - * a given r/w request. - * - * Task is to calculate the client (0 = i2c addr 50, 1 = i2c addr 51), - * the page, and the offset. - * - * Handles both single address (eg QSFP) and two address (eg SFP). - * For SFP, offset 0-255 are on client[0], >255 is on client[1] - * Offset 256-383 are on the lower half of client[1] - * Pages are accessible on the upper half of client[1]. - * Offset >383 are in 128 byte pages mapped into the upper half - * - * For QSFP, all offsets are on client[0] - * offset 0-127 are on the lower half of client[0] (no paging) - * Pages are accessible on the upper half of client[1]. - * Offset >127 are in 128 byte pages mapped into the upper half - * - * Callers must not read/write beyond the end of a client or a page - * without recomputing the client/page. Hence offset (within page) - * plus length must be less than or equal to 128. (Note that this - * routine does not have access to the length of the call, hence - * cannot do the validity check.) - * - * Offset within Lower Page 00h and Upper Page 00h are not recomputed - */ - -static uint8_t optoe_translate_offset(struct optoe_data *optoe, - loff_t *offset, struct i2c_client **client) -{ - unsigned int page = 0; - - *client = optoe->client[0]; - - /* if SFP style, offset > 255, shift to i2c addr 0x51 */ - if (optoe->dev_class == TWO_ADDR) { - if (*offset > 255) { - /* like QSFP, but shifted to client[1] */ - *client = optoe->client[1]; - *offset -= 256; - } - } - - /* - * if offset is in the range 0-128... - * page doesn't matter (using lower half), return 0. - * offset is already correct (don't add 128 to get to paged area) - */ - if (*offset < OPTOE_PAGE_SIZE) - return page; - - /* note, page will always be positive since *offset >= 128 */ - page = (*offset >> 7)-1; - /* 0x80 places the offset in the top half, offset is last 7 bits */ - *offset = OPTOE_PAGE_SIZE + (*offset & 0x7f); - - return page; /* note also returning client and offset */ -} - -static ssize_t optoe_eeprom_read(struct optoe_data *optoe, - struct i2c_client *client, - char *buf, unsigned int offset, size_t count) -{ - struct i2c_msg msg[2]; - u8 msgbuf[2]; - unsigned long timeout, read_time; - int status, i; - - memset(msg, 0, sizeof(msg)); - - switch (optoe->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - /*smaller eeproms can work given some SMBus extension calls */ - if (count > I2C_SMBUS_BLOCK_MAX) - count = I2C_SMBUS_BLOCK_MAX; - break; - case I2C_SMBUS_WORD_DATA: - /* Check for odd length transaction */ - count = (count == 1) ? 1 : 2; - break; - case I2C_SMBUS_BYTE_DATA: - count = 1; - break; - default: - /* - * When we have a better choice than SMBus calls, use a - * combined I2C message. Write address; then read up to - * io_limit data bytes. msgbuf is u8 and will cast to our - * needs. - */ - i = 0; - msgbuf[i++] = offset; - - msg[0].addr = client->addr; - msg[0].buf = msgbuf; - msg[0].len = i; - - msg[1].addr = client->addr; - msg[1].flags = I2C_M_RD; - msg[1].buf = buf; - msg[1].len = count; - } - - /* - * Reads fail if the previous write didn't complete yet. We may - * loop a few times until this one succeeds, waiting at least - * long enough for one entire page write to work. - */ - timeout = jiffies + msecs_to_jiffies(write_timeout); - do { - read_time = jiffies; - - switch (optoe->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - status = i2c_smbus_read_i2c_block_data(client, offset, - count, buf); - break; - case I2C_SMBUS_WORD_DATA: - status = i2c_smbus_read_word_data(client, offset); - if (status >= 0) { - buf[0] = status & 0xff; - if (count == 2) - buf[1] = status >> 8; - status = count; - } - break; - case I2C_SMBUS_BYTE_DATA: - status = i2c_smbus_read_byte_data(client, offset); - if (status >= 0) { - buf[0] = status; - status = count; - } - break; - default: - status = i2c_transfer(client->adapter, msg, 2); - if (status == 2) - status = count; - } - - dev_dbg(&client->dev, "eeprom read %zu@%d --> %d (%ld)\n", - count, offset, status, jiffies); - - if (status == count) /* happy path */ - return count; - - if (status == -ENXIO) /* no module present */ - return status; - - /* REVISIT: at HZ=100, this is sloooow */ - usleep_range(1000, 2000); - } while (time_before(read_time, timeout)); - - return -ETIMEDOUT; -} - -static ssize_t optoe_eeprom_write(struct optoe_data *optoe, - struct i2c_client *client, - const char *buf, - unsigned int offset, size_t count) -{ - struct i2c_msg msg; - ssize_t status; - unsigned long timeout, write_time; - unsigned int next_page_start; - int i = 0; - - /* write max is at most a page - * (In this driver, write_max is actually one byte!) - */ - if (count > optoe->write_max) - count = optoe->write_max; - - /* shorten count if necessary to avoid crossing page boundary */ - next_page_start = roundup(offset + 1, OPTOE_PAGE_SIZE); - if (offset + count > next_page_start) - count = next_page_start - offset; - - switch (optoe->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - /*smaller eeproms can work given some SMBus extension calls */ - if (count > I2C_SMBUS_BLOCK_MAX) - count = I2C_SMBUS_BLOCK_MAX; - break; - case I2C_SMBUS_WORD_DATA: - /* Check for odd length transaction */ - count = (count == 1) ? 1 : 2; - break; - case I2C_SMBUS_BYTE_DATA: - count = 1; - break; - default: - /* If we'll use I2C calls for I/O, set up the message */ - msg.addr = client->addr; - msg.flags = 0; - - /* msg.buf is u8 and casts will mask the values */ - msg.buf = optoe->writebuf; - - msg.buf[i++] = offset; - memcpy(&msg.buf[i], buf, count); - msg.len = i + count; - break; - } - - /* - * Reads fail if the previous write didn't complete yet. We may - * loop a few times until this one succeeds, waiting at least - * long enough for one entire page write to work. - */ - timeout = jiffies + msecs_to_jiffies(write_timeout); - do { - write_time = jiffies; - - switch (optoe->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - status = i2c_smbus_write_i2c_block_data(client, - offset, count, buf); - if (status == 0) - status = count; - break; - case I2C_SMBUS_WORD_DATA: - if (count == 2) { - status = i2c_smbus_write_word_data(client, - offset, (u16)((buf[0])|(buf[1] << 8))); - } else { - /* count = 1 */ - status = i2c_smbus_write_byte_data(client, - offset, buf[0]); - } - if (status == 0) - status = count; - break; - case I2C_SMBUS_BYTE_DATA: - status = i2c_smbus_write_byte_data(client, offset, - buf[0]); - if (status == 0) - status = count; - break; - default: - status = i2c_transfer(client->adapter, &msg, 1); - if (status == 1) - status = count; - break; - } - - dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", - count, offset, (long int) status, jiffies); - - if (status == count) - return count; - - /* REVISIT: at HZ=100, this is sloooow */ - usleep_range(1000, 2000); - } while (time_before(write_time, timeout)); - - return -ETIMEDOUT; -} - - -static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, - char *buf, loff_t off, - size_t count, int opcode) -{ - struct i2c_client *client; - ssize_t retval = 0; - uint8_t page = 0; - loff_t phy_offset = off; - int ret = 0; - - page = optoe_translate_offset(optoe, &phy_offset, &client); - dev_dbg(&client->dev, - "%s off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", - __func__, off, page, phy_offset, (long int) count, opcode); - if (page > 0) { - ret = optoe_eeprom_write(optoe, client, &page, - OPTOE_PAGE_SELECT_REG, 1); - if (ret < 0) { - dev_dbg(&client->dev, - "Write page register for page %d failed ret:%d!\n", - page, ret); - return ret; - } - } - - while (count) { - ssize_t status; - - if (opcode == OPTOE_READ_OP) { - status = optoe_eeprom_read(optoe, client, - buf, phy_offset, count); - } else { - status = optoe_eeprom_write(optoe, client, - buf, phy_offset, count); - } - if (status <= 0) { - if (retval == 0) - retval = status; - break; - } - buf += status; - phy_offset += status; - count -= status; - retval += status; - } - - - if (page > 0) { - /* return the page register to page 0 (why?) */ - page = 0; - ret = optoe_eeprom_write(optoe, client, &page, - OPTOE_PAGE_SELECT_REG, 1); - if (ret < 0) { - dev_err(&client->dev, - "Restore page register to 0 failed:%d!\n", ret); - /* error only if nothing has been transferred */ - if (retval == 0) - retval = ret; - } - } - return retval; -} - -/* - * Figure out if this access is within the range of supported pages. - * Note this is called on every access because we don't know if the - * module has been replaced since the last call. - * If/when modules support more pages, this is the routine to update - * to validate and allow access to additional pages. - * - * Returns updated len for this access: - * - entire access is legal, original len is returned. - * - access begins legal but is too long, len is truncated to fit. - * - initial offset exceeds supported pages, return OPTOE_EOF (zero) - */ -static ssize_t optoe_page_legal(struct optoe_data *optoe, - loff_t off, size_t len) -{ - struct i2c_client *client = optoe->client[0]; - u8 regval; - int status; - size_t maxlen; - - if (off < 0) - return -EINVAL; - if (optoe->dev_class == TWO_ADDR) { - /* SFP case */ - /* if only using addr 0x50 (first 256 bytes) we're good */ - if ((off + len) <= TWO_ADDR_NO_0X51_SIZE) - return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= TWO_ADDR_EEPROM_SIZE) - return OPTOE_EOF; - /* in between, are pages supported? */ - status = optoe_eeprom_read(optoe, client, ®val, - TWO_ADDR_PAGEABLE_REG, 1); - if (status < 0) - return status; /* error out (no module?) */ - if (regval & TWO_ADDR_PAGEABLE) { - /* Pages supported, trim len to the end of pages */ - maxlen = TWO_ADDR_EEPROM_SIZE - off; - } else { - /* pages not supported, trim len to unpaged size */ - if (off >= TWO_ADDR_EEPROM_UNPAGED_SIZE) - return OPTOE_EOF; - - /* will be accessing addr 0x51, is that supported? */ - /* byte 92, bit 6 implies DDM support, 0x51 support */ - status = optoe_eeprom_read(optoe, client, ®val, - TWO_ADDR_0X51_REG, 1); - if (status < 0) - return status; - if (regval & TWO_ADDR_0X51_SUPP) { - /* addr 0x51 is OK */ - maxlen = TWO_ADDR_EEPROM_UNPAGED_SIZE - off; - } else { - /* addr 0x51 NOT supported, trim to 256 max */ - if (off >= TWO_ADDR_NO_0X51_SIZE) - return OPTOE_EOF; - maxlen = TWO_ADDR_NO_0X51_SIZE - off; - } - } - len = (len > maxlen) ? maxlen : len; - dev_dbg(&client->dev, - "page_legal, SFP, off %lld len %ld\n", - off, (long int) len); - } else { - /* QSFP case */ - /* if no pages needed, we're good */ - if ((off + len) <= ONE_ADDR_EEPROM_UNPAGED_SIZE) - return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= ONE_ADDR_EEPROM_SIZE) - return OPTOE_EOF; - /* in between, are pages supported? */ - status = optoe_eeprom_read(optoe, client, ®val, - ONE_ADDR_PAGEABLE_REG, 1); - if (status < 0) - return status; /* error out (no module?) */ - if (regval & ONE_ADDR_NOT_PAGEABLE) { - /* pages not supported, trim len to unpaged size */ - if (off >= ONE_ADDR_EEPROM_UNPAGED_SIZE) - return OPTOE_EOF; - maxlen = ONE_ADDR_EEPROM_UNPAGED_SIZE - off; - } else { - /* Pages supported, trim len to the end of pages */ - maxlen = ONE_ADDR_EEPROM_SIZE - off; - } - len = (len > maxlen) ? maxlen : len; - dev_dbg(&client->dev, - "page_legal, QSFP, off %lld len %ld\n", - off, (long int) len); - } - return len; -} - -static ssize_t optoe_read_write(struct optoe_data *optoe, - char *buf, loff_t off, size_t len, int opcode) -{ - struct i2c_client *client = optoe->client[0]; - int chunk; - int status = 0; - ssize_t retval; - size_t pending_len = 0, chunk_len = 0; - loff_t chunk_offset = 0, chunk_start_offset = 0; - - dev_dbg(&client->dev, - "%s: off %lld len:%ld, opcode:%s\n", - __func__, off, (long int) len, - (opcode == OPTOE_READ_OP) ? "r" : "w"); - if (unlikely(!len)) - return len; - - /* - * Read data from chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&optoe->lock); - - /* - * Confirm this access fits within the device suppored addr range - */ - status = optoe_page_legal(optoe, off, len); - if ((status == OPTOE_EOF) || (status < 0)) { - mutex_unlock(&optoe->lock); - return status; - } - len = status; - - /* - * For each (128 byte) chunk involved in this request, issue a - * separate call to sff_eeprom_update_client(), to - * ensure that each access recalculates the client/page - * and writes the page register as needed. - * Note that chunk to page mapping is confusing, is different for - * QSFP and SFP, and never needs to be done. Don't try! - */ - pending_len = len; /* amount remaining to transfer */ - retval = 0; /* amount transferred */ - for (chunk = off >> 7; chunk <= (off + len - 1) >> 7; chunk++) { - - /* - * Compute the offset and number of bytes to be read/write - * - * 1. start at offset 0 (within the chunk), and read/write - * the entire chunk - * 2. start at offset 0 (within the chunk) and read/write less - * than entire chunk - * 3. start at an offset not equal to 0 and read/write the rest - * of the chunk - * 4. start at an offset not equal to 0 and read/write less than - * (end of chunk - offset) - */ - chunk_start_offset = chunk * OPTOE_PAGE_SIZE; - - if (chunk_start_offset < off) { - chunk_offset = off; - if ((off + pending_len) < (chunk_start_offset + - OPTOE_PAGE_SIZE)) - chunk_len = pending_len; - else - chunk_len = OPTOE_PAGE_SIZE - off; - } else { - chunk_offset = chunk_start_offset; - if (pending_len > OPTOE_PAGE_SIZE) - chunk_len = OPTOE_PAGE_SIZE; - else - chunk_len = pending_len; - } - - dev_dbg(&client->dev, - "sff_r/w: off %lld, len %ld, chunk_start_offset %lld, chunk_offset %lld, chunk_len %ld, pending_len %ld\n", - off, (long int) len, chunk_start_offset, chunk_offset, - (long int) chunk_len, (long int) pending_len); - - /* - * note: chunk_offset is from the start of the EEPROM, - * not the start of the chunk - */ - status = optoe_eeprom_update_client(optoe, buf, - chunk_offset, chunk_len, opcode); - if (status != chunk_len) { - /* This is another 'no device present' path */ - dev_dbg(&client->dev, - "o_u_c: chunk %d c_offset %lld c_len %ld failed %d!\n", - chunk, chunk_offset, (long int) chunk_len, status); - if (status > 0) - retval += status; - if (retval == 0) - retval = status; - break; - } - buf += status; - pending_len -= status; - retval += status; - } - mutex_unlock(&optoe->lock); - - return retval; -} - -static ssize_t optoe_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - struct i2c_client *client = to_i2c_client(container_of(kobj, - struct device, kobj)); - struct optoe_data *optoe = i2c_get_clientdata(client); - - return optoe_read_write(optoe, buf, off, count, OPTOE_READ_OP); -} - - -static ssize_t optoe_bin_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - struct i2c_client *client = to_i2c_client(container_of(kobj, - struct device, kobj)); - struct optoe_data *optoe = i2c_get_clientdata(client); - - return optoe_read_write(optoe, buf, off, count, OPTOE_WRITE_OP); -} - -static int optoe_remove(struct i2c_client *client) -{ - struct optoe_data *optoe; - int i; - - optoe = i2c_get_clientdata(client); - sysfs_remove_group(&client->dev.kobj, &optoe->attr_group); - sysfs_remove_bin_file(&client->dev.kobj, &optoe->bin); - - for (i = 1; i < optoe->num_addresses; i++) - i2c_unregister_device(optoe->client[i]); - -#ifdef EEPROM_CLASS - eeprom_device_unregister(optoe->eeprom_dev); -#endif - - kfree(optoe->writebuf); - kfree(optoe); - return 0; -} - -static ssize_t show_dev_class(struct device *dev, - struct device_attribute *dattr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct optoe_data *optoe = i2c_get_clientdata(client); - ssize_t count; - - mutex_lock(&optoe->lock); - count = sprintf(buf, "%d\n", optoe->dev_class); - mutex_unlock(&optoe->lock); - - return count; -} - -static ssize_t set_dev_class(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct optoe_data *optoe = i2c_get_clientdata(client); - int dev_class; - - /* - * dev_class is actually the number of i2c addresses used, thus - * legal values are "1" (QSFP class) and "2" (SFP class) - */ - - if (kstrtoint(buf, 0, &dev_class) != 0 || - dev_class < 1 || dev_class > 2) - return -EINVAL; - - mutex_lock(&optoe->lock); - optoe->dev_class = dev_class; - mutex_unlock(&optoe->lock); - - return count; -} - -/* - * if using the EEPROM CLASS driver, we don't report a port_name, - * the EEPROM CLASS drive handles that. Hence all this code is - * only compiled if we are NOT using the EEPROM CLASS driver. - */ -#ifndef EEPROM_CLASS - -static ssize_t show_port_name(struct device *dev, - struct device_attribute *dattr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct optoe_data *optoe = i2c_get_clientdata(client); - ssize_t count; - - mutex_lock(&optoe->lock); - count = sprintf(buf, "%s\n", optoe->port_name); - mutex_unlock(&optoe->lock); - - return count; -} - -static ssize_t set_port_name(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct optoe_data *optoe = i2c_get_clientdata(client); - char port_name[MAX_PORT_NAME_LEN]; - - /* no checking, this value is not used except by show_port_name */ - - if (sscanf(buf, "%19s", port_name) != 1) - return -EINVAL; - - mutex_lock(&optoe->lock); - strcpy(optoe->port_name, port_name); - mutex_unlock(&optoe->lock); - - return count; -} - -static DEVICE_ATTR(port_name, 0644, show_port_name, set_port_name); -#endif /* if NOT defined EEPROM_CLASS, the common case */ - -static DEVICE_ATTR(dev_class, 0644, show_dev_class, set_dev_class); - -static struct attribute *optoe_attrs[] = { -#ifndef EEPROM_CLASS - &dev_attr_port_name.attr, -#endif - &dev_attr_dev_class.attr, - NULL, -}; - -static struct attribute_group optoe_attr_group = { - .attrs = optoe_attrs, -}; - -static int optoe_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int err; - int use_smbus = 0; - struct optoe_platform_data chip; - struct optoe_data *optoe; - int num_addresses = 0; - char port_name[MAX_PORT_NAME_LEN]; - - if (client->addr != 0x50) { - dev_dbg(&client->dev, "probe, bad i2c addr: 0x%x\n", - client->addr); - err = -EINVAL; - goto exit; - } - - if (client->dev.platform_data) { - chip = *(struct optoe_platform_data *)client->dev.platform_data; - /* take the port name from the supplied platform data */ -#ifdef EEPROM_CLASS - strncpy(port_name, chip.eeprom_data->label, MAX_PORT_NAME_LEN); -#else - memcpy(port_name, chip.port_name, MAX_PORT_NAME_LEN); -#endif - dev_dbg(&client->dev, - "probe, chip provided, flags:0x%x; name: %s\n", - chip.flags, client->name); - } else { - if (!id->driver_data) { - err = -ENODEV; - goto exit; - } - dev_dbg(&client->dev, "probe, building chip\n"); - strcpy(port_name, "unitialized"); - chip.flags = 0; -#ifdef EEPROM_CLASS - chip.eeprom_data = NULL; -#endif - } - - /* Use I2C operations unless we're stuck with SMBus extensions. */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { - use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; - } else if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_WORD_DATA)) { - use_smbus = I2C_SMBUS_WORD_DATA; - } else if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_BYTE_DATA)) { - use_smbus = I2C_SMBUS_BYTE_DATA; - } else { - err = -EPFNOSUPPORT; - goto exit; - } - } - - - /* - * Make room for two i2c clients - */ - num_addresses = 2; - - optoe = kzalloc(sizeof(struct optoe_data) + - num_addresses * sizeof(struct i2c_client *), - GFP_KERNEL); - if (!optoe) { - err = -ENOMEM; - goto exit; - } - - mutex_init(&optoe->lock); - - /* determine whether this is a one-address or two-address module */ - if ((strcmp(client->name, "optoe1") == 0) || - (strcmp(client->name, "sff8436") == 0)) { - /* one-address (eg QSFP) family */ - optoe->dev_class = ONE_ADDR; - chip.byte_len = ONE_ADDR_EEPROM_SIZE; - num_addresses = 1; - } else if ((strcmp(client->name, "optoe2") == 0) || - (strcmp(client->name, "24c04") == 0)) { - /* SFP family */ - optoe->dev_class = TWO_ADDR; - chip.byte_len = TWO_ADDR_EEPROM_SIZE; - } else { /* those were the only two choices */ - err = -EINVAL; - goto exit; - } - - dev_dbg(&client->dev, "dev_class: %d\n", optoe->dev_class); - optoe->use_smbus = use_smbus; - optoe->chip = chip; - optoe->num_addresses = num_addresses; - memcpy(optoe->port_name, port_name, MAX_PORT_NAME_LEN); - - /* - * Export the EEPROM bytes through sysfs, since that's convenient. - * By default, only root should see the data (maybe passwords etc) - */ - sysfs_bin_attr_init(&optoe->bin); - optoe->bin.attr.name = "eeprom"; - optoe->bin.attr.mode = 0444; - optoe->bin.read = optoe_bin_read; - optoe->bin.size = chip.byte_len; - - if (!use_smbus || - (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || - i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_WORD_DATA) || - i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { - /* - * NOTE: AN-2079 - * Finisar recommends that the host implement 1 byte writes - * only since this module only supports 32 byte page boundaries. - * 2 byte writes are acceptable for PE and Vout changes per - * Application Note AN-2071. - */ - unsigned int write_max = 1; - - optoe->bin.write = optoe_bin_write; - optoe->bin.attr.mode |= 0200; - - if (write_max > io_limit) - write_max = io_limit; - if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) - write_max = I2C_SMBUS_BLOCK_MAX; - optoe->write_max = write_max; - - /* buffer (data + address at the beginning) */ - optoe->writebuf = kmalloc(write_max + 2, GFP_KERNEL); - if (!optoe->writebuf) { - err = -ENOMEM; - goto exit_kfree; - } - } else { - dev_warn(&client->dev, - "cannot write due to controller restrictions."); - } - - optoe->client[0] = client; - - /* SFF-8472 spec requires that the second I2C address be 0x51 */ - if (num_addresses == 2) { - optoe->client[1] = i2c_new_dummy(client->adapter, 0x51); - if (!optoe->client[1]) { - dev_err(&client->dev, "address 0x51 unavailable\n"); - err = -EADDRINUSE; - goto err_struct; - } - } - - /* create the sysfs eeprom file */ - err = sysfs_create_bin_file(&client->dev.kobj, &optoe->bin); - if (err) - goto err_struct; - - optoe->attr_group = optoe_attr_group; - - err = sysfs_create_group(&client->dev.kobj, &optoe->attr_group); - if (err) { - dev_err(&client->dev, "failed to create sysfs attribute group.\n"); - goto err_struct; - } - -#ifdef EEPROM_CLASS - optoe->eeprom_dev = eeprom_device_register(&client->dev, - chip.eeprom_data); - if (IS_ERR(optoe->eeprom_dev)) { - dev_err(&client->dev, "error registering eeprom device.\n"); - err = PTR_ERR(optoe->eeprom_dev); - goto err_sysfs_cleanup; - } -#endif - - i2c_set_clientdata(client, optoe); - - dev_info(&client->dev, "%zu byte %s EEPROM, %s\n", - optoe->bin.size, client->name, - optoe->bin.write ? "read/write" : "read-only"); - - if (use_smbus == I2C_SMBUS_WORD_DATA || - use_smbus == I2C_SMBUS_BYTE_DATA) { - dev_notice(&client->dev, - "Falling back to %s reads, performance will suffer\n", - use_smbus == I2C_SMBUS_WORD_DATA ? "word" : "byte"); - } - - return 0; - -#ifdef EEPROM_CLASS -err_sysfs_cleanup: - sysfs_remove_group(&client->dev.kobj, &optoe->attr_group); - sysfs_remove_bin_file(&client->dev.kobj, &optoe->bin); -#endif - -err_struct: - if (num_addresses == 2) { - if (optoe->client[1]) - i2c_unregister_device(optoe->client[1]); - } - - kfree(optoe->writebuf); -exit_kfree: - kfree(optoe); -exit: - dev_dbg(&client->dev, "probe error %d\n", err); - - return err; -} - -/*-------------------------------------------------------------------------*/ - -static struct i2c_driver optoe_driver = { - .driver = { - .name = "optoe", - .owner = THIS_MODULE, - }, - .probe = optoe_probe, - .remove = optoe_remove, - .id_table = optoe_ids, -}; - -static int __init optoe_init(void) -{ - - if (!io_limit) { - pr_err("optoe: io_limit must not be 0!\n"); - return -EINVAL; - } - - io_limit = rounddown_pow_of_two(io_limit); - return i2c_add_driver(&optoe_driver); -} -module_init(optoe_init); - -static void __exit optoe_exit(void) -{ - i2c_del_driver(&optoe_driver); -} -module_exit(optoe_exit); - -MODULE_DESCRIPTION("Driver for optical transceiver (SFP, QSFP, ...) EEPROMs"); -MODULE_AUTHOR("DON BOLLINGER "); -MODULE_LICENSE("GPL"); diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-cpld.c b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-cpld.c new file mode 100644 index 00000000..ba36420c --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-cpld.c @@ -0,0 +1,1117 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as5512_54x CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as5512_54x_cpld1, + as5512_54x_cpld2, + as5512_54x_cpld3 +}; + +struct as5512_54x_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as5512_54x_cpld_id[] = { + { "as5512_54x_cpld1", as5512_54x_cpld1 }, + { "as5512_54x_cpld2", as5512_54x_cpld2 }, + { "as5512_54x_cpld3", as5512_54x_cpld3 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as5512_54x_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index + +enum as5512_54x_cpld1_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_PRESENT_ATTR_ID(35), + TRANSCEIVER_PRESENT_ATTR_ID(36), + TRANSCEIVER_PRESENT_ATTR_ID(37), + TRANSCEIVER_PRESENT_ATTR_ID(38), + TRANSCEIVER_PRESENT_ATTR_ID(39), + TRANSCEIVER_PRESENT_ATTR_ID(40), + TRANSCEIVER_PRESENT_ATTR_ID(41), + TRANSCEIVER_PRESENT_ATTR_ID(42), + TRANSCEIVER_PRESENT_ATTR_ID(43), + TRANSCEIVER_PRESENT_ATTR_ID(44), + TRANSCEIVER_PRESENT_ATTR_ID(45), + TRANSCEIVER_PRESENT_ATTR_ID(46), + TRANSCEIVER_PRESENT_ATTR_ID(47), + TRANSCEIVER_PRESENT_ATTR_ID(48), + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_TXDISABLE_ATTR_ID(1), + TRANSCEIVER_TXDISABLE_ATTR_ID(2), + TRANSCEIVER_TXDISABLE_ATTR_ID(3), + TRANSCEIVER_TXDISABLE_ATTR_ID(4), + TRANSCEIVER_TXDISABLE_ATTR_ID(5), + TRANSCEIVER_TXDISABLE_ATTR_ID(6), + TRANSCEIVER_TXDISABLE_ATTR_ID(7), + TRANSCEIVER_TXDISABLE_ATTR_ID(8), + TRANSCEIVER_TXDISABLE_ATTR_ID(9), + TRANSCEIVER_TXDISABLE_ATTR_ID(10), + TRANSCEIVER_TXDISABLE_ATTR_ID(11), + TRANSCEIVER_TXDISABLE_ATTR_ID(12), + TRANSCEIVER_TXDISABLE_ATTR_ID(13), + TRANSCEIVER_TXDISABLE_ATTR_ID(14), + TRANSCEIVER_TXDISABLE_ATTR_ID(15), + TRANSCEIVER_TXDISABLE_ATTR_ID(16), + TRANSCEIVER_TXDISABLE_ATTR_ID(17), + TRANSCEIVER_TXDISABLE_ATTR_ID(18), + TRANSCEIVER_TXDISABLE_ATTR_ID(19), + TRANSCEIVER_TXDISABLE_ATTR_ID(20), + TRANSCEIVER_TXDISABLE_ATTR_ID(21), + TRANSCEIVER_TXDISABLE_ATTR_ID(22), + TRANSCEIVER_TXDISABLE_ATTR_ID(23), + TRANSCEIVER_TXDISABLE_ATTR_ID(24), + TRANSCEIVER_TXDISABLE_ATTR_ID(25), + TRANSCEIVER_TXDISABLE_ATTR_ID(26), + TRANSCEIVER_TXDISABLE_ATTR_ID(27), + TRANSCEIVER_TXDISABLE_ATTR_ID(28), + TRANSCEIVER_TXDISABLE_ATTR_ID(29), + TRANSCEIVER_TXDISABLE_ATTR_ID(30), + TRANSCEIVER_TXDISABLE_ATTR_ID(31), + TRANSCEIVER_TXDISABLE_ATTR_ID(32), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(35), + TRANSCEIVER_TXDISABLE_ATTR_ID(36), + TRANSCEIVER_TXDISABLE_ATTR_ID(37), + TRANSCEIVER_TXDISABLE_ATTR_ID(38), + TRANSCEIVER_TXDISABLE_ATTR_ID(39), + TRANSCEIVER_TXDISABLE_ATTR_ID(40), + TRANSCEIVER_TXDISABLE_ATTR_ID(41), + TRANSCEIVER_TXDISABLE_ATTR_ID(42), + TRANSCEIVER_TXDISABLE_ATTR_ID(43), + TRANSCEIVER_TXDISABLE_ATTR_ID(44), + TRANSCEIVER_TXDISABLE_ATTR_ID(45), + TRANSCEIVER_TXDISABLE_ATTR_ID(46), + TRANSCEIVER_TXDISABLE_ATTR_ID(47), + TRANSCEIVER_TXDISABLE_ATTR_ID(48), + TRANSCEIVER_RXLOS_ATTR_ID(1), + TRANSCEIVER_RXLOS_ATTR_ID(2), + TRANSCEIVER_RXLOS_ATTR_ID(3), + TRANSCEIVER_RXLOS_ATTR_ID(4), + TRANSCEIVER_RXLOS_ATTR_ID(5), + TRANSCEIVER_RXLOS_ATTR_ID(6), + TRANSCEIVER_RXLOS_ATTR_ID(7), + TRANSCEIVER_RXLOS_ATTR_ID(8), + TRANSCEIVER_RXLOS_ATTR_ID(9), + TRANSCEIVER_RXLOS_ATTR_ID(10), + TRANSCEIVER_RXLOS_ATTR_ID(11), + TRANSCEIVER_RXLOS_ATTR_ID(12), + TRANSCEIVER_RXLOS_ATTR_ID(13), + TRANSCEIVER_RXLOS_ATTR_ID(14), + TRANSCEIVER_RXLOS_ATTR_ID(15), + TRANSCEIVER_RXLOS_ATTR_ID(16), + TRANSCEIVER_RXLOS_ATTR_ID(17), + TRANSCEIVER_RXLOS_ATTR_ID(18), + TRANSCEIVER_RXLOS_ATTR_ID(19), + TRANSCEIVER_RXLOS_ATTR_ID(20), + TRANSCEIVER_RXLOS_ATTR_ID(21), + TRANSCEIVER_RXLOS_ATTR_ID(22), + TRANSCEIVER_RXLOS_ATTR_ID(23), + TRANSCEIVER_RXLOS_ATTR_ID(24), + TRANSCEIVER_RXLOS_ATTR_ID(25), + TRANSCEIVER_RXLOS_ATTR_ID(26), + TRANSCEIVER_RXLOS_ATTR_ID(27), + TRANSCEIVER_RXLOS_ATTR_ID(28), + TRANSCEIVER_RXLOS_ATTR_ID(29), + TRANSCEIVER_RXLOS_ATTR_ID(30), + TRANSCEIVER_RXLOS_ATTR_ID(31), + TRANSCEIVER_RXLOS_ATTR_ID(32), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(35), + TRANSCEIVER_RXLOS_ATTR_ID(36), + TRANSCEIVER_RXLOS_ATTR_ID(37), + TRANSCEIVER_RXLOS_ATTR_ID(38), + TRANSCEIVER_RXLOS_ATTR_ID(39), + TRANSCEIVER_RXLOS_ATTR_ID(40), + TRANSCEIVER_RXLOS_ATTR_ID(41), + TRANSCEIVER_RXLOS_ATTR_ID(42), + TRANSCEIVER_RXLOS_ATTR_ID(43), + TRANSCEIVER_RXLOS_ATTR_ID(44), + TRANSCEIVER_RXLOS_ATTR_ID(45), + TRANSCEIVER_RXLOS_ATTR_ID(46), + TRANSCEIVER_RXLOS_ATTR_ID(47), + TRANSCEIVER_RXLOS_ATTR_ID(48), + TRANSCEIVER_TXFAULT_ATTR_ID(1), + TRANSCEIVER_TXFAULT_ATTR_ID(2), + TRANSCEIVER_TXFAULT_ATTR_ID(3), + TRANSCEIVER_TXFAULT_ATTR_ID(4), + TRANSCEIVER_TXFAULT_ATTR_ID(5), + TRANSCEIVER_TXFAULT_ATTR_ID(6), + TRANSCEIVER_TXFAULT_ATTR_ID(7), + TRANSCEIVER_TXFAULT_ATTR_ID(8), + TRANSCEIVER_TXFAULT_ATTR_ID(9), + TRANSCEIVER_TXFAULT_ATTR_ID(10), + TRANSCEIVER_TXFAULT_ATTR_ID(11), + TRANSCEIVER_TXFAULT_ATTR_ID(12), + TRANSCEIVER_TXFAULT_ATTR_ID(13), + TRANSCEIVER_TXFAULT_ATTR_ID(14), + TRANSCEIVER_TXFAULT_ATTR_ID(15), + TRANSCEIVER_TXFAULT_ATTR_ID(16), + TRANSCEIVER_TXFAULT_ATTR_ID(17), + TRANSCEIVER_TXFAULT_ATTR_ID(18), + TRANSCEIVER_TXFAULT_ATTR_ID(19), + TRANSCEIVER_TXFAULT_ATTR_ID(20), + TRANSCEIVER_TXFAULT_ATTR_ID(21), + TRANSCEIVER_TXFAULT_ATTR_ID(22), + TRANSCEIVER_TXFAULT_ATTR_ID(23), + TRANSCEIVER_TXFAULT_ATTR_ID(24), + TRANSCEIVER_TXFAULT_ATTR_ID(25), + TRANSCEIVER_TXFAULT_ATTR_ID(26), + TRANSCEIVER_TXFAULT_ATTR_ID(27), + TRANSCEIVER_TXFAULT_ATTR_ID(28), + TRANSCEIVER_TXFAULT_ATTR_ID(29), + TRANSCEIVER_TXFAULT_ATTR_ID(30), + TRANSCEIVER_TXFAULT_ATTR_ID(31), + TRANSCEIVER_TXFAULT_ATTR_ID(32), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(35), + TRANSCEIVER_TXFAULT_ATTR_ID(36), + TRANSCEIVER_TXFAULT_ATTR_ID(37), + TRANSCEIVER_TXFAULT_ATTR_ID(38), + TRANSCEIVER_TXFAULT_ATTR_ID(39), + TRANSCEIVER_TXFAULT_ATTR_ID(40), + TRANSCEIVER_TXFAULT_ATTR_ID(41), + TRANSCEIVER_TXFAULT_ATTR_ID(42), + TRANSCEIVER_TXFAULT_ATTR_ID(43), + TRANSCEIVER_TXFAULT_ATTR_ID(44), + TRANSCEIVER_TXFAULT_ATTR_ID(45), + TRANSCEIVER_TXFAULT_ATTR_ID(46), + TRANSCEIVER_TXFAULT_ATTR_ID(47), + TRANSCEIVER_TXFAULT_ATTR_ID(48), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_tx_disable(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); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as5512_54x_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as5512_54x_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_TXFAULT_##index) +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, MODULE_RXLOS_ALL); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(35); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(36); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(37); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(38); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(39); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(40); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(41); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(42); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(43); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(44); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(45); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(46); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(47); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(48); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(54); + +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(35); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(36); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(37); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(38); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(39); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(40); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(41); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(42); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(43); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(44); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(45); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(46); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(47); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(48); + +static struct attribute *as5512_54x_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as5512_54x_cpld1_group = { + .attrs = as5512_54x_cpld1_attributes, +}; + +static struct attribute *as5512_54x_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_SFP_TRANSCEIVER_ATTR(1), + DECLARE_SFP_TRANSCEIVER_ATTR(2), + DECLARE_SFP_TRANSCEIVER_ATTR(3), + DECLARE_SFP_TRANSCEIVER_ATTR(4), + DECLARE_SFP_TRANSCEIVER_ATTR(5), + DECLARE_SFP_TRANSCEIVER_ATTR(6), + DECLARE_SFP_TRANSCEIVER_ATTR(7), + DECLARE_SFP_TRANSCEIVER_ATTR(8), + DECLARE_SFP_TRANSCEIVER_ATTR(9), + DECLARE_SFP_TRANSCEIVER_ATTR(10), + DECLARE_SFP_TRANSCEIVER_ATTR(11), + DECLARE_SFP_TRANSCEIVER_ATTR(12), + DECLARE_SFP_TRANSCEIVER_ATTR(13), + DECLARE_SFP_TRANSCEIVER_ATTR(14), + DECLARE_SFP_TRANSCEIVER_ATTR(15), + DECLARE_SFP_TRANSCEIVER_ATTR(16), + DECLARE_SFP_TRANSCEIVER_ATTR(17), + DECLARE_SFP_TRANSCEIVER_ATTR(18), + DECLARE_SFP_TRANSCEIVER_ATTR(19), + DECLARE_SFP_TRANSCEIVER_ATTR(20), + DECLARE_SFP_TRANSCEIVER_ATTR(21), + DECLARE_SFP_TRANSCEIVER_ATTR(22), + DECLARE_SFP_TRANSCEIVER_ATTR(23), + DECLARE_SFP_TRANSCEIVER_ATTR(24), + NULL +}; + +static const struct attribute_group as5512_54x_cpld2_group = { + .attrs = as5512_54x_cpld2_attributes, +}; + +static struct attribute *as5512_54x_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_TRANSCEIVER_PRESENT_ATTR(35), + DECLARE_TRANSCEIVER_PRESENT_ATTR(36), + DECLARE_TRANSCEIVER_PRESENT_ATTR(37), + DECLARE_TRANSCEIVER_PRESENT_ATTR(38), + DECLARE_TRANSCEIVER_PRESENT_ATTR(39), + DECLARE_TRANSCEIVER_PRESENT_ATTR(40), + DECLARE_TRANSCEIVER_PRESENT_ATTR(41), + DECLARE_TRANSCEIVER_PRESENT_ATTR(42), + DECLARE_TRANSCEIVER_PRESENT_ATTR(43), + DECLARE_TRANSCEIVER_PRESENT_ATTR(44), + DECLARE_TRANSCEIVER_PRESENT_ATTR(45), + DECLARE_TRANSCEIVER_PRESENT_ATTR(46), + DECLARE_TRANSCEIVER_PRESENT_ATTR(47), + DECLARE_TRANSCEIVER_PRESENT_ATTR(48), + DECLARE_TRANSCEIVER_PRESENT_ATTR(49), + DECLARE_TRANSCEIVER_PRESENT_ATTR(50), + DECLARE_TRANSCEIVER_PRESENT_ATTR(51), + DECLARE_TRANSCEIVER_PRESENT_ATTR(52), + DECLARE_TRANSCEIVER_PRESENT_ATTR(53), + DECLARE_TRANSCEIVER_PRESENT_ATTR(54), + DECLARE_SFP_TRANSCEIVER_ATTR(25), + DECLARE_SFP_TRANSCEIVER_ATTR(26), + DECLARE_SFP_TRANSCEIVER_ATTR(27), + DECLARE_SFP_TRANSCEIVER_ATTR(28), + DECLARE_SFP_TRANSCEIVER_ATTR(29), + DECLARE_SFP_TRANSCEIVER_ATTR(30), + DECLARE_SFP_TRANSCEIVER_ATTR(31), + DECLARE_SFP_TRANSCEIVER_ATTR(32), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(35), + DECLARE_SFP_TRANSCEIVER_ATTR(36), + DECLARE_SFP_TRANSCEIVER_ATTR(37), + DECLARE_SFP_TRANSCEIVER_ATTR(38), + DECLARE_SFP_TRANSCEIVER_ATTR(39), + DECLARE_SFP_TRANSCEIVER_ATTR(40), + DECLARE_SFP_TRANSCEIVER_ATTR(41), + DECLARE_SFP_TRANSCEIVER_ATTR(42), + DECLARE_SFP_TRANSCEIVER_ATTR(43), + DECLARE_SFP_TRANSCEIVER_ATTR(44), + DECLARE_SFP_TRANSCEIVER_ATTR(45), + DECLARE_SFP_TRANSCEIVER_ATTR(46), + DECLARE_SFP_TRANSCEIVER_ATTR(47), + DECLARE_SFP_TRANSCEIVER_ATTR(48), + NULL +}; + +static const struct attribute_group as5512_54x_cpld3_group = { + .attrs = as5512_54x_cpld3_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status, num_regs = 0; + u8 values[4] = {0}; + u8 regs[] = {0x6, 0x7, 0x8, 0x14}; + struct i2c_client *client = to_i2c_client(dev); + struct as5512_54x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + num_regs = (data->type == as5512_54x_cpld2) ? 3 : 4; + + for (i = 0; i < num_regs; i++) { + status = as5512_54x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 54 in order */ + if (data->type == as5512_54x_cpld2) { + status = sprintf(buf, "%.2x %.2x %.2x\n", + values[0], values[1], values[2]); + } + else { /* as5512_54x_cpld3 */ + values[3] &= 0x3F; + status = sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3]); + } + + return status; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[3] = {0}; + u8 regs[] = {0xF, 0x10, 0x11}; + struct i2c_client *client = to_i2c_client(dev); + struct as5512_54x_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as5512_54x_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = (u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 24 in order */ + return sprintf(buf, "%.2x %.2x %.2x\n", values[0], values[1], values[2]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as5512_54x_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x6; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x7; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0x8; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x6; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_PRESENT_33 ... MODULE_PRESENT_40: + reg = 0x7; + mask = 0x1 << (attr->index - MODULE_PRESENT_33); + break; + case MODULE_PRESENT_41 ... MODULE_PRESENT_48: + reg = 0x8; + mask = 0x1 << (attr->index - MODULE_PRESENT_41); + break; + case MODULE_PRESENT_49 ... MODULE_PRESENT_54: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_PRESENT_49); + break; + case MODULE_TXFAULT_1 ... MODULE_TXFAULT_8: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_TXFAULT_1); + break; + case MODULE_TXFAULT_9 ... MODULE_TXFAULT_16: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_TXFAULT_9); + break; + case MODULE_TXFAULT_17 ... MODULE_TXFAULT_24: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_TXFAULT_17); + break; + case MODULE_TXFAULT_25 ... MODULE_TXFAULT_32: + reg = 0x9; + mask = 0x1 << (attr->index - MODULE_TXFAULT_25); + break; + case MODULE_TXFAULT_33 ... MODULE_TXFAULT_40: + reg = 0xA; + mask = 0x1 << (attr->index - MODULE_TXFAULT_33); + break; + case MODULE_TXFAULT_41 ... MODULE_TXFAULT_48: + reg = 0xB; + mask = 0x1 << (attr->index - MODULE_TXFAULT_41); + break; + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + case MODULE_RXLOS_1 ... MODULE_RXLOS_8: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_RXLOS_1); + break; + case MODULE_RXLOS_9 ... MODULE_RXLOS_16: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_RXLOS_9); + break; + case MODULE_RXLOS_17 ... MODULE_RXLOS_24: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_RXLOS_17); + break; + case MODULE_RXLOS_25 ... MODULE_RXLOS_32: + reg = 0xF; + mask = 0x1 << (attr->index - MODULE_RXLOS_25); + break; + case MODULE_RXLOS_33 ... MODULE_RXLOS_40: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_RXLOS_33); + break; + case MODULE_RXLOS_41 ... MODULE_RXLOS_48: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_RXLOS_41); + break; + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_54) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as5512_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_tx_disable(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 as5512_54x_cpld_data *data = i2c_get_clientdata(client); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0xC; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0xD; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0xE; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as5512_54x_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as5512_54x_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +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 as5512_54x_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 = as5512_54x_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 as5512_54x_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 as5512_54x_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 ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as5512_54x_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as5512_54x_cpld_data *data; + int ret = -ENODEV; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as5512_54x_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + /* Register sysfs hooks */ + switch (data->type) { + case as5512_54x_cpld1: + group = &as5512_54x_cpld1_group; + break; + case as5512_54x_cpld2: + group = &as5512_54x_cpld2_group; + break; + case as5512_54x_cpld3: + group = &as5512_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as5512_54x_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as5512_54x_cpld_remove(struct i2c_client *client) +{ + struct as5512_54x_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as5512_54x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as5512_54x_cpld1: + group = &as5512_54x_cpld1_group; + break; + case as5512_54x_cpld2: + group = &as5512_54x_cpld2_group; + break; + case as5512_54x_cpld3: + group = &as5512_54x_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as5512_54x_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; +} + +static int as5512_54x_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; +} + +int as5512_54x_cpld_read(unsigned short 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 = as5512_54x_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5512_54x_cpld_read); + +int as5512_54x_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 = as5512_54x_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5512_54x_cpld_write); + +static struct i2c_driver as5512_54x_cpld_driver = { + .driver = { + .name = "as5512_54x_cpld", + .owner = THIS_MODULE, + }, + .probe = as5512_54x_cpld_probe, + .remove = as5512_54x_cpld_remove, + .id_table = as5512_54x_cpld_id, +}; + +static int __init as5512_54x_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as5512_54x_cpld_driver); +} + +static void __exit as5512_54x_cpld_exit(void) +{ + i2c_del_driver(&as5512_54x_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as5512_54x_cpld_init); +module_exit(as5512_54x_cpld_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-fan.c b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-fan.c index 67e3dd66..9f2bbf59 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-fan.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-fan.c @@ -131,8 +131,8 @@ static ssize_t fan_set_duty_cycle(struct device *dev, static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf); -extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); -extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +extern int as5512_54x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5512_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); /*******************/ @@ -269,12 +269,12 @@ static const struct attribute_group accton_as5512_54x_fan_group = { static int accton_as5512_54x_fan_read_value(u8 reg) { - return accton_i2c_cpld_read(0x60, reg); + return as5512_54x_cpld_read(0x60, reg); } static int accton_as5512_54x_fan_write_value(u8 reg, u8 value) { - return accton_i2c_cpld_write(0x60, reg, value); + return as5512_54x_cpld_write(0x60, reg, value); } static void accton_as5512_54x_fan_update_device(struct device *dev) @@ -405,11 +405,6 @@ static int __init accton_as5512_54x_fan_init(void) { int ret; - extern int platform_accton_as5512_54x(void); - if(!platform_accton_as5512_54x()) { - return -ENODEV; - } - ret = platform_driver_register(&accton_as5512_54x_fan_driver); if (ret < 0) { goto exit; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-leds.c b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-leds.c index 43160557..02eb3d7e 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-leds.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-leds.c @@ -29,8 +29,8 @@ #include #include -extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); -extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +extern int as5512_54x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5512_54x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); #define DRVNAME "as5512_54x_led" @@ -168,12 +168,12 @@ static u8 led_light_mode_to_reg_val(enum led_type type, static int accton_as5512_54x_led_read_value(u8 reg) { - return accton_i2c_cpld_read(0x60, reg); + return as5512_54x_cpld_read(0x60, reg); } static int accton_as5512_54x_led_write_value(u8 reg, u8 value) { - return accton_i2c_cpld_write(0x60, reg, value); + return as5512_54x_cpld_write(0x60, reg, value); } static void accton_as5512_54x_led_update(void) @@ -411,11 +411,6 @@ static int __init accton_as5512_54x_led_init(void) { int ret; - extern int platform_accton_as5512_54x(void); - if(!platform_accton_as5512_54x()) { - return -ENODEV; - } - ret = platform_driver_register(&accton_as5512_54x_led_driver); if (ret < 0) { goto exit; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-psu.c b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-psu.c index 66d61f3c..fb5e02ca 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-psu.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-psu.c @@ -36,7 +36,7 @@ static ssize_t show_index(struct device *dev, struct device_attribute *da, char static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); static int as5512_54x_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); -extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5512_54x_cpld_read(unsigned short cpld_addr, u8 reg); /* Addresses scanned */ @@ -253,7 +253,7 @@ static struct as5512_54x_psu_data *as5512_54x_psu_update_device(struct device *d } /* Read psu status */ - status = accton_i2c_cpld_read(0x60, 0x2); + status = as5512_54x_cpld_read(0x60, 0x2); if (status < 0) { dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); @@ -271,25 +271,9 @@ static struct as5512_54x_psu_data *as5512_54x_psu_update_device(struct device *d return data; } -static int __init as5512_54x_psu_init(void) -{ - extern int platform_accton_as5512_54x(void); - if(!platform_accton_as5512_54x()) { - return -ENODEV; - } - - return i2c_add_driver(&as5512_54x_psu_driver); -} - -static void __exit as5512_54x_psu_exit(void) -{ - i2c_del_driver(&as5512_54x_psu_driver); -} +module_i2c_driver(as5512_54x_psu_driver); MODULE_AUTHOR("Brandon Chuang "); MODULE_DESCRIPTION("accton as5512_54x_psu driver"); MODULE_LICENSE("GPL"); -module_init(as5512_54x_psu_init); -module_exit(as5512_54x_psu_exit); - diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-sfp.c b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-sfp.c deleted file mode 100644 index d89e71d0..00000000 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/modules/builds/x86-64-accton-as5512-54x-sfp.c +++ /dev/null @@ -1,1237 +0,0 @@ -/* - * SFP driver for accton as5512_54x sfp - * - * Copyright (C) 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 - -#define DRIVER_NAME "as5512_54x_sfp" - -#define DEBUG_MODE 0 - -#if (DEBUG_MODE == 1) - #define DEBUG_PRINT(fmt, args...) \ - printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) -#else - #define DEBUG_PRINT(fmt, args...) -#endif - -#define NUM_OF_SFP_PORT 54 -#define EEPROM_NAME "sfp_eeprom" -#define EEPROM_SIZE 256 /* 256 byte eeprom */ -#define BIT_INDEX(i) (1ULL << (i)) -#define USE_I2C_BLOCK_READ 1 -#define I2C_RW_RETRY_COUNT 3 -#define I2C_RW_RETRY_INTERVAL 100 /* ms */ - -#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) -#define SFP_EEPROM_A2_I2C_ADDR (0xA2 >> 1) - -#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 -#define SFF8024_DEVICE_ID_SFP 0x3 -#define SFF8024_DEVICE_ID_QSFP 0xC -#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD -#define SFF8024_DEVICE_ID_QSFP28 0x11 - -#define SFF8472_DIAG_MON_TYPE_ADDR 92 -#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 -#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 -#define SFF8472_10G_BASE_MASK 0xF0 - -#define SFF8436_RX_LOS_ADDR 3 -#define SFF8436_TX_FAULT_ADDR 4 -#define SFF8436_TX_DISABLE_ADDR 86 - -static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); -static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); -extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); -extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); - -/* Addresses scanned - */ -static const unsigned short normal_i2c[] = { SFP_EEPROM_A0_I2C_ADDR, SFP_EEPROM_A2_I2C_ADDR, I2C_CLIENT_END }; - -#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) - -enum port_numbers { -sfp1, sfp2, sfp3, sfp4, sfp5, sfp6, sfp7, sfp8, -sfp9, sfp10, sfp11, sfp12, sfp13, sfp14, sfp15, sfp16, -sfp17, sfp18, sfp19, sfp20, sfp21, sfp22, sfp23, sfp24, -sfp25, sfp26, sfp27, sfp28, sfp29, sfp30, sfp31, sfp32, -sfp33, sfp34, sfp35, sfp36, sfp37, sfp38, sfp39, sfp40, -sfp41, sfp42, sfp43, sfp44, sfp45, sfp46, sfp47, sfp48, -sfp49, sfp50, sfp51, sfp52, sfp53, sfp54 -}; - -static const struct i2c_device_id sfp_device_id[] = { -{ "sfp1", sfp1 }, { "sfp2", sfp2 }, { "sfp3", sfp3 }, { "sfp4", sfp4 }, -{ "sfp5", sfp5 }, { "sfp6", sfp6 }, { "sfp7", sfp7 }, { "sfp8", sfp8 }, -{ "sfp9", sfp9 }, { "sfp10", sfp10 }, { "sfp11", sfp11 }, { "sfp12", sfp12 }, -{ "sfp13", sfp13 }, { "sfp14", sfp14 }, { "sfp15", sfp15 }, { "sfp16", sfp16 }, -{ "sfp17", sfp17 }, { "sfp18", sfp18 }, { "sfp19", sfp19 }, { "sfp20", sfp20 }, -{ "sfp21", sfp21 }, { "sfp22", sfp22 }, { "sfp23", sfp23 }, { "sfp24", sfp24 }, -{ "sfp25", sfp25 }, { "sfp26", sfp26 }, { "sfp27", sfp27 }, { "sfp28", sfp28 }, -{ "sfp29", sfp29 }, { "sfp30", sfp30 }, { "sfp31", sfp31 }, { "sfp32", sfp32 }, -{ "sfp33", sfp33 }, { "sfp34", sfp34 }, { "sfp35", sfp35 }, { "sfp36", sfp36 }, -{ "sfp37", sfp37 }, { "sfp38", sfp38 }, { "sfp39", sfp39 }, { "sfp40", sfp40 }, -{ "sfp41", sfp41 }, { "sfp42", sfp42 }, { "sfp43", sfp43 }, { "sfp44", sfp44 }, -{ "sfp45", sfp45 }, { "sfp46", sfp46 }, { "sfp47", sfp47 }, { "sfp48", sfp48 }, -{ "sfp49", sfp49 }, { "sfp50", sfp50 }, { "sfp51", sfp51 }, { "sfp52", sfp52 }, -{ "sfp53", sfp53 }, { "sfp54", sfp54 }, -{ /* LIST END */ } -}; -MODULE_DEVICE_TABLE(i2c, sfp_device_id); - -/* - * list of valid port types - * note OOM_PORT_TYPE_NOT_PRESENT to indicate no - * module is present in this port - */ -typedef enum oom_driver_port_type_e { - OOM_DRIVER_PORT_TYPE_INVALID, - OOM_DRIVER_PORT_TYPE_NOT_PRESENT, - OOM_DRIVER_PORT_TYPE_SFP, - OOM_DRIVER_PORT_TYPE_SFP_PLUS, - OOM_DRIVER_PORT_TYPE_QSFP, - OOM_DRIVER_PORT_TYPE_QSFP_PLUS, - OOM_DRIVER_PORT_TYPE_QSFP28 -} oom_driver_port_type_t; - -enum driver_type_e { - DRIVER_TYPE_SFP_MSA, - DRIVER_TYPE_SFP_DDM, - DRIVER_TYPE_QSFP -}; - -/* Each client has this additional data - */ -struct eeprom_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - struct bin_attribute bin; /* eeprom data */ -}; - -struct sfp_msa_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u64 status[6]; /* bit0:port0, bit1:port1 and so on */ - /* index 0 => tx_fail - 1 => tx_disable - 2 => rx_loss - 3 => device id - 4 => 10G Ethernet Compliance Codes - to distinguish SFP or SFP+ - 5 => DIAGNOSTIC MONITORING TYPE */ - struct eeprom_data eeprom; -}; - -struct sfp_ddm_data { - struct eeprom_data eeprom; -}; - -struct qsfp_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u8 status[3]; /* bit0:port0, bit1:port1 and so on */ - /* index 0 => tx_fail - 1 => tx_disable - 2 => rx_loss */ - - u8 device_id; - struct eeprom_data eeprom; -}; - -struct sfp_port_data { - struct mutex update_lock; - enum driver_type_e driver_type; - int port; /* CPLD port index */ - oom_driver_port_type_t port_type; - u64 present; /* present status, bit0:port0, bit1:port1 and so on */ - - struct sfp_msa_data *msa; - struct sfp_ddm_data *ddm; - struct qsfp_data *qsfp; - - struct i2c_client *client; -}; - -enum sfp_sysfs_attributes { - PRESENT, - PRESENT_ALL, - PORT_NUMBER, - PORT_TYPE, - DDM_IMPLEMENTED, - TX_FAULT, - TX_FAULT1, - TX_FAULT2, - TX_FAULT3, - TX_FAULT4, - TX_DISABLE, - TX_DISABLE1, - TX_DISABLE2, - TX_DISABLE3, - TX_DISABLE4, - RX_LOS, - RX_LOS1, - RX_LOS2, - RX_LOS3, - RX_LOS4, - RX_LOS_ALL -}; - -static ssize_t show_port_number(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); -} - -static struct sfp_port_data* sfp_update_present(struct i2c_client *client) -{ - int i = 0, j = 0, status = -1; - u8 reg; - unsigned short cpld_addr; - struct sfp_port_data *data = i2c_get_clientdata(client); - - DEBUG_PRINT("Starting sfp present status update"); - mutex_lock(&data->update_lock); - data->present = 0; - - /* Read present status of port 1~48(SFP port) */ - for (i = 0; i < 2; i++) { - for (j = 0; j < 3; j++) { - cpld_addr = 0x61+i; - reg = 0x6+j; - status = accton_i2c_cpld_read(cpld_addr, reg); - - if (unlikely(status < 0)) { - data = ERR_PTR(status); - dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); - goto exit; - } - - DEBUG_PRINT("Present status = 0x%lx\r\n", data->present); - data->present |= (u64)status << ((i*24) + (j%3)*8); - } - } - - /* Read present status of port 49-54(QSFP port) */ - cpld_addr = 0x62; - reg = 0x14; - status = accton_i2c_cpld_read(cpld_addr, reg); - - if (unlikely(status < 0)) { - data = ERR_PTR(status); - dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); - goto exit; - } - else { - data->present |= (u64)status << 48; - } - - DEBUG_PRINT("Present status = 0x%lx", data->present); -exit: - mutex_unlock(&data->update_lock); - return data; -} - -static struct sfp_port_data* sfp_update_tx_rx_status(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - int i = 0, j = 0; - int status = -1; - - if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { - return data; - } - - DEBUG_PRINT("Starting as5512_54x sfp tx rx status update"); - mutex_lock(&data->update_lock); - data->msa->valid = 0; - memset(data->msa->status, 0, sizeof(data->msa->status)); - - /* Read status of port 1~48(SFP port) */ - for (i = 0; i < 2; i++) { - for (j = 0; j < 9; j++) { - u8 reg; - unsigned short cpld_addr; - reg = 0x9+j; - cpld_addr = 0x61+i; - - status = accton_i2c_cpld_read(cpld_addr, reg); - if (unlikely(status < 0)) { - data = ERR_PTR(status); - dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); - goto exit; - } - - data->msa->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); - } - } - - data->msa->valid = 1; - data->msa->last_updated = jiffies; - -exit: - mutex_unlock(&data->update_lock); - return data; -} - -static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - unsigned short cpld_addr = 0; - u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0; - long disable; - int error; - - error = kstrtol(buf, 10, &disable); - if (error) { - return error; - } - - mutex_lock(&data->update_lock); - - if(data->port < 24) { - cpld_addr = 0x61; - cpld_reg = 0xC + data->port / 8; - cpld_bit = 1 << (data->port % 8); - } - else { /* port 24 ~ 48 */ - cpld_addr = 0x62; - cpld_reg = 0xC + (data->port - 24) / 8; - cpld_bit = 1 << (data->port % 8); - } - - /* Read current status */ - cpld_val = accton_i2c_cpld_read(cpld_addr, cpld_reg); - - /* Update tx_disable status */ - if (disable) { - data->msa->status[1] |= BIT_INDEX(data->port); - cpld_val |= cpld_bit; - } - else { - data->msa->status[1] &= ~BIT_INDEX(data->port); - cpld_val &= ~cpld_bit; - } - - accton_i2c_cpld_write(cpld_addr, cpld_reg, cpld_val); - mutex_unlock(&data->update_lock); - return count; -} - -static int sfp_is_port_present(struct i2c_client *client, int port) -{ - struct sfp_port_data *data = i2c_get_clientdata(client); - - data = sfp_update_present(client); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - return (data->present & BIT_INDEX(data->port)) ? 0 : 1; -} - -static ssize_t show_present(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - - if (PRESENT_ALL == attr->index) { - int i; - u8 values[7] = {0}; - struct sfp_port_data *data = sfp_update_present(client); - - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - for (i = 0; i < ARRAY_SIZE(values); i++) { - values[i] = ~(u8)(data->present >> (i * 8)); - } - - /* Return values 1 -> 54 in order */ - return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", - values[0], values[1], values[2], - values[3], values[4], values[5], - values[6] & 0x3F); - } - else { - struct sfp_port_data *data = i2c_get_clientdata(client); - int present = sfp_is_port_present(client, data->port); - - if (IS_ERR_VALUE(present)) { - return present; - } - - /* PRESENT */ - return sprintf(buf, "%d\n", present); - } -} - -static struct sfp_port_data *sfp_update_port_type(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - u8 buf = 0; - int status; - - mutex_lock(&data->update_lock); - - switch (data->driver_type) { - case DRIVER_TYPE_SFP_MSA: - { - status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); - if (unlikely(status < 0)) { - data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; - break; - } - - if (buf != SFF8024_DEVICE_ID_SFP) { - data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; - break; - } - - status = sfp_eeprom_read(client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); - if (unlikely(status < 0)) { - data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; - break; - } - - DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); - data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; - break; - } - case DRIVER_TYPE_QSFP: - { - status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); - if (unlikely(status < 0)) { - data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; - break; - } - - DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); - switch (buf) { - case SFF8024_DEVICE_ID_QSFP: - data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; - break; - case SFF8024_DEVICE_ID_QSFP_PLUS: - data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; - break; - case SFF8024_DEVICE_ID_QSFP28: - data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; - break; - default: - data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; - break; - } - - break; - } - default: - break; - } - - mutex_unlock(&data->update_lock); - return data; -} - -static ssize_t show_port_type(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - int present = sfp_is_port_present(client, data->port); - - if (IS_ERR_VALUE(present)) { - return present; - } - - if (!present) { - return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); - } - - sfp_update_port_type(dev); - return sprintf(buf, "%d\n", data->port_type); -} - -static struct sfp_port_data* qsfp_update_tx_rx_status(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - int i, status = -1; - u8 buf = 0; - u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; - - if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { - return data; - } - - DEBUG_PRINT("Starting sfp tx rx status update"); - mutex_lock(&data->update_lock); - data->qsfp->valid = 0; - memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); - - /* Notify device to update tx fault/ tx disable/ rx los status */ - for (i = 0; i < ARRAY_SIZE(reg); i++) { - status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); - if (unlikely(status < 0)) { - data = ERR_PTR(status); - goto exit; - } - } - msleep(200); - - /* Read actual tx fault/ tx disable/ rx los status */ - for (i = 0; i < ARRAY_SIZE(reg); i++) { - status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); - if (unlikely(status < 0)) { - data = ERR_PTR(status); - goto exit; - } - - DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); - data->qsfp->status[i] = (buf & 0xF); - } - - data->qsfp->valid = 1; - data->qsfp->last_updated = jiffies; - -exit: - mutex_unlock(&data->update_lock); - return data; -} - -static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, - char *buf) -{ - int status; - u8 val = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - - status = sfp_is_port_present(client, data->port); - if (IS_ERR_VALUE(status)) { - return status; - } - - data = qsfp_update_tx_rx_status(dev); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - switch (attr->index) { - case TX_FAULT1: - case TX_FAULT2: - case TX_FAULT3: - case TX_FAULT4: - val = (data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)) ? 1 : 0; - break; - case TX_DISABLE1: - case TX_DISABLE2: - case TX_DISABLE3: - case TX_DISABLE4: - val = (data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)) ? 1 : 0; - break; - case RX_LOS1: - case RX_LOS2: - case RX_LOS3: - case RX_LOS4: - val = (data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)) ? 1 : 0; - break; - default: - break; - } - - return sprintf(buf, "%d\n", val); -} - -static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - long disable; - int status; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct sfp_port_data *data = NULL; - - status = kstrtol(buf, 10, &disable); - if (status) { - return status; - } - - data = qsfp_update_tx_rx_status(dev); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - mutex_lock(&data->update_lock); - - if (disable) { - data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); - } - else { - data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); - } - - DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); - status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); - if (unlikely(status < 0)) { - count = status; - } - - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, - char *buf) -{ - int status; - char ddm; - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - - status = sfp_is_port_present(client, data->port); - if (IS_ERR_VALUE(status)) { - return status; - } - - status = sfp_eeprom_read(client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); - if (unlikely(status < 0)) { - return status; - } - - return sprintf(buf, "%d\n", (ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK) ? 1 : 0); -} - -static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, - char *buf) -{ - u8 val = 0, index = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct sfp_port_data *data = sfp_update_tx_rx_status(dev); - - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - if(attr->index == RX_LOS_ALL) { - int i = 0; - u8 values[6] = {0}; - - for (i = 0; i < ARRAY_SIZE(values); i++) { - values[i] = (u8)(data->msa->status[2] >> (i * 8)); - } - - /** Return values 1 -> 48 in order */ - return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", - values[0], values[1], values[2], - values[3], values[4], values[5]); - } - - switch (attr->index) { - case TX_FAULT: - index = 0; - break; - case TX_DISABLE: - index = 1; - break; - case RX_LOS: - index = 2; - break; - default: - break; - } - - val = (data->msa->status[index] & BIT_INDEX(data->port)) ? 1 : 0; - return sprintf(buf, "%d\n", val); -} - -/* SFP/QSFP common attributes for sysfs */ -static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); -static SENSOR_DEVICE_ATTR(sfp_port_type, S_IRUGO, show_port_type, NULL, PORT_TYPE); -static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); -static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); - -/* QSFP attributes for sysfs */ -static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); -static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); -static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); -static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); -static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); -static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); -static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); -static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); -static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); -static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); -static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); -static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); -static struct attribute *qsfp_attributes[] = { - &sensor_dev_attr_sfp_port_number.dev_attr.attr, - &sensor_dev_attr_sfp_port_type.dev_attr.attr, - &sensor_dev_attr_sfp_is_present.dev_attr.attr, - &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, - NULL -}; - -/* SFP msa attributes for sysfs */ -static SENSOR_DEVICE_ATTR(sfp_ddm_implemented, S_IRUGO, sfp_show_ddm_implemented, NULL, DDM_IMPLEMENTED); -static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS); -static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS_ALL); -static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, TX_DISABLE); -static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, TX_FAULT); -static struct attribute *sfp_msa_attributes[] = { - &sensor_dev_attr_sfp_port_number.dev_attr.attr, - &sensor_dev_attr_sfp_port_type.dev_attr.attr, - &sensor_dev_attr_sfp_is_present.dev_attr.attr, - &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, - &sensor_dev_attr_sfp_ddm_implemented.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, - NULL -}; - -/* SFP ddm attributes for sysfs */ -static struct attribute *sfp_ddm_attributes[] = { - NULL -}; - -static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, - int data_len) -{ -#if USE_I2C_BLOCK_READ - int status, retry = I2C_RW_RETRY_COUNT; - - if (data_len > I2C_SMBUS_BLOCK_MAX) { - data_len = I2C_SMBUS_BLOCK_MAX; - } - - while (retry) { - status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - return status; - } - - return data_len; -#else - int status, retry = I2C_RW_RETRY_COUNT; - - while (retry) { - status = i2c_smbus_write_byte_data(client, command, *data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - return status; - } - - return 1; -#endif - - -} - -static ssize_t sfp_port_write(struct sfp_port_data *data, - const char *buf, loff_t off, size_t count) -{ - ssize_t retval = 0; - - if (unlikely(!count)) { - return count; - } - - /* - * Write data to chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&data->update_lock); - - while (count) { - ssize_t status; - - status = sfp_eeprom_write(data->client, off, buf, count); - if (status <= 0) { - if (retval == 0) { - retval = status; - } - break; - } - buf += status; - off += status; - count -= status; - retval += status; - } - - mutex_unlock(&data->update_lock); - return retval; -} - - -static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - struct sfp_port_data *data; - DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); - data = dev_get_drvdata(container_of(kobj, struct device, kobj)); - return sfp_port_write(data, buf, off, count); -} - -static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, - int data_len) -{ -#if USE_I2C_BLOCK_READ - int status, retry = I2C_RW_RETRY_COUNT; - - if (data_len > I2C_SMBUS_BLOCK_MAX) { - data_len = I2C_SMBUS_BLOCK_MAX; - } - - while (retry) { - status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - goto abort; - } - if (unlikely(status != data_len)) { - status = -EIO; - goto abort; - } - - //result = data_len; - -abort: - return status; -#else - int status, retry = I2C_RW_RETRY_COUNT; - - while (retry) { - status = i2c_smbus_read_byte_data(client, command); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, result); - goto abort; - } - - *data = (u8)status; - status = 1; - -abort: - return status; -#endif -} - -static ssize_t sfp_port_read(struct sfp_port_data *data, - char *buf, loff_t off, size_t count) -{ - ssize_t retval = 0; - - if (unlikely(!count)) { - DEBUG_PRINT("Count = 0, return"); - return count; - } - - /* - * Read data from chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&data->update_lock); - - while (count) { - ssize_t status; - - status = sfp_eeprom_read(data->client, off, buf, count); - if (status <= 0) { - if (retval == 0) { - retval = status; - } - break; - } - - buf += status; - off += status; - count -= status; - retval += status; - } - - mutex_unlock(&data->update_lock); - return retval; - -} - -static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - struct sfp_port_data *data; - DEBUG_PRINT("offset = (%d), count = (%d)", off, count); - data = dev_get_drvdata(container_of(kobj, struct device, kobj)); - return sfp_port_read(data, buf, off, count); -} - -static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) -{ - int err; - - sysfs_bin_attr_init(eeprom); - eeprom->attr.name = EEPROM_NAME; - eeprom->attr.mode = S_IWUSR | S_IRUGO; - eeprom->read = sfp_bin_read; - eeprom->write = sfp_bin_write; - eeprom->size = EEPROM_SIZE; - - /* Create eeprom file */ - err = sysfs_create_bin_file(kobj, eeprom); - if (err) { - return err; - } - - return 0; -} - -static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) -{ - sysfs_remove_bin_file(kobj, eeprom); - return 0; -} - -static const struct attribute_group sfp_msa_group = { - .attrs = sfp_msa_attributes, -}; - -static int sfp_i2c_check_functionality(struct i2c_client *client) -{ -#if USE_I2C_BLOCK_READ - return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); -#else - return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); -#endif -} - -static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, - struct sfp_msa_data **data) -{ - int status; - struct sfp_msa_data *msa; - - if (!sfp_i2c_check_functionality(client)) { - status = -EIO; - goto exit; - } - - msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); - if (!msa) { - status = -ENOMEM; - goto exit; - } - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); - if (status) { - goto exit_free; - } - - /* init eeprom */ - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); - if (status) { - goto exit_remove; - } - - *data = msa; - dev_info(&client->dev, "sfp msa '%s'\n", client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); -exit_free: - kfree(msa); -exit: - - return status; -} - -static const struct attribute_group sfp_ddm_group = { - .attrs = sfp_ddm_attributes, -}; - -static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, - struct sfp_ddm_data **data) -{ - int status; - struct sfp_ddm_data *ddm; - - if (!sfp_i2c_check_functionality(client)) { - status = -EIO; - goto exit; - } - - ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); - if (!ddm) { - status = -ENOMEM; - goto exit; - } - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); - if (status) { - goto exit_free; - } - - /* init eeprom */ - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); - if (status) { - goto exit_remove; - } - - *data = ddm; - dev_info(&client->dev, "sfp ddm '%s'\n", client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); -exit_free: - kfree(ddm); -exit: - - return status; -} - -static const struct attribute_group qsfp_group = { - .attrs = qsfp_attributes, -}; - -static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, - struct qsfp_data **data) -{ - int status; - struct qsfp_data *qsfp; - - if (!sfp_i2c_check_functionality(client)) { - status = -EIO; - goto exit; - } - - qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); - if (!qsfp) { - status = -ENOMEM; - goto exit; - } - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &qsfp_group); - if (status) { - goto exit_free; - } - - /* init eeprom */ - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); - if (status) { - goto exit_remove; - } - - /* Bring QSFPs out of reset */ - accton_i2c_cpld_write(0x62, 0x15, 0x3F); - - *data = qsfp; - dev_info(&client->dev, "qsfp '%s'\n", client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &qsfp_group); -exit_free: - kfree(qsfp); -exit: - - return status; -} - -static int sfp_device_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - struct sfp_port_data *data = NULL; - - data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); - if (!data) { - return -ENOMEM; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - data->port = dev_id->driver_data; - data->client = client; - - if (dev_id->driver_data >= sfp1 && dev_id->driver_data <= sfp48) { - if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { - data->driver_type = DRIVER_TYPE_SFP_MSA; - return sfp_msa_probe(client, dev_id, &data->msa); - } - else if (client->addr == SFP_EEPROM_A2_I2C_ADDR) { - data->driver_type = DRIVER_TYPE_SFP_DDM; - return sfp_ddm_probe(client, dev_id, &data->ddm); - } - } - else { /* sfp49 ~ sfp54 */ - if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { - data->driver_type = DRIVER_TYPE_QSFP; - return qsfp_probe(client, dev_id, &data->qsfp); - } - } - - return -ENODEV; -} - -static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) -{ - sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); - sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); - kfree(data); - return 0; -} - -static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) -{ - sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); - sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); - kfree(data); - return 0; -} - -static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) -{ - sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); - sysfs_remove_group(&client->dev.kobj, &qsfp_group); - kfree(data); - return 0; -} - -static int sfp_device_remove(struct i2c_client *client) -{ - struct sfp_port_data *data = i2c_get_clientdata(client); - - switch (data->driver_type) { - case DRIVER_TYPE_SFP_MSA: - return sfp_msa_remove(client, data->msa); - case DRIVER_TYPE_SFP_DDM: - return sfp_ddm_remove(client, data->ddm); - case DRIVER_TYPE_QSFP: - return qfp_remove(client, data->qsfp); - } - - return 0; -} - -static struct i2c_driver sfp_driver = { - .driver = { - .name = DRIVER_NAME, - }, - .probe = sfp_device_probe, - .remove = sfp_device_remove, - .id_table = sfp_device_id, - .address_list = normal_i2c, -}; - -static int __init sfp_init(void) -{ - extern int platform_accton_as5512_54x(void); - if(!platform_accton_as5512_54x()) { - return -ENODEV; - } - - return i2c_add_driver(&sfp_driver); -} - -static void __exit sfp_exit(void) -{ - i2c_del_driver(&sfp_driver); -} - -MODULE_AUTHOR("Brandon Chuang "); -MODULE_DESCRIPTION("accton as5512_54x_sfp driver"); -MODULE_LICENSE("GPL"); - -module_init(sfp_init); -module_exit(sfp_exit); - - diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/onlp/builds/src/module/src/sfpi.c b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/onlp/builds/src/module/src/sfpi.c index 141b8645..f4c59343 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/onlp/builds/src/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/onlp/builds/src/module/src/sfpi.c @@ -24,58 +24,53 @@ * ***********************************************************/ #include - -#include /* For O_RDWR && open */ -#include -#include -#include -#include - -#include "platform_lib.h" - -#define MAX_SFP_PATH 64 -static char sfp_node_path[MAX_SFP_PATH] = {0}; +#include +#include +#include "x86_64_accton_as5512_54x_int.h" +#include "x86_64_accton_as5512_54x_log.h" #define MUX_START_INDEX 2 -#define NUM_OF_SFP_PORT 54 -static const int sfp_mux_index[NUM_OF_SFP_PORT] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, -52, 50, 48, 53, 51, 49 -}; -#define FRONT_PORT_TO_MUX_INDEX(port) (sfp_mux_index[port]+MUX_START_INDEX) +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" +#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/0-00%d/module_present_%d" +#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/0-00%d/module_rx_los_%d" +#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/0-00%d/module_tx_fault_%d" +#define MODULE_TXDISABLE_FORMAT "/sys/bus/i2c/devices/0-00%d/module_tx_disable_%d" +#define MODULE_PRESENT_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/0-0061/module_present_all" +#define MODULE_PRESENT_ALL_ATTR_CPLD3 "/sys/bus/i2c/devices/0-0062/module_present_all" +#define MODULE_RXLOS_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/0-0061/module_rx_los_all" +#define MODULE_RXLOS_ALL_ATTR_CPLD3 "/sys/bus/i2c/devices/0-0062/module_rx_los_all" -static int -sfp_node_read_int(char *node_path, int *value, int data_len) +static int front_port_bus_index(int port) { - int ret = 0; - char buf[8] = {0}; - *value = 0; + int rport = 0; - ret = deviceNodeReadString(node_path, buf, sizeof(buf), data_len); - - if (ret == 0) { - *value = atoi(buf); + switch (port) + { + case 48: + rport = 52; + break; + case 49: + rport = 50; + break; + case 50: + rport = 48; + break; + case 51: + rport = 53; + break; + case 52: + rport = 51; + break; + case 53: + rport = 49; + break; + default: + rport = port; + break; } - return ret; -} - -static char* -sfp_get_port_path_addr(int port, int addr, char *node_name) -{ - sprintf(sfp_node_path, "/sys/bus/i2c/devices/%d-00%d/%s", - FRONT_PORT_TO_MUX_INDEX(port), addr, - node_name); - return sfp_node_path; -} - -static char* -sfp_get_port_path(int port, char *node_name) -{ - return sfp_get_port_path_addr(port, 50, node_name); + return (rport + MUX_START_INDEX); } /************************************************************ @@ -114,10 +109,10 @@ onlp_sfpi_is_present(int port) * Return < 0 if error. */ int present; - char* path = sfp_get_port_path(port, "sfp_is_present"); - - if (sfp_node_read_int(path, &present, 0) != 0) { - AIM_LOG_INFO("Unable to read present status from port(%d)\r\n", port); + int addr = (port < 24) ? 61 : 62; + + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } @@ -128,29 +123,35 @@ int onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) { uint32_t bytes[7]; - char* path; FILE* fp; - path = sfp_get_port_path(0, "sfp_is_present_all"); - fp = fopen(path, "r"); - + /* Read present status of port 0~23 */ + fp = fopen(MODULE_PRESENT_ALL_ATTR_CPLD2, "r"); if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file."); + AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD2."); return ONLP_STATUS_E_INTERNAL; } - int count = fscanf(fp, "%x %x %x %x %x %x %x", - bytes+0, - bytes+1, - bytes+2, - bytes+3, - bytes+4, - bytes+5, - bytes+6 - ); + + int count = fscanf(fp, "%x %x %x", bytes+0, bytes+1, bytes+2); fclose(fp); - if(count != AIM_ARRAYSIZE(bytes)) { + if(count != 3) { /* Likely a CPLD read timeout. */ - AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file."); + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD2."); + return ONLP_STATUS_E_INTERNAL; + } + + /* Read present status of port 24~53 */ + fp = fopen(MODULE_PRESENT_ALL_ATTR_CPLD3, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD3."); + return ONLP_STATUS_E_INTERNAL; + } + + count = fscanf(fp, "%x %x %x %x", bytes+3, bytes+4, bytes+5, bytes+6); + fclose(fp); + if(count != 4) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD3."); return ONLP_STATUS_E_INTERNAL; } @@ -177,33 +178,39 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) int onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) { - uint32_t bytes[7]; - char* path; + uint32_t bytes[6]; + uint32_t *ptr = bytes; FILE* fp; - path = sfp_get_port_path(0, "sfp_rx_los_all"); - fp = fopen(path, "r"); + /* Read present status of port 0~23 */ + int addr, i = 0; - if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the sfp_rx_los_all device file."); - return ONLP_STATUS_E_INTERNAL; - } - int count = fscanf(fp, "%x %x %x %x %x %x", - bytes+0, - bytes+1, - bytes+2, - bytes+3, - bytes+4, - bytes+5 - ); - fclose(fp); - if(count != 6) { - AIM_LOG_ERROR("Unable to read all fields from the sfp_rx_los_all device file."); - return ONLP_STATUS_E_INTERNAL; + for (addr = 61; addr <= 62; addr++) { + if (addr == 61) { + fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD2, "r"); + } + else { + fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD3, "r"); + } + + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_rx_los_all device file of CPLD(0x%d)", addr); + return ONLP_STATUS_E_INTERNAL; + } + + int count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2); + fclose(fp); + if(count != 3) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields from the module_rx_los_all device file of CPLD(0x%d)", addr); + return ONLP_STATUS_E_INTERNAL; + } + + ptr += count; } /* Convert to 64 bit integer in port order */ - int i = 0; + i = 0; uint64_t rx_los_all = 0 ; for(i = 5; i >= 0; i--) { rx_los_all <<= 8; @@ -222,18 +229,22 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) int onlp_sfpi_eeprom_read(int port, uint8_t data[256]) { - char* path = sfp_get_port_path(port, "sfp_eeprom"); - /* * Read the SFP eeprom into data[] * * Return MISSING if SFP is missing. * Return OK if eeprom is read */ + int size = 0; memset(data, 0, 256); - if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) { - AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port); + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, front_port_bus_index(port)) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port); return ONLP_STATUS_E_INTERNAL; } @@ -243,17 +254,60 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256]) int onlp_sfpi_dom_read(int port, uint8_t data[256]) { - char* path = sfp_get_port_path_addr(port, 51, "sfp_eeprom"); - memset(data, 0, 256); + FILE* fp; + char file[64] = {0}; + + sprintf(file, PORT_EEPROM_FORMAT, front_port_bus_index(port)); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } - if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) { - AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port); + if (fseek(fp, 256, SEEK_CUR) != 0) { + fclose(fp); + AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + int ret = fread(data, 1, 256, fp); + fclose(fp); + if (ret != 256) { + AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port); return ONLP_STATUS_E_INTERNAL; } return ONLP_STATUS_OK; } +int +onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = front_port_bus_index(port); + return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) +{ + int bus = front_port_bus_index(port); + return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = front_port_bus_index(port); + return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) +{ + int bus = front_port_bus_index(port); + return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + int onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) { @@ -263,13 +317,13 @@ onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) return ONLP_STATUS_E_UNSUPPORTED; } + int addr = (port < 24) ? 61 : 62; + switch(control) { case ONLP_SFP_CONTROL_TX_DISABLE: { - char* path = sfp_get_port_path(port, "sfp_tx_disable"); - - if (deviceNodeWriteInt(path, value, 0) != 0) { + if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -291,19 +345,18 @@ int onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) { int rv; - char* path = NULL; if (port < 0 || port >= 48) { return ONLP_STATUS_E_UNSUPPORTED; } + int addr = (port < 24) ? 61 : 62; + switch(control) { case ONLP_SFP_CONTROL_RX_LOS: { - path = sfp_get_port_path(port, "sfp_rx_los"); - - if (sfp_node_read_int(path, value, 0) != 0) { + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -315,9 +368,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_FAULT: { - path = sfp_get_port_path(port, "sfp_tx_fault"); - - if (sfp_node_read_int(path, value, 0) != 0) { + if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -329,9 +380,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_DISABLE: { - path = sfp_get_port_path(port, "sfp_tx_disable"); - - if (sfp_node_read_int(path, value, 0) != 0) { + if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/platform-config/r0/src/python/x86_64_accton_as5512_54x_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/platform-config/r0/src/python/x86_64_accton_as5512_54x_r0/__init__.py index 5f00ee18..3e920af3 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/platform-config/r0/src/python/x86_64_accton_as5512_54x_r0/__init__.py +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5512-54x/platform-config/r0/src/python/x86_64_accton_as5512_54x_r0/__init__.py @@ -8,10 +8,10 @@ class OnlPlatform_x86_64_accton_as5512_54x_r0(OnlPlatformAccton, SYS_OBJECT_ID=".5512.54.1" def baseconfig(self): - + self.insmod('optoe') self.insmod('cpr_4011_4mxx') - self.insmod('accton_i2c_cpld') - self.insmod_platform() + for m in [ 'cpld', 'fan', 'psu', 'leds' ]: + self.insmod("x86-64-accton-as5512-54x-%s.ko" % m) ########### initialize I2C bus 0 ########### @@ -30,23 +30,29 @@ class OnlPlatform_x86_64_accton_as5512_54x_r0(OnlPlatformAccton, # initialize CPLDs self.new_i2c_devices( [ - ('accton_i2c_cpld', 0x60, 0), - ('accton_i2c_cpld', 0x61, 0), - ('accton_i2c_cpld', 0x62, 0), + ('as5512_54x_cpld1', 0x60, 0), + ('as5512_54x_cpld2', 0x61, 0), + ('as5512_54x_cpld3', 0x62, 0), ] ) # initialize SFP devices for port in range(1, 49): - self.new_i2c_device('sfp%d' % port, 0x50, port+1) - self.new_i2c_device('sfp%d' % port, 0x51, port+1) + self.new_i2c_device('optoe2', 0x50, port+1) + subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port+1), shell=True) # Initialize QSFP devices - self.new_i2c_device('sfp51', 0x50, 50) - self.new_i2c_device('sfp54', 0x50, 51) - self.new_i2c_device('sfp50', 0x50, 52) - self.new_i2c_device('sfp53', 0x50, 53) - self.new_i2c_device('sfp49', 0x50, 54) - self.new_i2c_device('sfp52', 0x50, 55) + self.new_i2c_device('optoe1', 0x50, 50) + self.new_i2c_device('optoe1', 0x50, 51) + self.new_i2c_device('optoe1', 0x50, 52) + self.new_i2c_device('optoe1', 0x50, 53) + self.new_i2c_device('optoe1', 0x50, 54) + self.new_i2c_device('optoe1', 0x50, 55) + subprocess.call('echo port51 > /sys/bus/i2c/devices/50-0050/port_name', shell=True) + subprocess.call('echo port54 > /sys/bus/i2c/devices/51-0050/port_name', shell=True) + subprocess.call('echo port50 > /sys/bus/i2c/devices/52-0050/port_name', shell=True) + subprocess.call('echo port53 > /sys/bus/i2c/devices/53-0050/port_name', shell=True) + subprocess.call('echo port49 > /sys/bus/i2c/devices/54-0050/port_name', shell=True) + subprocess.call('echo port52 > /sys/bus/i2c/devices/55-0050/port_name', shell=True) ########### initialize I2C bus 1 ########### self.new_i2c_devices( diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-cpld.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-cpld.c new file mode 100644 index 00000000..0ec59ad4 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-cpld.c @@ -0,0 +1,1098 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as5916_54xk CPLD1/CPLD2 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as5916_54xk_cpld1, + as5916_54xk_cpld2 +}; + +struct as5916_54xk_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as5916_54xk_cpld_id[] = { + { "as5916_54xk_cpld1", as5916_54xk_cpld1 }, + { "as5916_54xk_cpld2", as5916_54xk_cpld2 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as5916_54xk_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index + +enum as5916_54xk_cpld1_sysfs_attributes { + CPLD_VERSION, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_PRESENT_ATTR_ID(35), + TRANSCEIVER_PRESENT_ATTR_ID(36), + TRANSCEIVER_PRESENT_ATTR_ID(37), + TRANSCEIVER_PRESENT_ATTR_ID(38), + TRANSCEIVER_PRESENT_ATTR_ID(39), + TRANSCEIVER_PRESENT_ATTR_ID(40), + TRANSCEIVER_PRESENT_ATTR_ID(41), + TRANSCEIVER_PRESENT_ATTR_ID(42), + TRANSCEIVER_PRESENT_ATTR_ID(43), + TRANSCEIVER_PRESENT_ATTR_ID(44), + TRANSCEIVER_PRESENT_ATTR_ID(45), + TRANSCEIVER_PRESENT_ATTR_ID(46), + TRANSCEIVER_PRESENT_ATTR_ID(47), + TRANSCEIVER_PRESENT_ATTR_ID(48), + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_TXDISABLE_ATTR_ID(1), + TRANSCEIVER_TXDISABLE_ATTR_ID(2), + TRANSCEIVER_TXDISABLE_ATTR_ID(3), + TRANSCEIVER_TXDISABLE_ATTR_ID(4), + TRANSCEIVER_TXDISABLE_ATTR_ID(5), + TRANSCEIVER_TXDISABLE_ATTR_ID(6), + TRANSCEIVER_TXDISABLE_ATTR_ID(7), + TRANSCEIVER_TXDISABLE_ATTR_ID(8), + TRANSCEIVER_TXDISABLE_ATTR_ID(9), + TRANSCEIVER_TXDISABLE_ATTR_ID(10), + TRANSCEIVER_TXDISABLE_ATTR_ID(11), + TRANSCEIVER_TXDISABLE_ATTR_ID(12), + TRANSCEIVER_TXDISABLE_ATTR_ID(13), + TRANSCEIVER_TXDISABLE_ATTR_ID(14), + TRANSCEIVER_TXDISABLE_ATTR_ID(15), + TRANSCEIVER_TXDISABLE_ATTR_ID(16), + TRANSCEIVER_TXDISABLE_ATTR_ID(17), + TRANSCEIVER_TXDISABLE_ATTR_ID(18), + TRANSCEIVER_TXDISABLE_ATTR_ID(19), + TRANSCEIVER_TXDISABLE_ATTR_ID(20), + TRANSCEIVER_TXDISABLE_ATTR_ID(21), + TRANSCEIVER_TXDISABLE_ATTR_ID(22), + TRANSCEIVER_TXDISABLE_ATTR_ID(23), + TRANSCEIVER_TXDISABLE_ATTR_ID(24), + TRANSCEIVER_TXDISABLE_ATTR_ID(25), + TRANSCEIVER_TXDISABLE_ATTR_ID(26), + TRANSCEIVER_TXDISABLE_ATTR_ID(27), + TRANSCEIVER_TXDISABLE_ATTR_ID(28), + TRANSCEIVER_TXDISABLE_ATTR_ID(29), + TRANSCEIVER_TXDISABLE_ATTR_ID(30), + TRANSCEIVER_TXDISABLE_ATTR_ID(31), + TRANSCEIVER_TXDISABLE_ATTR_ID(32), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(35), + TRANSCEIVER_TXDISABLE_ATTR_ID(36), + TRANSCEIVER_TXDISABLE_ATTR_ID(37), + TRANSCEIVER_TXDISABLE_ATTR_ID(38), + TRANSCEIVER_TXDISABLE_ATTR_ID(39), + TRANSCEIVER_TXDISABLE_ATTR_ID(40), + TRANSCEIVER_TXDISABLE_ATTR_ID(41), + TRANSCEIVER_TXDISABLE_ATTR_ID(42), + TRANSCEIVER_TXDISABLE_ATTR_ID(43), + TRANSCEIVER_TXDISABLE_ATTR_ID(44), + TRANSCEIVER_TXDISABLE_ATTR_ID(45), + TRANSCEIVER_TXDISABLE_ATTR_ID(46), + TRANSCEIVER_TXDISABLE_ATTR_ID(47), + TRANSCEIVER_TXDISABLE_ATTR_ID(48), + TRANSCEIVER_RXLOS_ATTR_ID(1), + TRANSCEIVER_RXLOS_ATTR_ID(2), + TRANSCEIVER_RXLOS_ATTR_ID(3), + TRANSCEIVER_RXLOS_ATTR_ID(4), + TRANSCEIVER_RXLOS_ATTR_ID(5), + TRANSCEIVER_RXLOS_ATTR_ID(6), + TRANSCEIVER_RXLOS_ATTR_ID(7), + TRANSCEIVER_RXLOS_ATTR_ID(8), + TRANSCEIVER_RXLOS_ATTR_ID(9), + TRANSCEIVER_RXLOS_ATTR_ID(10), + TRANSCEIVER_RXLOS_ATTR_ID(11), + TRANSCEIVER_RXLOS_ATTR_ID(12), + TRANSCEIVER_RXLOS_ATTR_ID(13), + TRANSCEIVER_RXLOS_ATTR_ID(14), + TRANSCEIVER_RXLOS_ATTR_ID(15), + TRANSCEIVER_RXLOS_ATTR_ID(16), + TRANSCEIVER_RXLOS_ATTR_ID(17), + TRANSCEIVER_RXLOS_ATTR_ID(18), + TRANSCEIVER_RXLOS_ATTR_ID(19), + TRANSCEIVER_RXLOS_ATTR_ID(20), + TRANSCEIVER_RXLOS_ATTR_ID(21), + TRANSCEIVER_RXLOS_ATTR_ID(22), + TRANSCEIVER_RXLOS_ATTR_ID(23), + TRANSCEIVER_RXLOS_ATTR_ID(24), + TRANSCEIVER_RXLOS_ATTR_ID(25), + TRANSCEIVER_RXLOS_ATTR_ID(26), + TRANSCEIVER_RXLOS_ATTR_ID(27), + TRANSCEIVER_RXLOS_ATTR_ID(28), + TRANSCEIVER_RXLOS_ATTR_ID(29), + TRANSCEIVER_RXLOS_ATTR_ID(30), + TRANSCEIVER_RXLOS_ATTR_ID(31), + TRANSCEIVER_RXLOS_ATTR_ID(32), + TRANSCEIVER_RXLOS_ATTR_ID(33), + TRANSCEIVER_RXLOS_ATTR_ID(34), + TRANSCEIVER_RXLOS_ATTR_ID(35), + TRANSCEIVER_RXLOS_ATTR_ID(36), + TRANSCEIVER_RXLOS_ATTR_ID(37), + TRANSCEIVER_RXLOS_ATTR_ID(38), + TRANSCEIVER_RXLOS_ATTR_ID(39), + TRANSCEIVER_RXLOS_ATTR_ID(40), + TRANSCEIVER_RXLOS_ATTR_ID(41), + TRANSCEIVER_RXLOS_ATTR_ID(42), + TRANSCEIVER_RXLOS_ATTR_ID(43), + TRANSCEIVER_RXLOS_ATTR_ID(44), + TRANSCEIVER_RXLOS_ATTR_ID(45), + TRANSCEIVER_RXLOS_ATTR_ID(46), + TRANSCEIVER_RXLOS_ATTR_ID(47), + TRANSCEIVER_RXLOS_ATTR_ID(48), + TRANSCEIVER_TXFAULT_ATTR_ID(1), + TRANSCEIVER_TXFAULT_ATTR_ID(2), + TRANSCEIVER_TXFAULT_ATTR_ID(3), + TRANSCEIVER_TXFAULT_ATTR_ID(4), + TRANSCEIVER_TXFAULT_ATTR_ID(5), + TRANSCEIVER_TXFAULT_ATTR_ID(6), + TRANSCEIVER_TXFAULT_ATTR_ID(7), + TRANSCEIVER_TXFAULT_ATTR_ID(8), + TRANSCEIVER_TXFAULT_ATTR_ID(9), + TRANSCEIVER_TXFAULT_ATTR_ID(10), + TRANSCEIVER_TXFAULT_ATTR_ID(11), + TRANSCEIVER_TXFAULT_ATTR_ID(12), + TRANSCEIVER_TXFAULT_ATTR_ID(13), + TRANSCEIVER_TXFAULT_ATTR_ID(14), + TRANSCEIVER_TXFAULT_ATTR_ID(15), + TRANSCEIVER_TXFAULT_ATTR_ID(16), + TRANSCEIVER_TXFAULT_ATTR_ID(17), + TRANSCEIVER_TXFAULT_ATTR_ID(18), + TRANSCEIVER_TXFAULT_ATTR_ID(19), + TRANSCEIVER_TXFAULT_ATTR_ID(20), + TRANSCEIVER_TXFAULT_ATTR_ID(21), + TRANSCEIVER_TXFAULT_ATTR_ID(22), + TRANSCEIVER_TXFAULT_ATTR_ID(23), + TRANSCEIVER_TXFAULT_ATTR_ID(24), + TRANSCEIVER_TXFAULT_ATTR_ID(25), + TRANSCEIVER_TXFAULT_ATTR_ID(26), + TRANSCEIVER_TXFAULT_ATTR_ID(27), + TRANSCEIVER_TXFAULT_ATTR_ID(28), + TRANSCEIVER_TXFAULT_ATTR_ID(29), + TRANSCEIVER_TXFAULT_ATTR_ID(30), + TRANSCEIVER_TXFAULT_ATTR_ID(31), + TRANSCEIVER_TXFAULT_ATTR_ID(32), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(35), + TRANSCEIVER_TXFAULT_ATTR_ID(36), + TRANSCEIVER_TXFAULT_ATTR_ID(37), + TRANSCEIVER_TXFAULT_ATTR_ID(38), + TRANSCEIVER_TXFAULT_ATTR_ID(39), + TRANSCEIVER_TXFAULT_ATTR_ID(40), + TRANSCEIVER_TXFAULT_ATTR_ID(41), + TRANSCEIVER_TXFAULT_ATTR_ID(42), + TRANSCEIVER_TXFAULT_ATTR_ID(43), + TRANSCEIVER_TXFAULT_ATTR_ID(44), + TRANSCEIVER_TXFAULT_ATTR_ID(45), + TRANSCEIVER_TXFAULT_ATTR_ID(46), + TRANSCEIVER_TXFAULT_ATTR_ID(47), + TRANSCEIVER_TXFAULT_ATTR_ID(48), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_tx_disable(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); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as5916_54xk_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as5916_54xk_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* transceiver attributes */ +#define DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index) +#define DECLARE_TRANSCEIVER_PRESENT_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr + +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_TXFAULT_##index) +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, MODULE_RXLOS_ALL); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(1); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(2); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(3); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(4); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(5); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(6); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(7); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(8); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(9); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(10); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(11); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(12); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(13); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(14); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(15); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(16); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(17); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(18); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(19); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(20); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(21); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(22); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(23); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(24); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(25); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(26); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(27); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(28); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(29); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(30); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(31); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(32); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(33); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(34); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(35); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(36); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(37); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(38); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(39); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(40); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(41); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(42); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(43); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(44); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(45); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(46); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(47); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(48); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(49); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(50); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(51); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(52); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(53); +DECLARE_TRANSCEIVER_PRESENT_SENSOR_DEVICE_ATTR(54); + +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(35); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(36); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(37); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(38); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(39); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(40); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(41); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(42); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(43); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(44); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(45); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(46); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(47); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(48); + +static struct attribute *as5916_54xk_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(1), + DECLARE_TRANSCEIVER_PRESENT_ATTR(2), + DECLARE_TRANSCEIVER_PRESENT_ATTR(3), + DECLARE_TRANSCEIVER_PRESENT_ATTR(4), + DECLARE_TRANSCEIVER_PRESENT_ATTR(5), + DECLARE_TRANSCEIVER_PRESENT_ATTR(6), + DECLARE_TRANSCEIVER_PRESENT_ATTR(7), + DECLARE_TRANSCEIVER_PRESENT_ATTR(8), + DECLARE_TRANSCEIVER_PRESENT_ATTR(9), + DECLARE_TRANSCEIVER_PRESENT_ATTR(10), + DECLARE_TRANSCEIVER_PRESENT_ATTR(11), + DECLARE_TRANSCEIVER_PRESENT_ATTR(12), + DECLARE_TRANSCEIVER_PRESENT_ATTR(13), + DECLARE_TRANSCEIVER_PRESENT_ATTR(14), + DECLARE_TRANSCEIVER_PRESENT_ATTR(15), + DECLARE_TRANSCEIVER_PRESENT_ATTR(16), + DECLARE_TRANSCEIVER_PRESENT_ATTR(17), + DECLARE_TRANSCEIVER_PRESENT_ATTR(18), + DECLARE_TRANSCEIVER_PRESENT_ATTR(19), + DECLARE_TRANSCEIVER_PRESENT_ATTR(20), + DECLARE_TRANSCEIVER_PRESENT_ATTR(21), + DECLARE_TRANSCEIVER_PRESENT_ATTR(22), + DECLARE_TRANSCEIVER_PRESENT_ATTR(23), + DECLARE_TRANSCEIVER_PRESENT_ATTR(24), + DECLARE_SFP_TRANSCEIVER_ATTR(1), + DECLARE_SFP_TRANSCEIVER_ATTR(2), + DECLARE_SFP_TRANSCEIVER_ATTR(3), + DECLARE_SFP_TRANSCEIVER_ATTR(4), + DECLARE_SFP_TRANSCEIVER_ATTR(5), + DECLARE_SFP_TRANSCEIVER_ATTR(6), + DECLARE_SFP_TRANSCEIVER_ATTR(7), + DECLARE_SFP_TRANSCEIVER_ATTR(8), + DECLARE_SFP_TRANSCEIVER_ATTR(9), + DECLARE_SFP_TRANSCEIVER_ATTR(10), + DECLARE_SFP_TRANSCEIVER_ATTR(11), + DECLARE_SFP_TRANSCEIVER_ATTR(12), + DECLARE_SFP_TRANSCEIVER_ATTR(13), + DECLARE_SFP_TRANSCEIVER_ATTR(14), + DECLARE_SFP_TRANSCEIVER_ATTR(15), + DECLARE_SFP_TRANSCEIVER_ATTR(16), + DECLARE_SFP_TRANSCEIVER_ATTR(17), + DECLARE_SFP_TRANSCEIVER_ATTR(18), + DECLARE_SFP_TRANSCEIVER_ATTR(19), + DECLARE_SFP_TRANSCEIVER_ATTR(20), + DECLARE_SFP_TRANSCEIVER_ATTR(21), + DECLARE_SFP_TRANSCEIVER_ATTR(22), + DECLARE_SFP_TRANSCEIVER_ATTR(23), + DECLARE_SFP_TRANSCEIVER_ATTR(24), + NULL +}; + +static const struct attribute_group as5916_54xk_cpld1_group = { + .attrs = as5916_54xk_cpld1_attributes, +}; + +static struct attribute *as5916_54xk_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_TRANSCEIVER_PRESENT_ATTR(25), + DECLARE_TRANSCEIVER_PRESENT_ATTR(26), + DECLARE_TRANSCEIVER_PRESENT_ATTR(27), + DECLARE_TRANSCEIVER_PRESENT_ATTR(28), + DECLARE_TRANSCEIVER_PRESENT_ATTR(29), + DECLARE_TRANSCEIVER_PRESENT_ATTR(30), + DECLARE_TRANSCEIVER_PRESENT_ATTR(31), + DECLARE_TRANSCEIVER_PRESENT_ATTR(32), + DECLARE_TRANSCEIVER_PRESENT_ATTR(33), + DECLARE_TRANSCEIVER_PRESENT_ATTR(34), + DECLARE_TRANSCEIVER_PRESENT_ATTR(35), + DECLARE_TRANSCEIVER_PRESENT_ATTR(36), + DECLARE_TRANSCEIVER_PRESENT_ATTR(37), + DECLARE_TRANSCEIVER_PRESENT_ATTR(38), + DECLARE_TRANSCEIVER_PRESENT_ATTR(39), + DECLARE_TRANSCEIVER_PRESENT_ATTR(40), + DECLARE_TRANSCEIVER_PRESENT_ATTR(41), + DECLARE_TRANSCEIVER_PRESENT_ATTR(42), + DECLARE_TRANSCEIVER_PRESENT_ATTR(43), + DECLARE_TRANSCEIVER_PRESENT_ATTR(44), + DECLARE_TRANSCEIVER_PRESENT_ATTR(45), + DECLARE_TRANSCEIVER_PRESENT_ATTR(46), + DECLARE_TRANSCEIVER_PRESENT_ATTR(47), + DECLARE_TRANSCEIVER_PRESENT_ATTR(48), + DECLARE_TRANSCEIVER_PRESENT_ATTR(49), + DECLARE_TRANSCEIVER_PRESENT_ATTR(50), + DECLARE_TRANSCEIVER_PRESENT_ATTR(51), + DECLARE_TRANSCEIVER_PRESENT_ATTR(52), + DECLARE_TRANSCEIVER_PRESENT_ATTR(53), + DECLARE_TRANSCEIVER_PRESENT_ATTR(54), + DECLARE_SFP_TRANSCEIVER_ATTR(25), + DECLARE_SFP_TRANSCEIVER_ATTR(26), + DECLARE_SFP_TRANSCEIVER_ATTR(27), + DECLARE_SFP_TRANSCEIVER_ATTR(28), + DECLARE_SFP_TRANSCEIVER_ATTR(29), + DECLARE_SFP_TRANSCEIVER_ATTR(30), + DECLARE_SFP_TRANSCEIVER_ATTR(31), + DECLARE_SFP_TRANSCEIVER_ATTR(32), + DECLARE_SFP_TRANSCEIVER_ATTR(33), + DECLARE_SFP_TRANSCEIVER_ATTR(34), + DECLARE_SFP_TRANSCEIVER_ATTR(35), + DECLARE_SFP_TRANSCEIVER_ATTR(36), + DECLARE_SFP_TRANSCEIVER_ATTR(37), + DECLARE_SFP_TRANSCEIVER_ATTR(38), + DECLARE_SFP_TRANSCEIVER_ATTR(39), + DECLARE_SFP_TRANSCEIVER_ATTR(40), + DECLARE_SFP_TRANSCEIVER_ATTR(41), + DECLARE_SFP_TRANSCEIVER_ATTR(42), + DECLARE_SFP_TRANSCEIVER_ATTR(43), + DECLARE_SFP_TRANSCEIVER_ATTR(44), + DECLARE_SFP_TRANSCEIVER_ATTR(45), + DECLARE_SFP_TRANSCEIVER_ATTR(46), + DECLARE_SFP_TRANSCEIVER_ATTR(47), + DECLARE_SFP_TRANSCEIVER_ATTR(48), + NULL +}; + +static const struct attribute_group as5916_54xk_cpld2_group = { + .attrs = as5916_54xk_cpld2_attributes, +}; + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status, num_regs = 0; + u8 values[4] = {0}; + u8 regs[] = {0x10, 0x11, 0x12, 0x52}; + struct i2c_client *client = to_i2c_client(dev); + struct as5916_54xk_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + num_regs = (data->type == as5916_54xk_cpld1) ? 3 : 4; + + for (i = 0; i < num_regs; i++) { + status = as5916_54xk_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + if (data->type == as5916_54xk_cpld1) { + status = sprintf(buf, "%.2x %.2x %.2x\n", + values[0], values[1], values[2]); + } + else { /* as5916_54xk_cpld2 */ + values[3] &= 0x3F; + status = sprintf(buf, "%.2x %.2x %.2x %.2x\n", + values[0], values[1], values[2], values[3]); + } + + return status; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[3] = {0}; + u8 regs[] = {0x30, 0x32, 0x34}; + struct i2c_client *client = to_i2c_client(dev); + struct as5916_54xk_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as5916_54xk_cpld_read_internal(client, regs[i]); + + if (status < 0) { + goto exit; + } + + values[i] = (u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 24 in order */ + return sprintf(buf, "%.2x %.2x %.2x\n", values[0], values[1], values[2]); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as5916_54xk_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_PRESENT_8: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_PRESENT_1); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_16: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_PRESENT_9); + break; + case MODULE_PRESENT_17 ... MODULE_PRESENT_24: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_PRESENT_17); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_32: + reg = 0x10; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + break; + case MODULE_PRESENT_33 ... MODULE_PRESENT_40: + reg = 0x11; + mask = 0x1 << (attr->index - MODULE_PRESENT_33); + break; + case MODULE_PRESENT_41 ... MODULE_PRESENT_48: + reg = 0x12; + mask = 0x1 << (attr->index - MODULE_PRESENT_41); + break; + case MODULE_PRESENT_49 ... MODULE_PRESENT_54: + reg = 0x52; + mask = 0x1 << (attr->index - MODULE_PRESENT_49); + break; + case MODULE_TXFAULT_1 ... MODULE_TXFAULT_8: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_TXFAULT_1); + break; + case MODULE_TXFAULT_9 ... MODULE_TXFAULT_16: + reg = 0x16; + mask = 0x1 << (attr->index - MODULE_TXFAULT_9); + break; + case MODULE_TXFAULT_17 ... MODULE_TXFAULT_24: + reg = 0x18; + mask = 0x1 << (attr->index - MODULE_TXFAULT_17); + break; + case MODULE_TXFAULT_25 ... MODULE_TXFAULT_32: + reg = 0x14; + mask = 0x1 << (attr->index - MODULE_TXFAULT_25); + break; + case MODULE_TXFAULT_33 ... MODULE_TXFAULT_40: + reg = 0x16; + mask = 0x1 << (attr->index - MODULE_TXFAULT_33); + break; + case MODULE_TXFAULT_41 ... MODULE_TXFAULT_48: + reg = 0x18; + mask = 0x1 << (attr->index - MODULE_TXFAULT_41); + break; + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0x20; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0x22; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0x24; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0x20; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0x22; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0x24; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + case MODULE_RXLOS_1 ... MODULE_RXLOS_8: + reg = 0x30; + mask = 0x1 << (attr->index - MODULE_RXLOS_1); + break; + case MODULE_RXLOS_9 ... MODULE_RXLOS_16: + reg = 0x32; + mask = 0x1 << (attr->index - MODULE_RXLOS_9); + break; + case MODULE_RXLOS_17 ... MODULE_RXLOS_24: + reg = 0x34; + mask = 0x1 << (attr->index - MODULE_RXLOS_17); + break; + case MODULE_RXLOS_25 ... MODULE_RXLOS_32: + reg = 0x30; + mask = 0x1 << (attr->index - MODULE_RXLOS_25); + break; + case MODULE_RXLOS_33 ... MODULE_RXLOS_40: + reg = 0x32; + mask = 0x1 << (attr->index - MODULE_RXLOS_33); + break; + case MODULE_RXLOS_41 ... MODULE_RXLOS_48: + reg = 0x34; + mask = 0x1 << (attr->index - MODULE_RXLOS_41); + break; + default: + return 0; + } + + if (attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_54) { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = as5916_54xk_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_tx_disable(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 as5916_54xk_cpld_data *data = i2c_get_clientdata(client); + long disable; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + switch (attr->index) { + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_8: + reg = 0x20; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_1); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_16: + reg = 0x22; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_9); + break; + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_24: + reg = 0x24; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_17); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_32: + reg = 0x20; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_40: + reg = 0x22; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_33); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_48: + reg = 0x24; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_41); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as5916_54xk_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + status &= ~mask; + } + + status = as5916_54xk_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +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 as5916_54xk_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 = as5916_54xk_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 as5916_54xk_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 as5916_54xk_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 ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as5916_54xk_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as5916_54xk_cpld_data *data; + int ret = -ENODEV; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as5916_54xk_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + /* Register sysfs hooks */ + switch (data->type) { + case as5916_54xk_cpld1: + group = &as5916_54xk_cpld1_group; + break; + case as5916_54xk_cpld2: + group = &as5916_54xk_cpld2_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as5916_54xk_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as5916_54xk_cpld_remove(struct i2c_client *client) +{ + struct as5916_54xk_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as5916_54xk_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as5916_54xk_cpld1: + group = &as5916_54xk_cpld1_group; + break; + case as5916_54xk_cpld2: + group = &as5916_54xk_cpld2_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int as5916_54xk_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; +} + +static int as5916_54xk_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; +} + +int as5916_54xk_cpld_read(unsigned short 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 = as5916_54xk_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5916_54xk_cpld_read); + +int as5916_54xk_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 = as5916_54xk_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as5916_54xk_cpld_write); + +static struct i2c_driver as5916_54xk_cpld_driver = { + .driver = { + .name = "as5916_54xk_cpld", + .owner = THIS_MODULE, + }, + .probe = as5916_54xk_cpld_probe, + .remove = as5916_54xk_cpld_remove, + .id_table = as5916_54xk_cpld_id, +}; + +static int __init as5916_54xk_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as5916_54xk_cpld_driver); +} + +static void __exit as5916_54xk_cpld_exit(void) +{ + i2c_del_driver(&as5916_54xk_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as5916_54xk_cpld_init); +module_exit(as5916_54xk_cpld_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-leds.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-leds.c index f155e970..078e005a 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-leds.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-leds.c @@ -38,8 +38,8 @@ #define DEBUG_PRINT(fmt, args...) #endif -extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); -extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); +extern int as5916_54xk_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5916_54xk_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); struct accton_as5916_54xk_led_data { struct platform_device *pdev; @@ -157,12 +157,12 @@ static u8 led_light_mode_to_reg_val(enum led_type type, static int accton_as5916_54xk_led_read_value(u8 reg) { - return accton_i2c_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg); + return as5916_54xk_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg); } static int accton_as5916_54xk_led_write_value(u8 reg, u8 value) { - return accton_i2c_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value); + return as5916_54xk_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value); } static void accton_as5916_54xk_led_update(void) diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-psu.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-psu.c index a2737499..f89fc298 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-psu.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-psu.c @@ -37,7 +37,7 @@ static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf); static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf); static int as5916_54xk_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len); -extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as5916_54xk_cpld_read(unsigned short cpld_addr, u8 reg); /* Addresses scanned */ @@ -234,7 +234,7 @@ static struct as5916_54xk_psu_data *as5916_54xk_psu_update_device(struct device dev_dbg(&client->dev, "Starting as5916_54xk update\n"); /* Read psu status */ - status = accton_i2c_cpld_read(0x60, 0x2); + status = as5916_54xk_cpld_read(0x60, 0x2); if (status < 0) { dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", status); diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-sfp.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-sfp.c deleted file mode 100644 index c606e5c2..00000000 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/modules/builds/x86-64-accton-as5916-54xk-sfp.c +++ /dev/null @@ -1,1315 +0,0 @@ -/* - * SFP driver for accton as5916_54xk sfp - * - * Copyright (C) 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 - -#define DRIVER_NAME "as5916_54xk_sfp" /* Platform dependent */ - -#define DEBUG_MODE 0 - -#if (DEBUG_MODE == 1) - #define DEBUG_PRINT(fmt, args...) \ - printk (KERN_INFO "%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) -#else - #define DEBUG_PRINT(fmt, args...) -#endif - -#define NUM_OF_SFP_PORT 54 -#define EEPROM_NAME "sfp_eeprom" -#define EEPROM_SIZE 256 /* 256 byte eeprom */ -#define BIT_INDEX(i) (1ULL << (i)) -#define USE_I2C_BLOCK_READ 1 /* Platform dependent */ -#define I2C_RW_RETRY_COUNT 3 -#define I2C_RW_RETRY_INTERVAL 100 /* ms */ - -#define SFP_EEPROM_A0_I2C_ADDR (0xA0 >> 1) -#define SFP_EEPROM_A2_I2C_ADDR (0xA2 >> 1) - -#define SFF8024_PHYSICAL_DEVICE_ID_ADDR 0x0 -#define SFF8024_DEVICE_ID_SFP 0x3 -#define SFF8024_DEVICE_ID_QSFP 0xC -#define SFF8024_DEVICE_ID_QSFP_PLUS 0xD -#define SFF8024_DEVICE_ID_QSFP28 0x11 - -#define SFF8472_DIAG_MON_TYPE_ADDR 92 -#define SFF8472_DIAG_MON_TYPE_DDM_MASK 0x40 -#define SFF8472_10G_ETH_COMPLIANCE_ADDR 0x3 -#define SFF8472_10G_BASE_MASK 0xF0 - -#define SFF8436_RX_LOS_ADDR 3 -#define SFF8436_TX_FAULT_ADDR 4 -#define SFF8436_TX_DISABLE_ADDR 86 - -/* Platform dependent +++ */ -#define I2C_ADDR_CPLD1 0x60 -#define I2C_ADDR_CPLD2 0x62 -/* Platform dependent --- */ - -static ssize_t show_port_number(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t show_port_type(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t show_present(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count); -static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, const char *buf, size_t count);; -static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, char *buf); -static ssize_t sfp_eeprom_read(struct i2c_client *, u8, u8 *,int); -static ssize_t sfp_eeprom_write(struct i2c_client *, u8 , const char *,int); -extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg); -extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); - -enum sfp_sysfs_attributes { - PRESENT, - PRESENT_ALL, - PORT_NUMBER, - PORT_TYPE, - DDM_IMPLEMENTED, - TX_FAULT, - TX_FAULT1, - TX_FAULT2, - TX_FAULT3, - TX_FAULT4, - TX_DISABLE, - TX_DISABLE1, - TX_DISABLE2, - TX_DISABLE3, - TX_DISABLE4, - RX_LOS, - RX_LOS1, - RX_LOS2, - RX_LOS3, - RX_LOS4, - RX_LOS_ALL -}; - -/* SFP/QSFP common attributes for sysfs */ -static SENSOR_DEVICE_ATTR(sfp_port_number, S_IRUGO, show_port_number, NULL, PORT_NUMBER); -static SENSOR_DEVICE_ATTR(sfp_port_type, S_IRUGO, show_port_type, NULL, PORT_TYPE); -static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, show_present, NULL, PRESENT); -static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, show_present, NULL, PRESENT_ALL); -static SENSOR_DEVICE_ATTR(sfp_rx_los, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS); -static SENSOR_DEVICE_ATTR(sfp_tx_disable, S_IWUSR | S_IRUGO, sfp_show_tx_rx_status, sfp_set_tx_disable, TX_DISABLE); -static SENSOR_DEVICE_ATTR(sfp_tx_fault, S_IRUGO, sfp_show_tx_rx_status, NULL, TX_FAULT); - -/* QSFP attributes for sysfs */ -static SENSOR_DEVICE_ATTR(sfp_rx_los1, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS1); -static SENSOR_DEVICE_ATTR(sfp_rx_los2, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS2); -static SENSOR_DEVICE_ATTR(sfp_rx_los3, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS3); -static SENSOR_DEVICE_ATTR(sfp_rx_los4, S_IRUGO, qsfp_show_tx_rx_status, NULL, RX_LOS4); -static SENSOR_DEVICE_ATTR(sfp_tx_disable1, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE1); -static SENSOR_DEVICE_ATTR(sfp_tx_disable2, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE2); -static SENSOR_DEVICE_ATTR(sfp_tx_disable3, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE3); -static SENSOR_DEVICE_ATTR(sfp_tx_disable4, S_IWUSR | S_IRUGO, qsfp_show_tx_rx_status, qsfp_set_tx_disable, TX_DISABLE4); -static SENSOR_DEVICE_ATTR(sfp_tx_fault1, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT1); -static SENSOR_DEVICE_ATTR(sfp_tx_fault2, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT2); -static SENSOR_DEVICE_ATTR(sfp_tx_fault3, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT3); -static SENSOR_DEVICE_ATTR(sfp_tx_fault4, S_IRUGO, qsfp_show_tx_rx_status, NULL, TX_FAULT4); -static struct attribute *qsfp_attributes[] = { - &sensor_dev_attr_sfp_port_number.dev_attr.attr, - &sensor_dev_attr_sfp_port_type.dev_attr.attr, - &sensor_dev_attr_sfp_is_present.dev_attr.attr, - &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los1.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los2.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los3.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los4.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable1.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable2.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable3.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable4.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault1.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault2.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault3.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault4.dev_attr.attr, - NULL -}; - -/* SFP msa attributes for sysfs */ -static SENSOR_DEVICE_ATTR(sfp_ddm_implemented, S_IRUGO, sfp_show_ddm_implemented, NULL, DDM_IMPLEMENTED); -static SENSOR_DEVICE_ATTR(sfp_rx_los_all, S_IRUGO, sfp_show_tx_rx_status, NULL, RX_LOS_ALL); -static struct attribute *sfp_msa_attributes[] = { - &sensor_dev_attr_sfp_port_number.dev_attr.attr, - &sensor_dev_attr_sfp_port_type.dev_attr.attr, - &sensor_dev_attr_sfp_is_present.dev_attr.attr, - &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, - &sensor_dev_attr_sfp_ddm_implemented.dev_attr.attr, - &sensor_dev_attr_sfp_tx_fault.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los.dev_attr.attr, - &sensor_dev_attr_sfp_rx_los_all.dev_attr.attr, - &sensor_dev_attr_sfp_tx_disable.dev_attr.attr, - NULL -}; - -/* SFP ddm attributes for sysfs */ -static struct attribute *sfp_ddm_attributes[] = { - NULL -}; - -/* Platform dependent +++ */ -#define CPLD_PORT_TO_FRONT_PORT(port) (port+1) - -enum port_numbers { -as5916_54xk_sfp1, as5916_54xk_sfp2, as5916_54xk_sfp3, as5916_54xk_sfp4, as5916_54xk_sfp5, as5916_54xk_sfp6, as5916_54xk_sfp7, as5916_54xk_sfp8, -as5916_54xk_sfp9, as5916_54xk_sfp10, as5916_54xk_sfp11, as5916_54xk_sfp12, as5916_54xk_sfp13, as5916_54xk_sfp14, as5916_54xk_sfp15, as5916_54xk_sfp16, -as5916_54xk_sfp17, as5916_54xk_sfp18, as5916_54xk_sfp19, as5916_54xk_sfp20, as5916_54xk_sfp21, as5916_54xk_sfp22, as5916_54xk_sfp23, as5916_54xk_sfp24, -as5916_54xk_sfp25, as5916_54xk_sfp26, as5916_54xk_sfp27, as5916_54xk_sfp28, as5916_54xk_sfp29, as5916_54xk_sfp30, as5916_54xk_sfp31, as5916_54xk_sfp32, -as5916_54xk_sfp33, as5916_54xk_sfp34, as5916_54xk_sfp35, as5916_54xk_sfp36, as5916_54xk_sfp37, as5916_54xk_sfp38, as5916_54xk_sfp39, as5916_54xk_sfp40, -as5916_54xk_sfp41, as5916_54xk_sfp42, as5916_54xk_sfp43, as5916_54xk_sfp44, as5916_54xk_sfp45, as5916_54xk_sfp46, as5916_54xk_sfp47, as5916_54xk_sfp48, -as5916_54xk_sfp49, as5916_54xk_sfp50, as5916_54xk_sfp51, as5916_54xk_sfp52, as5916_54xk_sfp53, as5916_54xk_sfp54 -}; - -static const struct i2c_device_id sfp_device_id[] = { -{ "as5916_54xk_sfp1", as5916_54xk_sfp1 }, { "as5916_54xk_sfp2", as5916_54xk_sfp2 }, { "as5916_54xk_sfp3", as5916_54xk_sfp3 }, { "as5916_54xk_sfp4", as5916_54xk_sfp4 }, -{ "as5916_54xk_sfp5", as5916_54xk_sfp5 }, { "as5916_54xk_sfp6", as5916_54xk_sfp6 }, { "as5916_54xk_sfp7", as5916_54xk_sfp7 }, { "as5916_54xk_sfp8", as5916_54xk_sfp8 }, -{ "as5916_54xk_sfp9", as5916_54xk_sfp9 }, { "as5916_54xk_sfp10", as5916_54xk_sfp10 }, { "as5916_54xk_sfp11", as5916_54xk_sfp11 }, { "as5916_54xk_sfp12", as5916_54xk_sfp12 }, -{ "as5916_54xk_sfp13", as5916_54xk_sfp13 }, { "as5916_54xk_sfp14", as5916_54xk_sfp14 }, { "as5916_54xk_sfp15", as5916_54xk_sfp15 }, { "as5916_54xk_sfp16", as5916_54xk_sfp16 }, -{ "as5916_54xk_sfp17", as5916_54xk_sfp17 }, { "as5916_54xk_sfp18", as5916_54xk_sfp18 }, { "as5916_54xk_sfp19", as5916_54xk_sfp19 }, { "as5916_54xk_sfp20", as5916_54xk_sfp20 }, -{ "as5916_54xk_sfp21", as5916_54xk_sfp21 }, { "as5916_54xk_sfp22", as5916_54xk_sfp22 }, { "as5916_54xk_sfp23", as5916_54xk_sfp23 }, { "as5916_54xk_sfp24", as5916_54xk_sfp24 }, -{ "as5916_54xk_sfp25", as5916_54xk_sfp25 }, { "as5916_54xk_sfp26", as5916_54xk_sfp26 }, { "as5916_54xk_sfp27", as5916_54xk_sfp27 }, { "as5916_54xk_sfp28", as5916_54xk_sfp28 }, -{ "as5916_54xk_sfp29", as5916_54xk_sfp29 }, { "as5916_54xk_sfp30", as5916_54xk_sfp30 }, { "as5916_54xk_sfp31", as5916_54xk_sfp31 }, { "as5916_54xk_sfp32", as5916_54xk_sfp32 }, -{ "as5916_54xk_sfp33", as5916_54xk_sfp33 }, { "as5916_54xk_sfp34", as5916_54xk_sfp34 }, { "as5916_54xk_sfp35", as5916_54xk_sfp35 }, { "as5916_54xk_sfp36", as5916_54xk_sfp36 }, -{ "as5916_54xk_sfp37", as5916_54xk_sfp37 }, { "as5916_54xk_sfp38", as5916_54xk_sfp38 }, { "as5916_54xk_sfp39", as5916_54xk_sfp39 }, { "as5916_54xk_sfp40", as5916_54xk_sfp40 }, -{ "as5916_54xk_sfp41", as5916_54xk_sfp41 }, { "as5916_54xk_sfp42", as5916_54xk_sfp42 }, { "as5916_54xk_sfp43", as5916_54xk_sfp43 }, { "as5916_54xk_sfp44", as5916_54xk_sfp44 }, -{ "as5916_54xk_sfp45", as5916_54xk_sfp45 }, { "as5916_54xk_sfp46", as5916_54xk_sfp46 }, { "as5916_54xk_sfp47", as5916_54xk_sfp47 }, { "as5916_54xk_sfp48", as5916_54xk_sfp48 }, -{ "as5916_54xk_sfp49", as5916_54xk_sfp49 }, { "as5916_54xk_sfp50", as5916_54xk_sfp50 }, { "as5916_54xk_sfp51", as5916_54xk_sfp51 }, { "as5916_54xk_sfp52", as5916_54xk_sfp52 }, -{ "as5916_54xk_sfp53", as5916_54xk_sfp53 }, { "as5916_54xk_sfp54", as5916_54xk_sfp54 }, -{ /* LIST END */ } -}; -MODULE_DEVICE_TABLE(i2c, sfp_device_id); -/* Platform dependent --- */ - -/* - * list of valid port types - * note OOM_PORT_TYPE_NOT_PRESENT to indicate no - * module is present in this port - */ -typedef enum oom_driver_port_type_e { - OOM_DRIVER_PORT_TYPE_INVALID, - OOM_DRIVER_PORT_TYPE_NOT_PRESENT, - OOM_DRIVER_PORT_TYPE_SFP, - OOM_DRIVER_PORT_TYPE_SFP_PLUS, - OOM_DRIVER_PORT_TYPE_QSFP, - OOM_DRIVER_PORT_TYPE_QSFP_PLUS, - OOM_DRIVER_PORT_TYPE_QSFP28 -} oom_driver_port_type_t; - -enum driver_type_e { - DRIVER_TYPE_SFP_MSA, - DRIVER_TYPE_SFP_DDM, - DRIVER_TYPE_QSFP -}; - -/* Each client has this additional data - */ -struct eeprom_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - struct bin_attribute bin; /* eeprom data */ -}; - -struct sfp_msa_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u64 status[6]; /* bit0:port0, bit1:port1 and so on */ - /* index 0 => tx_fail - 1 => tx_disable - 2 => rx_loss - 3 => device id - 4 => 10G Ethernet Compliance Codes - to distinguish SFP or SFP+ - 5 => DIAGNOSTIC MONITORING TYPE */ - struct eeprom_data eeprom; -}; - -struct sfp_ddm_data { - struct eeprom_data eeprom; -}; - -struct qsfp_data { - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u8 status[3]; /* bit0:port0, bit1:port1 and so on */ - /* index 0 => tx_fail - 1 => tx_disable - 2 => rx_loss */ - - u8 device_id; - struct eeprom_data eeprom; -}; - -struct sfp_port_data { - struct mutex update_lock; - enum driver_type_e driver_type; - int port; /* CPLD port index */ - oom_driver_port_type_t port_type; - u64 present; /* present status, bit0:port0, bit1:port1 and so on */ - - struct sfp_msa_data *msa; - struct sfp_ddm_data *ddm; - struct qsfp_data *qsfp; - - struct i2c_client *client; -}; - -static ssize_t show_port_number(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - return sprintf(buf, "%d\n", CPLD_PORT_TO_FRONT_PORT(data->port)); -} - -/* Platform dependent +++ */ -static struct sfp_port_data *sfp_update_present(struct i2c_client *client) -{ - int i = 0, j = 0, status = -1; - u8 reg; - unsigned short cpld_addr; - struct sfp_port_data *data = i2c_get_clientdata(client); - - DEBUG_PRINT("Starting sfp present status update"); - mutex_lock(&data->update_lock); - data->present = 0; - - /* Read present status of port 1~48(SFP port) */ - for (i = 0; i < 2; i++) { - for (j = 0; j < 3; j++) { - cpld_addr = I2C_ADDR_CPLD1 + i*2; - reg = 0x10+j; - status = accton_i2c_cpld_read(cpld_addr, reg); - - if (unlikely(status < 0)) { - dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); - goto exit; - } - - DEBUG_PRINT("Present status = 0x%lx\r\n", data->present); - data->present |= (u64)status << ((i*24) + (j%3)*8); - } - } - - /* Read present status of port 49-52(QSFP port) */ - cpld_addr = I2C_ADDR_CPLD2; - reg = 0x52; - status = accton_i2c_cpld_read(cpld_addr, reg); - - if (unlikely(status < 0)) { - dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, reg, status); - goto exit; - } - else { - data->present |= (u64)(status & 0x3F) << 48; - } - - DEBUG_PRINT("Present status = 0x%lx", data->present); -exit: - mutex_unlock(&data->update_lock); - return (status < 0) ? ERR_PTR(status) : data; -} - -static struct sfp_port_data* sfp_update_tx_rx_status(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - int i = 0, j = 0; - int status = -1; - u8 tx_rx_regs[] = {0x14, 0x16, 0x18, 0x20, 0x22, 0x24, 0x30, 0x32, 0x34}; - - if (time_before(jiffies, data->msa->last_updated + HZ + HZ / 2) && data->msa->valid) { - return data; - } - - DEBUG_PRINT("Starting as5916_54xk sfp tx rx status update"); - mutex_lock(&data->update_lock); - data->msa->valid = 0; - memset(data->msa->status, 0, sizeof(data->msa->status)); - - /* Read status of port 1~48(SFP port) */ - for (i = 0; i < 2; i++) { - for (j = 0; j < ARRAY_SIZE(tx_rx_regs); j++) { - unsigned short cpld_addr = I2C_ADDR_CPLD1 + i*2; - - status = accton_i2c_cpld_read(cpld_addr, tx_rx_regs[j]); - if (unlikely(status < 0)) { - dev_dbg(&client->dev, "cpld(0x%x) reg(0x%x) err %d\n", cpld_addr, tx_rx_regs[i], status); - goto exit; - } - - data->msa->status[j/3] |= (u64)status << ((i*24) + (j%3)*8); - } - } - - data->msa->valid = 1; - data->msa->last_updated = jiffies; - -exit: - mutex_unlock(&data->update_lock); - return (status < 0) ? ERR_PTR(status) : data; -} - -static ssize_t sfp_set_tx_disable(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - unsigned short cpld_addr = 0; - u8 cpld_reg = 0, cpld_val = 0, cpld_bit = 0; - long disable; - int error; - u8 tx_disable_regs[] = {0x20, 0x22, 0x24}; - - if (data->driver_type == DRIVER_TYPE_QSFP) { - return qsfp_set_tx_disable(dev, da, buf, count); - } - - error = kstrtol(buf, 10, &disable); - if (error) { - return error; - } - - mutex_lock(&data->update_lock); - - if(data->port < 24) { - cpld_addr = I2C_ADDR_CPLD1; - cpld_reg = tx_disable_regs[data->port / 8]; - cpld_bit = 1 << (data->port % 8); - } - else { /* port 24 ~ 48 */ - cpld_addr = I2C_ADDR_CPLD2; - cpld_reg = tx_disable_regs[(data->port - 24) / 8]; - cpld_bit = 1 << (data->port % 8); - } - - /* Read current status */ - cpld_val = accton_i2c_cpld_read(cpld_addr, cpld_reg); - - /* Update tx_disable status */ - if (disable) { - data->msa->status[1] |= BIT_INDEX(data->port); - cpld_val |= cpld_bit; - } - else { - data->msa->status[1] &= ~BIT_INDEX(data->port); - cpld_val &= ~cpld_bit; - } - - accton_i2c_cpld_write(cpld_addr, cpld_reg, cpld_val); - mutex_unlock(&data->update_lock); - return count; -} - -static int sfp_is_port_present(struct i2c_client *client, int port) -{ - struct sfp_port_data *data = i2c_get_clientdata(client); - - data = sfp_update_present(client); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - return !(data->present & BIT_INDEX(data->port)); /* Platform dependent */ -} - -static ssize_t show_present(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - - if (PRESENT_ALL == attr->index) { - int i; - u8 values[7] = {0}; - struct sfp_port_data *data = sfp_update_present(client); - - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - for (i = 0; i < ARRAY_SIZE(values); i++) { - values[i] = ~(u8)(data->present >> (i * 8)); - } - - /* Return values 1 -> 54 in order */ - return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", - values[0], values[1], values[2], - values[3], values[4], values[5], - values[6] & 0x3F); - } - else { - struct sfp_port_data *data = i2c_get_clientdata(client); - int present = sfp_is_port_present(client, data->port); - - if (IS_ERR_VALUE(present)) { - return present; - } - - /* PRESENT */ - return sprintf(buf, "%d\n", present); - } -} -/* Platform dependent --- */ - -static struct sfp_port_data *sfp_update_port_type(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - u8 buf = 0; - int status; - - mutex_lock(&data->update_lock); - - switch (data->driver_type) { - case DRIVER_TYPE_SFP_MSA: - { - status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); - if (unlikely(status < 0)) { - data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; - break; - } - - if (buf != SFF8024_DEVICE_ID_SFP) { - data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; - break; - } - - status = sfp_eeprom_read(client, SFF8472_10G_ETH_COMPLIANCE_ADDR, &buf, sizeof(buf)); - if (unlikely(status < 0)) { - data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; - break; - } - - DEBUG_PRINT("sfp port type (0x3) data = (0x%x)", buf); - data->port_type = buf & SFF8472_10G_BASE_MASK ? OOM_DRIVER_PORT_TYPE_SFP_PLUS : OOM_DRIVER_PORT_TYPE_SFP; - break; - } - case DRIVER_TYPE_QSFP: - { - status = sfp_eeprom_read(client, SFF8024_PHYSICAL_DEVICE_ID_ADDR, &buf, sizeof(buf)); - if (unlikely(status < 0)) { - data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; - break; - } - - DEBUG_PRINT("qsfp port type (0x0) buf = (0x%x)", buf); - switch (buf) { - case SFF8024_DEVICE_ID_QSFP: - data->port_type = OOM_DRIVER_PORT_TYPE_QSFP; - break; - case SFF8024_DEVICE_ID_QSFP_PLUS: - data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; - break; - case SFF8024_DEVICE_ID_QSFP28: - data->port_type = OOM_DRIVER_PORT_TYPE_QSFP_PLUS; - break; - default: - data->port_type = OOM_DRIVER_PORT_TYPE_INVALID; - break; - } - - break; - } - default: - break; - } - - mutex_unlock(&data->update_lock); - return data; -} - -static ssize_t show_port_type(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - int present = sfp_is_port_present(client, data->port); - - if (IS_ERR_VALUE(present)) { - return present; - } - - if (!present) { - return sprintf(buf, "%d\n", OOM_DRIVER_PORT_TYPE_NOT_PRESENT); - } - - sfp_update_port_type(dev); - return sprintf(buf, "%d\n", data->port_type); -} - -static struct sfp_port_data *qsfp_update_tx_rx_status(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - int i, status = -1; - u8 buf = 0; - u8 reg[] = {SFF8436_TX_FAULT_ADDR, SFF8436_TX_DISABLE_ADDR, SFF8436_RX_LOS_ADDR}; - - if (time_before(jiffies, data->qsfp->last_updated + HZ + HZ / 2) && data->qsfp->valid) { - return data; - } - - DEBUG_PRINT("Starting sfp tx rx status update"); - mutex_lock(&data->update_lock); - data->qsfp->valid = 0; - memset(data->qsfp->status, 0, sizeof(data->qsfp->status)); - - /* Notify device to update tx fault/ tx disable/ rx los status */ - for (i = 0; i < ARRAY_SIZE(reg); i++) { - status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); - if (unlikely(status < 0)) { - goto exit; - } - } - msleep(200); - - /* Read actual tx fault/ tx disable/ rx los status */ - for (i = 0; i < ARRAY_SIZE(reg); i++) { - status = sfp_eeprom_read(client, reg[i], &buf, sizeof(buf)); - if (unlikely(status < 0)) { - goto exit; - } - - DEBUG_PRINT("qsfp reg(0x%x) status = (0x%x)", reg[i], data->qsfp->status[i]); - data->qsfp->status[i] = (buf & 0xF); - } - - data->qsfp->valid = 1; - data->qsfp->last_updated = jiffies; - -exit: - mutex_unlock(&data->update_lock); - return (status < 0) ? ERR_PTR(status) : data; -} - -static ssize_t qsfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, - char *buf) -{ - int present; - u8 val = 0; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - - present = sfp_is_port_present(client, data->port); - if (IS_ERR_VALUE(present)) { - return present; - } - - if (present == 0) { - /* port is not present */ - return -ENXIO; - } - - data = qsfp_update_tx_rx_status(dev); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - switch (attr->index) { - case TX_FAULT: - val = !!(data->qsfp->status[2] & 0xF); - break; - case TX_FAULT1: - case TX_FAULT2: - case TX_FAULT3: - case TX_FAULT4: - val = !!(data->qsfp->status[2] & BIT_INDEX(attr->index - TX_FAULT1)); - break; - case TX_DISABLE: - val = data->qsfp->status[1] & 0xF; - break; - case TX_DISABLE1: - case TX_DISABLE2: - case TX_DISABLE3: - case TX_DISABLE4: - val = !!(data->qsfp->status[1] & BIT_INDEX(attr->index - TX_DISABLE1)); - break; - case RX_LOS: - val = !!(data->qsfp->status[0] & 0xF); - break; - case RX_LOS1: - case RX_LOS2: - case RX_LOS3: - case RX_LOS4: - val = !!(data->qsfp->status[0] & BIT_INDEX(attr->index - RX_LOS1)); - break; - default: - break; - } - - return sprintf(buf, "%d\n", val); -} - -static ssize_t qsfp_set_tx_disable(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - long disable; - int status; - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - - status = sfp_is_port_present(client, data->port); - if (IS_ERR_VALUE(status)) { - return status; - } - - if (!status) { - /* port is not present */ - return -ENXIO; - } - - status = kstrtol(buf, 10, &disable); - if (status) { - return status; - } - - data = qsfp_update_tx_rx_status(dev); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - mutex_lock(&data->update_lock); - - if (attr->index == TX_DISABLE) { - data->qsfp->status[1] = disable & 0xF; - } - else {/* TX_DISABLE1 ~ TX_DISABLE4*/ - if (disable) { - data->qsfp->status[1] |= (1 << (attr->index - TX_DISABLE1)); - } - else { - data->qsfp->status[1] &= ~(1 << (attr->index - TX_DISABLE1)); - } - } - - DEBUG_PRINT("index = (%d), status = (0x%x)", attr->index, data->qsfp->status[1]); - status = sfp_eeprom_write(data->client, SFF8436_TX_DISABLE_ADDR, &data->qsfp->status[1], sizeof(data->qsfp->status[1])); - if (unlikely(status < 0)) { - count = status; - } - - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t sfp_show_ddm_implemented(struct device *dev, struct device_attribute *da, - char *buf) -{ - int status; - char ddm; - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - - status = sfp_is_port_present(client, data->port); - if (IS_ERR_VALUE(status)) { - return status; - } - - if (status == 0) { - /* port is not present */ - return -ENODEV; - } - - status = sfp_eeprom_read(client, SFF8472_DIAG_MON_TYPE_ADDR, &ddm, sizeof(ddm)); - if (unlikely(status < 0)) { - return status; - } - - return sprintf(buf, "%d\n", !!(ddm & SFF8472_DIAG_MON_TYPE_DDM_MASK)); -} - -/* Platform dependent +++ */ -static ssize_t sfp_show_tx_rx_status(struct device *dev, struct device_attribute *da, - char *buf) -{ - u8 val = 0, index = 0; - struct i2c_client *client = to_i2c_client(dev); - struct sfp_port_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - if (data->driver_type == DRIVER_TYPE_QSFP) { - return qsfp_show_tx_rx_status(dev, da, buf); - } - - data = sfp_update_tx_rx_status(dev); - if (IS_ERR(data)) { - return PTR_ERR(data); - } - - if(attr->index == RX_LOS_ALL) { - int i = 0; - u8 values[6] = {0}; - - for (i = 0; i < ARRAY_SIZE(values); i++) { - values[i] = (u8)(data->msa->status[2] >> (i * 8)); - } - - /** Return values 1 -> 48 in order */ - return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", - values[0], values[1], values[2], - values[3], values[4], values[5]); - } - - switch (attr->index) { - case TX_FAULT: - index = 0; - break; - case TX_DISABLE: - index = 1; - break; - case RX_LOS: - index = 2; - break; - default: - return 0; - } - - val = !!(data->msa->status[index] & BIT_INDEX(data->port)); - return sprintf(buf, "%d\n", val); -} -/* Platform dependent --- */ -static ssize_t sfp_eeprom_write(struct i2c_client *client, u8 command, const char *data, - int data_len) -{ -#if USE_I2C_BLOCK_READ - int status, retry = I2C_RW_RETRY_COUNT; - - if (data_len > I2C_SMBUS_BLOCK_MAX) { - data_len = I2C_SMBUS_BLOCK_MAX; - } - - while (retry) { - status = i2c_smbus_write_i2c_block_data(client, command, data_len, data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - return status; - } - - return data_len; -#else - int status, retry = I2C_RW_RETRY_COUNT; - - while (retry) { - status = i2c_smbus_write_byte_data(client, command, *data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - return status; - } - - return 1; -#endif - - -} - -static ssize_t sfp_port_write(struct sfp_port_data *data, - const char *buf, loff_t off, size_t count) -{ - ssize_t retval = 0; - - if (unlikely(!count)) { - return count; - } - - /* - * Write data to chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&data->update_lock); - - while (count) { - ssize_t status; - - status = sfp_eeprom_write(data->client, off, buf, count); - if (status <= 0) { - if (retval == 0) { - retval = status; - } - break; - } - buf += status; - off += status; - count -= status; - retval += status; - } - - mutex_unlock(&data->update_lock); - return retval; -} - - -static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - int present; - struct sfp_port_data *data; - DEBUG_PRINT("%s(%d) offset = (%d), count = (%d)", off, count); - data = dev_get_drvdata(container_of(kobj, struct device, kobj)); - - present = sfp_is_port_present(data->client, data->port); - if (IS_ERR_VALUE(present)) { - return present; - } - - if (present == 0) { - /* port is not present */ - return -ENODEV; - } - - return sfp_port_write(data, buf, off, count); -} - -static ssize_t sfp_eeprom_read(struct i2c_client *client, u8 command, u8 *data, - int data_len) -{ -#if USE_I2C_BLOCK_READ - int status, retry = I2C_RW_RETRY_COUNT; - - if (data_len > I2C_SMBUS_BLOCK_MAX) { - data_len = I2C_SMBUS_BLOCK_MAX; - } - - while (retry) { - status = i2c_smbus_read_i2c_block_data(client, command, data_len, data); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - goto abort; - } - if (unlikely(status != data_len)) { - status = -EIO; - goto abort; - } - - //result = data_len; - -abort: - return status; -#else - int status, retry = I2C_RW_RETRY_COUNT; - - while (retry) { - status = i2c_smbus_read_byte_data(client, command); - if (unlikely(status < 0)) { - msleep(I2C_RW_RETRY_INTERVAL); - retry--; - continue; - } - - break; - } - - if (unlikely(status < 0)) { - dev_dbg(&client->dev, "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", command, status); - goto abort; - } - - *data = (u8)status; - status = 1; - -abort: - return status; -#endif -} - -static ssize_t sfp_port_read(struct sfp_port_data *data, - char *buf, loff_t off, size_t count) -{ - ssize_t retval = 0; - - if (unlikely(!count)) { - DEBUG_PRINT("Count = 0, return"); - return count; - } - - /* - * Read data from chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&data->update_lock); - - while (count) { - ssize_t status; - - status = sfp_eeprom_read(data->client, off, buf, count); - if (status <= 0) { - if (retval == 0) { - retval = status; - } - break; - } - - buf += status; - off += status; - count -= status; - retval += status; - } - - mutex_unlock(&data->update_lock); - return retval; - -} - -static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - int present; - struct sfp_port_data *data; - DEBUG_PRINT("offset = (%d), count = (%d)", off, count); - data = dev_get_drvdata(container_of(kobj, struct device, kobj)); - - present = sfp_is_port_present(data->client, data->port); - if (IS_ERR_VALUE(present)) { - return present; - } - - if (present == 0) { - /* port is not present */ - return -ENODEV; - } - - return sfp_port_read(data, buf, off, count); -} - -static int sfp_sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) -{ - int err; - - sysfs_bin_attr_init(eeprom); - eeprom->attr.name = EEPROM_NAME; - eeprom->attr.mode = S_IWUSR | S_IRUGO; - eeprom->read = sfp_bin_read; - eeprom->write = sfp_bin_write; - eeprom->size = EEPROM_SIZE; - - /* Create eeprom file */ - err = sysfs_create_bin_file(kobj, eeprom); - if (err) { - return err; - } - - return 0; -} - -static int sfp_sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) -{ - sysfs_remove_bin_file(kobj, eeprom); - return 0; -} - -static const struct attribute_group sfp_msa_group = { - .attrs = sfp_msa_attributes, -}; - -static int sfp_i2c_check_functionality(struct i2c_client *client) -{ -#if USE_I2C_BLOCK_READ - return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK); -#else - return i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA); -#endif -} - -static int sfp_msa_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, - struct sfp_msa_data **data) -{ - int status; - struct sfp_msa_data *msa; - - if (!sfp_i2c_check_functionality(client)) { - status = -EIO; - goto exit; - } - - msa = kzalloc(sizeof(struct sfp_msa_data), GFP_KERNEL); - if (!msa) { - status = -ENOMEM; - goto exit; - } - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &sfp_msa_group); - if (status) { - goto exit_free; - } - - /* init eeprom */ - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &msa->eeprom.bin); - if (status) { - goto exit_remove; - } - - *data = msa; - dev_info(&client->dev, "sfp msa '%s'\n", client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); -exit_free: - kfree(msa); -exit: - - return status; -} - -static const struct attribute_group sfp_ddm_group = { - .attrs = sfp_ddm_attributes, -}; - -static int sfp_ddm_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, - struct sfp_ddm_data **data) -{ - int status; - struct sfp_ddm_data *ddm; - - if (!sfp_i2c_check_functionality(client)) { - status = -EIO; - goto exit; - } - - ddm = kzalloc(sizeof(struct sfp_ddm_data), GFP_KERNEL); - if (!ddm) { - status = -ENOMEM; - goto exit; - } - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &sfp_ddm_group); - if (status) { - goto exit_free; - } - - /* init eeprom */ - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &ddm->eeprom.bin); - if (status) { - goto exit_remove; - } - - *data = ddm; - dev_info(&client->dev, "sfp ddm '%s'\n", client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); -exit_free: - kfree(ddm); -exit: - - return status; -} - -static const struct attribute_group qsfp_group = { - .attrs = qsfp_attributes, -}; - -static int qsfp_probe(struct i2c_client *client, const struct i2c_device_id *dev_id, - struct qsfp_data **data) -{ - int status; - struct qsfp_data *qsfp; - - if (!sfp_i2c_check_functionality(client)) { - status = -EIO; - goto exit; - } - - qsfp = kzalloc(sizeof(struct qsfp_data), GFP_KERNEL); - if (!qsfp) { - status = -ENOMEM; - goto exit; - } - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &qsfp_group); - if (status) { - goto exit_free; - } - - /* init eeprom */ - status = sfp_sysfs_eeprom_init(&client->dev.kobj, &qsfp->eeprom.bin); - if (status) { - goto exit_remove; - } - - *data = qsfp; - dev_info(&client->dev, "qsfp '%s'\n", client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &qsfp_group); -exit_free: - kfree(qsfp); -exit: - - return status; -} - -/* Platform dependent +++ */ -static int sfp_device_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - struct sfp_port_data *data = NULL; - - data = kzalloc(sizeof(struct sfp_port_data), GFP_KERNEL); - if (!data) { - return -ENOMEM; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - data->port = dev_id->driver_data; - data->client = client; - - if (dev_id->driver_data >= as5916_54xk_sfp1 && dev_id->driver_data <= as5916_54xk_sfp48) { - if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { - data->driver_type = DRIVER_TYPE_SFP_MSA; - return sfp_msa_probe(client, dev_id, &data->msa); - } - else if (client->addr == SFP_EEPROM_A2_I2C_ADDR) { - data->driver_type = DRIVER_TYPE_SFP_DDM; - return sfp_ddm_probe(client, dev_id, &data->ddm); - } - } - else { /* as5916_54xk_sfp49 ~ as5916_54xk_sfp54 */ - if (client->addr == SFP_EEPROM_A0_I2C_ADDR) { - data->driver_type = DRIVER_TYPE_QSFP; - return qsfp_probe(client, dev_id, &data->qsfp); - } - } - - return -ENODEV; -} -/* Platform dependent --- */ - -static int sfp_msa_remove(struct i2c_client *client, struct sfp_msa_data *data) -{ - sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); - sysfs_remove_group(&client->dev.kobj, &sfp_msa_group); - kfree(data); - return 0; -} - -static int sfp_ddm_remove(struct i2c_client *client, struct sfp_ddm_data *data) -{ - sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); - sysfs_remove_group(&client->dev.kobj, &sfp_ddm_group); - kfree(data); - return 0; -} - -static int qfp_remove(struct i2c_client *client, struct qsfp_data *data) -{ - sfp_sysfs_eeprom_cleanup(&client->dev.kobj, &data->eeprom.bin); - sysfs_remove_group(&client->dev.kobj, &qsfp_group); - kfree(data); - return 0; -} - -static int sfp_device_remove(struct i2c_client *client) -{ - struct sfp_port_data *data = i2c_get_clientdata(client); - - switch (data->driver_type) { - case DRIVER_TYPE_SFP_MSA: - return sfp_msa_remove(client, data->msa); - case DRIVER_TYPE_SFP_DDM: - return sfp_ddm_remove(client, data->ddm); - case DRIVER_TYPE_QSFP: - return qfp_remove(client, data->qsfp); - } - - return 0; -} - -/* Addresses scanned - */ -static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; - -static struct i2c_driver sfp_driver = { - .driver = { - .name = DRIVER_NAME, - }, - .probe = sfp_device_probe, - .remove = sfp_device_remove, - .id_table = sfp_device_id, - .address_list = normal_i2c, -}; - -static int __init sfp_init(void) -{ - return i2c_add_driver(&sfp_driver); -} - -static void __exit sfp_exit(void) -{ - i2c_del_driver(&sfp_driver); -} - -MODULE_AUTHOR("Brandon Chuang "); -MODULE_DESCRIPTION("accton as5916_54xk_sfp driver"); -MODULE_LICENSE("GPL"); - -late_initcall(sfp_init); -module_exit(sfp_exit); - - diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/onlp/builds/src/module/src/sfpi.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/onlp/builds/src/module/src/sfpi.c index f4d29904..4f7abdd1 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/onlp/builds/src/module/src/sfpi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/onlp/builds/src/module/src/sfpi.c @@ -24,17 +24,21 @@ * ***********************************************************/ #include +#include #include -#include "platform_lib.h" - +#include "x86_64_accton_as5916_54xk_int.h" #include "x86_64_accton_as5916_54xk_log.h" -#define NUM_OF_SFP_PORT 54 -#define MAX_PORT_PATH 64 +#define PORT_BUS_INDEX(port) (port+33) -#define SFP_PORT_FORMAT "/sys/bus/i2c/devices/%d-0050/%s" -#define SFP_PORT_DOM_FORMAT "/sys/bus/i2c/devices/%d-0051/%s" -#define SFP_BUS_INDEX(port) (port+33) +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" +#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_present_%d" +#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_rx_los_%d" +#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_fault_%d" +#define MODULE_TXDISABLE_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_disable_%d" +#define MODULE_PRESENT_ALL_ATTR "/sys/bus/i2c/devices/%d-00%d/module_present_all" +#define MODULE_RXLOS_ALL_ATTR_CPLD1 "/sys/bus/i2c/devices/11-0060/module_rx_los_all" +#define MODULE_RXLOS_ALL_ATTR_CPLD2 "/sys/bus/i2c/devices/12-0062/module_rx_los_all" /************************************************************ * @@ -56,7 +60,7 @@ onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) */ int p; - for(p = 0; p < NUM_OF_SFP_PORT; p++) { + for(p = 0; p < 54; p++) { AIM_BITMAP_SET(bmap, p); } @@ -72,7 +76,12 @@ onlp_sfpi_is_present(int port) * Return < 0 if error. */ int present; - if (onlp_file_read_int(&present, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_is_present") < 0) { + int bus, addr; + + addr = (port < 24) ? 60 : 62; + bus = (addr == 60) ? 11 : 12; + + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, bus, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); return ONLP_STATUS_E_INTERNAL; } @@ -83,31 +92,45 @@ onlp_sfpi_is_present(int port) int onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) { - uint32_t bytes[7]; - char path[MAX_PORT_PATH] = {0}; + uint32_t bytes[7], *ptr = NULL; FILE* fp; + int addr; - sprintf(path, SFP_PORT_FORMAT, SFP_BUS_INDEX(0), "sfp_is_present_all"); - fp = fopen(path, "r"); + ptr = bytes; - if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file."); - return ONLP_STATUS_E_INTERNAL; - } - int count = fscanf(fp, "%x %x %x %x %x %x %x", - bytes+0, - bytes+1, - bytes+2, - bytes+3, - bytes+4, - bytes+5, - bytes+6 - ); - fclose(fp); - if(count != AIM_ARRAYSIZE(bytes)) { - /* Likely a CPLD read timeout. */ - AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file."); - return ONLP_STATUS_E_INTERNAL; + for (addr = 60; addr <= 62; addr+=2) { + /* Read present status of port 0~53 */ + int count = 0; + char file[64] = {0}; + int bus = (addr == 60) ? 11 : 12; + + sprintf(file, MODULE_PRESENT_ALL_ATTR, bus, addr); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD(0x%d).", addr); + return ONLP_STATUS_E_INTERNAL; + } + + if (addr == 60) { /* CPLD1 */ + count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2); + fclose(fp); + if(count != 3) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD(0x%d).", addr); + return ONLP_STATUS_E_INTERNAL; + } + } + else { /* CPLD2 */ + count = fscanf(fp, "%x %x %x %x", ptr+0, ptr+1, ptr+2, ptr+3); + fclose(fp); + if(count != 4) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD(0x%d).", addr); + return ONLP_STATUS_E_INTERNAL; + } + } + + ptr += count; } /* Mask out non-existant QSFP ports */ @@ -130,64 +153,44 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) return ONLP_STATUS_OK; } -int -onlp_sfpi_eeprom_read(int port, uint8_t data[256]) -{ - int size = 0; - if(onlp_file_read(data, 256, &size, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_eeprom") == ONLP_STATUS_OK) { - if(size == 256) { - return ONLP_STATUS_OK; - } - } - - return ONLP_STATUS_E_INTERNAL; -} - -int -onlp_sfpi_dom_read(int port, uint8_t data[256]) -{ - int size = 0; - if(onlp_file_read(data, 256, &size, SFP_PORT_DOM_FORMAT, SFP_BUS_INDEX(port), "sfp_eeprom") == ONLP_STATUS_OK) { - if(size == 256) { - return ONLP_STATUS_OK; - } - } - - return ONLP_STATUS_E_INTERNAL; -} - int onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) { uint32_t bytes[6]; - char path[MAX_PORT_PATH] = {0}; + uint32_t *ptr = bytes; FILE* fp; - sprintf(path, SFP_PORT_FORMAT, SFP_BUS_INDEX(0), "sfp_rx_los_all"); - fp = fopen(path, "r"); + /* Read present status of port 0~23 */ + int addr, i = 0; - if(fp == NULL) { - AIM_LOG_ERROR("Unable to open the sfp_rx_los_all device file."); - return ONLP_STATUS_E_INTERNAL; - } - int count = fscanf(fp, "%x %x %x %x %x %x", - bytes+0, - bytes+1, - bytes+2, - bytes+3, - bytes+4, - bytes+5 - ); - fclose(fp); - if(count != 6) { - AIM_LOG_ERROR("Unable to read all fields from the sfp_rx_los_all device file."); - return ONLP_STATUS_E_INTERNAL; + for (addr = 60; addr <= 62; addr+=2) { + if (addr == 60) { + fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD1, "r"); + } + else { + fp = fopen(MODULE_RXLOS_ALL_ATTR_CPLD2, "r"); + } + + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_rx_los_all device file of CPLD(0x%d)", addr); + return ONLP_STATUS_E_INTERNAL; + } + + int count = fscanf(fp, "%x %x %x", ptr+0, ptr+1, ptr+2); + fclose(fp); + if(count != 3) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields from the module_rx_los_all device file of CPLD(0x%d)", addr); + return ONLP_STATUS_E_INTERNAL; + } + + ptr += count; } /* Convert to 64 bit integer in port order */ - int i = 0; + i = 0; uint64_t rx_los_all = 0 ; - for(i = 5; i >= 0; i--) { + for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) { rx_los_all <<= 8; rx_los_all |= bytes[i]; } @@ -201,16 +204,77 @@ onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) return ONLP_STATUS_OK; } +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + /* + * Read the SFP eeprom into data[] + * + * Return MISSING if SFP is missing. + * Return OK if eeprom is read + */ + int size = 0; + memset(data, 0, 256); + + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port)) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + FILE* fp; + char file[64] = {0}; + + sprintf(file, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port)); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (fseek(fp, 256, SEEK_CUR) != 0) { + fclose(fp); + AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + int ret = fread(data, 1, 256, fp); + fclose(fp); + if (ret != 256) { + AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + int onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) { int rv; + if (port < 0 || port >= 48) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + int addr = (port < 24) ? 60 : 62; + int bus = (addr == 60) ? 11 : 12; + switch(control) { case ONLP_SFP_CONTROL_TX_DISABLE: { - if (onlp_file_write_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_tx_disable") != 0) { + if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -233,12 +297,19 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) { int rv; + if (port < 0 || port >= 48) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + int addr = (port < 24) ? 60 : 62; + int bus = (addr == 60) ? 11 : 12; + switch(control) { case ONLP_SFP_CONTROL_RX_LOS: { - if (onlp_file_read_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_rx_los") < 0) { - AIM_LOG_ERROR("Unable to read rx_los status from port(%d)\r\n", port); + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } else { @@ -249,7 +320,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_FAULT: { - if (onlp_file_read_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_tx_fault") < 0) { + if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, bus, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -261,7 +332,7 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) case ONLP_SFP_CONTROL_TX_DISABLE: { - if (onlp_file_read_int(value, SFP_PORT_FORMAT, SFP_BUS_INDEX(port), "sfp_tx_disable") < 0) { + if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) { AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port); rv = ONLP_STATUS_E_INTERNAL; } @@ -278,7 +349,6 @@ onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) return rv; } - int onlp_sfpi_denit(void) { diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/platform-config/r1/src/python/x86_64_accton_as5916_54xk_r1/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/platform-config/r1/src/python/x86_64_accton_as5916_54xk_r1/__init__.py index da17b4ea..dc4b3fe0 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/platform-config/r1/src/python/x86_64_accton_as5916_54xk_r1/__init__.py +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xk/platform-config/r1/src/python/x86_64_accton_as5916_54xk_r1/__init__.py @@ -8,9 +8,9 @@ class OnlPlatform_x86_64_accton_as5916_54xk_r1(OnlPlatformAccton, SYS_OBJECT_ID=".5916.54" def baseconfig(self): - self.insmod("accton_i2c_cpld") + self.insmod('optoe') self.insmod("ym2651y") - for m in [ "sfp", "psu", "fan", "leds" ]: + for m in [ "cpld", "psu", "fan", "leds" ]: self.insmod("x86-64-accton-as5916-54xk-%s" % m) ########### initialize I2C bus 0 ########### @@ -30,8 +30,8 @@ class OnlPlatform_x86_64_accton_as5916_54xk_r1(OnlPlatformAccton, ('lm75', 0x4b, 10), # initialize CPLDs - ('accton_i2c_cpld', 0x60, 11), - ('accton_i2c_cpld', 0x62, 12), + ('as5916_54xk_cpld1', 0x60, 11), + ('as5916_54xk_cpld2', 0x62, 12), # initialize multiplexer (PCA9548) ('pca9548', 0x74, 2), @@ -61,12 +61,14 @@ class OnlPlatform_x86_64_accton_as5916_54xk_r1(OnlPlatformAccton, # initialize SFP devices for port in range(1, 49): - self.new_i2c_device('as5916_54xk_sfp%d' % port, 0x50, port+32) - self.new_i2c_device('as5916_54xk_sfp%d' % port, 0x51, port+32) + self.new_i2c_device('optoe2', 0x50, port+32) # initialize QSFP devices for port in range(49, 55): - self.new_i2c_device('as5916_54xk_sfp%d' % port, 0x50, port+32) + self.new_i2c_device('optoe1', 0x50, port+32) + + for port in range(1, 55): + subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port+32), shell=True) return True diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/sysi.c b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/sysi.c index d01d1dc9..21e6daf1 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/sysi.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/onlp/builds/src/module/src/sysi.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -55,17 +56,26 @@ onlp_sysi_platform_get(void) int onlp_sysi_onie_data_get(uint8_t** data, int* size) { + int ret = ONLP_STATUS_OK; + int i = 0; uint8_t* rdata = aim_zmalloc(256); - if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) { - if(*size == 256) { - *data = rdata; - return ONLP_STATUS_OK; + + for (i = 0; i < 128; i++) { + ret = onlp_i2c_readw(0, 0x56, i*2, ONLP_I2C_F_FORCE); + if (ret < 0) { + aim_free(rdata); + *size = 0; + return ret; } + + rdata[i*2] = ret & 0xff; + rdata[i*2+1] = (ret >> 8) & 0xff; } - aim_free(rdata); - *size = 0; - return ONLP_STATUS_E_INTERNAL; + *size = 256; + *data = rdata; + + return ONLP_STATUS_OK; } int diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/platform-config/r0/src/python/x86_64_accton_as5916_54xks_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/platform-config/r0/src/python/x86_64_accton_as5916_54xks_r0/__init__.py index d723aa4a..5dd206e8 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/platform-config/r0/src/python/x86_64_accton_as5916_54xks_r0/__init__.py +++ b/packages/platforms/accton/x86-64/x86-64-accton-as5916-54xks/platform-config/r0/src/python/x86_64_accton_as5916_54xks_r0/__init__.py @@ -54,8 +54,6 @@ class OnlPlatform_x86_64_accton_as5916_54xks_r0(OnlPlatformAccton, ('pca9548', 0x75, 30), ('pca9548', 0x75, 31), - # initiate IDPROM - ('24c02', 0x56, 0), ] ) diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7312-54x/platform-config/r0/src/lib/x86-64-accton-as7312-54x-r0.yml b/packages/platforms/accton/x86-64/x86-64-accton-as7312-54x/platform-config/r0/src/lib/x86-64-accton-as7312-54x-r0.yml index cc11bcf6..45051486 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7312-54x/platform-config/r0/src/lib/x86-64-accton-as7312-54x-r0.yml +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7312-54x/platform-config/r0/src/lib/x86-64-accton-as7312-54x-r0.yml @@ -23,6 +23,8 @@ x86-64-accton-as7312-54x-r0: args: >- nopat console=ttyS1,115200n8 + i2c-ismt.bus_speed=100 + i2c-ismt.delay=100 ##network ## interfaces: diff --git a/packages/platforms/accton/x86-64/x86-64-accton-as7312-54xs/platform-config/r0/src/lib/x86-64-accton-as7312-54xs-r0.yml b/packages/platforms/accton/x86-64/x86-64-accton-as7312-54xs/platform-config/r0/src/lib/x86-64-accton-as7312-54xs-r0.yml index d649eb5c..a1d10a4b 100644 --- a/packages/platforms/accton/x86-64/x86-64-accton-as7312-54xs/platform-config/r0/src/lib/x86-64-accton-as7312-54xs-r0.yml +++ b/packages/platforms/accton/x86-64/x86-64-accton-as7312-54xs/platform-config/r0/src/lib/x86-64-accton-as7312-54xs-r0.yml @@ -23,6 +23,8 @@ x86-64-accton-as7312-54xs-r0: args: >- nopat console=ttyS1,115200n8 + i2c-ismt.bus_speed=100 + i2c-ismt.delay=100 ##network ## interfaces: diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/PKG.yml index 3f59762e..d857a900 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/PKG.yml +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/PKG.yml @@ -1 +1 @@ -!include $ONL_TEMPLATES/platform-modules.yml VENDOR=accton BASENAME=x86-64-accton-csp9250 ARCH=amd64 KERNELS="onl-kernel-3.16-lts-x86-64-all:amd64" +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=accton BASENAME=x86-64-accton-csp9250 ARCH=amd64 KERNELS="onl-kernel-4.14-lts-x86-64-all:amd64" diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-leds.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-leds.c index f3a2f878..c6237ccd 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-leds.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-leds.c @@ -33,10 +33,6 @@ extern int csp9250_i2c_cpld_read (unsigned short cpld_addr, u8 reg); extern int csp9250_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); -extern void led_classdev_unregister(struct led_classdev *led_cdev); -extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev); -extern void led_classdev_resume(struct led_classdev *led_cdev); -extern void led_classdev_suspend(struct led_classdev *led_cdev); #define DRVNAME "accton_csp9250_led" diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-sfp.c b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-sfp.c index d13bf7c9..1a3f1775 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-sfp.c +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/modules/builds/x86-64-accton-csp9250-sfp.c @@ -1005,9 +1005,8 @@ static ssize_t sfp_port_read(struct sfp_port_data *data, char *buf, loff_t off, size_t count) { ssize_t retval = 0; - printk("acc trace %s:%d\n", __FUNCTION__, __LINE__); + if (unlikely(!count)) { - printk("acc trace %s:%d\n", __FUNCTION__, __LINE__); DEBUG_PRINT("Count = 0, return"); return count; } @@ -1017,7 +1016,6 @@ static ssize_t sfp_port_read(struct sfp_port_data *data, * from this host, but not from other I2C masters. */ mutex_lock(&data->update_lock); - printk("acc trace %s:%d, off=0x%x,data->client->addr=0x%x\n", __FUNCTION__, __LINE__, off,data->client->addr); while (count) { ssize_t status; @@ -1026,7 +1024,6 @@ static ssize_t sfp_port_read(struct sfp_port_data *data, if (retval == 0) { retval = status; } - printk("acc trace %s:%d\n", __FUNCTION__, __LINE__); break; } @@ -1049,13 +1046,10 @@ static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, struct sfp_port_data *data; DEBUG_PRINT("offset = (%d), count = (%d)", off, count); data = dev_get_drvdata(container_of(kobj, struct device, kobj)); - printk("acc trace %s:%d, data->port=%d\n", __FUNCTION__, __LINE__, data->port); - printk("offset = (%d), count = (%d)", off, count); present = sfp_is_port_present(data->client, data->port); if (IS_ERR_VALUE(present)) { return present; } - printk("Acc trace %s:%d, present=%d\n", __FUNCTION__, __LINE__, present); if (present == 0) { /* port is not present */ return -ENODEV; @@ -1331,11 +1325,6 @@ static struct i2c_driver sfp_driver = { static int __init csp9250_sfp_init(void) { - //extern int platform_accton_csp9250(void); - //if(!platform_accton_csp9250()) { - // return -ENODEV; - //} - printk("Acc trace %s\n", __FUNCTION__); return i2c_add_driver(&sfp_driver); } diff --git a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/platform-config/r0/src/lib/x86-64-accton-csp9250-r0.yml b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/platform-config/r0/src/lib/x86-64-accton-csp9250-r0.yml index 8425af5c..5ff7bf95 100755 --- a/packages/platforms/accton/x86-64/x86-64-accton-csp9250/platform-config/r0/src/lib/x86-64-accton-csp9250-r0.yml +++ b/packages/platforms/accton/x86-64/x86-64-accton-csp9250/platform-config/r0/src/lib/x86-64-accton-csp9250-r0.yml @@ -12,7 +12,7 @@ x86-64-accton-csp9250-r0: serial: >- console=tty0 kernel: - <<: *kernel-3-16 + <<: *kernel-4-14 args: >- console=tty0, diff --git a/packages/platforms/netberg/vendor-config/src/python/netberg/__init__.py b/packages/platforms/netberg/vendor-config/src/python/netberg/__init__.py index 96061bb8..ce64a2e9 100755 --- a/packages/platforms/netberg/vendor-config/src/python/netberg/__init__.py +++ b/packages/platforms/netberg/vendor-config/src/python/netberg/__init__.py @@ -4,4 +4,4 @@ from onl.platform.base import * class OnlPlatformNetberg(OnlPlatformBase): MANUFACTURER='Netberg' - PRIVATE_ENTERPRISE_NUMBER=47294 + PRIVATE_ENTERPRISE_NUMBER=50424 diff --git a/packages/platforms/netberg/x86-64/modules/builds/hardware_monitor.c b/packages/platforms/netberg/x86-64/modules/builds/hardware_monitor.c index fa3e711e..179f8047 100755 --- a/packages/platforms/netberg/x86-64/modules/builds/hardware_monitor.c +++ b/packages/platforms/netberg/x86-64/modules/builds/hardware_monitor.c @@ -25,8 +25,11 @@ enum platform_type { #define W83795ADG_VENDOR_ID 0x5CA3 #define W83795ADG_CHIP_ID 0x79 -#define W83795ADG_TEMP_COUNT 2 -#define W83795ADG_FAN_COUNT 8 +#define W83795ADG_NUM2 2 +#define W83795ADG_NUM8 8 + +#define W83795ADG_TEMP_COUNT 4 +#define W83795ADG_FAN_COUNT 10 #define W83795ADG_FAN_SPEED_FACTOR 1350000 /* 1.35 * 10^6 */ #define W83795ADG_FAN_POLES_NUMBER 4 #define W83795ADG_VSEN_COUNT 7 @@ -44,6 +47,7 @@ enum platform_type { /* Bank 0*/ #define W83795ADG_REG_CONFIG 0x01 /* Configuration Register */ #define W83795ADG_REG_TEMP_CTRL2 0x05 /* Temperature Monitoring Control Register */ +#define W83795ADG_REG_FANIN_CTRL2 0x07 /* FANIN CTRL2. FANIN Monitoring Control Register */ #define W83795ADG_REG_VSEN1 0x10 /* VSEN1 voltage readout high byte */ #define W83795ADG_REG_VSEN2 0x11 /* VSEN2 voltage readout high byte */ #define W83795ADG_REG_VSEN3 0x12 /* VSEN3 voltage readout high byte */ @@ -87,6 +91,8 @@ enum platform_type { #define CPLD_REG_LED 0x44 /* FAN LED */ +#define CPLD_REG_MUX 0x4A /* I2C MUX control Register */ + /* 9548 Channel Index */ #define PCA9548_CH00 0 #define PCA9548_CH01 1 @@ -195,6 +201,7 @@ typedef enum /* QSFP */ #define QSFP_COUNT 64 #define QSFP_DATA_SIZE 256 +#define SFP_COPPER_DATA_SIZE 512 #define EEPROM_DATA_SIZE 256 @@ -310,9 +317,10 @@ SFP_PORT_DATA_t sfpPortData_78F[] = { static struct i2c_client qsfpDataA0_client; static struct i2c_client qsfpDataA2_client; +static struct i2c_client SfpCopperData_client; /* i2c bus 0 */ -static struct i2c_client pca9535pwr_client; +static struct i2c_client pca9535pwr_client_bus0; static struct i2c_client cpld_client; static struct i2c_client pca9548_client_bus0; static struct i2c_client pca9535_client_bus0[4]; @@ -324,15 +332,15 @@ static struct i2c_client psu_mcu_client_bus0; /* i2c bus 1 */ static struct i2c_client pca9548_client[4]; -static struct i2c_client pca9535pwr_client_bus1[6]; +static struct i2c_client pca9535pwr_client[6]; static struct i2c_client eeprom_client; -static struct i2c_client eeprom_client_2; static struct i2c_client psu_eeprom_client; static struct i2c_client psu_mcu_client; static unsigned int FanErr[W83795ADG_FAN_COUNT] = {0}; static unsigned int FanDir = 0; +static unsigned int FanDir2 = 0; static unsigned int isBMCSupport = 0; static unsigned int platformBuildRev = 0xffff; @@ -344,9 +352,12 @@ static char platformPsuABS = 0; unsigned int SFPPortAbsStatus[QSFP_COUNT]; unsigned int SFPPortRxLosStatus[QSFP_COUNT]; +unsigned int SFPPortTxFaultStatus[QSFP_COUNT]; char SFPPortDataValid[QSFP_COUNT]; char SFPPortTxDisable[QSFP_COUNT]; +static struct i2c_client cpld_client_bus1; + struct i2c_bus0_hardware_monitor_data { struct device *hwmon_dev; struct attribute_group hwmon_group; @@ -405,16 +416,27 @@ struct i2c_bus1_hardware_monitor_data { unsigned short qsfpPortAbsStatus[4]; char qsfpPortDataA0[QSFP_COUNT][QSFP_DATA_SIZE]; char qsfpPortDataA2[QSFP_COUNT][QSFP_DATA_SIZE]; + char SfpCopperPortData[QSFP_COUNT][SFP_COPPER_DATA_SIZE]; unsigned short qsfpPortDataValid[4]; unsigned short sfpPortTxDisable[3]; unsigned short sfpPortRateSelect[3]; unsigned short sfpPortRxLosStatus[4]; + unsigned short sfpPortTxFaultStatus[4]; unsigned short fanAbs[2]; unsigned short fanDir[2]; unsigned short systemLedStatus; unsigned short frontLedStatus; + unsigned char sfpPortDataValidAst[64]; + unsigned char sfpPortAbsRxLosStatus[24]; + unsigned char qsfpPortAbsStatusAst[16]; + unsigned char sfpPortRateSelectAst[12]; + unsigned char sfpPortTxDisableAst[6]; + + char qsfpPortTxDisableData[QSFP_COUNT]; + char qsfpPortTxDisableDataUpdate[QSFP_COUNT]; + struct i2c_client *sfpPortClient[QSFP_COUNT]; }; /* Addresses to scan */ @@ -460,6 +482,12 @@ static fanControlTable_t fanControlTable[] = {62, 70, 85}, /* temperature threshold (going to up) */ {58, 66, 70}, /* temperature threshold (going to down) */ {0x70, 0xB7, 0xFF} /* fan rpm : 8000, 13000, 16000 */ + }, + /* Asterion */ + { + {70, 75, 80}, /* temperature threshold (going to up) */ + {60, 65, 70}, /* temperature threshold (going to down) */ + {0x8B, 0xD1, 0xFF} /* fan rpm : 12000, 18000, 22000 */ } }; @@ -483,6 +511,12 @@ static fanControlTable_t fanControlTable_B2F[] = {58, 63, 80}, /* temperature threshold (going to up) */ {54, 60, 63}, /* temperature threshold (going to down) */ {0x6F, 0xB7, 0xFF} /* fan rpm : 8000, 13000, 16000 */ + }, + /* Asterion */ + { + {70, 75, 80}, /* temperature threshold (going to up) */ + {60, 65, 70}, /* temperature threshold (going to down) */ + {0x8B, 0xD1, 0xFF} /* fan rpm : 12000, 18000, 22000 */ } }; @@ -508,6 +542,39 @@ static int i2c_device_byte_write(const struct i2c_client *client, unsigned char } #endif +#define BIT_INDEX(i) (1ULL << (i)) +#define SFF8436_RX_LOS_ADDR 3 +#define SFF8436_TX_FAULT_ADDR 4 +#define SFF8436_TX_DISABLE_ADDR 86 + +#define I2C_RW_RETRY_COUNT 3 +#define I2C_RW_RETRY_INTERVAL 100 /* ms */ + +enum port_sysfs_attributes { + PRESENT, + RX_LOS, + RX_LOS1, + RX_LOS2, + RX_LOS3, + RX_LOS4, + TX_DISABLE, + TX_DISABLE1, + TX_DISABLE2, + TX_DISABLE3, + TX_DISABLE4, + TX_FAULT, + TX_FAULT1, + TX_FAULT2, + TX_FAULT3, + TX_FAULT4, + EEPROM_A0_PAGE, + EEPROM_A2_PAGE, + SFP_COPPER, + LAST_ATTRIBUTE +}; + +static struct mutex portStatusLock; + static int i2c_device_word_write(const struct i2c_client *client, unsigned char command, unsigned short value) { unsigned int retry = 10; @@ -531,21 +598,8 @@ static int i2c_device_word_write(const struct i2c_client *client, unsigned char return ret; } -int qsfpDataRead(struct i2c_client *client, char *buf) +int eepromDataBlockRead(struct i2c_client *client, char *buf) { -#if 0 - unsigned int index; - int value; - - for (index=0; index> 8; + buf[index*2] = value & 0x00ff; + } + return 0; } int eepromDataRead(struct i2c_client *client, char *buf) @@ -601,6 +710,13 @@ static int i2c_bus0_hardware_monitor_update_thread(void *p) fanErr = 0; for (i=0; i= W83795ADG_NUM8) && (data->modelId != ASTERION_WITH_BMC) && (data->modelId != ASTERION_WITHOUT_BMC)) + { + FanErr[i] = 0; + continue; + } + fanSpeed = 0; /* Choose W83795ADG bank 0 */ i2c_smbus_write_byte_data(client, W83795ADG_REG_BANK, 0x00); @@ -625,9 +741,9 @@ static int i2c_bus0_hardware_monitor_update_thread(void *p) if (data->hwRev == 0x00) /* Proto */ { if (fanErr == 1) - i2c_smbus_write_byte_data(&pca9535pwr_client, PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x80); + i2c_smbus_write_byte_data(&pca9535pwr_client_bus0, PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x80); else - i2c_smbus_write_byte_data(&pca9535pwr_client, PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x00); + i2c_smbus_write_byte_data(&pca9535pwr_client_bus0, PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x00); } else if (data->hwRev == 0x02) /* Beta */ { @@ -648,6 +764,10 @@ static int i2c_bus0_hardware_monitor_update_thread(void *p) /* Get Remote Temp */ for (i=0; i= W83795ADG_NUM2) && (data->modelId != ASTERION_WITH_BMC) && (data->modelId != ASTERION_WITHOUT_BMC)) + break; + MNTRTD = (int) i2c_smbus_read_byte_data(client, (W83795ADG_REG_TR1+i)); MNTTD = (int) i2c_smbus_read_byte_data(client, W83795ADG_REG_VR_LSB); /* temperature is negative */ @@ -672,6 +792,9 @@ static int i2c_bus0_hardware_monitor_update_thread(void *p) maxTemp = data->macTemp; for (i=0; i= W83795ADG_NUM2) && (data->modelId != ASTERION_WITH_BMC) && (data->modelId != ASTERION_WITHOUT_BMC)) + break; + if (data->remoteTempInt[i] > maxTemp) maxTemp = data->remoteTempInt[i]; } @@ -705,11 +828,20 @@ static int i2c_bus0_hardware_monitor_update_thread(void *p) else fanTable = &(fanControlTable_B2F[2]); break; + + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + if (FanDir2 != 0) + fanTable = &(fanControlTable[3]); + else + fanTable = &(fanControlTable_B2F[3]); + break; } if (fanErr) { fanDuty = fanTable->fanDutySet[2]; + LastTemp = 0; } else { @@ -748,8 +880,8 @@ static int i2c_bus0_hardware_monitor_update_thread(void *p) fanDuty = fanTable->fanDutySet[2]; } } + LastTemp = maxTemp; } - LastTemp = maxTemp; if ((fanDuty!=0)&&(data->fanDuty!=fanDuty)) { @@ -792,9 +924,11 @@ static int i2c_bus0_hardware_monitor_update_thread(void *p) { port_status = i2c_smbus_read_word_data(&(pca9535_client_bus0[j]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); port = ((j*2)+(i*8)); + SFPPortTxFaultStatus[port] = (PCA9553_TEST_BIT(port_status, 0)==0); SFPPortAbsStatus[port] = (PCA9553_TEST_BIT(port_status, 1)==0); SFPPortRxLosStatus[port] = (PCA9553_TEST_BIT(port_status, 2)==0); port++; + SFPPortTxFaultStatus[port] = (PCA9553_TEST_BIT(port_status, 6)==0); SFPPortAbsStatus[port] = (PCA9553_TEST_BIT(port_status, 7)==0); SFPPortRxLosStatus[port] = (PCA9553_TEST_BIT(port_status, 8)==0); } @@ -919,9 +1053,10 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) struct i2c_client *client = p; struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); int i, ret; - unsigned short value, fanErr; + unsigned short value, value2, fanErr, fanErr2; unsigned int step = 0; unsigned char qsfpPortData[QSFP_DATA_SIZE]; + unsigned char SfpCopperPortData[SFP_COPPER_DATA_SIZE]; unsigned short port_status; int j, port; @@ -944,7 +1079,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) /* QSFP Port */ for (i=0; i<2; i++) - data->qsfpPortAbsStatus[i] = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + data->qsfpPortAbsStatus[i] = i2c_smbus_read_word_data(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); step = 1; break; @@ -964,7 +1099,12 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) ret = i2c_smbus_write_byte(&(pca9548_client[0]), (1<=0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + if (data->qsfpPortTxDisableDataUpdate[i] == 1) + { + eepromDataByteWrite(&qsfpDataA0_client, SFF8436_TX_DISABLE_ADDR, &data->qsfpPortTxDisableData[i], sizeof(char)); + data->qsfpPortTxDisableDataUpdate[i] = 0; + } + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i][0]), qsfpPortData, QSFP_DATA_SIZE); @@ -976,8 +1116,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) else { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[0], i); + data->qsfpPortTxDisableDataUpdate[i] = 1; } } } @@ -986,8 +1126,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) for (i=0; i<8; i++) { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[0], i); + data->qsfpPortTxDisableDataUpdate[i] = 1; } } @@ -1009,7 +1149,12 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) ret = i2c_smbus_write_byte(&(pca9548_client[1]), (1<<(i-8))); if (ret>=0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + if (data->qsfpPortTxDisableDataUpdate[i] == 1) + { + eepromDataByteWrite(&qsfpDataA0_client, SFF8436_TX_DISABLE_ADDR, &data->qsfpPortTxDisableData[i], sizeof(char)); + data->qsfpPortTxDisableDataUpdate[i] = 0; + } + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i][0]), qsfpPortData, QSFP_DATA_SIZE); @@ -1021,8 +1166,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) else { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[0], i); + data->qsfpPortTxDisableDataUpdate[i] = 1; } } } @@ -1031,8 +1176,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) for (i=8; i<16; i++) { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[0], i); + data->qsfpPortTxDisableDataUpdate[i] = 1; } } @@ -1054,7 +1199,12 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) ret = i2c_smbus_write_byte(&(pca9548_client[2]), (1<=0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + if (data->qsfpPortTxDisableDataUpdate[i+16] == 1) + { + eepromDataByteWrite(&qsfpDataA0_client, SFF8436_TX_DISABLE_ADDR, &data->qsfpPortTxDisableData[i+16], sizeof(char)); + data->qsfpPortTxDisableDataUpdate[i+16] = 0; + } + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i+16][0]), qsfpPortData, QSFP_DATA_SIZE); @@ -1066,8 +1216,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) else { memset(&(data->qsfpPortDataA0[i+16][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i+16][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[1], i); + data->qsfpPortTxDisableDataUpdate[i+16] = 1; } } } @@ -1076,8 +1226,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) for (i=0; i<8; i++) { memset(&(data->qsfpPortDataA0[i+16][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i+16][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[1], i); + data->qsfpPortTxDisableDataUpdate[i+16] = 1; } } @@ -1099,7 +1249,12 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) ret = i2c_smbus_write_byte(&(pca9548_client[3]), (1<<(i-8))); if (ret>=0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + if (data->qsfpPortTxDisableDataUpdate[i+16] == 1) + { + eepromDataByteWrite(&qsfpDataA0_client, SFF8436_TX_DISABLE_ADDR, &data->qsfpPortTxDisableData[i+16], sizeof(char)); + data->qsfpPortTxDisableDataUpdate[i+16] = 0; + } + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i+16][0]), qsfpPortData, QSFP_DATA_SIZE); @@ -1111,8 +1266,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) else { memset(&(data->qsfpPortDataA0[i+16][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i+16][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[1], i); + data->qsfpPortTxDisableDataUpdate[i+16] = 1; } } } @@ -1121,8 +1276,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) for (i=8; i<16; i++) { memset(&(data->qsfpPortDataA0[i+16][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i+16][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[1], i); + data->qsfpPortTxDisableDataUpdate[i+16] = 1; } } @@ -1140,7 +1295,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) value = 0xcccc; fanErr = 0; - for (i=0; ifrontLedStatus); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->frontLedStatus); } /* FAN Status */ - value = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[0]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + value = i2c_smbus_read_word_data(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); data->fanAbs[0] = (value&0x4444); data->fanDir[0] = (value&0x8888); FanDir = data->fanDir[0]; @@ -1245,7 +1400,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) /* SFP Port */ for (i=0; i<4; i++) - data->qsfpPortAbsStatus[i] = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + data->qsfpPortAbsStatus[i] = i2c_smbus_read_word_data(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); /* Turn on PCA9548#1 channel 1 on I2C-bus1 */ ret = i2c_smbus_write_byte(&(pca9548_client[1]), (1<sfpPortRxLosStatus[i] = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + for (i=0; i<3; i++) + data->sfpPortRxLosStatus[i] = i2c_smbus_read_word_data(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + + /* Turn on PCA9548#1 channel 2 on I2C-bus1 */ + ret = i2c_smbus_write_byte(&(pca9548_client[1]), (1<sfpPortTxFaultStatus[i] = i2c_smbus_read_word_data(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); step = 1; break; @@ -1276,16 +1440,19 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { if (PCA9553_TEST_BIT(data->qsfpPortDataValid[0], i) == 0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i][0]), qsfpPortData, QSFP_DATA_SIZE); PCA9553_SET_BIT(data->qsfpPortDataValid[0], i); } } - ret = qsfpDataRead(&qsfpDataA2_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); if (ret>=0) memcpy(&(data->qsfpPortDataA2[i][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[i][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); } i2c_smbus_write_byte(&(pca9548_client[0]), 0x00); } @@ -1293,6 +1460,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[0], i); } } @@ -1303,6 +1471,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[0], i); } } @@ -1327,16 +1496,19 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { if (PCA9553_TEST_BIT(data->qsfpPortDataValid[0], i) == 0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i][0]), qsfpPortData, QSFP_DATA_SIZE); PCA9553_SET_BIT(data->qsfpPortDataValid[0], i); } } - ret = qsfpDataRead(&qsfpDataA2_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); if (ret>=0) memcpy(&(data->qsfpPortDataA2[i][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[i][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); } i2c_smbus_write_byte(&(pca9548_client[0]), 0x00); } @@ -1344,6 +1516,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[0], i); } } @@ -1354,6 +1527,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[0], i); } } @@ -1378,16 +1552,19 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { if (PCA9553_TEST_BIT(data->qsfpPortDataValid[1], i) == 0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i+16][0]), qsfpPortData, QSFP_DATA_SIZE); PCA9553_SET_BIT(data->qsfpPortDataValid[1], i); } } - ret = qsfpDataRead(&qsfpDataA2_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); if (ret>=0) memcpy(&(data->qsfpPortDataA2[i+16][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[i+16][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); } i2c_smbus_write_byte(&(pca9548_client[0]), 0x00); } @@ -1395,6 +1572,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i+16][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i+16][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i+16][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[1], i); } } @@ -1405,6 +1583,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i+16][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i+16][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i+16][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[1], i); } } @@ -1429,16 +1608,19 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { if (PCA9553_TEST_BIT(data->qsfpPortDataValid[1], i) == 0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i+16][0]), qsfpPortData, QSFP_DATA_SIZE); PCA9553_SET_BIT(data->qsfpPortDataValid[1], i); } } - ret = qsfpDataRead(&qsfpDataA2_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); if (ret>=0) memcpy(&(data->qsfpPortDataA2[i+16][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[i+16][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); } i2c_smbus_write_byte(&(pca9548_client[0]), 0x00); } @@ -1446,6 +1628,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i+16][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i+16][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i+16][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[1], i); } } @@ -1456,6 +1639,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i+16][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i+16][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i+16][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[1], i); } } @@ -1480,16 +1664,19 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { if (PCA9553_TEST_BIT(data->qsfpPortDataValid[2], i) == 0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i+32][0]), qsfpPortData, QSFP_DATA_SIZE); PCA9553_SET_BIT(data->qsfpPortDataValid[2], i); } } - ret = qsfpDataRead(&qsfpDataA2_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); if (ret>=0) memcpy(&(data->qsfpPortDataA2[i+32][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[i+32][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); } i2c_smbus_write_byte(&(pca9548_client[0]), 0x00); } @@ -1497,6 +1684,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i+32][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i+32][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i+32][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[2], i); } } @@ -1507,6 +1695,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i+32][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i+32][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i+32][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[2], i); } } @@ -1531,16 +1720,19 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { if (PCA9553_TEST_BIT(data->qsfpPortDataValid[2], i) == 0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i+32][0]), qsfpPortData, QSFP_DATA_SIZE); PCA9553_SET_BIT(data->qsfpPortDataValid[2], i); } } - ret = qsfpDataRead(&qsfpDataA2_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); if (ret>=0) memcpy(&(data->qsfpPortDataA2[i+32][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[i+32][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); } i2c_smbus_write_byte(&(pca9548_client[0]), 0x00); } @@ -1548,6 +1740,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i+32][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i+32][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i+32][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[2], i); } } @@ -1558,6 +1751,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i+32][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i+32][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i+32][0]), 0, SFP_COPPER_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[2], i); } } @@ -1580,7 +1774,12 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) ret = i2c_smbus_write_byte(&(pca9548_client[0]), (1<=0) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + if (data->qsfpPortTxDisableDataUpdate[i+48] == 1) + { + eepromDataByteWrite(&qsfpDataA0_client, SFF8436_TX_DISABLE_ADDR, &data->qsfpPortTxDisableData[i+48], sizeof(char)); + data->qsfpPortTxDisableDataUpdate[i+48] = 0; + } + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i+48][0]), qsfpPortData, QSFP_DATA_SIZE); @@ -1592,8 +1791,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) else { memset(&(data->qsfpPortDataA0[i+48][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i+48][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[3], i); + data->qsfpPortTxDisableDataUpdate[i+48] = 1; } } } @@ -1602,8 +1801,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) for (i=0; i<6; i++) { memset(&(data->qsfpPortDataA0[i+48][0]), 0, QSFP_DATA_SIZE); - memset(&(data->qsfpPortDataA2[i+48][0]), 0, QSFP_DATA_SIZE); PCA9553_CLEAR_BIT(data->qsfpPortDataValid[3], i); + data->qsfpPortTxDisableDataUpdate[i+48] = 1; } } @@ -1625,7 +1824,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) value = 0xcccc; fanErr = 0; - for (i=0; ifrontLedStatus); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->frontLedStatus); /* FAN Status */ - value = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[0]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + value = i2c_smbus_read_word_data(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); data->fanAbs[0] = (value&0x4444); data->fanDir[0] = (value&0x8888); FanDir = data->fanDir[0]; @@ -1722,11 +1921,13 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) for (j=0; j<4; j++) { - port_status = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[j]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + port_status = i2c_smbus_read_word_data(&(pca9535pwr_client[j]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); port = ((j*2)+40); + SFPPortTxFaultStatus[port] = (PCA9553_TEST_BIT(port_status, 0)==0); SFPPortAbsStatus[port] = (PCA9553_TEST_BIT(port_status, 1)==0); SFPPortRxLosStatus[port] = (PCA9553_TEST_BIT(port_status, 2)==0); port++; + SFPPortTxFaultStatus[port] = (PCA9553_TEST_BIT(port_status, 6)==0); SFPPortAbsStatus[port] = (PCA9553_TEST_BIT(port_status, 7)==0); SFPPortRxLosStatus[port] = (PCA9553_TEST_BIT(port_status, 8)==0); } @@ -1741,7 +1942,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) break; fanErr = 0; - for (i=0; ifrontLedStatus); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->frontLedStatus); i2c_smbus_write_byte_data(client, 0, 0x00); step = 2; @@ -1795,11 +1996,11 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) if (ret < 0) break; - value = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[0]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + value = i2c_smbus_read_word_data(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); SFPPortAbsStatus[48] = (PCA9553_TEST_BIT(value, 9)==0); SFPPortAbsStatus[49] = (PCA9553_TEST_BIT(value, 4)==0); SFPPortAbsStatus[51] = (PCA9553_TEST_BIT(value, 14)==0); - value = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[1]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + value = i2c_smbus_read_word_data(&(pca9535pwr_client[1]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); SFPPortAbsStatus[50] = (PCA9553_TEST_BIT(value, 4)==0); SFPPortAbsStatus[52] = (PCA9553_TEST_BIT(value, 14)==0); SFPPortAbsStatus[53] = (PCA9553_TEST_BIT(value, 9)==0); @@ -1815,7 +2016,7 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) value = 0xcccc; fanErr = 0; - for (i=0; ifanAbs[0] = (value&0x4444); data->fanDir[0] = (value&0x8888); FanDir = data->fanDir[0]; @@ -1864,7 +2065,12 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) i2c_smbus_write_byte_data(&(pca9548_client[0]), 0, sfpPortData_78F[i].portMaskBitForPCA9548_2TO5); if ((SFPPortDataValid[i] == 0)||(i>=48)) { - ret = qsfpDataRead(&qsfpDataA0_client,qsfpPortData); + if ((i>=48)&&(data->qsfpPortTxDisableDataUpdate[i] == 1)) + { + eepromDataByteWrite(&qsfpDataA0_client, SFF8436_TX_DISABLE_ADDR, &data->qsfpPortTxDisableData[i], sizeof(char)); + data->qsfpPortTxDisableDataUpdate[i] = 0; + } + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); if (ret>=0) { memcpy(&(data->qsfpPortDataA0[i][0]), qsfpPortData, QSFP_DATA_SIZE); @@ -1873,9 +2079,12 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) } if (i<48) { - ret = qsfpDataRead(&qsfpDataA2_client,qsfpPortData); + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); if (ret>=0) memcpy(&(data->qsfpPortDataA2[i][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[i][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); } i2c_smbus_write_byte_data(&(pca9548_client[0]), 0, 0x00); i2c_smbus_write_byte_data(&(pca9548_client[1]), 0, 0x00); @@ -1884,6 +2093,8 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) { memset(&(data->qsfpPortDataA0[i][0]), 0, QSFP_DATA_SIZE); memset(&(data->qsfpPortDataA2[i][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i][0]), 0, SFP_COPPER_DATA_SIZE); + data->qsfpPortTxDisableDataUpdate[i] = 1; SFPPortDataValid[i] = 0; } } @@ -1898,6 +2109,345 @@ static int i2c_bus1_hardware_monitor_update_thread(void *p) case ASTERION_WITH_BMC: case ASTERION_WITHOUT_BMC: + switch (step) + { + case 0: + /* Turn on PCA9548#0 channel 0 on I2C-bus1 */ + ret = i2c_smbus_write_byte(client, (1 << PCA9548_CH00)); + if (ret < 0) + break; + + /* SFP Port 0~23, SFP Port - RXLOS */ + for (i = 0; i < 10; i++) + data->sfpPortAbsRxLosStatus[i] = i2c_smbus_read_byte_data(&(cpld_client_bus1), (0x20 + i)); + + data->sfpPortAbsRxLosStatus[10] = i2c_smbus_read_byte_data(&(cpld_client_bus1), 0x30); + data->sfpPortAbsRxLosStatus[11] = i2c_smbus_read_byte_data(&(cpld_client_bus1), 0x31); + + /* Turn on PCA9548#0 channel 1 on I2C-bus1 */ + ret = i2c_smbus_write_byte(client, (1 << PCA9548_CH01)); + if (ret < 0) + break; + + /* SFP Port 24~47, SFP Port - RXLOS */ + for (i = 0; i < 10; i++) + data->sfpPortAbsRxLosStatus[i + 12] = i2c_smbus_read_byte_data(&(cpld_client_bus1), 0x20 + i); + + data->sfpPortAbsRxLosStatus[22] = i2c_smbus_read_byte_data(&(cpld_client_bus1), 0x30); + data->sfpPortAbsRxLosStatus[23] = i2c_smbus_read_byte_data(&(cpld_client_bus1), 0x31); + + /* Turn on PCA9548#0 channel 2 on I2C-bus1 */ + ret = i2c_smbus_write_byte(client, (1 << PCA9548_CH02)); + if (ret < 0) + break; + + /* QSFP Port 48~63 */ + for (i = 0; i < 16; i++) + data->qsfpPortAbsStatusAst[i] = i2c_smbus_read_byte_data(&(cpld_client_bus1), (0x20 + i)); + + step = 1; + break; + + case 1: + /* Turn on PCA9548#0 channel 0 on I2C-bus1 */ + ret = i2c_smbus_write_byte(client, (1 << PCA9548_CH00)); + if (ret < 0) + break; + + for (i = 0; i < 12; i++) /* SFP 0,2,4 ... 22 */ + { + if ((data->sfpPortAbsRxLosStatus[i] & 0x02) == 0) /* present */ + { + ret = i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, (0x01 + (i * 2))); + + if (ret >= 0) + { + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); + + if (ret >= 0) + { + memcpy(&(data->qsfpPortDataA0[i * 2][0]), qsfpPortData, QSFP_DATA_SIZE); + data->sfpPortDataValidAst[i * 2] = 1; + } + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); + memcpy(&(data->qsfpPortDataA2[i * 2][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[i * 2][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); + } + i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, 0x00); + } + else + { + memset(&(data->qsfpPortDataA0[i * 2][0]), 0, QSFP_DATA_SIZE); + memset(&(data->qsfpPortDataA2[i * 2][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[i * 2][0]), 0, SFP_COPPER_DATA_SIZE); + data->sfpPortDataValidAst[i * 2] = 0; + } + } + + for (i = 0; i < 12; i++) /* SFP 1,3,5 ... 23 */ + { + if ((data->sfpPortAbsRxLosStatus[i] & 0x20) == 0) /* present */ + { + ret = i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, (0x02 + (i * 2))); + if (ret >= 0) + { + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); + if (ret >= 0) + { + memcpy(&(data->qsfpPortDataA0[1 + (i * 2)][0]), qsfpPortData, QSFP_DATA_SIZE); + data->sfpPortDataValidAst[1 + (i * 2)] = 1; + } + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); + if (ret >= 0) + memcpy(&(data->qsfpPortDataA2[1 + (i * 2)][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[1 + (i * 2)][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); + } + i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, 0x00); + } + else + { + memset(&(data->qsfpPortDataA0[1 + (i * 2)][0]), 0, QSFP_DATA_SIZE); + memset(&(data->qsfpPortDataA2[1 + (i * 2)][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[1 + (i * 2)][0]), 0, SFP_COPPER_DATA_SIZE); + data->sfpPortDataValidAst[1 + (i * 2)] = 0; + } + } + + step = 2; + break; + + case 2: + /* Turn on PCA9548#0 channel 1 on I2C-bus1 */ + ret = i2c_smbus_write_byte(client, (1 << PCA9548_CH01)); + if (ret < 0) + break; + + for (i = 0; i < 12; i++) /* SFP 24,26,28 ... 46 */ + { + if ((data->sfpPortAbsRxLosStatus[i + 12] & 0x02) == 0) /* present */ + { + ret = i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, (0x01 + (i * 2))); + if (ret >= 0) + { + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); + if (ret >= 0) + { + memcpy(&(data->qsfpPortDataA0[(i +12) * 2][0]), qsfpPortData, QSFP_DATA_SIZE); + data->sfpPortDataValidAst[(i + 12) * 2] = 1; + } + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); + if (ret >= 0) + memcpy(&(data->qsfpPortDataA2[(i + 12) * 2][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[(i + 12) * 2][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); + } + i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, 0x00); + } + else + { + memset(&(data->qsfpPortDataA0[(i + 12) * 2][0]), 0, QSFP_DATA_SIZE); + memset(&(data->qsfpPortDataA2[(i + 12) * 2][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[(i + 12) * 2][0]), 0, SFP_COPPER_DATA_SIZE); + data->sfpPortDataValidAst[(i + 12) * 2] = 0; + } + } + + for (i = 0; i < 12; i++) /* SFP 25,27,29 ... 47 */ + { + if ((data->sfpPortAbsRxLosStatus[i + 12] & 0x20) == 0) /* present */ + { + ret = i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, (0x02 + (i * 2))); + if (ret >= 0) + { + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); + if (ret >= 0) + { + memcpy(&(data->qsfpPortDataA0[1 + ((i + 12) * 2)][0]), qsfpPortData, QSFP_DATA_SIZE); + data->sfpPortDataValidAst[1 + ((i + 12) * 2)] = 1; + } + ret = eepromDataBlockRead(&qsfpDataA2_client,qsfpPortData); + if (ret >= 0) + memcpy(&(data->qsfpPortDataA2[1 + ((i + 12) * 2)][0]), qsfpPortData, QSFP_DATA_SIZE); + ret = eepromDataWordRead(&SfpCopperData_client,SfpCopperPortData); + if (ret>=0) + memcpy(&(data->SfpCopperPortData[1 + ((i + 12) * 2)][0]), SfpCopperPortData, SFP_COPPER_DATA_SIZE); + } + i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, 0x00); + } + else + { + memset(&(data->qsfpPortDataA0[1 + ((i + 12) * 2)][0]), 0, QSFP_DATA_SIZE); + memset(&(data->qsfpPortDataA2[1 + ((i + 12) * 2)][0]), 0, QSFP_DATA_SIZE); + memset(&(data->SfpCopperPortData[1 + ((i + 12) * 2)][0]), 0, SFP_COPPER_DATA_SIZE); + data->sfpPortDataValidAst[1 + ((i + 12) * 2)] = 0; + } + } + + step = 3; + break; + + case 3: + /* Turn on PCA9548#0 channel 2 on I2C-bus1 */ + ret = i2c_smbus_write_byte(client, (1 << PCA9548_CH02)); + if (ret < 0) + break; + + for (i = 0; i < 16; i++) /* QSFP 48~63 */ + { + if ((data->qsfpPortAbsStatusAst[i] & 0x02) == 0) /* present */ + { + ret = i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, (0x01 + i)); + if (ret >= 0) + { + if (data->qsfpPortTxDisableDataUpdate[48 + i] == 1) + { + eepromDataByteWrite(&qsfpDataA0_client, SFF8436_TX_DISABLE_ADDR, &data->qsfpPortTxDisableData[48 + i], sizeof(char)); + data->qsfpPortTxDisableDataUpdate[48 + i] = 0; + } + ret = eepromDataBlockRead(&qsfpDataA0_client,qsfpPortData); + if (ret >= 0) + { + memcpy(&(data->qsfpPortDataA0[48 + i][0]), qsfpPortData, QSFP_DATA_SIZE); + data->sfpPortDataValidAst[48 + i] = 1; + } + } + i2c_smbus_write_byte_data(&(cpld_client_bus1), CPLD_REG_MUX, 0x00); + } + else + { + memset(&(data->qsfpPortDataA0[48 + i][0]), 0, QSFP_DATA_SIZE); + data->sfpPortDataValidAst[48 + i] = 0; + data->qsfpPortTxDisableDataUpdate[48 + i] = 1; + } + } + + step = 4; + break; + + case 4: + /* Turn on PCA9548#0 channel 3 on I2C-bus1 : FAN Status */ + ret = i2c_smbus_write_byte(client, (1 << PCA9548_CH03)); + if (ret < 0) + break; + + value = 0xcccc; + fanErr = 0; + for (i = 0; i < W83795ADG_NUM8; i++) + { + if (FanErr[i] == 1) + fanErr |= (0x1 << i); + } + + if (fanErr & 0x03) + value |= 0x0001; + else + value |= 0x0002; + + if (fanErr & 0x0c) + value |= 0x0010; + else + value |= 0x0020; + + if (fanErr & 0x30) + value |= 0x0100; + else + value |= 0x0200; + + if (fanErr & 0xc0) + value |= 0x1000; + else + value |= 0x2000; + + ret = i2c_device_word_write(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, value); + if (ret < 0) + break; + + /* FAN Status */ + value = i2c_smbus_read_word_data(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + data->fanAbs[0] = (value & 0x4444); + data->fanDir[0] = (value & 0x8888); + FanDir = data->fanDir[0]; + + fanErr2 = 0; + for (i = W83795ADG_NUM8; i < W83795ADG_FAN_COUNT; i++) + { + if (FanErr[i] == 1) + fanErr2 |= (0x1 << (i - 8)); + } + + if (fanErr2 & 0x03) + value2 = 0x0010; + else + value2 = 0x0020; + + ret = i2c_device_word_write(&(pca9535pwr_client[1]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, value2); + if (ret < 0) + break; + + /* FAN Status */ + value2 = i2c_smbus_read_word_data(&(pca9535pwr_client[1]), PCA9553_COMMAND_BYTE_REG_INPUT_PORT_0); + + data->fanAbs[1] = (value2 & 0x0040); + data->fanDir[1] = (value2 & 0x0080); + FanDir2 = data->fanDir[1]; + + /* Turn on PCA9548#0 channel 4 on I2C-bus1 : System LED */ + ret = i2c_smbus_write_byte(client, (1 << PCA9548_CH04)); + if (ret < 0) + break; + + data->frontLedStatus |= 0x00ff; + if (fanErr == 0 && fanErr2 == 0) + data->frontLedStatus &= (~0x0010); /* FAN_LED_G# */ + else + data->frontLedStatus &= (~0x0020); /* FAN_LED_Y# */ + + if ((platformPsuABS & 0x01) == 0x00) /* PSU1 Present */ + { + if (platformPsuPG & 0x04) /* PSU1_PG_LDC Power Goodasserted */ + data->frontLedStatus &= (~0x0001); /* PSU1_LED_G# */ + else + data->frontLedStatus &= (~0x0002); /* PSU1_LED_Y# */ + } + if ((platformPsuABS & 0x02) == 0x00) /* PSU2 Present */ + { + if (platformPsuPG & 0x08) /* PSU2_PG_LDC Power Goodasserted */ + data->frontLedStatus &= (~0x0004); /* PSU2_LED_G# */ + else + data->frontLedStatus &= (~0x0008); /* PSU2_LED_Y# */ + } + + switch (data->systemLedStatus) + { + default: + case 0: /* Booting */ + break; + + case 1: /* Critical*/ + data->frontLedStatus &= (~0x0080); /* SYS_LED_Y# */ + break; + + case 2: /* Normal */ + data->frontLedStatus &= (~0x0040); /* SYS_LED_G# */ + break; + } + + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->frontLedStatus); + + step = 0; + break; + + default: + step = 0; + break; + } + i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x33, 0x00); + i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x33, 0xff); break; default: @@ -1960,10 +2510,27 @@ static ssize_t show_psu_pg_sen(struct device *dev, struct device_attribute *deva value = data->psuPG; mutex_unlock(&data->lock); - if (attr->index == 0) - value &= 0x08; - else - value &= 0x10; + switch(platformModelId) + { + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + if (attr->index == 0) + value &= 0x04; + else + value &= 0x08; + } + break; + + default: + { + if (attr->index == 0) + value &= 0x08; + else + value &= 0x10; + } + break; + } return sprintf(buf, "%d\n", value?1:0); } @@ -2183,8 +2750,6 @@ static ssize_t set_rov(struct device *dev, struct device_attribute *devattr, con { case HURACAN_WITH_BMC: case HURACAN_WITHOUT_BMC: - case ASTERION_WITH_BMC: - case ASTERION_WITHOUT_BMC: case HURACAN_A_WITH_BMC: case HURACAN_A_WITHOUT_BMC: { @@ -2219,6 +2784,8 @@ static ssize_t set_rov(struct device *dev, struct device_attribute *devattr, con case SESTO_WITH_BMC: case SESTO_WITHOUT_BMC: + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: { /* - 4'b0000 = 1.2000V -> 0x47 @@ -2363,6 +2930,8 @@ static SENSOR_DEVICE_ATTR(fan10_duty, S_IRUGO, show_fan_duty, NULL, 9); static SENSOR_DEVICE_ATTR(remote_temp1, S_IRUGO, show_remote_temp, NULL, 0); static SENSOR_DEVICE_ATTR(remote_temp2, S_IRUGO, show_remote_temp, NULL, 1); +static SENSOR_DEVICE_ATTR(remote_temp3, S_IRUGO, show_remote_temp, NULL, 2); +static SENSOR_DEVICE_ATTR(remote_temp4, S_IRUGO, show_remote_temp, NULL, 3); static SENSOR_DEVICE_ATTR(vsen1, S_IRUGO, show_voltage_sen, NULL, 0); static SENSOR_DEVICE_ATTR(vsen2, S_IRUGO, show_voltage_sen, NULL, 1); @@ -2507,6 +3076,8 @@ static struct attribute *i2c_bus0_hardware_monitor_attr_asterion[] = { &sensor_dev_attr_remote_temp1.dev_attr.attr, &sensor_dev_attr_remote_temp2.dev_attr.attr, + &sensor_dev_attr_remote_temp3.dev_attr.attr, + &sensor_dev_attr_remote_temp4.dev_attr.attr, &sensor_dev_attr_vsen1.dev_attr.attr, &sensor_dev_attr_vsen2.dev_attr.attr, @@ -2520,7 +3091,8 @@ static struct attribute *i2c_bus0_hardware_monitor_attr_asterion[] = { static ssize_t show_port_abs(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&(pca9535pwr_client_bus1[0])); + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&(pca9535pwr_client[0])); + struct i2c_bus1_hardware_monitor_data *dataAst = i2c_get_clientdata(&(cpld_client_bus1)); int rc = 0; switch(platformModelId) @@ -2530,6 +3102,34 @@ static ssize_t show_port_abs(struct device *dev, struct device_attribute *devatt rc = ((SFPPortAbsStatus[attr->index]==1)&&(SFPPortDataValid[attr->index]==1)); break; + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + unsigned char qsfpPortAbsAst = 0, index = 0, bit = 0; + unsigned char sfpPortDataValidAst = 0; + + if (attr->index < 48) + { + index = (attr->index / 2); + bit = ((attr->index & 0x01) ? 5 : 1); + mutex_lock(&dataAst->lock); + qsfpPortAbsAst = dataAst->sfpPortAbsRxLosStatus[index]; + sfpPortDataValidAst = dataAst->sfpPortDataValidAst[attr->index]; + mutex_unlock(&dataAst->lock); + rc = ((PCA9553_TEST_BIT(qsfpPortAbsAst, bit) ? 0 : 1)&&sfpPortDataValidAst); + } + else + { + index = (attr->index % 48); + mutex_lock(&dataAst->lock); + qsfpPortAbsAst = dataAst->qsfpPortAbsStatusAst[index]; + sfpPortDataValidAst = dataAst->sfpPortDataValidAst[attr->index]; + mutex_unlock(&dataAst->lock); + rc = ((PCA9553_TEST_BIT(qsfpPortAbsAst, 1) ? 0 : 1)&&sfpPortDataValidAst); + } + } + break; + default: { unsigned short qsfpPortAbs=0, index=0, bit=0; @@ -2552,7 +3152,7 @@ static ssize_t show_port_abs(struct device *dev, struct device_attribute *devatt static ssize_t show_port_rxlos(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&(pca9535pwr_client_bus1[0])); + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&(pca9535pwr_client[0])); int rc = 0; switch(platformModelId) @@ -2576,6 +3176,20 @@ static ssize_t show_port_rxlos(struct device *dev, struct device_attribute *deva } break; + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + unsigned char qsfpPortRxLos = 0, index = 0, bit = 0; + + index = (attr->index / 2); + bit = ((attr->index & 0x01) ? 4 : 0); + mutex_lock(&data->lock); + qsfpPortRxLos = data->sfpPortAbsRxLosStatus[index]; + mutex_unlock(&data->lock); + rc = (PCA9553_TEST_BIT(qsfpPortRxLos, bit) ? 1 : 0); + } + break; + default: break; } @@ -2586,8 +3200,7 @@ static ssize_t show_port_rxlos(struct device *dev, struct device_attribute *deva static ssize_t show_port_data_a0(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&qsfpDataA0_client); unsigned char qsfpPortData[QSFP_DATA_SIZE]; ssize_t count = 0; @@ -2605,8 +3218,7 @@ static ssize_t show_port_data_a0(struct device *dev, struct device_attribute *de static ssize_t show_port_data_a2(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&qsfpDataA2_client); unsigned char qsfpPortData[QSFP_DATA_SIZE]; ssize_t count = 0; @@ -2621,6 +3233,24 @@ static ssize_t show_port_data_a2(struct device *dev, struct device_attribute *de return count; } +static ssize_t show_port_sfp_copper(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&SfpCopperData_client); + unsigned char SfpCopperPortData[SFP_COPPER_DATA_SIZE]; + ssize_t count = 0; + + memset(SfpCopperPortData, 0, SFP_COPPER_DATA_SIZE); + mutex_lock(&data->lock); + memcpy(SfpCopperPortData, &(data->SfpCopperPortData[attr->index][0]), SFP_COPPER_DATA_SIZE); + mutex_unlock(&data->lock); + + count = SFP_COPPER_DATA_SIZE; + memcpy(buf, (char *)SfpCopperPortData, SFP_COPPER_DATA_SIZE); + + return count; +} + static ssize_t show_fan_abs(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -2721,7 +3351,7 @@ static ssize_t show_eeprom(struct device *dev, struct device_attribute *devattr, case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - if ((platformBuildRev == 0x01)&&(platformHwRev == 0x03)) /* PVT */ + if (platformHwRev == 0x03) /* PVT */ { struct i2c_client *client = to_i2c_client(dev); struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); @@ -2729,8 +3359,8 @@ static ssize_t show_eeprom(struct device *dev, struct device_attribute *devattr, mutex_lock(&data->lock); /* Turn on PCA9548#1 channel 2 on I2C-bus1 */ i2c_smbus_write_byte(client, 0x04); - i2c_smbus_write_byte_data(&eeprom_client_2, 0x00, 0x00); - ret = eepromDataRead(&eeprom_client_2, &(eepromData[0])); + i2c_smbus_write_byte_data(&eeprom_client, 0x00, 0x00); + ret = eepromDataRead(&eeprom_client, &(eepromData[0])); i2c_smbus_write_byte(client, 0x00); mutex_unlock(&data->lock); } @@ -2815,7 +3445,7 @@ static ssize_t show_psu_eeprom(struct device *dev, struct device_attribute *deva else /* Turn on PCA9548 channel 6 on I2C-bus1 */ i2c_smbus_write_byte(client, 0x40); - ret = qsfpDataRead(&psu_eeprom_client, &(eepromData[0])); + ret = eepromDataBlockRead(&psu_eeprom_client, &(eepromData[0])); i2c_smbus_write_byte(client, 0x00); mutex_unlock(&data->lock); } @@ -2835,7 +3465,7 @@ static ssize_t show_psu_eeprom(struct device *dev, struct device_attribute *deva else /* Turn on PCA9548#1 channel 6 on I2C-bus1 */ i2c_smbus_write_byte(&(pca9548_client[1]), 0x40); - ret = qsfpDataRead(&psu_eeprom_client, &(eepromData[0])); + ret = eepromDataBlockRead(&psu_eeprom_client, &(eepromData[0])); i2c_smbus_write_byte(&(pca9548_client[1]), 0x00); mutex_unlock(&data->lock); } @@ -2844,18 +3474,35 @@ static ssize_t show_psu_eeprom(struct device *dev, struct device_attribute *deva case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); - - mutex_lock(&data_bus0->lock); - if (index) - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + /* + Because the write ability of EEPROM with 0xAx address on I2C bus 0 (I801 bus) is blocked by BIOS, + it does not support I2C block read, it supports byte read only. + The PSUs will be moved to I2C bus 1 (iSMT bus) in PVT rev2. + */ + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ + { + mutex_lock(&data->lock); + if (index) + i2c_smbus_write_byte(client, 0x20); /* Turn on PCA9548 channel 5 on I2C-bus1 */ + else + i2c_smbus_write_byte(client, 0x10); /* Turn on PCA9548 channel 4 on I2C-bus1 */ + ret = eepromDataBlockRead(&psu_eeprom_client, &(eepromData[0])); + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } else - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - ret = qsfpDataRead(&psu_eeprom_client_bus0, &(eepromData[0])); - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); + { + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if (index) + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + else + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + ret = eepromDataByteRead(&psu_eeprom_client_bus0, &(eepromData[0])); + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); + } } break; @@ -2883,6 +3530,8 @@ static ssize_t show_psu_vout(struct device *dev, struct device_attribute *devatt ssize_t count = 0; unsigned int temp = 0; unsigned int psu_present = 0; + unsigned char valueE = 0; + unsigned short valueY = 0; index = (attr->index&0x1); if (index&0x01) /* PSU 2 */ @@ -2944,36 +3593,70 @@ static ssize_t show_psu_vout(struct device *dev, struct device_attribute *devatt case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); - - mutex_lock(&data_bus0->lock); - if (index) - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ + { + mutex_lock(&data->lock); + if (index) + i2c_smbus_write_byte(client, 0x20); /* Turn on PCA9548 channel 5 on I2C-bus1 */ + else + i2c_smbus_write_byte(client, 0x10); /* Turn on PCA9548 channel 4 on I2C-bus1 */ + valueN = i2c_smbus_read_byte_data(&psu_mcu_client, 0x20); + valueV = (unsigned int)i2c_smbus_read_word_data(&psu_mcu_client, 0x8B); + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } else - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - valueN = i2c_smbus_read_byte_data(&psu_mcu_client_bus0, 0x20); - valueV = (unsigned int)i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x8B); - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); + { + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if (index) + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + else + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + valueN = i2c_smbus_read_byte_data(&psu_mcu_client_bus0, 0x20); + valueV = (unsigned int)i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x8B); + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); + } } break; default: break; } - if (valueN & 0x10) + + if (valueN == 0xff) { - valueN = 0xF0 + (valueN & 0x0F); - valueN = (~valueN) +1; - temp = (unsigned int)(1<> 11); + valueE = valueV + 1; + temp = (unsigned int)(1 << valueE); + if (temp) + count = sprintf(buf, "%d.%04d\n", valueY >> valueE, ((valueY % temp) * 10000) / temp); + } + else + { + valueN = (((valueV) >> 11) & 0x0F); + count = sprintf(buf, "%d\n", (valueY*(1<lock); - if (index) - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ + { + mutex_lock(&data->lock); + if (index) + i2c_smbus_write_byte(client, 0x20); /* Turn on PCA9548 channel 5 on I2C-bus1 */ + else + i2c_smbus_write_byte(client, 0x10); /* Turn on PCA9548 channel 4 on I2C-bus1 */ + value = i2c_smbus_read_word_data(&psu_mcu_client, 0x8C); + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } else - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x8C); - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); + { + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if (index) + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + else + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x8C); + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); + } } break; @@ -3165,18 +3860,30 @@ static ssize_t show_psu_temp_1(struct device *dev, struct device_attribute *deva case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); - - mutex_lock(&data_bus0->lock); - if (index) - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ + { + mutex_lock(&data->lock); + if (index) + i2c_smbus_write_byte(client, 0x20); /* Turn on PCA9548 channel 5 on I2C-bus1 */ + else + i2c_smbus_write_byte(client, 0x10); /* Turn on PCA9548 channel 4 on I2C-bus1 */ + value = i2c_smbus_read_word_data(&psu_mcu_client, 0x8D); + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } else - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x8D); - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); + { + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if (index) + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + else + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x8D); + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); + } } break; @@ -3235,8 +3942,6 @@ static ssize_t show_psu_temp_2(struct device *dev, struct device_attribute *deva { case HURACAN_WITH_BMC: case HURACAN_WITHOUT_BMC: - case ASTERION_WITH_BMC: - case ASTERION_WITHOUT_BMC: case HURACAN_A_WITH_BMC: case HURACAN_A_WITHOUT_BMC: { @@ -3276,21 +3981,37 @@ static ssize_t show_psu_temp_2(struct device *dev, struct device_attribute *deva case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); - - mutex_lock(&data_bus0->lock); - if (index) - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ + { + mutex_lock(&data->lock); + if (index) + i2c_smbus_write_byte(client, 0x20); /* Turn on PCA9548 channel 5 on I2C-bus1 */ + else + i2c_smbus_write_byte(client, 0x10); /* Turn on PCA9548 channel 4 on I2C-bus1 */ + value = i2c_smbus_read_word_data(&psu_mcu_client, 0x8E); + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } else - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x8E); - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); + { + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if (index) + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + else + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x8E); + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); + } } break; + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + break; + default: break; } @@ -3384,18 +4105,30 @@ static ssize_t show_psu_fan_speed(struct device *dev, struct device_attribute *d case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); - - mutex_lock(&data_bus0->lock); - if (index) - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ + { + mutex_lock(&data->lock); + if (index) + i2c_smbus_write_byte(client, 0x20); /* Turn on PCA9548 channel 5 on I2C-bus1 */ + else + i2c_smbus_write_byte(client, 0x10); /* Turn on PCA9548 channel 4 on I2C-bus1 */ + value = i2c_smbus_read_word_data(&psu_mcu_client, 0x90); + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } else - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x90); - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); + { + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if (index) + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + else + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x90); + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); + } } break; @@ -3479,18 +4212,30 @@ static ssize_t show_psu_pout(struct device *dev, struct device_attribute *devatt case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); - - mutex_lock(&data_bus0->lock); - if (index) - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ + { + mutex_lock(&data->lock); + if (index) + i2c_smbus_write_byte(client, 0x20); /* Turn on PCA9548 channel 5 on I2C-bus1 */ + else + i2c_smbus_write_byte(client, 0x10); /* Turn on PCA9548 channel 4 on I2C-bus1 */ + value = i2c_smbus_read_word_data(&psu_mcu_client, 0x96); + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } else - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x96); - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); + { + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if (index) + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + else + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x96); + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); + } } break; @@ -3549,8 +4294,6 @@ static ssize_t show_psu_pin(struct device *dev, struct device_attribute *devattr { case HURACAN_WITH_BMC: case HURACAN_WITHOUT_BMC: - case ASTERION_WITH_BMC: - case ASTERION_WITHOUT_BMC: case HURACAN_A_WITH_BMC: case HURACAN_A_WITHOUT_BMC: { @@ -3590,21 +4333,37 @@ static ssize_t show_psu_pin(struct device *dev, struct device_attribute *devattr case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); - - mutex_lock(&data_bus0->lock); - if (index) - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ + { + mutex_lock(&data->lock); + if (index) + i2c_smbus_write_byte(client, 0x20); /* Turn on PCA9548 channel 5 on I2C-bus1 */ + else + i2c_smbus_write_byte(client, 0x10); /* Turn on PCA9548 channel 4 on I2C-bus1 */ + value = i2c_smbus_read_word_data(&psu_mcu_client, 0x97); + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } else - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x97); - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); + { + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if (index) + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + else + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + value = i2c_smbus_read_word_data(&psu_mcu_client_bus0, 0x97); + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); + } } break; + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + break; + default: break; } @@ -3715,7 +4474,6 @@ static ssize_t set_psu_power_off(struct device *dev, struct device_attribute *de case NCIIX_WITH_BMC: case NCIIX_WITHOUT_BMC: { - struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); /* Setting the ON_OFF_CONFIG Command (02h) to type 9 (SW : turn-on/off by operation command). I2C Command: B2 02 19 59 @@ -3729,23 +4487,48 @@ static ssize_t set_psu_power_off(struct device *dev, struct device_attribute *de */ unsigned short cmd_data_2 = 0x2900; - mutex_lock(&data_bus0->lock); - if ((platformPsuABS&0x01)==0x00) /* PSU1 Present */ + if ((platformBuildRev > 0x01) && (platformHwRev == 0x03)) /* PVT rev2*/ { - /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); - i2c_smbus_write_word_data(&psu_mcu_client_bus0, 0x02, cmd_data_1); - i2c_smbus_write_word_data(&psu_mcu_client_bus0, 0x01, cmd_data_2); + mutex_lock(&data->lock); + if ((platformPsuABS & 0x01) == 0x00) /* PSU1 Present */ + { + /* Turn on PCA9548#0 channel 4 on I2C-bus1 */ + i2c_smbus_write_byte(client, 0x10); + i2c_smbus_write_word_data(&psu_mcu_client, 0x02, cmd_data_1); + i2c_smbus_write_word_data(&psu_mcu_client, 0x01, cmd_data_2); + } + if ((platformPsuABS & 0x02) == 0x00) /* PSU2 Present */ + { + /* Turn on PCA9548#0 channel 5 on I2C-bus1 */ + i2c_smbus_write_byte(client, 0x20); + i2c_smbus_write_word_data(&psu_mcu_client, 0x02, cmd_data_1); + i2c_smbus_write_word_data(&psu_mcu_client, 0x01, cmd_data_2); + } + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); } - if ((platformPsuABS&0x02)==0x00) /* PSU2 Present */ + else { - /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ - i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); - i2c_smbus_write_word_data(&psu_mcu_client_bus0, 0x02, cmd_data_1); - i2c_smbus_write_word_data(&psu_mcu_client_bus0, 0x01, cmd_data_2); + struct i2c_bus0_hardware_monitor_data *data_bus0 = i2c_get_clientdata(&psu_eeprom_client_bus0); + + mutex_lock(&data_bus0->lock); + if ((platformPsuABS & 0x01) == 0x00) /* PSU1 Present */ + { + /* Turn on PCA9548#0 channel 1 on I2C-bus0 */ + i2c_smbus_write_byte(&pca9548_client_bus0, 0x02); + i2c_smbus_write_word_data(&psu_mcu_client_bus0, 0x02, cmd_data_1); + i2c_smbus_write_word_data(&psu_mcu_client_bus0, 0x01, cmd_data_2); + } + if ((platformPsuABS & 0x02) == 0x00) /* PSU2 Present */ + { + /* Turn on PCA9548#0 channel 2 on I2C-bus0 */ + i2c_smbus_write_byte(&pca9548_client_bus0, 0x04); + i2c_smbus_write_word_data(&psu_mcu_client_bus0, 0x02, cmd_data_1); + i2c_smbus_write_word_data(&psu_mcu_client_bus0, 0x01, cmd_data_2); + } + i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); + mutex_unlock(&data_bus0->lock); } - i2c_smbus_write_byte(&pca9548_client_bus0, 0x00); - mutex_unlock(&data_bus0->lock); } break; @@ -3776,6 +4559,108 @@ static ssize_t set_system_led(struct device *dev, struct device_attribute *devat return count; } +static ssize_t show_fan_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); + unsigned int temp; + unsigned int frontLedStatus; + + mutex_lock(&data->lock); + frontLedStatus = (unsigned int)data->frontLedStatus; + switch(platformModelId) + { + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + if (!(frontLedStatus & 0x0010)) + temp = 2; /* Normal */ + else if (!(frontLedStatus & 0x0020)) + temp = 1; /* Critical */ + else + temp = 0; /* Booting */ + } + break; + default: + { + if (!(frontLedStatus & 0x0008)) + temp = 2; /* Normal */ + else if (!(frontLedStatus & 0x0004)) + temp = 1; /* Critical */ + else + temp = 0; /* Booting */ + } + break; + } + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", temp); +} + +static ssize_t show_psu_led(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); + unsigned int temp; + unsigned int frontLedStatus; + + mutex_lock(&data->lock); + frontLedStatus = (unsigned int)data->frontLedStatus; + switch(platformModelId) + { + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + if (attr->index == 0) + { + if (!(frontLedStatus & 0x0001)) + temp = 2; /* Normal */ + else if (!(frontLedStatus & 0x0002)) + temp = 1; /* Critical */ + else + temp = 0; /* Booting */ + } + else + { + if (!(frontLedStatus & 0x0004)) + temp = 2; /* Normal */ + else if (!(frontLedStatus & 0x0008)) + temp = 1; /* Critical */ + else + temp = 0; /* Booting */ + } + } + break; + default: + { + if (attr->index == 0) + { + if (!(frontLedStatus & 0x0002)) + temp = 2; /* Normal */ + else if (!(frontLedStatus & 0x0001)) + temp = 1; /* Critical */ + else + temp = 0; /* Booting */ + } + else + { + if (!(frontLedStatus & 0x0020)) + temp = 2; /* Normal */ + else if (!(frontLedStatus & 0x0010)) + temp = 1; /* Critical */ + else + temp = 0; /* Booting */ + } + } + break; + } + + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", temp); +} + static ssize_t show_port_tx_disable(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); @@ -3786,8 +4671,7 @@ static ssize_t show_port_tx_disable(struct device *dev, struct device_attribute case SESTO_WITH_BMC: case SESTO_WITHOUT_BMC: { - struct i2c_client *client = to_i2c_client(dev); - struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&(pca9535pwr_client[0])); unsigned short index=0, bit=0; index = (attr->index/16); @@ -3805,6 +4689,19 @@ static ssize_t show_port_tx_disable(struct device *dev, struct device_attribute } break; + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&(pca9535pwr_client[0])); + unsigned short bit = 0; + + bit = (attr->index % 8); + mutex_lock(&data->lock); + rc = (PCA9553_TEST_BIT(data->sfpPortTxDisableAst[attr->index / 8], bit) ? 1 : 0); + mutex_unlock(&data->lock); + } + break; + default: break; } @@ -3816,14 +4713,17 @@ static ssize_t show_port_tx_disable(struct device *dev, struct device_attribute static ssize_t set_port_tx_disable(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); + struct i2c_client *client, pca9548Client; + struct i2c_bus1_hardware_monitor_data *data; long temp; if (kstrtol(buf, 10, &temp)) return -EINVAL; temp = clamp_val(temp, 0, 1); + pca9548Client = pca9548_client[1]; + client = &pca9548Client; + data = i2c_get_clientdata(client); switch(platformModelId) { case SESTO_WITH_BMC: @@ -3840,7 +4740,7 @@ static ssize_t set_port_tx_disable(struct device *dev, struct device_attribute * else PCA9553_CLEAR_BIT(data->sfpPortTxDisable[index], bit); i2c_smbus_write_byte(&(pca9548_client[1]), (1<sfpPortTxDisable[index]); + i2c_device_word_write(&(pca9535pwr_client[index]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortTxDisable[index]); i2c_smbus_write_byte(&(pca9548_client[1]), 0x00); mutex_unlock(&data->lock); } @@ -3851,17 +4751,18 @@ static ssize_t set_port_tx_disable(struct device *dev, struct device_attribute * { unsigned short value = 0; + pca9548Client.addr = 0x70; SFPPortTxDisable[attr->index] = (temp&0x1); if ((attr->index/8) == 5) /* SFP+ 40~47 */ { mutex_lock(&data->lock); i2c_smbus_write_byte(client, sfpPortData_78F[attr->index].portMaskIOsForPCA9548_0); - value = i2c_smbus_read_word_data(&(pca9535pwr_client_bus1[sfpPortData_78F[attr->index].i2cAddrForPCA9535]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0); + value = i2c_smbus_read_word_data(&(pca9535pwr_client[sfpPortData_78F[attr->index].i2cAddrForPCA9535]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0); if (temp==1) PCA9553_SET_BIT(value, sfpPortData_78F[attr->index].portMaskBitForTxEnPin); else PCA9553_CLEAR_BIT(value, sfpPortData_78F[attr->index].portMaskBitForTxEnPin); - i2c_device_word_write(&(pca9535pwr_client_bus1[sfpPortData_78F[attr->index].i2cAddrForPCA9535]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, value); + i2c_device_word_write(&(pca9535pwr_client[sfpPortData_78F[attr->index].i2cAddrForPCA9535]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, value); i2c_smbus_write_byte(client, 0x00); mutex_unlock(&data->lock); } @@ -3883,6 +4784,37 @@ static ssize_t set_port_tx_disable(struct device *dev, struct device_attribute * } break; + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + unsigned short index = 0, bit = 0; + + pca9548Client.addr = 0x72; + index = (attr->index / 8); + bit = (attr->index % 8); + + mutex_lock(&data->lock); + if (temp == 1) + PCA9553_SET_BIT(data->sfpPortTxDisableAst[index], bit); + else + PCA9553_CLEAR_BIT(data->sfpPortTxDisableAst[index], bit); + + if (index < 3) + { + i2c_smbus_write_byte(client, (1 << PCA9548_CH00)); + i2c_smbus_write_byte_data(&(cpld_client_bus1), (0x40 + index), data->sfpPortTxDisableAst[index]); + } + else + { + i2c_smbus_write_byte(client, (1 << PCA9548_CH01)); + i2c_smbus_write_byte_data(&(cpld_client_bus1), (0x40 + (index - 3)), data->sfpPortTxDisableAst[index]); + } + + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } + break; + default: break; } @@ -3912,6 +4844,20 @@ static ssize_t show_port_rate_select(struct device *dev, struct device_attribute } break; + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + struct i2c_client *client = to_i2c_client(dev); + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); + unsigned short index = 0; + + index = (attr->index % 4); + mutex_lock(&data->lock); + rc = (PCA9553_TEST_BIT(data->sfpPortRateSelectAst[attr->index / 4], (index * 2)) ? 1 : 0); + mutex_unlock(&data->lock); + } + break; + default: break; } @@ -3950,15 +4896,15 @@ static ssize_t set_port_rate_select(struct device *dev, struct device_attribute switch(index) { case 0: - i2c_device_word_write(&(pca9535pwr_client_bus1[0]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[0]); + i2c_device_word_write(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[0]); break; case 1: - i2c_device_word_write(&(pca9535pwr_client_bus1[1]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[1]); + i2c_device_word_write(&(pca9535pwr_client[1]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[1]); break; case 2: - i2c_device_word_write(&(pca9535pwr_client_bus1[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[2]); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[2]); break; default: @@ -3968,15 +4914,15 @@ static ssize_t set_port_rate_select(struct device *dev, struct device_attribute switch(index) { case 0: - i2c_device_word_write(&(pca9535pwr_client_bus1[0]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[0]); + i2c_device_word_write(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[0]); break; case 1: - i2c_device_word_write(&(pca9535pwr_client_bus1[1]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[1]); + i2c_device_word_write(&(pca9535pwr_client[1]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[1]); break; case 2: - i2c_device_word_write(&(pca9535pwr_client_bus1[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[2]); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->sfpPortRateSelect[2]); break; default: @@ -3987,6 +4933,97 @@ static ssize_t set_port_rate_select(struct device *dev, struct device_attribute } break; + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + unsigned short index = 0, bit = 0; + + index = (attr->index / 4); + bit = (attr->index % 4); + + mutex_lock(&data->lock); + if (attr->index >= 0 && attr->index < 24) + { + /* Turn on PCA9548#0 channel 0 on I2C-bus1 - RX_RS, TX_RS */ + i2c_smbus_write_byte(client, (1 << PCA9548_CH00)); + + if (temp == 1) + { + PCA9553_SET_BIT(data->sfpPortRateSelectAst[index], (bit * 2)); + PCA9553_SET_BIT(data->sfpPortRateSelectAst[index], (bit * 2 + 1)); + } + else + { + PCA9553_CLEAR_BIT(data->sfpPortRateSelectAst[index], (bit * 2)); + PCA9553_CLEAR_BIT(data->sfpPortRateSelectAst[index], (bit * 2 + 1)); + } + + switch(index) + { + case 0: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x8, data->sfpPortRateSelectAst[index]); + break; + case 1: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x9, data->sfpPortRateSelectAst[index]); + break; + case 2: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x10, data->sfpPortRateSelectAst[index]); + break; + case 3: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x11, data->sfpPortRateSelectAst[index]); + break; + case 4: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x12, data->sfpPortRateSelectAst[index]); + break; + case 5: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x13, data->sfpPortRateSelectAst[index]); + break; + } + } + else + { + /* Turn on PCA9548#0 channel 1 on I2C-bus1 - RX_RS, TX_RS */ + i2c_smbus_write_byte(client, (1 << PCA9548_CH01)); + + if (temp == 1) + { + PCA9553_SET_BIT(data->sfpPortRateSelectAst[index], (bit * 2)); + PCA9553_SET_BIT(data->sfpPortRateSelectAst[index], (bit * 2 + 1)); + } + else + { + PCA9553_CLEAR_BIT(data->sfpPortRateSelectAst[index], (bit * 2)); + PCA9553_CLEAR_BIT(data->sfpPortRateSelectAst[index], (bit * 2 + 1)); + } + + switch(index) + { + case 6: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x8, data->sfpPortRateSelectAst[index]); + break; + case 7: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x9, data->sfpPortRateSelectAst[index]); + break; + case 8: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x10, data->sfpPortRateSelectAst[index]); + break; + case 9: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x11, data->sfpPortRateSelectAst[index]); + break; + case 10: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x12, data->sfpPortRateSelectAst[index]); + break; + case 11: + i2c_smbus_write_byte_data(&(cpld_client_bus1), 0x13, data->sfpPortRateSelectAst[index]); + break; + } + } + + i2c_smbus_write_byte(client, 0x00); + mutex_unlock(&data->lock); + } + break; + default: break; } @@ -3994,8 +5031,62 @@ static ssize_t set_port_rate_select(struct device *dev, struct device_attribute return count; } +static ssize_t show_port_tx_fault(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int rc = 0; + + switch(platformModelId) + { + case SESTO_WITH_BMC: + case SESTO_WITHOUT_BMC: + { + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&(pca9535pwr_client[0])); + unsigned short index = 0, bit = 0; + + index = (attr->index / 16); + bit = (attr->index % 16); + mutex_lock(&data->lock); + rc = (PCA9553_TEST_BIT(data->sfpPortTxFaultStatus[index], bit) ? 1 : 0); + mutex_unlock(&data->lock); + } + break; + + case NCIIX_WITH_BMC: + case NCIIX_WITHOUT_BMC: + { + rc = (SFPPortTxFaultStatus[attr->index] ? 0 : 1); + } + break; + + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&(pca9535pwr_client[0])); + unsigned char qsfpPortRxLos = 0, index = 0, bit = 0; + + index = (attr->index / 2); + bit = ((attr->index & 0x01) ? 7 : 3); + mutex_lock(&data->lock); + qsfpPortRxLos = data->sfpPortAbsRxLosStatus[index]; + mutex_unlock(&data->lock); + rc = (PCA9553_TEST_BIT(qsfpPortRxLos, bit) ? 1 : 0); + } + break; + + default: + break; + } + + + return sprintf(buf, "%d\n", rc); +} + static DEVICE_ATTR(eeprom, S_IRUGO, show_eeprom, NULL); static DEVICE_ATTR(system_led, S_IWUSR, NULL, set_system_led); +static DEVICE_ATTR(fan_led, S_IRUGO, show_fan_led, NULL); +static SENSOR_DEVICE_ATTR(psu1_led, S_IRUGO, show_psu_led, NULL, 0); +static SENSOR_DEVICE_ATTR(psu2_led, S_IRUGO, show_psu_led, NULL, 1); static SENSOR_DEVICE_ATTR(port_1_data_a0, S_IRUGO, show_port_data_a0, NULL, 0); static SENSOR_DEVICE_ATTR(port_2_data_a0, S_IRUGO, show_port_data_a0, NULL, 1); @@ -4127,6 +5218,71 @@ static SENSOR_DEVICE_ATTR(port_62_data_a2, S_IRUGO, show_port_data_a2, NULL, 61) static SENSOR_DEVICE_ATTR(port_63_data_a2, S_IRUGO, show_port_data_a2, NULL, 62); static SENSOR_DEVICE_ATTR(port_64_data_a2, S_IRUGO, show_port_data_a2, NULL, 63); +static SENSOR_DEVICE_ATTR(port_1_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 0); +static SENSOR_DEVICE_ATTR(port_2_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 1); +static SENSOR_DEVICE_ATTR(port_3_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 2); +static SENSOR_DEVICE_ATTR(port_4_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 3); +static SENSOR_DEVICE_ATTR(port_5_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 4); +static SENSOR_DEVICE_ATTR(port_6_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 5); +static SENSOR_DEVICE_ATTR(port_7_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 6); +static SENSOR_DEVICE_ATTR(port_8_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 7); +static SENSOR_DEVICE_ATTR(port_9_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 8); +static SENSOR_DEVICE_ATTR(port_10_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 9); +static SENSOR_DEVICE_ATTR(port_11_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 10); +static SENSOR_DEVICE_ATTR(port_12_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 11); +static SENSOR_DEVICE_ATTR(port_13_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 12); +static SENSOR_DEVICE_ATTR(port_14_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 13); +static SENSOR_DEVICE_ATTR(port_15_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 14); +static SENSOR_DEVICE_ATTR(port_16_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 15); +static SENSOR_DEVICE_ATTR(port_17_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 16); +static SENSOR_DEVICE_ATTR(port_18_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 17); +static SENSOR_DEVICE_ATTR(port_19_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 18); +static SENSOR_DEVICE_ATTR(port_20_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 19); +static SENSOR_DEVICE_ATTR(port_21_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 20); +static SENSOR_DEVICE_ATTR(port_22_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 21); +static SENSOR_DEVICE_ATTR(port_23_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 22); +static SENSOR_DEVICE_ATTR(port_24_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 23); +static SENSOR_DEVICE_ATTR(port_25_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 24); +static SENSOR_DEVICE_ATTR(port_26_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 25); +static SENSOR_DEVICE_ATTR(port_27_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 26); +static SENSOR_DEVICE_ATTR(port_28_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 27); +static SENSOR_DEVICE_ATTR(port_29_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 28); +static SENSOR_DEVICE_ATTR(port_30_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 29); +static SENSOR_DEVICE_ATTR(port_31_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 30); +static SENSOR_DEVICE_ATTR(port_32_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 31); +static SENSOR_DEVICE_ATTR(port_33_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 32); +static SENSOR_DEVICE_ATTR(port_34_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 33); +static SENSOR_DEVICE_ATTR(port_35_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 34); +static SENSOR_DEVICE_ATTR(port_36_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 35); +static SENSOR_DEVICE_ATTR(port_37_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 36); +static SENSOR_DEVICE_ATTR(port_38_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 37); +static SENSOR_DEVICE_ATTR(port_39_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 38); +static SENSOR_DEVICE_ATTR(port_40_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 39); +static SENSOR_DEVICE_ATTR(port_41_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 40); +static SENSOR_DEVICE_ATTR(port_42_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 41); +static SENSOR_DEVICE_ATTR(port_43_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 42); +static SENSOR_DEVICE_ATTR(port_44_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 43); +static SENSOR_DEVICE_ATTR(port_45_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 44); +static SENSOR_DEVICE_ATTR(port_46_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 45); +static SENSOR_DEVICE_ATTR(port_47_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 46); +static SENSOR_DEVICE_ATTR(port_48_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 47); +static SENSOR_DEVICE_ATTR(port_49_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 48); +static SENSOR_DEVICE_ATTR(port_50_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 49); +static SENSOR_DEVICE_ATTR(port_51_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 50); +static SENSOR_DEVICE_ATTR(port_52_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 51); +static SENSOR_DEVICE_ATTR(port_53_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 52); +static SENSOR_DEVICE_ATTR(port_54_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 53); +static SENSOR_DEVICE_ATTR(port_55_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 54); +static SENSOR_DEVICE_ATTR(port_56_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 55); +static SENSOR_DEVICE_ATTR(port_57_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 56); +static SENSOR_DEVICE_ATTR(port_58_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 57); +static SENSOR_DEVICE_ATTR(port_59_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 58); +static SENSOR_DEVICE_ATTR(port_60_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 59); +static SENSOR_DEVICE_ATTR(port_61_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 60); +static SENSOR_DEVICE_ATTR(port_62_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 61); +static SENSOR_DEVICE_ATTR(port_63_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 62); +static SENSOR_DEVICE_ATTR(port_64_sfp_copper, S_IRUGO, show_port_sfp_copper, NULL, 63); + static SENSOR_DEVICE_ATTR(port_1_abs, S_IRUGO, show_port_abs, NULL, 0); static SENSOR_DEVICE_ATTR(port_2_abs, S_IRUGO, show_port_abs, NULL, 1); static SENSOR_DEVICE_ATTR(port_3_abs, S_IRUGO, show_port_abs, NULL, 2); @@ -4375,6 +5531,9 @@ static DEVICE_ATTR(psu_power_off, S_IWUSR, NULL, set_psu_power_off); static struct attribute *i2c_bus1_hardware_monitor_attr_huracan[] = { &dev_attr_eeprom.attr, &dev_attr_system_led.attr, + &dev_attr_fan_led.attr, + &sensor_dev_attr_psu1_led.dev_attr.attr, + &sensor_dev_attr_psu2_led.dev_attr.attr, &sensor_dev_attr_port_1_data_a0.dev_attr.attr, &sensor_dev_attr_port_2_data_a0.dev_attr.attr, @@ -4442,6 +5601,39 @@ static struct attribute *i2c_bus1_hardware_monitor_attr_huracan[] = { &sensor_dev_attr_port_31_data_a2.dev_attr.attr, &sensor_dev_attr_port_32_data_a2.dev_attr.attr, + &sensor_dev_attr_port_1_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_2_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_3_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_4_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_5_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_6_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_7_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_8_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_9_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_10_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_11_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_12_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_13_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_14_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_15_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_16_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_17_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_18_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_19_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_20_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_21_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_22_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_23_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_24_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_25_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_26_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_27_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_28_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_29_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_30_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_31_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_32_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_1_abs.dev_attr.attr, &sensor_dev_attr_port_2_abs.dev_attr.attr, &sensor_dev_attr_port_3_abs.dev_attr.attr, @@ -4512,6 +5704,9 @@ static struct attribute *i2c_bus1_hardware_monitor_attr_huracan[] = { static struct attribute *i2c_bus1_hardware_monitor_attr_sesto[] = { &dev_attr_eeprom.attr, &dev_attr_system_led.attr, + &dev_attr_fan_led.attr, + &sensor_dev_attr_psu1_led.dev_attr.attr, + &sensor_dev_attr_psu2_led.dev_attr.attr, &sensor_dev_attr_port_1_data_a0.dev_attr.attr, &sensor_dev_attr_port_2_data_a0.dev_attr.attr, @@ -4623,6 +5818,61 @@ static struct attribute *i2c_bus1_hardware_monitor_attr_sesto[] = { &sensor_dev_attr_port_53_data_a2.dev_attr.attr, &sensor_dev_attr_port_54_data_a2.dev_attr.attr, + &sensor_dev_attr_port_1_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_2_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_3_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_4_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_5_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_6_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_7_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_8_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_9_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_10_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_11_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_12_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_13_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_14_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_15_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_16_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_17_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_18_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_19_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_20_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_21_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_22_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_23_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_24_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_25_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_26_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_27_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_28_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_29_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_30_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_31_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_32_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_33_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_34_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_35_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_36_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_37_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_38_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_39_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_40_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_41_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_42_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_43_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_44_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_45_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_46_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_47_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_48_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_49_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_50_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_51_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_52_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_53_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_54_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_1_abs.dev_attr.attr, &sensor_dev_attr_port_2_abs.dev_attr.attr, &sensor_dev_attr_port_3_abs.dev_attr.attr, @@ -4862,6 +6112,9 @@ static struct attribute *i2c_bus1_hardware_monitor_attr_sesto[] = { static struct attribute *i2c_bus1_hardware_monitor_attr_nc2x[] = { &dev_attr_eeprom.attr, &dev_attr_system_led.attr, + &dev_attr_fan_led.attr, + &sensor_dev_attr_psu1_led.dev_attr.attr, + &sensor_dev_attr_psu2_led.dev_attr.attr, &sensor_dev_attr_port_1_data_a0.dev_attr.attr, &sensor_dev_attr_port_2_data_a0.dev_attr.attr, @@ -4973,6 +6226,61 @@ static struct attribute *i2c_bus1_hardware_monitor_attr_nc2x[] = { &sensor_dev_attr_port_53_data_a2.dev_attr.attr, &sensor_dev_attr_port_54_data_a2.dev_attr.attr, + &sensor_dev_attr_port_1_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_2_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_3_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_4_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_5_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_6_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_7_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_8_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_9_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_10_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_11_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_12_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_13_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_14_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_15_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_16_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_17_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_18_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_19_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_20_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_21_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_22_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_23_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_24_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_25_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_26_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_27_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_28_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_29_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_30_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_31_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_32_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_33_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_34_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_35_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_36_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_37_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_38_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_39_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_40_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_41_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_42_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_43_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_44_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_45_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_46_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_47_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_48_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_49_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_50_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_51_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_52_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_53_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_54_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_1_abs.dev_attr.attr, &sensor_dev_attr_port_2_abs.dev_attr.attr, &sensor_dev_attr_port_3_abs.dev_attr.attr, @@ -5163,6 +6471,9 @@ static struct attribute *i2c_bus1_hardware_monitor_attr_nc2x[] = { static struct attribute *i2c_bus1_hardware_monitor_attr_asterion[] = { &dev_attr_eeprom.attr, &dev_attr_system_led.attr, + &dev_attr_fan_led.attr, + &sensor_dev_attr_psu1_led.dev_attr.attr, + &sensor_dev_attr_psu2_led.dev_attr.attr, &sensor_dev_attr_port_1_data_a0.dev_attr.attr, &sensor_dev_attr_port_2_data_a0.dev_attr.attr, @@ -5294,6 +6605,71 @@ static struct attribute *i2c_bus1_hardware_monitor_attr_asterion[] = { &sensor_dev_attr_port_63_data_a2.dev_attr.attr, &sensor_dev_attr_port_64_data_a2.dev_attr.attr, + &sensor_dev_attr_port_1_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_2_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_3_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_4_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_5_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_6_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_7_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_8_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_9_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_10_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_11_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_12_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_13_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_14_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_15_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_16_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_17_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_18_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_19_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_20_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_21_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_22_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_23_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_24_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_25_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_26_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_27_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_28_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_29_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_30_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_31_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_32_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_33_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_34_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_35_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_36_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_37_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_38_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_39_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_40_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_41_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_42_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_43_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_44_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_45_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_46_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_47_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_48_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_49_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_50_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_51_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_52_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_53_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_54_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_55_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_56_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_57_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_58_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_59_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_60_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_61_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_62_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_63_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_64_sfp_copper.dev_attr.attr, + &sensor_dev_attr_port_1_abs.dev_attr.attr, &sensor_dev_attr_port_2_abs.dev_attr.attr, &sensor_dev_attr_port_3_abs.dev_attr.attr, @@ -5524,30 +6900,415 @@ static struct attribute *i2c_bus1_hardware_monitor_attr_asterion[] = { &sensor_dev_attr_psu1_vout.dev_attr.attr, &sensor_dev_attr_psu1_iout.dev_attr.attr, &sensor_dev_attr_psu1_temp_1.dev_attr.attr, - &sensor_dev_attr_psu1_temp_2.dev_attr.attr, &sensor_dev_attr_psu1_fan_speed.dev_attr.attr, &sensor_dev_attr_psu1_pout.dev_attr.attr, - &sensor_dev_attr_psu1_pin.dev_attr.attr, &sensor_dev_attr_psu2_vout.dev_attr.attr, &sensor_dev_attr_psu2_iout.dev_attr.attr, &sensor_dev_attr_psu2_temp_1.dev_attr.attr, - &sensor_dev_attr_psu2_temp_2.dev_attr.attr, &sensor_dev_attr_psu2_fan_speed.dev_attr.attr, &sensor_dev_attr_psu2_pout.dev_attr.attr, - &sensor_dev_attr_psu2_pin.dev_attr.attr, &dev_attr_psu_power_off.attr, NULL }; +static int is_port_present(struct i2c_bus1_hardware_monitor_data *data, int port) +{ + int rc = 0; + + switch(platformModelId) + { + case NCIIX_WITH_BMC: + case NCIIX_WITHOUT_BMC: + rc = ((SFPPortAbsStatus[port] == 1) && (SFPPortDataValid[port] == 1)); + break; + + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + { + unsigned char qsfpPortAbsAst = 0, index = 0, bit = 0; + unsigned char sfpPortDataValidAst = 0; + + if (port < 48) + { + index = (port / 2); + bit = ((port & 0x01) ? 5 : 1); + qsfpPortAbsAst = data->sfpPortAbsRxLosStatus[index]; + sfpPortDataValidAst = data->sfpPortDataValidAst[port]; + rc = ((PCA9553_TEST_BIT(qsfpPortAbsAst, bit) ? 0 : 1) && (sfpPortDataValidAst)); + } + else + { + index = (port % 48); + qsfpPortAbsAst = data->qsfpPortAbsStatusAst[index]; + sfpPortDataValidAst = data->sfpPortDataValidAst[port]; + rc = ((PCA9553_TEST_BIT(qsfpPortAbsAst, 1) ? 0 : 1) && (sfpPortDataValidAst)); + } + } + break; + + default: + { + unsigned short qsfpPortAbs = 0, index = 0, bit = 0; + unsigned short qsfpPortDataValid = 0; + + index = (port / 16); + bit = (port % 16); + qsfpPortAbs = data->qsfpPortAbsStatus[index]; + qsfpPortDataValid = data->qsfpPortDataValid[index]; + rc = ((PCA9553_TEST_BIT(qsfpPortAbs, bit) ? 0 : 1) && (PCA9553_TEST_BIT(qsfpPortDataValid, bit))); + } + break; + } + + return rc; +} + +static ssize_t get_qsfp_port_tx_rx_status(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&qsfpDataA0_client); + unsigned char qsfpPortData[QSFP_DATA_SIZE]; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int index = (client->addr - 1); + int val = 0; + + memset(qsfpPortData, 0, QSFP_DATA_SIZE); + + mutex_lock(&data->lock); + if (is_port_present(data, index) == 1) + memcpy(qsfpPortData, &(data->qsfpPortDataA0[index][0]), QSFP_DATA_SIZE); + else + { + qsfpPortData[SFF8436_RX_LOS_ADDR] = qsfpPortData[SFF8436_TX_FAULT_ADDR] = 0xF; + qsfpPortData[SFF8436_TX_DISABLE_ADDR] = data->qsfpPortTxDisableData[index]; + } + mutex_unlock(&data->lock); + + switch (attr->index) + { + case RX_LOS: + val = (qsfpPortData[SFF8436_RX_LOS_ADDR] & 0xF); + break; + case RX_LOS1: + case RX_LOS2: + case RX_LOS3: + case RX_LOS4: + val = (qsfpPortData[SFF8436_RX_LOS_ADDR] & BIT_INDEX(attr->index - RX_LOS1)); + break; + + case TX_DISABLE: + val = (qsfpPortData[SFF8436_TX_DISABLE_ADDR] & 0xF); + break; + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + val = (qsfpPortData[SFF8436_TX_DISABLE_ADDR] & BIT_INDEX(attr->index - TX_DISABLE1)); + break; + + case TX_FAULT: + val = (qsfpPortData[SFF8436_TX_FAULT_ADDR] & 0xF); + break; + case TX_FAULT1: + case TX_FAULT2: + case TX_FAULT3: + case TX_FAULT4: + val = (qsfpPortData[SFF8436_TX_FAULT_ADDR] & BIT_INDEX(attr->index - TX_FAULT1)); + break; + + default: + break; + } + return sprintf(buf, "%d\n", ((val) ? 1 : 0)); +} + +static ssize_t get_port_status(struct device *dev, struct device_attribute *devattr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int status = LAST_ATTRIBUTE; + ssize_t count = 0; + + mutex_lock(&portStatusLock); + + status = attr->index; + + /* common status */ + switch (status) + { + case PRESENT: + attr->index = (client->addr - 1); + count = show_port_abs(dev, devattr, buf); + attr->index = status; + mutex_unlock(&portStatusLock); + return count; + + case EEPROM_A0_PAGE: + attr->index = (client->addr - 1); + count = show_port_data_a0(dev, devattr, buf); + attr->index = status; + mutex_unlock(&portStatusLock); + return count; + + case EEPROM_A2_PAGE: + attr->index = (client->addr - 1); + count = show_port_data_a2(dev, devattr, buf); + attr->index = status; + mutex_unlock(&portStatusLock); + return count; + + case SFP_COPPER: + attr->index = (client->addr - 1); + count = show_port_sfp_copper(dev, devattr, buf); + attr->index = status; + mutex_unlock(&portStatusLock); + return count; + + default: + break; + } + + /* status for QSFP ports */ + if (strncmp(client->name, "qsfp", strlen("qsfp")) == 0) + { + count = get_qsfp_port_tx_rx_status(dev, devattr, buf); + mutex_unlock(&portStatusLock); + return count; + } + + /* status for SFP+ ports */ + attr->index = (client->addr - 1); + switch (status) + { + case RX_LOS: + case RX_LOS1: + case RX_LOS2: + case RX_LOS3: + case RX_LOS4: + count = show_port_rxlos(dev, devattr, buf); + break; + + case TX_DISABLE: + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + count = show_port_tx_disable(dev, devattr, buf); + break; + + case TX_FAULT: + case TX_FAULT1: + case TX_FAULT2: + case TX_FAULT3: + case TX_FAULT4: + count = show_port_tx_fault(dev, devattr, buf); + break; + + default: + count = sprintf(buf, "0\n"); + break; + } + attr->index = status; + mutex_unlock(&portStatusLock); + return count; +} + +static ssize_t set_qsfp_port_tx_status(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&qsfpDataA0_client); + unsigned char qsfpPortData[QSFP_DATA_SIZE]; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int index = (client->addr - 1); + long disable; + + if (kstrtol(buf, 10, &disable)) + return -EINVAL; + disable = clamp_val(disable, 0, 1); + + memset(qsfpPortData, 0, QSFP_DATA_SIZE); + + mutex_lock(&data->lock); + memcpy(qsfpPortData, &(data->qsfpPortDataA0[index][0]), QSFP_DATA_SIZE); + switch (attr->index) + { + case TX_DISABLE: + if (disable == 1) + data->qsfpPortTxDisableData[index] = (qsfpPortData[SFF8436_TX_DISABLE_ADDR] |0xF); + else + data->qsfpPortTxDisableData[index] = (qsfpPortData[SFF8436_TX_DISABLE_ADDR] & 0xF0); + data->qsfpPortTxDisableDataUpdate[index] = 1; + break; + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + if (disable == 1) + data->qsfpPortTxDisableData[index] = (qsfpPortData[SFF8436_TX_DISABLE_ADDR] | (1 << (attr->index - TX_DISABLE1))); + else + data->qsfpPortTxDisableData[index] = (qsfpPortData[SFF8436_TX_DISABLE_ADDR] & ~(1 << (attr->index - TX_DISABLE1))); + data->qsfpPortTxDisableDataUpdate[index] = 1; + break; + + default: + break; + } + mutex_unlock(&data->lock); + return count; +} + +static ssize_t set_port_tx_status(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int status = LAST_ATTRIBUTE; + + mutex_lock(&portStatusLock); + + /* status for QSFP ports */ + if (strncmp(client->name, "qsfp", strlen("qsfp")) == 0) + { + set_qsfp_port_tx_status(dev, devattr, buf, count); + mutex_unlock(&portStatusLock); + return count; + } + + /* status for SFP+ ports */ + status = attr->index; + attr->index = (client->addr - 1); + switch (status) + { + case TX_DISABLE: + case TX_DISABLE1: + case TX_DISABLE2: + case TX_DISABLE3: + case TX_DISABLE4: + set_port_tx_disable(dev, devattr, buf, count); + break; + + default: + break; + } + attr->index = status; + mutex_unlock(&portStatusLock); + return count; +} + +static ssize_t set_port_sfp_copper(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + + /* QSFP ports */ + if (strncmp(client->name, "qsfp", strlen("qsfp")) == 0) + { + return count; + } + /* SFP+ ports */ + else + { + struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(&SfpCopperData_client); + int index = (client->addr - 1); + long value; + + if ((platformModelId != NCIIX_WITH_BMC) && (platformModelId != NCIIX_WITHOUT_BMC)) + return count; + + if (kstrtol(buf, 10, &value)) + return -EINVAL; + + mutex_lock(&data->lock); + if (SFPPortAbsStatus[index]) /*present*/ + { + i2c_smbus_write_byte_data(&(pca9548_client[1]), 0, sfpPortData_78F[index].portMaskBitForPCA9548_1); + i2c_smbus_write_byte_data(&(pca9548_client[0]), 0, sfpPortData_78F[index].portMaskBitForPCA9548_2TO5); + i2c_device_word_write(&SfpCopperData_client, + (unsigned char)((value >> 16) & 0xff), + (unsigned short)(value & 0xffff)); + i2c_smbus_write_byte_data(&(pca9548_client[0]), 0, 0x00); + i2c_smbus_write_byte_data(&(pca9548_client[1]), 0, 0x00); + } + mutex_unlock(&data->lock); + } + + return count; +} + +static SENSOR_DEVICE_ATTR(abs, S_IRUGO, get_port_status, NULL, PRESENT); +static SENSOR_DEVICE_ATTR(rxlos, S_IRUGO, get_port_status, NULL, RX_LOS); +static SENSOR_DEVICE_ATTR(rxlos1, S_IRUGO, get_port_status, NULL, RX_LOS1); +static SENSOR_DEVICE_ATTR(rxlos2, S_IRUGO, get_port_status, NULL, RX_LOS2); +static SENSOR_DEVICE_ATTR(rxlos3, S_IRUGO, get_port_status, NULL, RX_LOS3); +static SENSOR_DEVICE_ATTR(rxlos4, S_IRUGO, get_port_status, NULL, RX_LOS4); +static SENSOR_DEVICE_ATTR(tx_disable, S_IWUSR | S_IRUGO, get_port_status, set_port_tx_status, TX_DISABLE); +static SENSOR_DEVICE_ATTR(tx_disable1, S_IWUSR | S_IRUGO, get_port_status, set_port_tx_status, TX_DISABLE1); +static SENSOR_DEVICE_ATTR(tx_disable2, S_IWUSR | S_IRUGO, get_port_status, set_port_tx_status, TX_DISABLE2); +static SENSOR_DEVICE_ATTR(tx_disable3, S_IWUSR | S_IRUGO, get_port_status, set_port_tx_status, TX_DISABLE3); +static SENSOR_DEVICE_ATTR(tx_disable4, S_IWUSR | S_IRUGO, get_port_status, set_port_tx_status, TX_DISABLE4); +static SENSOR_DEVICE_ATTR(tx_fault, S_IRUGO, get_port_status, NULL, TX_FAULT); +static SENSOR_DEVICE_ATTR(tx_fault1, S_IRUGO, get_port_status, NULL, TX_FAULT1); +static SENSOR_DEVICE_ATTR(tx_fault2, S_IRUGO, get_port_status, NULL, TX_FAULT2); +static SENSOR_DEVICE_ATTR(tx_fault3, S_IRUGO, get_port_status, NULL, TX_FAULT3); +static SENSOR_DEVICE_ATTR(tx_fault4, S_IRUGO, get_port_status, NULL, TX_FAULT4); +static SENSOR_DEVICE_ATTR(data_a0, S_IRUGO, get_port_status, NULL, EEPROM_A0_PAGE); +static SENSOR_DEVICE_ATTR(data_a2, S_IRUGO, get_port_status, NULL, EEPROM_A2_PAGE); +static SENSOR_DEVICE_ATTR(sfp_copper, S_IWUSR | S_IRUGO, get_port_status, set_port_sfp_copper, SFP_COPPER); + +static struct attribute *sfp_attributes[] = { + &sensor_dev_attr_abs.dev_attr.attr, + &sensor_dev_attr_rxlos.dev_attr.attr, + &sensor_dev_attr_rxlos1.dev_attr.attr, + &sensor_dev_attr_rxlos2.dev_attr.attr, + &sensor_dev_attr_rxlos3.dev_attr.attr, + &sensor_dev_attr_rxlos4.dev_attr.attr, + &sensor_dev_attr_tx_disable.dev_attr.attr, + &sensor_dev_attr_tx_disable1.dev_attr.attr, + &sensor_dev_attr_tx_disable2.dev_attr.attr, + &sensor_dev_attr_tx_disable3.dev_attr.attr, + &sensor_dev_attr_tx_disable4.dev_attr.attr, + &sensor_dev_attr_tx_fault.dev_attr.attr, + &sensor_dev_attr_tx_fault1.dev_attr.attr, + &sensor_dev_attr_tx_fault2.dev_attr.attr, + &sensor_dev_attr_tx_fault3.dev_attr.attr, + &sensor_dev_attr_tx_fault4.dev_attr.attr, + &sensor_dev_attr_data_a0.dev_attr.attr, + &sensor_dev_attr_data_a2.dev_attr.attr, + &sensor_dev_attr_sfp_copper.dev_attr.attr, + NULL +}; + +static const struct attribute_group sfp_group = { + .attrs = sfp_attributes, +}; + +static struct i2c_client *sfpPortDeviceCreate(struct i2c_adapter *adap, int port, const char *sfpType) +{ + struct i2c_client *client = NULL; + int status; + + client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!client) + return NULL; + + client->adapter = adap; + client->addr = (port + 1); + sprintf(client->name, "%s_%03d", sfpType, (port + 1)); + client->dev.parent = &client->adapter->dev; + dev_set_name(&client->dev, "port_%03d", (port + 1)); + status = device_register(&client->dev); + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &sfp_group); + return client; +} + static void i2c_bus0_devices_client_address_init(struct i2c_client *client) { int index; - pca9535pwr_client = *client; - pca9535pwr_client.addr = 0x27; + pca9535pwr_client_bus0 = *client; + pca9535pwr_client_bus0.addr = 0x27; cpld_client = *client; cpld_client.addr = 0x33; @@ -5635,7 +7396,7 @@ static void i2c_bus0_hardware_monitor_hw_default_config(struct i2c_client *clien /* Get device id */ data->dviceId= i2c_smbus_read_byte_data(client, W83795ADG_REG_DEVICE_ID); - /* set FANCTL8 ¡V FANCTL1 output mode control to PWM output duty cycle mode. */ + /* set FANCTL8 - FANCTL1 output mode control to PWM output duty cycle mode. */ i2c_smbus_write_byte_data(client, W83795ADG_REG_FOMC, 0x00); i2c_smbus_write_byte_data(client, W83795ADG_REG_F1OV, 0xff); i2c_smbus_write_byte_data(client, W83795ADG_REG_F2OV, 0xff); @@ -5644,6 +7405,10 @@ static void i2c_bus0_hardware_monitor_hw_default_config(struct i2c_client *clien i2c_smbus_write_byte_data(client, W83795ADG_REG_BANK, 0x00); /* Enable TR1~TR4 thermistor temperature monitoring */ i2c_smbus_write_byte_data(client, W83795ADG_REG_TEMP_CTRL2, 0xff); + + /* set FANCTL2 to enable FANIN9 and FANIN10 monitoring */ + i2c_smbus_write_byte_data(client, W83795ADG_REG_FANIN_CTRL2, 0x03); + /* Enable monitoring operations */ configByte |= 0x01; i2c_smbus_write_byte_data(client, W83795ADG_REG_CONFIG, configByte); @@ -5732,10 +7497,10 @@ static void i2c_bus0_hardware_monitor_hw_default_config(struct i2c_client *clien default: /* set default value for IO expander #0 */ - i2c_smbus_write_word_data(&pca9535pwr_client, PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); + i2c_smbus_write_word_data(&pca9535pwr_client_bus0, PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); /* set input-1/output-0 mode for IO expander #0 */ - i2c_smbus_write_word_data(&pca9535pwr_client, PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_smbus_write_word_data(&pca9535pwr_client, PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xff7f); + i2c_smbus_write_word_data(&pca9535pwr_client_bus0, PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_smbus_write_word_data(&pca9535pwr_client_bus0, PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xff7f); break; } @@ -5754,27 +7519,47 @@ static void i2c_bus1_devices_client_address_init(struct i2c_client *client) for (index=0; index<6; index++) { - pca9535pwr_client_bus1[index] = *client; - pca9535pwr_client_bus1[index].addr = (0x20+index); + pca9535pwr_client[index] = *client; + pca9535pwr_client[index].addr = (0x20+index); } + cpld_client_bus1 = *client; + cpld_client_bus1.addr = 0x33; + qsfpDataA0_client = *client; qsfpDataA0_client.addr = 0x50; qsfpDataA2_client = *client; qsfpDataA2_client.addr = 0x51; - eeprom_client = *client; - eeprom_client.addr = 0x54; + SfpCopperData_client = *client; + SfpCopperData_client.addr = 0x56; - eeprom_client_2 = *client; - eeprom_client_2.addr = 0x56; + switch(platformModelId) + { + case NCIIX_WITH_BMC: + case NCIIX_WITHOUT_BMC: + eeprom_client = *client; + eeprom_client.addr = 0x56; - psu_eeprom_client = *client; - psu_eeprom_client.addr = 0x50; + psu_eeprom_client = *client; + psu_eeprom_client.addr = 0x51; - psu_mcu_client = *client; - psu_mcu_client.addr = 0x58; + psu_mcu_client = *client; + psu_mcu_client.addr = 0x59; + break; + + default: + eeprom_client = *client; + eeprom_client.addr = 0x54; + + psu_eeprom_client = *client; + psu_eeprom_client.addr = 0x50; + + psu_mcu_client = *client; + psu_mcu_client.addr = 0x58; + break; + } } static void i2c_bus1_io_expander_default_set(struct i2c_client *client) @@ -5793,8 +7578,8 @@ static void i2c_bus1_io_expander_default_set(struct i2c_client *client) /* set input-1/output-0 mode for IO expander #1-4 on channel 4 */ for (i=0; i<4; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); } /* Turn on PCA9548 channel 5 on I2C-bus1 */ @@ -5804,27 +7589,27 @@ static void i2c_bus1_io_expander_default_set(struct i2c_client *client) /* set input-1/output-0 mode for IO expander #1-2 on channel 5 */ for (i=0; i<2; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); } /* RST#(Module Reset) = 1 */ /* set input-1/output-0 mode for IO expander #3-4 on channel 5 */ for (i=2; i<4; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0xffff); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0xffff); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); } /* MODSEL# (Module Select) = 0 */ /* set input-1/output-0 mode for IO expander #5-6 on channel 5 */ for (i=4; i<6; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); } if (isBMCSupport == 0) @@ -5833,30 +7618,30 @@ static void i2c_bus1_io_expander_default_set(struct i2c_client *client) i2c_smbus_write_byte(client, (1<frontLedStatus); - i2c_device_word_write(&(pca9535pwr_client_bus1[2]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[2]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->frontLedStatus); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); } } @@ -5875,8 +7660,8 @@ static void i2c_bus1_io_expander_default_set(struct i2c_client *client) /* set input-1/output-0 mode for IO expander #1-4 on channel 0 */ for (i=0; i<4; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); } /* Turn on PCA9548#1 channel 1 on I2C-bus1 - RXLOS */ @@ -5884,8 +7669,8 @@ static void i2c_bus1_io_expander_default_set(struct i2c_client *client) /* set input-1/output-0 mode for IO expander #1-3 on channel 1 */ for (i=0; i<3; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); } /* Turn on PCA9548#1 channel 2 on I2C-bus1 - TXFAULT */ @@ -5893,8 +7678,8 @@ static void i2c_bus1_io_expander_default_set(struct i2c_client *client) /* set input-1/output-0 mode for IO expander #1-3 on channel 2 */ for (i=0; i<3; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); } /* Turn on PCA9548#1 channel 3 on I2C-bus1 - TX_RS = 1, LPMODE = 0, MODSEL = 0 */ @@ -5902,22 +7687,22 @@ static void i2c_bus1_io_expander_default_set(struct i2c_client *client) /* set input-1/output-0 mode for IO expander #1-4 on channel 3 */ for (i=0; i<3; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0xffff); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0xffff); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); } - i2c_device_word_write(&(pca9535pwr_client_bus1[3]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[3]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[3]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[3]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[3]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[3]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); /* Turn on PCA9548#1 channel 4 on I2C-bus1 - RX _RS = 1 */ i2c_smbus_write_byte(&(pca9548_client[1]), (1<frontLedStatus); - i2c_device_word_write(&(pca9535pwr_client_bus1[2]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[2]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, data->frontLedStatus); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); /* Turn off PCA9548#0 all channels on I2C-bus1 */ i2c_smbus_write_byte(client, 0x00); } @@ -5979,17 +7764,17 @@ static void i2c_bus1_io_expander_default_set(struct i2c_client *client) /* set input-1/output-0 mode for IO expander #20-23 on channel 0 : SFP+ 40-47 : TXEN = 0, RX_RS = 0, TX_RS = 0 */ for (i=0; i<4; i++) { - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); - i2c_device_word_write(&(pca9535pwr_client_bus1[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xf1c7); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[i]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xf1c7); } /* Turn on PCA9548#1 channel 1 on I2C-bus1 */ i2c_smbus_write_byte(client, (1<frontLedStatus); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[2]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0x0000); + + /* Turn on PCA9548#0 channel 5 on I2C-bus1 */ + i2c_smbus_write_byte(client, (1 << PCA9548_CH05)); + /* PSU Status */ + /* set input-1/output-0 mode for IO expander #1 on channel 5 */ + i2c_device_word_write(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_OUTPUT_PORT_0, 0x0000); + i2c_device_word_write(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_POLARITY_INVERSION_0, 0x0000); +/* If the PSU_PWROFF pin of IO expander is output mode, the power cycling of CPLD cannot work.*/ +#if 0 + i2c_device_word_write(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffbb); +#else + i2c_device_word_write(&(pca9535pwr_client[0]), PCA9553_COMMAND_BYTE_REG_CONFIGURATION_0, 0xffff); +#endif + + /* Turn off PCA9548#0 all channels on I2C-bus1 */ + i2c_smbus_write_byte(client, 0x00); break; default: @@ -6213,6 +8034,69 @@ static int w83795adg_hardware_monitor_probe(struct i2c_client *client, } else { + struct i2c_adapter *adap = to_i2c_adapter(&client->dev); + int port; + + for (port = 0; port < QSFP_COUNT; port++) + data->qsfpPortTxDisableDataUpdate[port] = 1; + mutex_init(&portStatusLock); + switch (platformModelId) + { + case HURACAN_WITH_BMC: + case HURACAN_WITHOUT_BMC: + case HURACAN_A_WITH_BMC: + case HURACAN_A_WITHOUT_BMC: + /* QSFP ports */ + for (port = 0; port < 32; port++) + { + data->sfpPortClient[port] = sfpPortDeviceCreate(adap, port, "qsfp"); + if (!data->sfpPortClient[port]) + return -ENOMEM; + } + break; + + case SESTO_WITH_BMC: + case SESTO_WITHOUT_BMC: + case NCIIX_WITH_BMC: + case NCIIX_WITHOUT_BMC: + /* SFP+ ports */ + for (port = 0; port < 48; port++) + { + data->sfpPortClient[port] = sfpPortDeviceCreate(adap, port, "sfp"); + if (!data->sfpPortClient[port]) + return -ENOMEM; + } + /* QSFP ports */ + for (port = 48; port < 54; port++) + { + data->sfpPortClient[port] = sfpPortDeviceCreate(adap, port, "qsfp"); + if (!data->sfpPortClient[port]) + return -ENOMEM; + } + break; + + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + /* SFP+ ports */ + for (port = 0; port < 48; port++) + { + data->sfpPortClient[port] = sfpPortDeviceCreate(adap, port, "sfp"); + if (!data->sfpPortClient[port]) + return -ENOMEM; + } + /* QSFP ports */ + for (port = 48; port < 64; port++) + { + data->sfpPortClient[port] = sfpPortDeviceCreate(adap, port, "qsfp"); + if (!data->sfpPortClient[port]) + return -ENOMEM; + } + break; + + default: + break; + } + init_completion(&data->auto_update_stop); data->auto_update = kthread_run(i2c_bus1_hardware_monitor_update_thread, client, dev_name(data->hwmon_dev)); if (IS_ERR(data->auto_update)) { @@ -6249,16 +8133,35 @@ static int w83795adg_hardware_monitor_remove(struct i2c_client *client) i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_LED_0x44, 0x00); #endif + mutex_destroy(&client->dev.mutex); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &data->hwmon_group); + mutex_destroy(&data->lock); } else if(client->adapter->nr == 0x1) { + int port; + struct i2c_client *c; struct i2c_bus1_hardware_monitor_data *data = i2c_get_clientdata(client); kthread_stop(data->auto_update); wait_for_completion(&data->auto_update_stop); + for (port = 0; port < QSFP_COUNT; port ++) + { + c = data->sfpPortClient[port]; + if (c) + { + sysfs_remove_group(&c->dev.kobj, &sfp_group); + mutex_destroy(&c->dev.mutex); + device_del(&c->dev); + kfree(c); + } + } + mutex_destroy(&portStatusLock); + + mutex_destroy(&client->dev.mutex); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &data->hwmon_group); + mutex_destroy(&data->lock); } return 0; } @@ -6284,8 +8187,22 @@ static void w83795adg_hardware_monitor_shutdown(struct i2c_client *client) i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_LED_0x44, 0x00); #endif /* reset MAC */ - i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x30, 0x6e); - i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x30, 0x6f); + switch(platformModelId) + { + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x30, 0x3e); + i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x30, 0x3f); + /* reset CPLD 2, 3 and 4 */ + i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x35, 0xfd); /* assert RST_CPLD2_3_4 */ + i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x35, 0xff); + break; + + default: + i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x30, 0x6e); + i2c_smbus_write_byte_data(&cpld_client, CPLD_REG_RESET_0x30, 0x6f); + break; + } hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &data->hwmon_group); diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/.gitignore b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/.gitignore new file mode 100755 index 00000000..ec93c180 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/.gitignore @@ -0,0 +1,2 @@ +*x86*64*netberg*aurora*420*rangeley*.mk +onlpdump.mk diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/modules/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/modules/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/modules/PKG.yml b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/modules/PKG.yml new file mode 100755 index 00000000..b3df78e4 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/no-platform-modules.yml ARCH=amd64 VENDOR=netberg BASENAME=x86-64-netberg-aurora-420-rangeley diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/PKG.yml b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/PKG.yml new file mode 100755 index 00000000..85e495fc --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-netberg-aurora-420-rangeley ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/Makefile new file mode 100755 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/lib/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/lib/Makefile new file mode 100755 index 00000000..b7174f7d --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/lib/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.eclipse.org/legal/epl-v10.html +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +# either express or implied. See the License for the specific +# language governing permissions and limitations under the +# License. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-netberg-aurora-420-rangeley +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_netberg_aurora_420_rangeley onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-netberg-aurora-420-rangeley.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/onlpdump/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/onlpdump/Makefile new file mode 100755 index 00000000..b88bedd8 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/onlpdump/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.eclipse.org/legal/epl-v10.html +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +# either express or implied. See the License for the specific +# language governing permissions and limitations under the +# License. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp x86_64_netberg_aurora_420_rangeley onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/.gitignore b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/.gitignore new file mode 100644 index 00000000..c81d16be --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/.gitignore @@ -0,0 +1 @@ +*.mk diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/.module b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/.module new file mode 100755 index 00000000..d3df16ce --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/.module @@ -0,0 +1 @@ +name: x86_64_netberg_aurora_420_rangeley diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/Makefile new file mode 100755 index 00000000..e0be8a99 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include $(ONL)/make/config.mk +MODULE := x86_64_netberg_aurora_420_rangeley +AUTOMODULE := x86_64_netberg_aurora_420_rangeley +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/auto/x86_64_netberg_aurora_420_rangeley.yml b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/auto/x86_64_netberg_aurora_420_rangeley.yml new file mode 100644 index 00000000..c9e72b4f --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/auto/x86_64_netberg_aurora_420_rangeley.yml @@ -0,0 +1,119 @@ +############################################################################### +# +# x86_64_netberg_aurora_420_rangeley Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB +- X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD: + doc: "RPM Threshold at which the fan is considered to have failed." + default: 3000 + +definitions: + cdefs: + X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_netberg_aurora_420_rangeley_config + + enum: &enums + + fan_id: + members: + - FAN1 : 1 + - FAN2 : 2 + - FAN3 : 3 + - FAN4 : 4 + - FAN5 : 5 + - FAN6 : 6 + - FAN7 : 7 + - FAN8 : 8 + - FAN9 : 9 + - FAN10 : 10 + + fan_oid: + members: + - FAN1 : ONLP_FAN_ID_CREATE(1) + - FAN2 : ONLP_FAN_ID_CREATE(2) + - FAN3 : ONLP_FAN_ID_CREATE(3) + - FAN4 : ONLP_FAN_ID_CREATE(4) + - FAN5 : ONLP_FAN_ID_CREATE(5) + - FAN6 : ONLP_FAN_ID_CREATE(6) + - FAN7 : ONLP_FAN_ID_CREATE(7) + - FAN8 : ONLP_FAN_ID_CREATE(8) + - FAN9 : ONLP_FAN_ID_CREATE(9) + - FAN10 : ONLP_FAN_ID_CREATE(10) + + psu_id: + members: + - PSU1 : 1 + - PSU2 : 2 + + psu_oid: + members: + - PSU1 : ONLP_PSU_ID_CREATE(1) + - PSU2 : ONLP_PSU_ID_CREATE(2) + + thermal_id: + members: + - THERMAL1 : 1 + - THERMAL2 : 2 + - THERMAL3 : 3 + - THERMAL4 : 4 + - THERMAL5 : 5 + - THERMAL6 : 6 + - THERMAL7 : 7 + + thermal_oid: + members: + - THERMAL1 : ONLP_THERMAL_ID_CREATE(1) + - THERMAL2 : ONLP_THERMAL_ID_CREATE(2) + - THERMAL3 : ONLP_THERMAL_ID_CREATE(3) + - THERMAL4 : ONLP_THERMAL_ID_CREATE(4) + - THERMAL5 : ONLP_THERMAL_ID_CREATE(5) + - THERMAL6 : ONLP_THERMAL_ID_CREATE(6) + - THERMAL7 : ONLP_THERMAL_ID_CREATE(7) + + led_id: + members: + - STAT : 1 + - FAN : 2 + - PSU1 : 3 + - PSU2 : 4 + + led_oid: + members: + - STAT : ONLP_LED_ID_CREATE(1) + - FAN : ONLP_LED_ID_CREATE(2) + - PSU1 : ONLP_LED_ID_CREATE(3) + - PSU2 : ONLP_LED_ID_CREATE(4) + + portingmacro: + X86_64_NETBERG_AURORA_420_RANGELEY: + macros: + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley.x b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley.x new file mode 100755 index 00000000..7be4645d --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_config.h b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_config.h new file mode 100755 index 00000000..6a506e23 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_netberg_aurora_420_rangeley Configuration Header + * + * @addtogroup x86_64_netberg_aurora_420_rangeley-config + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_H__ +#define __X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_LOGGING +#define X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT +#define X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT +#define X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB +#define X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB +#endif + +/** + * X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI +#define X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD + * + * RPM Threshold at which the fan is considered to have failed. */ + + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD +#define X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD 3000 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_netberg_aurora_420_rangeley_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_netberg_aurora_420_rangeley_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_netberg_aurora_420_rangeley_config_settings table. */ +extern x86_64_netberg_aurora_420_rangeley_config_settings_t x86_64_netberg_aurora_420_rangeley_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_netberg_aurora_420_rangeley_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_netberg_aurora_420_rangeley_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_netberg_aurora_420_rangeley_porting.h" + +#endif /* __X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_dox.h b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_dox.h new file mode 100755 index 00000000..d37fea93 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_netberg_aurora_420_rangeley Doxygen Header + * + *****************************************************************************/ +#ifndef __X86_64_NETBERG_AURORA_420_RANGELEY_DOX_H__ +#define __X86_64_NETBERG_AURORA_420_RANGELEY_DOX_H__ + +/** + * @defgroup x86_64_netberg_aurora_420_rangeley x86_64_netberg_aurora_420_rangeley - x86_64_netberg_aurora_420_rangeley Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_netberg_aurora_420_rangeley-x86_64_netberg_aurora_420_rangeley Public Interface + * @defgroup x86_64_netberg_aurora_420_rangeley-config Compile Time Configuration + * @defgroup x86_64_netberg_aurora_420_rangeley-porting Porting Macros + * + * @} + * + */ + +#endif /* __X86_64_NETBERG_AURORA_420_RANGELEY_DOX_H__ */ diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_porting.h b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_porting.h new file mode 100755 index 00000000..79f2983a --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/inc/x86_64_netberg_aurora_420_rangeley/x86_64_netberg_aurora_420_rangeley_porting.h @@ -0,0 +1,87 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_netberg_aurora_420_rangeley Porting Macros. + * + * @addtogroup x86_64_netberg_aurora_420_rangeley-porting + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_NETBERG_AURORA_420_RANGELEY_PORTING_H__ +#define __X86_64_NETBERG_AURORA_420_RANGELEY_PORTING_H__ + + +/* */ +#if X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_MEMSET + #if defined(GLOBAL_MEMSET) + #define X86_64_NETBERG_AURORA_420_RANGELEY_MEMSET GLOBAL_MEMSET + #elif X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB == 1 + #define X86_64_NETBERG_AURORA_420_RANGELEY_MEMSET memset + #else + #error The macro X86_64_NETBERG_AURORA_420_RANGELEY_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define X86_64_NETBERG_AURORA_420_RANGELEY_MEMCPY GLOBAL_MEMCPY + #elif X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB == 1 + #define X86_64_NETBERG_AURORA_420_RANGELEY_MEMCPY memcpy + #else + #error The macro X86_64_NETBERG_AURORA_420_RANGELEY_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define X86_64_NETBERG_AURORA_420_RANGELEY_STRNCPY GLOBAL_STRNCPY + #elif X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB == 1 + #define X86_64_NETBERG_AURORA_420_RANGELEY_STRNCPY strncpy + #else + #error The macro X86_64_NETBERG_AURORA_420_RANGELEY_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define X86_64_NETBERG_AURORA_420_RANGELEY_VSNPRINTF GLOBAL_VSNPRINTF + #elif X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB == 1 + #define X86_64_NETBERG_AURORA_420_RANGELEY_VSNPRINTF vsnprintf + #else + #error The macro X86_64_NETBERG_AURORA_420_RANGELEY_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define X86_64_NETBERG_AURORA_420_RANGELEY_SNPRINTF GLOBAL_SNPRINTF + #elif X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB == 1 + #define X86_64_NETBERG_AURORA_420_RANGELEY_SNPRINTF snprintf + #else + #error The macro X86_64_NETBERG_AURORA_420_RANGELEY_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_NETBERG_AURORA_420_RANGELEY_STRLEN + #if defined(GLOBAL_STRLEN) + #define X86_64_NETBERG_AURORA_420_RANGELEY_STRLEN GLOBAL_STRLEN + #elif X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB == 1 + #define X86_64_NETBERG_AURORA_420_RANGELEY_STRLEN strlen + #else + #error The macro X86_64_NETBERG_AURORA_420_RANGELEY_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __X86_64_NETBERG_AURORA_420_RANGELEY_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/make.mk b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/make.mk new file mode 100644 index 00000000..dea3e533 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_netberg_aurora_420_rangeley_INCLUDES := -I $(THIS_DIR)inc +x86_64_netberg_aurora_420_rangeley_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_netberg_aurora_420_rangeley_DEPENDMODULE_ENTRIES := init:x86_64_netberg_aurora_420_rangeley ucli:x86_64_netberg_aurora_420_rangeley + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/Makefile new file mode 100755 index 00000000..ef9d70ed --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_netberg_aurora_420_rangeley_ucli.c + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/fani.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/fani.c new file mode 100755 index 00000000..4cc75804 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/fani.c @@ -0,0 +1,234 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include + +#include "x86_64_netberg_aurora_420_rangeley_int.h" +#include "x86_64_netberg_aurora_420_rangeley_log.h" + +#include + + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +sys_fan_info_get__(onlp_fan_info_t* info, int id) +{ + int value = 0; + int rv; + + rv = onlp_file_read_int(&value, SYS_HWMON2_PREFIX "/fan%d_abs", ((id/2)+1)); + if (rv != ONLP_STATUS_OK) + return rv; + + if (value == 0) + { + info->status = ONLP_FAN_STATUS_FAILED; + } + else + { + info->status = ONLP_FAN_STATUS_PRESENT; + + rv = onlp_file_read_int(&value, SYS_HWMON2_PREFIX "/fan%d_dir", ((id/2)+1)); + if (rv != ONLP_STATUS_OK) + return rv; + + if (value == 1) + { + info->status |= ONLP_FAN_STATUS_B2F; + info->caps |= ONLP_FAN_CAPS_B2F; + } + else + { + info->status |= ONLP_FAN_STATUS_F2B; + info->caps |= ONLP_FAN_CAPS_F2B; + } + + rv = onlp_file_read_int(&(info->rpm), SYS_HWMON1_PREFIX "/fan%d_rpm", (id+1)); + if (rv == ONLP_STATUS_E_INTERNAL) + return rv; + + if (rv == ONLP_STATUS_E_MISSING) + { + info->status &= ~1; + return 0; + } + + if (info->rpm <= X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD) + info->status |= ONLP_FAN_STATUS_FAILED; + + + rv = onlp_file_read_int(&(info->percentage), SYS_HWMON1_PREFIX "/fan%d_duty", (id+1)); + if (rv == ONLP_STATUS_E_INTERNAL) + return rv; + + if (rv == ONLP_STATUS_E_MISSING) + { + info->status &= ~1; + return 0; + } + } + return 0; +} + +static int +psu_fan_info_get__(onlp_fan_info_t* info, int id) +{ + return onlp_file_read_int(&(info->rpm), SYS_HWMON2_PREFIX "/psu%d_fan_speed", id); +} + +/* Onboard Fans */ +static onlp_fan_info_t fans__[] = { + { }, /* Not used */ + { { FAN_OID_FAN1, "Fan1_rotor1", 0}, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN2, "Fan1_rotor2", 0}, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN3, "Fan2_rotor1", 0}, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN4, "Fan2_rotor2", 0}, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN5, "Fan3_rotor1", 0}, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN6, "Fan3_rotor2", 0}, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN7, "Fan4_rotor1", 0}, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN8, "Fan4_rotor2", 0}, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN9, "PSU-1 Fan", 0 }, ONLP_FAN_STATUS_PRESENT }, + { { FAN_OID_FAN10, "PSU-2 Fan", 0 }, ONLP_FAN_STATUS_PRESENT }, +}; + +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int +onlp_fani_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) +{ + int fid; + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_fan_info_t)); + fid = ONLP_OID_ID_GET(id); + *info = fans__[fid]; + + info->caps |= ONLP_FAN_CAPS_GET_RPM; + + switch(fid) + { + case FAN_ID_FAN1: + case FAN_ID_FAN2: + case FAN_ID_FAN3: + case FAN_ID_FAN4: + case FAN_ID_FAN5: + case FAN_ID_FAN6: + case FAN_ID_FAN7: + case FAN_ID_FAN8: + return sys_fan_info_get__(info, (fid - 1)); + break; + + case FAN_ID_FAN9: + case FAN_ID_FAN10: + return psu_fan_info_get__(info, (fid - FAN_ID_FAN9 + 1)); + break; + + default: + return ONLP_STATUS_E_INVALID; + break; + } + + return ONLP_STATUS_E_INVALID; +} + +/* + * This function sets the speed of the given fan in RPM. + * + * This function will only be called if the fan supprots the RPM_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_rpm_set(onlp_oid_t id, int rpm) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_percentage_set(onlp_oid_t id, int p) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan speed of the given OID as per + * the predefined ONLP fan speed modes: off, slow, normal, fast, max. + * + * Interpretation of these modes is up to the platform. + * + */ +int +onlp_fani_mode_set(onlp_oid_t id, onlp_fan_mode_t mode) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan direction of the given OID. + * + * This function is only relevant if the fan OID supports both direction + * capabilities. + * + * This function is optional unless the functionality is available. + */ +int +onlp_fani_dir_set(onlp_oid_t id, onlp_fan_dir_t dir) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * Generic fan ioctl. Optional. + */ +int +onlp_fani_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/ledi.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/ledi.c new file mode 100755 index 00000000..2b482315 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/ledi.c @@ -0,0 +1,221 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2013 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "x86_64_netberg_aurora_420_rangeley_int.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +/* LED related data + */ +enum led_light_mode { /*must be the same with the definition @ kernel driver */ + LED_MODE_OFF = 0, + LED_MODE_AMBER, + LED_MODE_GREEN, +}; + +int led_light_map_mode[][2] = +{ + {LED_MODE_OFF, ONLP_LED_MODE_OFF}, + {LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, + {LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, +}; + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t linfo[] = +{ + { }, /* Not used */ + { + { LED_OID_LED1, "Chassis LED 1 (STAT LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN, + ONLP_LED_MODE_OFF, + }, + { + { LED_OID_LED2, "Chassis LED 2 (FAN LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN, + ONLP_LED_MODE_OFF, + }, + { + { LED_OID_LED3, "Chassis LED 3 (PSU1 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN, + ONLP_LED_MODE_OFF, + }, + { + { LED_OID_LED4, "Chassis LED 4 (PSU2 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN, + ONLP_LED_MODE_OFF, + }, +}; + +static int conver_led_light_mode_to_driver(int led_ligth_mode) +{ + int i, nsize = sizeof(led_light_map_mode)/sizeof(led_light_map_mode[0]); + for(i=0; i + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include "x86_64_netberg_aurora_420_rangeley_int.h" +#include "x86_64_netberg_aurora_420_rangeley_log.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static onlp_psu_info_t psus__[] = { + { }, /* Not used */ + { + { + PSU_OID_PSU1, + "PSU-1", + 0, + { + FAN_OID_FAN9, + }, + } + }, + { + { + PSU_OID_PSU2, + "PSU-2", + 0, + { + FAN_OID_FAN10, + }, + } + }, +}; + +/* + * This function will be called prior to any other onlp_psui functions. + */ +int +onlp_psui_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int rv; + int pid; + uint8_t data[256]; + int value = -1; + int len; + double dvalue; + int i; + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_psu_info_t)); + pid = ONLP_OID_ID_GET(id); + *info = psus__[pid]; + + rv = onlp_file_read_int(&value, SYS_HWMON1_PREFIX "/psu%d_abs", pid); + if (rv != ONLP_STATUS_OK) + return rv; + if (value == 0) + { + info->status = ONLP_PSU_STATUS_UNPLUGGED; + return ONLP_STATUS_OK; + } + + /* PSU is present. */ + info->status = ONLP_PSU_STATUS_PRESENT; + + memset(data, 0, sizeof(data)); + rv = onlp_file_read(data, sizeof(data), &len, SYS_HWMON2_PREFIX "/psu%d_eeprom", pid); + if (rv == ONLP_STATUS_OK) + { + i = 11; + + /* Manufacturer Name */ + len = (data[i]&0x0f); + i++; + i += len; + + /* Product Name */ + len = (data[i]&0x0f); + i++; + memcpy(info->model, (char *) &(data[i]), len); + i += len; + + /* Product part,model number */ + len = (data[i]&0x0f); + i++; + i += len; + + /* Product Version */ + len = (data[i]&0x0f); + i++; + i += len; + + /* Product Serial Number */ + len = (data[i]&0x0f); + i++; + memcpy(info->serial, (char *) &(data[i]), len); + } + else + { + strcpy(info->model, "Missing"); + strcpy(info->serial, "Missing"); + } + + info->caps |= ONLP_PSU_CAPS_AC; + +#if 0 + /* PSU is powered. */ + rv = onlp_file_read_int(&value, SYS_HWMON1_PREFIX "/psu%d_pg", pid); + if (rv != ONLP_STATUS_OK) + return rv; + if (value == 0) + { + info->status |= ONLP_PSU_STATUS_FAILED; + return ONLP_STATUS_OK; + } +#endif + + memset(data, 0, sizeof(data)); + rv = onlp_file_read(data, sizeof(data), &len, SYS_HWMON2_PREFIX "/psu%d_iout", pid); + if (rv == ONLP_STATUS_OK) + { + dvalue = atof((const char *)data); + if (dvalue > 0.0) + { + info->caps |= ONLP_PSU_CAPS_IOUT; + info->miout = (int)(dvalue * 1000); + } + } + + memset(data, 0, sizeof(data)); + rv = onlp_file_read(data, sizeof(data), &len, SYS_HWMON2_PREFIX "/psu%d_vout", pid); + if (rv == ONLP_STATUS_OK) + { + dvalue = atof((const char *)data); + if (dvalue > 0.0) + { + info->caps |= ONLP_PSU_CAPS_VOUT; + info->mvout = (int)(dvalue * 1000); + } + } + + memset(data, 0, sizeof(data)); + rv = onlp_file_read(data, sizeof(data), &len, SYS_HWMON2_PREFIX "/psu%d_pin", pid); + if (rv == ONLP_STATUS_OK) + { + dvalue = atof((const char *)data); + if (dvalue > 0.0) + { + info->caps |= ONLP_PSU_CAPS_PIN; + info->mpin = (int)(dvalue * 1000); + } + } + + memset(data, 0, sizeof(data)); + rv = onlp_file_read(data, sizeof(data), &len, SYS_HWMON2_PREFIX "/psu%d_pout", pid); + if (rv == ONLP_STATUS_OK) + { + dvalue = atof((const char *)data); + if (dvalue > 0.0) + { + info->caps |= ONLP_PSU_CAPS_POUT; + info->mpout = (int)(dvalue * 1000); + } + } + + return ONLP_STATUS_OK; +} + +/* + * This is an optional generic ioctl() interface. + * Its purpose is to allow future expansion and + * custom functionality that is not otherwise exposed + * in the standard interface. + * + * The semantics of this function are platform specific. + * This function is completely optional. + */ +int +onlp_psui_ioctl(onlp_oid_t pid, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/sfpi.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/sfpi.c new file mode 100755 index 00000000..5aaf3760 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/sfpi.c @@ -0,0 +1,451 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * SFPI Interface for the Aurora 420 Platform + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include "x86_64_netberg_aurora_420_rangeley_int.h" +#include "x86_64_netberg_aurora_420_rangeley_log.h" + +#include +#include + +/* Model ID Definition */ +typedef enum +{ + HURACAN_WITH_BMC = 0x0, + HURACAN_WITHOUT_BMC, + CABRERAIII_WITH_BMC, + CABRERAIII_WITHOUT_BMC, + SESTO_WITH_BMC, + SESTO_WITHOUT_BMC, + NCIIX_WITH_BMC, + NCIIX_WITHOUT_BMC, + ASTERION_WITH_BMC, + ASTERION_WITHOUT_BMC, + HURACAN_A_WITH_BMC, + HURACAN_A_WITHOUT_BMC, + + MODEL_ID_LAST +} modelId_t; + +static int +onlp_board_model_id_get(void) +{ + static int board_model_id = MODEL_ID_LAST; + + if (board_model_id == MODEL_ID_LAST) + { + if (onlp_file_read_int(&board_model_id, SYS_HWMON1_PREFIX "/board_model_id") != ONLP_STATUS_OK) + return 0; + } + + return board_model_id; +} + +/* + * This function will be called prior to all other onlp_sfpi_* functions. + */ +int +onlp_sfpi_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * This function should populate the give bitmap with + * all valid, SFP-capable port numbers. + * + * Only port numbers in this bitmap will be queried by the the + * ONLP framework. + * + * No SFPI functions will be called with ports that are + * not in this bitmap. You can ignore all error checking + * on the incoming ports defined in this interface. + */ +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + int p; + int total_port = 0; + int board_model_id = onlp_board_model_id_get(); + + switch (board_model_id) + { + case HURACAN_WITH_BMC: + case HURACAN_WITHOUT_BMC: + case HURACAN_A_WITH_BMC: + case HURACAN_A_WITHOUT_BMC: + total_port = 32; + break; + + case SESTO_WITH_BMC: + case SESTO_WITHOUT_BMC: + case NCIIX_WITH_BMC: + case NCIIX_WITHOUT_BMC: + total_port = 54; + break; + + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + total_port = 64; + break; + + default: + break; + } + + AIM_BITMAP_CLR_ALL(bmap); + for(p = 0; p < total_port; p++) + AIM_BITMAP_SET(bmap, p); + + return ONLP_STATUS_OK; +} + +/* + * This function should return whether an SFP is inserted on the given + * port. + * + * Returns 1 if the SFP is present. + * Returns 0 if the SFP is not present. + * Returns ONLP_E_* if there was an error determining the status. + */ +int +onlp_sfpi_is_present(int port) +{ + int value = 0; + + onlp_file_read_int(&value, SYS_HWMON2_PREFIX "/port_%d_abs", (port+1)); + return value; +} + +int +onlp_sfpi_port_map(int port, int* rport) +{ + int board_model_id = onlp_board_model_id_get(); + + switch (board_model_id) + { + case HURACAN_WITH_BMC: + case HURACAN_WITHOUT_BMC: + case HURACAN_A_WITH_BMC: + case HURACAN_A_WITHOUT_BMC: + /* odd <=> even */ + if (port & 0x1) + *rport = (port - 1); + else + *rport = (port + 1); + break; + + default: + *rport = port; break; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + int p; + int total_port = 0; + int board_model_id = onlp_board_model_id_get(); + + switch (board_model_id) + { + case HURACAN_WITH_BMC: + case HURACAN_WITHOUT_BMC: + case HURACAN_A_WITH_BMC: + case HURACAN_A_WITHOUT_BMC: + total_port = 32; + break; + + case SESTO_WITH_BMC: + case SESTO_WITHOUT_BMC: + case NCIIX_WITH_BMC: + case NCIIX_WITHOUT_BMC: + total_port = 54; + break; + + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + total_port = 64; + break; + + default: + break; + } + + AIM_BITMAP_CLR_ALL(bmap); + for(p = 0; p < total_port; p++) + AIM_BITMAP_SET(bmap, p); + + return ONLP_STATUS_OK; +} + +/* + * This function reads the SFPs idrom and returns in + * in the data buffer provided. + */ +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + int rv = ONLP_STATUS_OK; + char fname[128]; + + memset(data, 0, 256); + memset(fname, 0, sizeof(fname)); + sprintf(fname, SYS_HWMON2_PREFIX "/port_%d_data_a0", (port+1)); + rv = onlplib_sfp_eeprom_read_file(fname, data); + if (rv != ONLP_STATUS_OK) + AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port); + + return rv; +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + int rv = ONLP_STATUS_OK; + char fname[128]; + + memset(data, 0, 256); + memset(fname, 0, sizeof(fname)); + sprintf(fname, SYS_HWMON2_PREFIX "/port_%d_data_a2", (port+1)); + rv = onlplib_sfp_eeprom_read_file(fname, data); + if (rv != ONLP_STATUS_OK) + AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port); + + return rv; +} + +/* + * Manually enable or disable the given SFP. + * + */ +int +onlp_sfpi_enable_set(int port, int enable) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * Returns whether the SFP is currently enabled or disabled. + */ +int +onlp_sfpi_enable_get(int port, int* enable) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * If the platform requires any setup or equalizer modifications + * based on the actual SFP that was inserted then that custom + * setup should be performed here. + * + * After a new SFP is detected by the ONLP framework this + * function will be called to perform the (optional) setup. + */ +int +onlp_sfpi_post_insert(int port, sff_info_t* sff_info) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * Return the current status of the SFP. + * See onlp_sfp_status_t; + */ +int +onlp_sfpi_status_get(int port, uint32_t* status) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +int onlp_sfpi_control_supported(int port, onlp_sfp_control_t control, int* supported) +{ + if (supported == NULL) + return ONLP_STATUS_E_PARAM; + + *supported = 0; + switch (control) + { + case ONLP_SFP_CONTROL_TX_DISABLE: + case ONLP_SFP_CONTROL_RX_LOS: + case ONLP_SFP_CONTROL_TX_FAULT: + { + int board_model_id = onlp_board_model_id_get(); + + switch (board_model_id) + { + case HURACAN_WITH_BMC: + case HURACAN_WITHOUT_BMC: + case HURACAN_A_WITH_BMC: + case HURACAN_A_WITHOUT_BMC: + case SESTO_WITH_BMC: + case SESTO_WITHOUT_BMC: + case NCIIX_WITH_BMC: + case NCIIX_WITHOUT_BMC: + case ASTERION_WITH_BMC: + case ASTERION_WITHOUT_BMC: + *supported = 1; + break; + + default: + break; + } + } + break; + + default: + break; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) +{ + int rv = ONLP_STATUS_OK; + int supported = 0; + + if ((onlp_sfpi_control_supported(port, control, &supported) == ONLP_STATUS_OK) && (supported == 0)) + return ONLP_STATUS_E_UNSUPPORTED; + + switch (control) + { + case ONLP_SFP_CONTROL_TX_DISABLE: + rv = onlp_file_write_int(value, SYS_HWMON2_PREFIX "/port_%d_tx_disable", (port+1)); + break; + + default: + rv = ONLP_STATUS_E_UNSUPPORTED; + break; + } + return rv; +} + +int +onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) +{ + int rv = ONLP_STATUS_OK; + int supported = 0; + + if (value == NULL) + return ONLP_STATUS_E_PARAM; + + if ((onlp_sfpi_control_supported(port, control, &supported) == ONLP_STATUS_OK) && (supported == 0)) + return ONLP_STATUS_E_UNSUPPORTED; + + *value = 0; + switch (control) + { + case ONLP_SFP_CONTROL_RX_LOS: + rv = onlp_file_read_int(value, SYS_HWMON2_PREFIX "/port_%d_rxlos", (port+1)); + break; + + case ONLP_SFP_CONTROL_TX_DISABLE: + rv = onlp_file_read_int(value, SYS_HWMON2_PREFIX "/port_%d_tx_disable", (port+1)); + break; + + case ONLP_SFP_CONTROL_TX_FAULT: + rv = onlp_file_read_int(value, SYS_HWMON2_PREFIX "/port_%d_tx_fault", (port+1)); + break; + + default: + rv = ONLP_STATUS_E_UNSUPPORTED; + break; + } + return rv; +} + +int +onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) +{ + int value = 0; + char fname[128]; + char data[512]; + + memset(data, 0, 512); + memset(fname, 0, sizeof(fname)); + sprintf(fname, SYS_HWMON2_PREFIX "/port_%d_sfp_copper", (port+1)); + + int fd = open(fname, O_RDONLY); + if (fd < 0) { + AIM_LOG_INFO("Unable to read devaddr(0xAC) from port(%d)\r\n", port); + return value; + } + + int nrd = read(fd, data, 512); + close(fd); + + if (nrd != 512) { + AIM_LOG_INTERNAL("Failed to read EEPROM file '%s'", fname); + return value; + } + + value = (((data[addr*2 + 1] & 0xff) << 8) | (data[addr*2] & 0xff)) & 0xffff; + + return value; +} + +int +onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) +{ + int rv = ONLP_STATUS_OK; + int data = 0; + + data = ((addr << 16) | (value & 0xffff)) & 0x00ffffff; + rv = onlp_file_write_int(data, SYS_HWMON2_PREFIX "/port_%d_sfp_copper", (port+1)); + + return rv; +} + +/* + * This is a generic ioctl interface. + */ +int +onlp_sfpi_ioctl(int port, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * De-initialize the SFPI subsystem. + */ +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/sysi.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/sysi.c new file mode 100755 index 00000000..7e044c3b --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/sysi.c @@ -0,0 +1,98 @@ +/************************************************************ + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "x86_64_netberg_aurora_420_rangeley_int.h" +#include "x86_64_netberg_aurora_420_rangeley_log.h" + +/* + * This is the first function called by the ONLP framework. + * + * It should return the name of your platform driver. + * + * If the name of your platform driver is the same as the + * current platform then this driver will be used. + * + * If the name of the driver is different from the current + * platform, or the driver is capable of supporting multiple + * platform variants, see onlp_sysi_platform_set() below. + */ +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-netberg-aurora-420-rangeley-r0"; +} + +/* + * This is the first function the ONLP framework will call + * after it has validated the the platform is supported using the mechanisms + * described above. + * + * If this function does not return ONL_STATUS_OK + * then platform initialization is aborted. + */ +int +onlp_sysi_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_sysi_onie_info_get(onlp_onie_info_t* onie) +{ + int rv; + uint8_t data[256]; + int len; + + memset(data, 0, sizeof(data)); + rv = onlp_file_read(data, sizeof(data), &len, SYS_HWMON2_PREFIX "/eeprom"); + if (rv == ONLP_STATUS_OK) + { + rv = onlp_onie_decode(onie, (uint8_t*)data, sizeof(data)); + if(rv >= 0) + { + onie->platform_name = aim_strdup("x86-64-netberg-aurora-420-rangeley-r0"); + } + } + return rv; +} + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + int i; + int n_thermal=7, n_fan=10, n_led=4; + + /* 2 PSUs */ + *e++ = ONLP_PSU_ID_CREATE(1); + *e++ = ONLP_PSU_ID_CREATE(2); + + /* LEDs Item */ + for (i=1; i<=n_led; i++) + { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* THERMALs Item */ + for (i=1; i<=n_thermal; i++) + { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* Fans Item */ + for (i=1; i<=n_fan; i++) + { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + return 0; +} + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/thermali.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/thermali.c new file mode 100755 index 00000000..e3241013 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/thermali.c @@ -0,0 +1,173 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "x86_64_netberg_aurora_420_rangeley_int.h" +#include "x86_64_netberg_aurora_420_rangeley_log.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +sys_thermal_info_get__(onlp_thermal_info_t* info, int id) +{ + int rv; + + if (id == THERMAL_ID_THERMAL3) + { + rv = onlp_file_read_int(&info->mcelsius, SYS_HWMON1_PREFIX "/mac_temp"); + info->mcelsius *= 1000; + } + else + { + uint8_t buffer[64]; + double dvalue; + int len; + + memset(buffer, 0, sizeof(buffer)); + rv = onlp_file_read(buffer, sizeof(buffer), &len, SYS_HWMON1_PREFIX "/remote_temp%d", id); + if (rv == ONLP_STATUS_OK) + { + dvalue = atof((const char *)buffer); + info->mcelsius = (int)(dvalue * 1000); + } + } + + if(rv == ONLP_STATUS_E_INTERNAL) + return rv; + + if(rv == ONLP_STATUS_E_MISSING) + { + info->status &= ~(ONLP_THERMAL_STATUS_PRESENT); + return ONLP_STATUS_OK; + } + + return ONLP_STATUS_OK; +} + +static int +psu1_thermal_info_get__(onlp_thermal_info_t* info, int id) +{ + int rv; + uint8_t buffer[64]; + double dvalue; + int len; + + memset(buffer, 0, sizeof(buffer)); + rv = onlp_file_read(buffer, sizeof(buffer), &len, SYS_HWMON2_PREFIX "/psu1_temp_%d", id); + if (rv == ONLP_STATUS_OK) + { + dvalue = atof((const char *)buffer); + info->mcelsius = (int)(dvalue * 1000); + } + return rv; +} + +static int +psu2_thermal_info_get__(onlp_thermal_info_t* info, int id) +{ + int rv; + uint8_t buffer[64]; + double dvalue; + int len; + + memset(buffer, 0, sizeof(buffer)); + rv = onlp_file_read(buffer, sizeof(buffer), &len, SYS_HWMON2_PREFIX "/psu2_temp_%d", id); + if (rv == ONLP_STATUS_OK) + { + dvalue = atof((const char *)buffer); + info->mcelsius = (int)(dvalue * 1000); + } + return rv; +} + +static onlp_thermal_info_t temps__[] = +{ + { }, /* Not used */ + { { THERMAL_OID_THERMAL1, "Chassis Thermal 1 (Front of MAC)", 0}, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0}, + { { THERMAL_OID_THERMAL2, "Chassis Thermal 2 (Rear of MAC)", 0}, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0}, + { { THERMAL_OID_THERMAL3, "Chassis Thermal 3 (MAC)", 0}, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0}, + + { { THERMAL_OID_THERMAL4, "PSU-1 Thermal 1", PSU_OID_PSU1 }, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0}, + { { THERMAL_OID_THERMAL5, "PSU-1 Thermal 2", PSU_OID_PSU1 }, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0}, + + { { THERMAL_OID_THERMAL6, "PSU-2 Thermal 1", PSU_OID_PSU2 }, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0}, + { { THERMAL_OID_THERMAL7, "PSU-2 Thermal 2", PSU_OID_PSU2 }, ONLP_THERMAL_STATUS_PRESENT, ONLP_THERMAL_CAPS_GET_TEMPERATURE, 0}, +}; + + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * Retrieve the information structure for the given thermal OID. + * + * If the OID is invalid, return ONLP_E_STATUS_INVALID. + * If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL. + * Otherwise, return ONLP_STATUS_OK with the OID's information. + * + * Note -- it is expected that you fill out the information + * structure even if the sensor described by the OID is not present. + */ +int +onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) +{ + int tid; + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_thermal_info_t)); + tid = ONLP_OID_ID_GET(id); + *info = temps__[tid]; + + switch(tid) + { + case THERMAL_ID_THERMAL1: + case THERMAL_ID_THERMAL2: + case THERMAL_ID_THERMAL3: + return sys_thermal_info_get__(info, tid); + + case THERMAL_ID_THERMAL4: + case THERMAL_ID_THERMAL5: + return psu1_thermal_info_get__(info, (tid - THERMAL_ID_THERMAL4 + 1)); + + case THERMAL_ID_THERMAL6: + case THERMAL_ID_THERMAL7: + return psu2_thermal_info_get__(info, (tid - THERMAL_ID_THERMAL6 + 1)); + } + + return ONLP_STATUS_E_INVALID; +} + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_config.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_config.c new file mode 100755 index 00000000..94ef2e10 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_config.c @@ -0,0 +1,80 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(_x) __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(_x) +x86_64_netberg_aurora_420_rangeley_config_settings_t x86_64_netberg_aurora_420_rangeley_config_settings[] = +{ +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_LOGGING + { __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_LOGGING), __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_LOGGING) }, +#else +{ X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_LOGGING(__x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT + { __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT), __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT(__x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB + { __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB), __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB) }, +#else +{ X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_STDLIB(__x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI + { __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI), __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI) }, +#else +{ X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI(__x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD + { __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD), __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE(X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD) }, +#else +{ X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_SYSFAN_RPM_FAILURE_THRESHOLD(__x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_VALUE +#undef __x86_64_netberg_aurora_420_rangeley_config_STRINGIFY_NAME + +const char* +x86_64_netberg_aurora_420_rangeley_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_netberg_aurora_420_rangeley_config_settings[i].name; i++) { + if(!strcmp(x86_64_netberg_aurora_420_rangeley_config_settings[i].name, setting)) { + return x86_64_netberg_aurora_420_rangeley_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_netberg_aurora_420_rangeley_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_netberg_aurora_420_rangeley_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_netberg_aurora_420_rangeley_config_settings[i].name, x86_64_netberg_aurora_420_rangeley_config_settings[i].value); + } + return i; +} + +/* */ diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_enums.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_enums.c new file mode 100755 index 00000000..1df7f4cd --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_int.h b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_int.h new file mode 100755 index 00000000..3067638c --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_int.h @@ -0,0 +1,271 @@ +/**************************************************************************//** + * + * x86_64_netberg_aurora_420_rangeley Internal Header + * + *****************************************************************************/ +#ifndef __X86_64_NETBERG_AURORA_420_RANGELEY_INT_H__ +#define __X86_64_NETBERG_AURORA_420_RANGELEY_INT_H__ + +#include +#include + +/* */ +/** fan_id */ +typedef enum fan_id_e { + FAN_ID_FAN1 = 1, + FAN_ID_FAN2 = 2, + FAN_ID_FAN3 = 3, + FAN_ID_FAN4 = 4, + FAN_ID_FAN5 = 5, + FAN_ID_FAN6 = 6, + FAN_ID_FAN7 = 7, + FAN_ID_FAN8 = 8, + FAN_ID_FAN9 = 9, + FAN_ID_FAN10 = 10, +} fan_id_t; + +/** Enum names. */ +const char* fan_id_name(fan_id_t e); + +/** Enum values. */ +int fan_id_value(const char* str, fan_id_t* e, int substr); + +/** Enum descriptions. */ +const char* fan_id_desc(fan_id_t e); + +/** Enum validator. */ +int fan_id_valid(fan_id_t e); + +/** validator */ +#define FAN_ID_VALID(_e) \ + (fan_id_valid((_e))) + +/** fan_id_map table. */ +extern aim_map_si_t fan_id_map[]; +/** fan_id_desc_map table. */ +extern aim_map_si_t fan_id_desc_map[]; + +/** fan_oid */ +typedef enum fan_oid_e { + FAN_OID_FAN1 = ONLP_FAN_ID_CREATE(1), + FAN_OID_FAN2 = ONLP_FAN_ID_CREATE(2), + FAN_OID_FAN3 = ONLP_FAN_ID_CREATE(3), + FAN_OID_FAN4 = ONLP_FAN_ID_CREATE(4), + FAN_OID_FAN5 = ONLP_FAN_ID_CREATE(5), + FAN_OID_FAN6 = ONLP_FAN_ID_CREATE(6), + FAN_OID_FAN7 = ONLP_FAN_ID_CREATE(7), + FAN_OID_FAN8 = ONLP_FAN_ID_CREATE(8), + FAN_OID_FAN9 = ONLP_FAN_ID_CREATE(9), + FAN_OID_FAN10 = ONLP_FAN_ID_CREATE(10), +} fan_oid_t; + +/** Enum names. */ +const char* fan_oid_name(fan_oid_t e); + +/** Enum values. */ +int fan_oid_value(const char* str, fan_oid_t* e, int substr); + +/** Enum descriptions. */ +const char* fan_oid_desc(fan_oid_t e); + +/** Enum validator. */ +int fan_oid_valid(fan_oid_t e); + +/** validator */ +#define FAN_OID_VALID(_e) \ + (fan_oid_valid((_e))) + +/** fan_oid_map table. */ +extern aim_map_si_t fan_oid_map[]; +/** fan_oid_desc_map table. */ +extern aim_map_si_t fan_oid_desc_map[]; + +/** led_id */ +typedef enum led_id_e { + LED_ID_LED1 = 1, + LED_ID_LED2 = 2, + LED_ID_LED3 = 3, + LED_ID_LED4 = 4, +} led_id_t; + +/** Enum names. */ +const char* led_id_name(led_id_t e); + +/** Enum values. */ +int led_id_value(const char* str, led_id_t* e, int substr); + +/** Enum descriptions. */ +const char* led_id_desc(led_id_t e); + +/** Enum validator. */ +int led_id_valid(led_id_t e); + +/** validator */ +#define LED_ID_VALID(_e) \ + (led_id_valid((_e))) + +/** led_id_map table. */ +extern aim_map_si_t led_id_map[]; +/** led_id_desc_map table. */ +extern aim_map_si_t led_id_desc_map[]; + +/** led_oid */ +typedef enum led_oid_e { + LED_OID_LED1 = ONLP_LED_ID_CREATE(1), + LED_OID_LED2 = ONLP_LED_ID_CREATE(2), + LED_OID_LED3 = ONLP_LED_ID_CREATE(3), + LED_OID_LED4 = ONLP_LED_ID_CREATE(4), +} led_oid_t; + +/** Enum names. */ +const char* led_oid_name(led_oid_t e); + +/** Enum values. */ +int led_oid_value(const char* str, led_oid_t* e, int substr); + +/** Enum descriptions. */ +const char* led_oid_desc(led_oid_t e); + +/** Enum validator. */ +int led_oid_valid(led_oid_t e); + +/** validator */ +#define LED_OID_VALID(_e) \ + (led_oid_valid((_e))) + +/** led_oid_map table. */ +extern aim_map_si_t led_oid_map[]; +/** led_oid_desc_map table. */ +extern aim_map_si_t led_oid_desc_map[]; + +/** psu_id */ +typedef enum psu_id_e { + PSU_ID_PSU1 = 1, + PSU_ID_PSU2 = 2, +} psu_id_t; + +/** Enum names. */ +const char* psu_id_name(psu_id_t e); + +/** Enum values. */ +int psu_id_value(const char* str, psu_id_t* e, int substr); + +/** Enum descriptions. */ +const char* psu_id_desc(psu_id_t e); + +/** Enum validator. */ +int psu_id_valid(psu_id_t e); + +/** validator */ +#define PSU_ID_VALID(_e) \ + (psu_id_valid((_e))) + +/** psu_id_map table. */ +extern aim_map_si_t psu_id_map[]; +/** psu_id_desc_map table. */ +extern aim_map_si_t psu_id_desc_map[]; + +/** psu_oid */ +typedef enum psu_oid_e { + PSU_OID_PSU1 = ONLP_PSU_ID_CREATE(1), + PSU_OID_PSU2 = ONLP_PSU_ID_CREATE(2), +} psu_oid_t; + +/** Enum names. */ +const char* psu_oid_name(psu_oid_t e); + +/** Enum values. */ +int psu_oid_value(const char* str, psu_oid_t* e, int substr); + +/** Enum descriptions. */ +const char* psu_oid_desc(psu_oid_t e); + +/** Enum validator. */ +int psu_oid_valid(psu_oid_t e); + +/** validator */ +#define PSU_OID_VALID(_e) \ + (psu_oid_valid((_e))) + +/** psu_oid_map table. */ +extern aim_map_si_t psu_oid_map[]; +/** psu_oid_desc_map table. */ +extern aim_map_si_t psu_oid_desc_map[]; + +/** thermal_id */ +typedef enum thermal_id_e { + THERMAL_ID_THERMAL1 = 1, + THERMAL_ID_THERMAL2 = 2, + THERMAL_ID_THERMAL3 = 3, + THERMAL_ID_THERMAL4 = 4, + THERMAL_ID_THERMAL5 = 5, + THERMAL_ID_THERMAL6 = 6, + THERMAL_ID_THERMAL7 = 7, +} thermal_id_t; + +/** Enum names. */ +const char* thermal_id_name(thermal_id_t e); + +/** Enum values. */ +int thermal_id_value(const char* str, thermal_id_t* e, int substr); + +/** Enum descriptions. */ +const char* thermal_id_desc(thermal_id_t e); + +/** Enum validator. */ +int thermal_id_valid(thermal_id_t e); + +/** validator */ +#define THERMAL_ID_VALID(_e) \ + (thermal_id_valid((_e))) + +/** thermal_id_map table. */ +extern aim_map_si_t thermal_id_map[]; +/** thermal_id_desc_map table. */ +extern aim_map_si_t thermal_id_desc_map[]; + +/** thermal_oid */ +typedef enum thermal_oid_e { + THERMAL_OID_THERMAL1 = ONLP_THERMAL_ID_CREATE(1), + THERMAL_OID_THERMAL2 = ONLP_THERMAL_ID_CREATE(2), + THERMAL_OID_THERMAL3 = ONLP_THERMAL_ID_CREATE(3), + THERMAL_OID_THERMAL4 = ONLP_THERMAL_ID_CREATE(4), + THERMAL_OID_THERMAL5 = ONLP_THERMAL_ID_CREATE(5), + THERMAL_OID_THERMAL6 = ONLP_THERMAL_ID_CREATE(6), + THERMAL_OID_THERMAL7 = ONLP_THERMAL_ID_CREATE(7), +} thermal_oid_t; + +/** Enum names. */ +const char* thermal_oid_name(thermal_oid_t e); + +/** Enum values. */ +int thermal_oid_value(const char* str, thermal_oid_t* e, int substr); + +/** Enum descriptions. */ +const char* thermal_oid_desc(thermal_oid_t e); + +/** Enum validator. */ +int thermal_oid_valid(thermal_oid_t e); + +/** validator */ +#define THERMAL_OID_VALID(_e) \ + (thermal_oid_valid((_e))) + +/** thermal_oid_map table. */ +extern aim_map_si_t thermal_oid_map[]; +/** thermal_oid_desc_map table. */ +extern aim_map_si_t thermal_oid_desc_map[]; +/* */ + +/* psu info table */ +struct psu_info_s { + char path[PATH_MAX]; + int present; + int busno; + int addr; +}; + +#define SYS_HWMON1_PREFIX "/sys/class/hwmon/hwmon1/device" +#define SYS_HWMON2_PREFIX "/sys/class/hwmon/hwmon2/device" + +#endif /* __X86_64_NETBERG_AURORA_420_RANGELEY_INT_H__ */ diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_log.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_log.c new file mode 100755 index 00000000..c465bdec --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_netberg_aurora_420_rangeley_log.h" +/* + * x86_64_netberg_aurora_420_rangeley log struct. + */ +AIM_LOG_STRUCT_DEFINE( + X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_OPTIONS_DEFAULT, + X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_log.h b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_log.h new file mode 100755 index 00000000..e3724e3f --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __X86_64_NETBERG_AURORA_420_RANGELEY_LOG_H__ +#define __X86_64_NETBERG_AURORA_420_RANGELEY_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_netberg_aurora_420_rangeley +#include + +#endif /* __X86_64_NETBERG_AURORA_420_RANGELEY_LOG_H__ */ diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_module.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_module.c new file mode 100755 index 00000000..1924d1a6 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_netberg_aurora_420_rangeley_log.h" + +static int +datatypes_init__(void) +{ +#define X86_64_NETBERG_AURORA_420_RANGELEY_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_netberg_aurora_420_rangeley_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_ucli.c b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_ucli.c new file mode 100755 index 00000000..5bfdc4cd --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/onlp/builds/src/x86_64_netberg_aurora_420_rangeley/module/src/x86_64_netberg_aurora_420_rangeley_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if X86_64_NETBERG_AURORA_420_RANGELEY_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_netberg_aurora_420_rangeley_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_netberg_aurora_420_rangeley) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_netberg_aurora_420_rangeley_ucli_module__ = + { + "x86_64_netberg_aurora_420_rangeley_ucli", + NULL, + x86_64_netberg_aurora_420_rangeley_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_netberg_aurora_420_rangeley_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_netberg_aurora_420_rangeley_ucli_module__); + n = ucli_node_create("x86_64_netberg_aurora_420_rangeley", NULL, &x86_64_netberg_aurora_420_rangeley_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_netberg_aurora_420_rangeley")); + return n; +} + +#else +void* +x86_64_netberg_aurora_420_rangeley_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/Makefile b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/PKG.yml b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/PKG.yml new file mode 100755 index 00000000..ad4b02d5 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=netberg BASENAME=x86-64-netberg-aurora-420-rangeley REVISION=r0 diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/src/lib/x86-64-netberg-aurora-420-rangeley-r0.yml b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/src/lib/x86-64-netberg-aurora-420-rangeley-r0.yml new file mode 100755 index 00000000..ad855b37 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/src/lib/x86-64-netberg-aurora-420-rangeley-r0.yml @@ -0,0 +1,30 @@ +--- + +###################################################################### +# +# platform-config for AURORA 420 +# +###################################################################### + +x86-64-netberg-aurora-420-rangeley-r0: + + grub: + + serial: >- + --port=0x2f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-3-16 + + args: >- + console=ttyS1,115200n8 + + ##network: + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:14.0 diff --git a/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/src/python/x86_64_netberg_aurora_420_rangeley_r0/__init__.py b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/src/python/x86_64_netberg_aurora_420_rangeley_r0/__init__.py new file mode 100644 index 00000000..94949cd7 --- /dev/null +++ b/packages/platforms/netberg/x86-64/x86-64-netberg-aurora-420-rangeley/platform-config/r0/src/python/x86_64_netberg_aurora_420_rangeley_r0/__init__.py @@ -0,0 +1,12 @@ +from onl.platform.base import * +from onl.platform.netberg import * + +class OnlPlatform_x86_64_netberg_aurora_420_rangeley_r0(OnlPlatformNetberg, + OnlPlatformPortConfig_48x10_6x40): + PLATFORM='x86-64-netberg-aurora-420-rangeley-r0' + MODEL="AURORA420" + SYS_OBJECT_ID=".420.1" + + def baseconfig(self): + self.insmod("hardware_monitor") + return True diff --git a/packages/platforms/quanta/x86-64/modules/builds/optoe.c b/packages/platforms/quanta/x86-64/modules/builds/optoe.c deleted file mode 100644 index 27d7ffbd..00000000 --- a/packages/platforms/quanta/x86-64/modules/builds/optoe.c +++ /dev/null @@ -1,1154 +0,0 @@ -/* - * optoe.c - A driver to read and write the EEPROM on optical transceivers - * (SFP, QSFP and similar I2C based devices) - * - * Copyright (C) 2014 Cumulus networks Inc. - * Copyright (C) 2017 Finisar Corp. - * Copyright (C) 2017 Quanta - * - * 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 Freeoftware Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -/* - * Description: - * a) Optical transceiver EEPROM read/write transactions are just like - * the at24 eeproms managed by the at24.c i2c driver - * b) The register/memory layout is up to 256 128 byte pages defined by - * a "pages valid" register and switched via a "page select" - * register as explained in below diagram. - * c) 256 bytes are mapped at a time. 'Lower page 00h' is the first 128 - * bytes of address space, and always references the same - * location, independent of the page select register. - * All mapped pages are mapped into the upper 128 bytes - * (offset 128-255) of the i2c address. - * d) Devices with one I2C address (eg QSFP) use I2C address 0x50 - * (A0h in the spec), and map all pages in the upper 128 bytes - * of that address. - * e) Devices with two I2C addresses (eg SFP) have 256 bytes of data - * at I2C address 0x50, and 256 bytes of data at I2C address - * 0x51 (A2h in the spec). Page selection and paged access - * only apply to this second I2C address (0x51). - * e) The address space is presented, by the driver, as a linear - * address space. For devices with one I2C client at address - * 0x50 (eg QSFP), offset 0-127 are in the lower - * half of address 50/A0h/client[0]. Offset 128-255 are in - * page 0, 256-383 are page 1, etc. More generally, offset - * 'n' resides in page (n/128)-1. ('page -1' is the lower - * half, offset 0-127). - * f) For devices with two I2C clients at address 0x50 and 0x51 (eg SFP), - * the address space places offset 0-127 in the lower - * half of 50/A0/client[0], offset 128-255 in the upper - * half. Offset 256-383 is in the lower half of 51/A2/client[1]. - * Offset 384-511 is in page 0, in the upper half of 51/A2/... - * Offset 512-639 is in page 1, in the upper half of 51/A2/... - * Offset 'n' is in page (n/128)-3 (for n > 383) - * - * One I2c addressed (eg QSFP) Memory Map - * - * 2-Wire Serial Address: 1010000x - * - * Lower Page 00h (128 bytes) - * ===================== - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * | | - * |Page Select Byte(127)| - * ===================== - * | - * | - * | - * | - * V - * ------------------------------------------------------------ - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * | | | | - * V V V V - * ------------ -------------- --------------- -------------- - * | | | | | | | | - * | Upper | | Upper | | Upper | | Upper | - * | Page 00h | | Page 01h | | Page 02h | | Page 03h | - * | | | (Optional) | | (Optional) | | (Optional | - * | | | | | | | for Cable | - * | | | | | | | Assemblies) | - * | ID | | AST | | User | | | - * | Fields | | Table | | EEPROM Data | | | - * | | | | | | | | - * | | | | | | | | - * | | | | | | | | - * ------------ -------------- --------------- -------------- - * - * The SFF 8436 (QSFP) spec only defines the 4 pages described above. - * In anticipation of future applications and devices, this driver - * supports access to the full architected range, 256 pages. - * - **/ - -/* #define DEBUG 1 */ - -#undef EEPROM_CLASS -#ifdef CONFIG_EEPROM_CLASS -#define EEPROM_CLASS -#endif -#ifdef CONFIG_EEPROM_CLASS_MODULE -#define EEPROM_CLASS -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef EEPROM_CLASS -#include -#endif - -#include - -/* - * The optoe driver is for read/write access to the EEPROM on standard - * I2C based optical transceivers (SFP, QSFP, etc) - * - * While based on the at24 driver, it eliminates code that supports other - * types of I2C EEPROMs, and adds support for pages accessed through the - * page-select register at offset 127. - */ - -struct optoe_platform_data { - u32 byte_len; /* size (sum of all addr) */ - u16 page_size; /* for writes */ - u8 flags; - - void (*setup)(struct memory_accessor *, void *context); - void *context; -#ifdef EEPROM_CLASS - struct eeprom_platform_data *eeprom_data; /* extra data for the eeprom_class */ -#endif - int oom_port_name; -}; - -/* fundamental unit of addressing for EEPROM */ -#define OPTOE_PAGE_SIZE 128 -/* - * Single address devices (eg QSFP) have 256 pages, plus the unpaged - * low 128 bytes. If the device does not support paging, it is - * only 2 'pages' long. - */ -#define OPTOE_ARCH_PAGES 256 -#define ONE_ADDR_EEPROM_SIZE ((1 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE) -#define ONE_ADDR_EEPROM_UNPAGED_SIZE (2 * OPTOE_PAGE_SIZE) -/* - * Dual address devices (eg SFP) have 256 pages, plus the unpaged - * low 128 bytes, plus 256 bytes at 0x50. If the device does not - * support paging, it is 4 'pages' long. - */ -#define TWO_ADDR_EEPROM_SIZE ((3 + OPTOE_ARCH_PAGES) * OPTOE_PAGE_SIZE) -#define TWO_ADDR_EEPROM_UNPAGED_SIZE (4 * OPTOE_PAGE_SIZE) - -/* a few constants to find our way around the EEPROM */ -#define OPTOE_PAGE_SELECT_REG 0x7F -#define ONE_ADDR_PAGEABLE_REG 0x02 -#define ONE_ADDR_NOT_PAGEABLE (1<<2) -#define TWO_ADDR_PAGEABLE_REG 0x40 -#define TWO_ADDR_PAGEABLE (1<<4) -#define OPTOE_ID_REG 0 - -/* The maximum length of a port name */ -#define MAX_PORT_NAME_LEN 20 -struct optoe_data { - struct optoe_platform_data chip; - struct memory_accessor macc; - int use_smbus; - char port_name[MAX_PORT_NAME_LEN]; - - /* - * Lock protects against activities from other Linux tasks, - * but not from changes by other I2C masters. - */ - struct mutex lock; - struct bin_attribute bin; - struct attribute_group attr_group; - - u8 *writebuf; - unsigned write_max; - - unsigned num_addresses; - -#ifdef EEPROM_CLASS - struct eeprom_device *eeprom_dev; -#endif - - /* dev_class: ONE_ADDR (QSFP) or TWO_ADDR (SFP) */ - int dev_class; - - struct i2c_client *client[]; -}; - -typedef enum optoe_opcode { - OPTOE_READ_OP = 0, - OPTOE_WRITE_OP = 1 -} optoe_opcode_e; - -/* - * This parameter is to help this driver avoid blocking other drivers out - * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C - * clock, one 256 byte read takes about 1/43 second which is excessive; - * but the 1/170 second it takes at 400 kHz may be quite reasonable; and - * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. - * - * This value is forced to be a power of two so that writes align on pages. - */ -static unsigned io_limit = OPTOE_PAGE_SIZE; - -/* - * specs often allow 5 msec for a page write, sometimes 20 msec; - * it's important to recover from write timeouts. - */ -static unsigned write_timeout = 25; - -/* - * flags to distinguish one-address (QSFP family) from two-address (SFP family) - * If the family is not known, figure it out when the device is accessed - */ -#define ONE_ADDR 1 -#define TWO_ADDR 2 - -static const struct i2c_device_id optoe_ids[] = { - { "optoe1", ONE_ADDR }, - { "optoe2", TWO_ADDR }, - { "sff8436", ONE_ADDR }, - { "24c04", TWO_ADDR }, - { /* END OF LIST */ } -}; -MODULE_DEVICE_TABLE(i2c, optoe_ids); - -/*-------------------------------------------------------------------------*/ -/* - * This routine computes the addressing information to be used for - * a given r/w request. - * - * Task is to calculate the client (0 = i2c addr 50, 1 = i2c addr 51), - * the page, and the offset. - * - * Handles both single address (eg QSFP) and two address (eg SFP). - * For SFP, offset 0-255 are on client[0], >255 is on client[1] - * Offset 256-383 are on the lower half of client[1] - * Pages are accessible on the upper half of client[1]. - * Offset >383 are in 128 byte pages mapped into the upper half - * - * For QSFP, all offsets are on client[0] - * offset 0-127 are on the lower half of client[0] (no paging) - * Pages are accessible on the upper half of client[1]. - * Offset >127 are in 128 byte pages mapped into the upper half - * - * Callers must not read/write beyond the end of a client or a page - * without recomputing the client/page. Hence offset (within page) - * plus length must be less than or equal to 128. (Note that this - * routine does not have access to the length of the call, hence - * cannot do the validity check.) - * - * Offset within Lower Page 00h and Upper Page 00h are not recomputed - */ - -static uint8_t optoe_translate_offset(struct optoe_data *optoe, - loff_t *offset, struct i2c_client **client) -{ - unsigned page = 0; - - *client = optoe->client[0]; - - /* if SFP style, offset > 255, shift to i2c addr 0x51 */ - if (optoe->dev_class == TWO_ADDR) { - if (*offset > 255) { - /* like QSFP, but shifted to client[1] */ - *client = optoe->client[1]; - *offset -= 256; - } - } - - /* - * if offset is in the range 0-128... - * page doesn't matter (using lower half), return 0. - * offset is already correct (don't add 128 to get to paged area) - */ - if (*offset < OPTOE_PAGE_SIZE) - return page; - - /* note, page will always be positive since *offset >= 128 */ - page = (*offset >> 7)-1; - /* 0x80 places the offset in the top half, offset is last 7 bits */ - *offset = OPTOE_PAGE_SIZE + (*offset & 0x7f); - - return page; /* note also returning client and offset */ -} - -static ssize_t optoe_eeprom_read(struct optoe_data *optoe, - struct i2c_client *client, - char *buf, unsigned offset, size_t count) -{ - struct i2c_msg msg[2]; - u8 msgbuf[2]; - unsigned long timeout, read_time; - int status, i; - - memset(msg, 0, sizeof(msg)); - - switch (optoe->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - /*smaller eeproms can work given some SMBus extension calls */ - if (count > I2C_SMBUS_BLOCK_MAX) - count = I2C_SMBUS_BLOCK_MAX; - break; - case I2C_SMBUS_WORD_DATA: - /* Check for odd length transaction */ - count = (count == 1) ? 1 : 2; - break; - case I2C_SMBUS_BYTE_DATA: - count = 1; - break; - default: - /* - * When we have a better choice than SMBus calls, use a - * combined I2C message. Write address; then read up to - * io_limit data bytes. msgbuf is u8 and will cast to our - * needs. - */ - i = 0; - msgbuf[i++] = offset; - - msg[0].addr = client->addr; - msg[0].buf = msgbuf; - msg[0].len = i; - - msg[1].addr = client->addr; - msg[1].flags = I2C_M_RD; - msg[1].buf = buf; - msg[1].len = count; - } - - /* - * Reads fail if the previous write didn't complete yet. We may - * loop a few times until this one succeeds, waiting at least - * long enough for one entire page write to work. - */ - timeout = jiffies + msecs_to_jiffies(write_timeout); - do { - read_time = jiffies; - - switch (optoe->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - status = i2c_smbus_read_i2c_block_data(client, offset, - count, buf); - break; - case I2C_SMBUS_WORD_DATA: - status = i2c_smbus_read_word_data(client, offset); - if (status >= 0) { - buf[0] = status & 0xff; - if (count == 2) - buf[1] = status >> 8; - status = count; - } - break; - case I2C_SMBUS_BYTE_DATA: - status = i2c_smbus_read_byte_data(client, offset); - if (status >= 0) { - buf[0] = status; - status = count; - } - break; - default: - status = i2c_transfer(client->adapter, msg, 2); - if (status == 2) - status = count; - } - - dev_dbg(&client->dev, "eeprom read %zu@%d --> %d (%ld)\n", - count, offset, status, jiffies); - - if (status == count) /* happy path */ - return count; - - if (status == -ENXIO) /* no module present */ - return status; - - /* REVISIT: at HZ=100, this is sloooow */ - msleep(1); - } while (time_before(read_time, timeout)); - - return -ETIMEDOUT; -} - -static ssize_t optoe_eeprom_write(struct optoe_data *optoe, - struct i2c_client *client, - const char *buf, - unsigned offset, size_t count) -{ - struct i2c_msg msg; - ssize_t status; - unsigned long timeout, write_time; - unsigned next_page_start; - int i = 0; - - /* write max is at most a page - * (In this driver, write_max is actually one byte!) - */ - if (count > optoe->write_max) - count = optoe->write_max; - - /* shorten count if necessary to avoid crossing page boundary */ - next_page_start = roundup(offset + 1, OPTOE_PAGE_SIZE); - if (offset + count > next_page_start) - count = next_page_start - offset; - - switch (optoe->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - /*smaller eeproms can work given some SMBus extension calls */ - if (count > I2C_SMBUS_BLOCK_MAX) - count = I2C_SMBUS_BLOCK_MAX; - break; - case I2C_SMBUS_WORD_DATA: - /* Check for odd length transaction */ - count = (count == 1) ? 1 : 2; - break; - case I2C_SMBUS_BYTE_DATA: - count = 1; - break; - default: - /* If we'll use I2C calls for I/O, set up the message */ - msg.addr = client->addr; - msg.flags = 0; - - /* msg.buf is u8 and casts will mask the values */ - msg.buf = optoe->writebuf; - - msg.buf[i++] = offset; - memcpy(&msg.buf[i], buf, count); - msg.len = i + count; - break; - } - - /* - * Reads fail if the previous write didn't complete yet. We may - * loop a few times until this one succeeds, waiting at least - * long enough for one entire page write to work. - */ - timeout = jiffies + msecs_to_jiffies(write_timeout); - do { - write_time = jiffies; - - switch (optoe->use_smbus) { - case I2C_SMBUS_I2C_BLOCK_DATA: - status = i2c_smbus_write_i2c_block_data(client, - offset, count, buf); - if (status == 0) - status = count; - break; - case I2C_SMBUS_WORD_DATA: - if (count == 2) { - status = i2c_smbus_write_word_data(client, - offset, (u16)((buf[0])|(buf[1] << 8))); - } else { - /* count = 1 */ - status = i2c_smbus_write_byte_data(client, - offset, buf[0]); - } - if (status == 0) - status = count; - break; - case I2C_SMBUS_BYTE_DATA: - status = i2c_smbus_write_byte_data(client, offset, - buf[0]); - if (status == 0) - status = count; - break; - default: - status = i2c_transfer(client->adapter, &msg, 1); - if (status == 1) - status = count; - break; - } - - dev_dbg(&client->dev, "eeprom write %zu@%d --> %ld (%lu)\n", - count, offset, (long int) status, jiffies); - - if (status == count) - return count; - - /* REVISIT: at HZ=100, this is sloooow */ - msleep(1); - } while (time_before(write_time, timeout)); - - return -ETIMEDOUT; -} - - -static ssize_t optoe_eeprom_update_client(struct optoe_data *optoe, - char *buf, loff_t off, - size_t count, optoe_opcode_e opcode) -{ - struct i2c_client *client; - ssize_t retval = 0; - uint8_t page = 0; - loff_t phy_offset = off; - int ret = 0; - - page = optoe_translate_offset(optoe, &phy_offset, &client); - dev_dbg(&client->dev, - "optoe_eeprom_update_client off %lld page:%d phy_offset:%lld, count:%ld, opcode:%d\n", - off, page, phy_offset, (long int) count, opcode); - if (page > 0) { - ret = optoe_eeprom_write(optoe, client, &page, - OPTOE_PAGE_SELECT_REG, 1); - if (ret < 0) { - dev_dbg(&client->dev, - "Write page register for page %d failed ret:%d!\n", - page, ret); - return ret; - } - } - - while (count) { - ssize_t status; - - if (opcode == OPTOE_READ_OP) { - status = optoe_eeprom_read(optoe, client, - buf, phy_offset, count); - } else { - status = optoe_eeprom_write(optoe, client, - buf, phy_offset, count); - } - if (status <= 0) { - if (retval == 0) - retval = status; - break; - } - buf += status; - phy_offset += status; - count -= status; - retval += status; - } - - - if (page > 0) { - /* return the page register to page 0 (why?) */ - page = 0; - ret = optoe_eeprom_write(optoe, client, &page, - OPTOE_PAGE_SELECT_REG, 1); - if (ret < 0) { - dev_err(&client->dev, - "Restore page register to 0 failed:%d!\n", ret); - /* error only if nothing has been transferred */ - if (retval == 0) retval = ret; - } - } - return retval; -} - -/* - * Figure out if this access is within the range of supported pages. - * Note this is called on every access because we don't know if the - * module has been replaced since the last call. - * If/when modules support more pages, this is the routine to update - * to validate and allow access to additional pages. - * - * Returns updated len for this access: - * - entire access is legal, original len is returned. - * - access begins legal but is too long, len is truncated to fit. - * - initial offset exceeds supported pages, return -EINVAL - */ -static ssize_t optoe_page_legal(struct optoe_data *optoe, - loff_t off, size_t len) -{ - struct i2c_client *client = optoe->client[0]; - u8 regval; - int status; - size_t maxlen; - - if (off < 0) return -EINVAL; - if (optoe->dev_class == TWO_ADDR) { - /* SFP case */ - /* if no pages needed, we're good */ - if ((off + len) <= TWO_ADDR_EEPROM_UNPAGED_SIZE) return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= TWO_ADDR_EEPROM_SIZE) return -EINVAL; - /* in between, are pages supported? */ - status = optoe_eeprom_read(optoe, client, ®val, - TWO_ADDR_PAGEABLE_REG, 1); - if (status < 0) return status; /* error out (no module?) */ - if (regval & TWO_ADDR_PAGEABLE) { - /* Pages supported, trim len to the end of pages */ - maxlen = TWO_ADDR_EEPROM_SIZE - off; - } else { - /* pages not supported, trim len to unpaged size */ - if (off >= TWO_ADDR_EEPROM_UNPAGED_SIZE) return -EINVAL; - maxlen = TWO_ADDR_EEPROM_UNPAGED_SIZE - off; - } - len = (len > maxlen) ? maxlen : len; - dev_dbg(&client->dev, - "page_legal, SFP, off %lld len %ld\n", - off, (long int) len); - } else { - /* QSFP case */ - /* if no pages needed, we're good */ - if ((off + len) <= ONE_ADDR_EEPROM_UNPAGED_SIZE) return len; - /* if offset exceeds possible pages, we're not good */ - if (off >= ONE_ADDR_EEPROM_SIZE) return -EINVAL; - /* in between, are pages supported? */ - status = optoe_eeprom_read(optoe, client, ®val, - ONE_ADDR_PAGEABLE_REG, 1); - if (status < 0) return status; /* error out (no module?) */ - if (regval & ONE_ADDR_NOT_PAGEABLE) { - /* pages not supported, trim len to unpaged size */ - if (off >= ONE_ADDR_EEPROM_UNPAGED_SIZE) return -EINVAL; - maxlen = ONE_ADDR_EEPROM_UNPAGED_SIZE - off; - } else { - /* Pages supported, trim len to the end of pages */ - maxlen = ONE_ADDR_EEPROM_SIZE - off; - } - len = (len > maxlen) ? maxlen : len; - dev_dbg(&client->dev, - "page_legal, QSFP, off %lld len %ld\n", - off, (long int) len); - } - return len; -} - -static ssize_t optoe_read_write(struct optoe_data *optoe, - char *buf, loff_t off, size_t len, optoe_opcode_e opcode) -{ - struct i2c_client *client = optoe->client[0]; - int chunk; - int status = 0; - ssize_t retval; - size_t pending_len = 0, chunk_len = 0; - loff_t chunk_offset = 0, chunk_start_offset = 0; - - dev_dbg(&client->dev, - "optoe_read_write: off %lld len:%ld, opcode:%s\n", - off, (long int) len, (opcode == OPTOE_READ_OP) ? "r": "w"); - if (unlikely(!len)) - return len; - - /* - * Read data from chip, protecting against concurrent updates - * from this host, but not from other I2C masters. - */ - mutex_lock(&optoe->lock); - - /* - * Confirm this access fits within the device suppored addr range - */ - status = optoe_page_legal(optoe, off, len); - if (status < 0) { - goto err; - } - len = status; - - /* - * For each (128 byte) chunk involved in this request, issue a - * separate call to sff_eeprom_update_client(), to - * ensure that each access recalculates the client/page - * and writes the page register as needed. - * Note that chunk to page mapping is confusing, is different for - * QSFP and SFP, and never needs to be done. Don't try! - */ - pending_len = len; /* amount remaining to transfer */ - retval = 0; /* amount transferred */ - for (chunk = off >> 7; chunk <= (off + len - 1) >> 7; chunk++) { - - /* - * Compute the offset and number of bytes to be read/write - * - * 1. start at offset 0 (within the chunk), and read/write - * the entire chunk - * 2. start at offset 0 (within the chunk) and read/write less - * than entire chunk - * 3. start at an offset not equal to 0 and read/write the rest - * of the chunk - * 4. start at an offset not equal to 0 and read/write less than - * (end of chunk - offset) - */ - chunk_start_offset = chunk * OPTOE_PAGE_SIZE; - - if (chunk_start_offset < off) { - chunk_offset = off; - if ((off + pending_len) < (chunk_start_offset + - OPTOE_PAGE_SIZE)) - chunk_len = pending_len; - else - chunk_len = OPTOE_PAGE_SIZE - off; - } else { - chunk_offset = chunk_start_offset; - if (pending_len > OPTOE_PAGE_SIZE) - chunk_len = OPTOE_PAGE_SIZE; - else - chunk_len = pending_len; - } - - dev_dbg(&client->dev, - "sff_r/w: off %lld, len %ld, chunk_start_offset %lld, chunk_offset %lld, chunk_len %ld, pending_len %ld\n", - off, (long int) len, chunk_start_offset, chunk_offset, - (long int) chunk_len, (long int) pending_len); - - /* - * note: chunk_offset is from the start of the EEPROM, - * not the start of the chunk - */ - status = optoe_eeprom_update_client(optoe, buf, - chunk_offset, chunk_len, opcode); - if (status != chunk_len) { - /* This is another 'no device present' path */ - dev_dbg(&client->dev, - "optoe_update_client for chunk %d chunk_offset %lld chunk_len %ld failed %d!\n", - chunk, chunk_offset, (long int) chunk_len, status); - goto err; - } - buf += status; - pending_len -= status; - retval += status; - } - mutex_unlock(&optoe->lock); - - return retval; - -err: - mutex_unlock(&optoe->lock); - - return status; -} - -static ssize_t optoe_bin_read(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - struct i2c_client *client = to_i2c_client(container_of(kobj, - struct device, kobj)); - struct optoe_data *optoe = i2c_get_clientdata(client); - - return optoe_read_write(optoe, buf, off, count, OPTOE_READ_OP); -} - - -static ssize_t optoe_bin_write(struct file *filp, struct kobject *kobj, - struct bin_attribute *attr, - char *buf, loff_t off, size_t count) -{ - struct i2c_client *client = to_i2c_client(container_of(kobj, - struct device, kobj)); - struct optoe_data *optoe = i2c_get_clientdata(client); - - return optoe_read_write(optoe, buf, off, count, OPTOE_WRITE_OP); -} -/*-------------------------------------------------------------------------*/ - -/* - * This lets other kernel code access the eeprom data. For example, it - * might hold a board's Ethernet address, or board-specific calibration - * data generated on the manufacturing floor. - */ - -static ssize_t optoe_macc_read(struct memory_accessor *macc, - char *buf, off_t offset, size_t count) -{ - struct optoe_data *optoe = container_of(macc, - struct optoe_data, macc); - - return optoe_read_write(optoe, buf, offset, count, OPTOE_READ_OP); -} - -static ssize_t optoe_macc_write(struct memory_accessor *macc, - const char *buf, off_t offset, size_t count) -{ - struct optoe_data *optoe = container_of(macc, - struct optoe_data, macc); - - return optoe_read_write(optoe, (char *) buf, offset, - count, OPTOE_WRITE_OP); -} - -/*-------------------------------------------------------------------------*/ - -static int optoe_remove(struct i2c_client *client) -{ - struct optoe_data *optoe; - int i; - - optoe = i2c_get_clientdata(client); - sysfs_remove_group(&client->dev.kobj, &optoe->attr_group); - sysfs_remove_bin_file(&client->dev.kobj, &optoe->bin); - - for (i = 1; i < optoe->num_addresses; i++) - i2c_unregister_device(optoe->client[i]); - -#ifdef EEPROM_CLASS - eeprom_device_unregister(optoe->eeprom_dev); -#endif - - kfree(optoe->writebuf); - kfree(optoe); - return 0; -} - -static ssize_t show_port_name(struct device *dev, - struct device_attribute *dattr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct optoe_data *optoe = i2c_get_clientdata(client); - ssize_t count; - - mutex_lock(&optoe->lock); - count = sprintf(buf, "%s\n", optoe->port_name); - mutex_unlock(&optoe->lock); - - return count; -} - -static ssize_t set_port_name(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct optoe_data *optoe = i2c_get_clientdata(client); - char port_name[MAX_PORT_NAME_LEN]; - - /* no checking, this value is not used except by show_port_name */ - - if (sscanf(buf, "%19s", port_name) != 1) - return -EINVAL; - - mutex_lock(&optoe->lock); - strcpy(optoe->port_name, port_name); - mutex_unlock(&optoe->lock); - - return count; -} - -static DEVICE_ATTR(port_name, S_IRUGO | S_IWUSR, - show_port_name, set_port_name); - -static ssize_t show_dev_class(struct device *dev, - struct device_attribute *dattr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct optoe_data *optoe = i2c_get_clientdata(client); - ssize_t count; - - mutex_lock(&optoe->lock); - count = sprintf(buf, "%d\n", optoe->dev_class); - mutex_unlock(&optoe->lock); - - return count; -} - -static ssize_t set_dev_class(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct optoe_data *optoe = i2c_get_clientdata(client); - int dev_class; - - /* - * dev_class is actually the number of sfp ports used, thus - * legal values are "1" (QSFP class) and "2" (SFP class) - */ - if (sscanf(buf, "%d", &dev_class) != 1 || - dev_class < 1 || dev_class > 2) - return -EINVAL; - - mutex_lock(&optoe->lock); - optoe->dev_class = dev_class; - mutex_unlock(&optoe->lock); - - return count; -} - -static DEVICE_ATTR(dev_class, S_IRUGO | S_IWUSR, - show_dev_class, set_dev_class); - -static struct attribute *optoe_attrs[] = { - &dev_attr_port_name.attr, - &dev_attr_dev_class.attr, - NULL, -}; - -static struct attribute_group optoe_attr_group = { - .attrs = optoe_attrs, -}; - -static int optoe_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int err; - int use_smbus = 0; - struct optoe_platform_data chip; - struct optoe_data *optoe; - int num_addresses = 0; - int i = 0; - - if (client->addr != 0x50) { - dev_dbg(&client->dev, "probe, bad i2c addr: 0x%x\n", - client->addr); - err = -EINVAL; - goto exit; - } - - if (client->dev.platform_data) { - chip = *(struct optoe_platform_data *)client->dev.platform_data; - dev_dbg(&client->dev, "probe, chip provided, flags:0x%x; name: %s\n", chip.flags, client->name); - } else { - if (!id->driver_data) { - err = -ENODEV; - goto exit; - } - dev_dbg(&client->dev, "probe, building chip\n"); - chip.flags = 0; - chip.setup = NULL; - chip.context = NULL; -#ifdef EEPROM_CLASS - chip.eeprom_data = NULL; -#endif - } - - /* Use I2C operations unless we're stuck with SMBus extensions. */ - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { - use_smbus = I2C_SMBUS_I2C_BLOCK_DATA; - } else if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_WORD_DATA)) { - use_smbus = I2C_SMBUS_WORD_DATA; - } else if (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_BYTE_DATA)) { - use_smbus = I2C_SMBUS_BYTE_DATA; - } else { - err = -EPFNOSUPPORT; - goto exit; - } - } - - - /* - * Make room for two i2c clients - */ - num_addresses = 2; - - optoe = kzalloc(sizeof(struct optoe_data) + - num_addresses * sizeof(struct i2c_client *), - GFP_KERNEL); - if (!optoe) { - err = -ENOMEM; - goto exit; - } - - mutex_init(&optoe->lock); - - /* determine whether this is a one-address or two-address module */ - if ((strcmp(client->name, "optoe1") == 0) || - (strcmp(client->name, "sff8436") == 0)) { - /* one-address (eg QSFP) family */ - optoe->dev_class = ONE_ADDR; - chip.byte_len = ONE_ADDR_EEPROM_SIZE; - num_addresses = 1; - } else if ((strcmp(client->name, "optoe2") == 0) || - (strcmp(client->name, "24c04") == 0)) { - /* SFP family */ - optoe->dev_class = TWO_ADDR; - chip.byte_len = TWO_ADDR_EEPROM_SIZE; - } else { /* those were the only two choices */ - err = -EINVAL; - goto exit; - } - - dev_dbg(&client->dev, "dev_class: %d\n", optoe->dev_class); - optoe->use_smbus = use_smbus; - optoe->chip = chip; - optoe->num_addresses = num_addresses; - - /* - * Use platform data to initial port name. - * Original port name is unitialized: strcpy(optoe->port_name, "unitialized"); - */ - sprintf(optoe->port_name, "%d", chip.oom_port_name); - - /* - * Export the EEPROM bytes through sysfs, since that's convenient. - * By default, only root should see the data (maybe passwords etc) - */ - sysfs_bin_attr_init(&optoe->bin); - optoe->bin.attr.name = "eeprom"; - optoe->bin.attr.mode = S_IRUGO; - optoe->bin.read = optoe_bin_read; - optoe->bin.size = chip.byte_len; - - optoe->macc.read = optoe_macc_read; - - if (!use_smbus || - (i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) || - i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_WORD_DATA) || - i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) { - /* - * NOTE: AN-2079 - * Finisar recommends that the host implement 1 byte writes - * only since this module only supports 32 byte page boundaries. - * 2 byte writes are acceptable for PE and Vout changes per - * Application Note AN-2071. - */ - unsigned write_max = 1; - - optoe->macc.write = optoe_macc_write; - - optoe->bin.write = optoe_bin_write; - optoe->bin.attr.mode |= S_IWUSR; - - if (write_max > io_limit) - write_max = io_limit; - if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) - write_max = I2C_SMBUS_BLOCK_MAX; - optoe->write_max = write_max; - - /* buffer (data + address at the beginning) */ - optoe->writebuf = kmalloc(write_max + 2, GFP_KERNEL); - if (!optoe->writebuf) { - err = -ENOMEM; - goto exit_kfree; - } - } else { - dev_warn(&client->dev, - "cannot write due to controller restrictions."); - } - - optoe->client[0] = client; - - /* use a dummy I2C device for two-address chips */ - for (i = 1; i < num_addresses; i++) { - optoe->client[i] = i2c_new_dummy(client->adapter, - client->addr + i); - if (!optoe->client[i]) { - dev_err(&client->dev, "address 0x%02x unavailable\n", - client->addr + i); - err = -EADDRINUSE; - goto err_struct; - } - } - - /* create the sysfs eeprom file */ - err = sysfs_create_bin_file(&client->dev.kobj, &optoe->bin); - if (err) - goto err_struct; - - optoe->attr_group = optoe_attr_group; - - err = sysfs_create_group(&client->dev.kobj, &optoe->attr_group); - if (err) { - dev_err(&client->dev, "failed to create sysfs attribute group.\n"); - goto err_struct; - } -#ifdef EEPROM_CLASS - optoe->eeprom_dev = eeprom_device_register(&client->dev, - chip.eeprom_data); - if (IS_ERR(optoe->eeprom_dev)) { - dev_err(&client->dev, "error registering eeprom device.\n"); - err = PTR_ERR(optoe->eeprom_dev); - goto err_sysfs_cleanup; - } -#endif - - i2c_set_clientdata(client, optoe); - - dev_info(&client->dev, "%zu byte %s EEPROM, %s\n", - optoe->bin.size, client->name, - optoe->bin.write ? "read/write" : "read-only"); - - if (use_smbus == I2C_SMBUS_WORD_DATA || - use_smbus == I2C_SMBUS_BYTE_DATA) { - dev_notice(&client->dev, "Falling back to %s reads, " - "performance will suffer\n", use_smbus == - I2C_SMBUS_WORD_DATA ? "word" : "byte"); - } - - if (chip.setup) - chip.setup(&optoe->macc, chip.context); - - return 0; - -#ifdef EEPROM_CLASS -err_sysfs_cleanup: - sysfs_remove_group(&client->dev.kobj, &optoe->attr_group); - sysfs_remove_bin_file(&client->dev.kobj, &optoe->bin); -#endif - -err_struct: - for (i = 1; i < num_addresses; i++) { - if (optoe->client[i]) - i2c_unregister_device(optoe->client[i]); - } - - kfree(optoe->writebuf); -exit_kfree: - kfree(optoe); -exit: - dev_dbg(&client->dev, "probe error %d\n", err); - - return err; -} - -/*-------------------------------------------------------------------------*/ - -static struct i2c_driver optoe_driver = { - .driver = { - .name = "optoe", - .owner = THIS_MODULE, - }, - .probe = optoe_probe, - .remove = optoe_remove, - .id_table = optoe_ids, -}; - -static int __init optoe_init(void) -{ - - if (!io_limit) { - pr_err("optoe: io_limit must not be 0!\n"); - return -EINVAL; - } - - io_limit = rounddown_pow_of_two(io_limit); - return i2c_add_driver(&optoe_driver); -} -module_init(optoe_init); - -static void __exit optoe_exit(void) -{ - i2c_del_driver(&optoe_driver); -} -module_exit(optoe_exit); - -MODULE_DESCRIPTION("Driver for optical transceiver (SFP, QSFP, ...) EEPROMs"); -MODULE_AUTHOR("Jonathan Tsai "); -MODULE_LICENSE("GPL"); diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ly8-rangeley/modules/builds/quanta_platform_ly8.c b/packages/platforms/quanta/x86-64/x86-64-quanta-ly8-rangeley/modules/builds/quanta_platform_ly8.c old mode 100644 new mode 100755 index d7e12b68..66018dde --- a/packages/platforms/quanta/x86-64/x86-64-quanta-ly8-rangeley/modules/builds/quanta_platform_ly8.c +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ly8-rangeley/modules/builds/quanta_platform_ly8.c @@ -78,7 +78,6 @@ struct i2c_init_data { int busno; int gpio_base; char name[I2C_NAME_SIZE]; - int oom_port_name; }; static struct i2c_init_data quanta_ly8_i2c_init_data[] = { @@ -99,54 +98,54 @@ static struct i2c_init_data quanta_ly8_i2c_init_data[] = { { .parent_bus = (0x10 + 0), .type = i2c_type_pca9554, .addr = 0x25, .name = "PCA9554(PCA9698INT)\0" }, { .parent_bus = (0x10 + 0), .type = i2c_type_pca9555, .addr = 0x24, .name = "PCA9555_3(FAN)\0" }, { .parent_bus = (0x10 + 0), .type = i2c_type_pca9555, .addr = 0x23, .name = "PCA9555_4(QSFP_EN)\0" }, - { .parent_bus = (0x20 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_1_EEPROM\0", .oom_port_name = 1 }, - { .parent_bus = (0x20 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_2_EEPROM\0", .oom_port_name = 2 }, - { .parent_bus = (0x20 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_3_EEPROM\0", .oom_port_name = 3 }, - { .parent_bus = (0x20 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_4_EEPROM\0", .oom_port_name = 4 }, - { .parent_bus = (0x20 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_5_EEPROM\0", .oom_port_name = 5 }, - { .parent_bus = (0x20 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_6_EEPROM\0", .oom_port_name = 6 }, - { .parent_bus = (0x20 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_7_EEPROM\0", .oom_port_name = 7 }, - { .parent_bus = (0x20 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_8_EEPROM\0", .oom_port_name = 8 }, - { .parent_bus = (0x28 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_9_EEPROM\0", .oom_port_name = 9 }, - { .parent_bus = (0x28 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_10_EEPROM\0", .oom_port_name = 10 }, - { .parent_bus = (0x28 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_11_EEPROM\0", .oom_port_name = 11 }, - { .parent_bus = (0x28 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_12_EEPROM\0", .oom_port_name = 12 }, - { .parent_bus = (0x28 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_13_EEPROM\0", .oom_port_name = 13 }, - { .parent_bus = (0x28 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_14_EEPROM\0", .oom_port_name = 14 }, - { .parent_bus = (0x28 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_15_EEPROM\0", .oom_port_name = 15 }, - { .parent_bus = (0x28 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_16_EEPROM\0", .oom_port_name = 16 }, - { .parent_bus = (0x30 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_17_EEPROM\0", .oom_port_name = 17 }, - { .parent_bus = (0x30 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_18_EEPROM\0", .oom_port_name = 18 }, - { .parent_bus = (0x30 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_19_EEPROM\0", .oom_port_name = 19 }, - { .parent_bus = (0x30 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_20_EEPROM\0", .oom_port_name = 20 }, - { .parent_bus = (0x30 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_21_EEPROM\0", .oom_port_name = 21 }, - { .parent_bus = (0x30 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_22_EEPROM\0", .oom_port_name = 22 }, - { .parent_bus = (0x30 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_23_EEPROM\0", .oom_port_name = 23 }, - { .parent_bus = (0x30 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_24_EEPROM\0", .oom_port_name = 24 }, - { .parent_bus = (0x38 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_25_EEPROM\0", .oom_port_name = 25 }, - { .parent_bus = (0x38 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_26_EEPROM\0", .oom_port_name = 26 }, - { .parent_bus = (0x38 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_27_EEPROM\0", .oom_port_name = 27 }, - { .parent_bus = (0x38 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_28_EEPROM\0", .oom_port_name = 28 }, - { .parent_bus = (0x38 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_29_EEPROM\0", .oom_port_name = 29 }, - { .parent_bus = (0x38 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_30_EEPROM\0", .oom_port_name = 30 }, - { .parent_bus = (0x38 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_31_EEPROM\0", .oom_port_name = 31 }, - { .parent_bus = (0x38 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_32_EEPROM\0", .oom_port_name = 32 }, - { .parent_bus = (0x40 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_33_EEPROM\0", .oom_port_name = 33 }, - { .parent_bus = (0x40 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_34_EEPROM\0", .oom_port_name = 34 }, - { .parent_bus = (0x40 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_35_EEPROM\0", .oom_port_name = 35 }, - { .parent_bus = (0x40 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_36_EEPROM\0", .oom_port_name = 36 }, - { .parent_bus = (0x40 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_37_EEPROM\0", .oom_port_name = 37 }, - { .parent_bus = (0x40 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_38_EEPROM\0", .oom_port_name = 38 }, - { .parent_bus = (0x40 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_39_EEPROM\0", .oom_port_name = 39 }, - { .parent_bus = (0x40 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_40_EEPROM\0", .oom_port_name = 40 }, - { .parent_bus = (0x48 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_41_EEPROM\0", .oom_port_name = 41 }, - { .parent_bus = (0x48 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_42_EEPROM\0", .oom_port_name = 42 }, - { .parent_bus = (0x48 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_43_EEPROM\0", .oom_port_name = 43 }, - { .parent_bus = (0x48 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_44_EEPROM\0", .oom_port_name = 44 }, - { .parent_bus = (0x48 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_45_EEPROM\0", .oom_port_name = 45 }, - { .parent_bus = (0x48 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_46_EEPROM\0", .oom_port_name = 46 }, - { .parent_bus = (0x48 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_47_EEPROM\0", .oom_port_name = 47 }, - { .parent_bus = (0x48 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_48_EEPROM\0", .oom_port_name = 48 }, + { .parent_bus = (0x20 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_1_EEPROM\0" }, + { .parent_bus = (0x20 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_2_EEPROM\0" }, + { .parent_bus = (0x20 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_3_EEPROM\0" }, + { .parent_bus = (0x20 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_4_EEPROM\0" }, + { .parent_bus = (0x20 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_5_EEPROM\0" }, + { .parent_bus = (0x20 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_6_EEPROM\0" }, + { .parent_bus = (0x20 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_7_EEPROM\0" }, + { .parent_bus = (0x20 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_8_EEPROM\0" }, + { .parent_bus = (0x28 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_9_EEPROM\0" }, + { .parent_bus = (0x28 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_10_EEPROM\0" }, + { .parent_bus = (0x28 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_11_EEPROM\0" }, + { .parent_bus = (0x28 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_12_EEPROM\0" }, + { .parent_bus = (0x28 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_13_EEPROM\0" }, + { .parent_bus = (0x28 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_14_EEPROM\0" }, + { .parent_bus = (0x28 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_15_EEPROM\0" }, + { .parent_bus = (0x28 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_16_EEPROM\0" }, + { .parent_bus = (0x30 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_17_EEPROM\0" }, + { .parent_bus = (0x30 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_18_EEPROM\0" }, + { .parent_bus = (0x30 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_19_EEPROM\0" }, + { .parent_bus = (0x30 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_20_EEPROM\0" }, + { .parent_bus = (0x30 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_21_EEPROM\0" }, + { .parent_bus = (0x30 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_22_EEPROM\0" }, + { .parent_bus = (0x30 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_23_EEPROM\0" }, + { .parent_bus = (0x30 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_24_EEPROM\0" }, + { .parent_bus = (0x38 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_25_EEPROM\0" }, + { .parent_bus = (0x38 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_26_EEPROM\0" }, + { .parent_bus = (0x38 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_27_EEPROM\0" }, + { .parent_bus = (0x38 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_28_EEPROM\0" }, + { .parent_bus = (0x38 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_29_EEPROM\0" }, + { .parent_bus = (0x38 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_30_EEPROM\0" }, + { .parent_bus = (0x38 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_31_EEPROM\0" }, + { .parent_bus = (0x38 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_32_EEPROM\0" }, + { .parent_bus = (0x40 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_33_EEPROM\0" }, + { .parent_bus = (0x40 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_34_EEPROM\0" }, + { .parent_bus = (0x40 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_35_EEPROM\0" }, + { .parent_bus = (0x40 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_36_EEPROM\0" }, + { .parent_bus = (0x40 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_37_EEPROM\0" }, + { .parent_bus = (0x40 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_38_EEPROM\0" }, + { .parent_bus = (0x40 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_39_EEPROM\0" }, + { .parent_bus = (0x40 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_40_EEPROM\0" }, + { .parent_bus = (0x48 + 0), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_41_EEPROM\0" }, + { .parent_bus = (0x48 + 1), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_42_EEPROM\0" }, + { .parent_bus = (0x48 + 2), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_43_EEPROM\0" }, + { .parent_bus = (0x48 + 3), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_44_EEPROM\0" }, + { .parent_bus = (0x48 + 4), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_45_EEPROM\0" }, + { .parent_bus = (0x48 + 5), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_46_EEPROM\0" }, + { .parent_bus = (0x48 + 6), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_47_EEPROM\0" }, + { .parent_bus = (0x48 + 7), .type = i2c_type_optoe2_SFP, .addr = 0x50, .name = "SFP_48_EEPROM\0" }, { .parent_bus = (0x10 + 3), .type = i2c_type_pca9698, .addr = 0x23, .name = "PCA9698(SFP_1-8)\0" }, { .parent_bus = (0x10 + 3), .type = i2c_type_pca9698, .addr = 0x21, .name = "PCA9698(SFP_9-16)\0" }, @@ -156,10 +155,10 @@ static struct i2c_init_data quanta_ly8_i2c_init_data[] = { { .parent_bus = (0x10 + 4), .type = i2c_type_pca9698, .addr = 0x25, .name = "PCA9698(SFP_41-48)\0" }, { .parent_bus = (0x10 + 5), .type = i2c_type_pca9548, .addr = 0x76, .busno = 0x50, .name = "PCA9548_8\0" }, - { .parent_bus = (0x50 + 0), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QSFP_1_EEPROM\0", .oom_port_name = 49 }, - { .parent_bus = (0x50 + 1), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QSFP_2_EEPROM\0", .oom_port_name = 50 }, - { .parent_bus = (0x50 + 2), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QSFP_3_EEPROM\0", .oom_port_name = 51 }, - { .parent_bus = (0x50 + 3), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QSFP_4_EEPROM\0", .oom_port_name = 52 }, + { .parent_bus = (0x50 + 0), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QSFP_1_EEPROM\0" }, + { .parent_bus = (0x50 + 1), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QSFP_2_EEPROM\0" }, + { .parent_bus = (0x50 + 2), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QSFP_3_EEPROM\0" }, + { .parent_bus = (0x50 + 3), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QSFP_4_EEPROM\0" }, { .parent_bus = (0x10 + 5), .type = i2c_type_pca9555, .addr = 0x24, .name = "PCA9555_1(LED)\0" }, { .parent_bus = (0x10 + 6), .type = i2c_type_pca9555, .addr = 0x23, .name = "PCA9555_2(QSFP)\0" }, @@ -167,8 +166,8 @@ static struct i2c_init_data quanta_ly8_i2c_init_data[] = { /* QSFP+ DB */ { .parent_bus = (0x10 + 7), .type = i2c_type_pca9555, .addr = 0x23, .name = "PCA9555(QDB)\0" }, { .parent_bus = (0x10 + 7), .type = i2c_type_pca9546, .addr = 0x76, .busno = 0x58, .name = "PCA9546(QDB)\0" }, - { .parent_bus = (0x58 + 0), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QDB_QSFP_1_EEPROM\0", .oom_port_name = 53 }, - { .parent_bus = (0x58 + 1), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QDB_QSFP_2_EEPROM\0", .oom_port_name = 54 }, + { .parent_bus = (0x58 + 0), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QDB_QSFP_1_EEPROM\0" }, + { .parent_bus = (0x58 + 1), .type = i2c_type_optoe1_QSFP, .addr = 0x50, .name = "QDB_QSFP_2_EEPROM\0" }, { .parent_bus = (0x00 + 0), .type = i2c_type_pca9546, .addr = 0x72, .busno = 0x18, .name = "PCA9546\0" }, { .parent_bus = (0x18 + 0), .type = i2c_type_emerson700, .addr = 0x6f, .name = "PSU_1\0" }, /* RPSU 1 */ @@ -249,31 +248,9 @@ static inline struct pca953x_platform_data *pca953x_platform_data_get(int type, return &platform_data; } -struct optoe_platform_data { - u32 byte_len; /* size (sum of all addr) */ - u16 page_size; /* for writes */ - u8 flags; - - void (*setup)(struct memory_accessor *, void *context); - void *context; - - int oom_port_name; -}; - -static inline struct optoe_platform_data *optoe_platform_data_get(int port_name) { - static struct optoe_platform_data platform_data; - - platform_data = (struct optoe_platform_data) { - .oom_port_name = port_name, - }; - - return &platform_data; -} - static inline struct i2c_board_info *i2c_board_info_get(struct i2c_init_data data) { struct pca954x_platform_data *mux_platform_data; struct pca953x_platform_data *gpio_platform_data; - struct optoe_platform_data *oom_platform_data; static struct i2c_board_info board_info; switch(data.type) { @@ -303,16 +280,6 @@ static inline struct i2c_board_info *i2c_board_info_get(struct i2c_init_data dat break; case i2c_type_optoe1_QSFP: case i2c_type_optoe2_SFP: - oom_platform_data = optoe_platform_data_get(data.oom_port_name); - if(oom_platform_data == NULL) { - return (struct i2c_board_info *) NULL; - } - - board_info = (struct i2c_board_info) { - .platform_data = oom_platform_data, - }; - break; - case i2c_type_rtc: case i2c_type_spd: case i2c_type_24c02: diff --git a/packages/platforms/quanta/x86-64/x86-64-quanta-ly8-rangeley/platform-config/r0/src/python/x86_64_quanta_ly8_rangeley_r0/__init__.py b/packages/platforms/quanta/x86-64/x86-64-quanta-ly8-rangeley/platform-config/r0/src/python/x86_64_quanta_ly8_rangeley_r0/__init__.py old mode 100644 new mode 100755 index 268c0d5f..ef3c38e2 --- a/packages/platforms/quanta/x86-64/x86-64-quanta-ly8-rangeley/platform-config/r0/src/python/x86_64_quanta_ly8_rangeley_r0/__init__.py +++ b/packages/platforms/quanta/x86-64/x86-64-quanta-ly8-rangeley/platform-config/r0/src/python/x86_64_quanta_ly8_rangeley_r0/__init__.py @@ -25,4 +25,14 @@ class OnlPlatform_x86_64_quanta_ly8_rangeley_r0(OnlPlatformQuanta, os.system("ln -snf /dev/rtc1 /dev/rtc") os.system("hwclock --hctosys") + #SFP for 1~48 port + #QSFP for 49~52 port + for port_number in range(1,53): + bus_number = port_number + 31 + os.system("echo %d >/sys/bus/i2c/devices/%d-0050/port_name" % (port_number, bus_number)) + + #QDB QSFP 53~54port + os.system("echo 53 >/sys/bus/i2c/devices/88-0050/port_name") + os.system("echo 54 >/sys/bus/i2c/devices/89-0050/port_name") + return True diff --git a/sm/bigcode b/sm/bigcode index 3a0ca236..59b58a4c 160000 --- a/sm/bigcode +++ b/sm/bigcode @@ -1 +1 @@ -Subproject commit 3a0ca236ecba75278dffa31c7c4c91a9be2285f4 +Subproject commit 59b58a4c8b7fb59060e4d76a2872458bb806ed5f