diff --git a/packages/base/all/vendor-config-onl/src/python/onl/platform/base.py b/packages/base/all/vendor-config-onl/src/python/onl/platform/base.py index 1457f23c..785ca5d1 100644 --- a/packages/base/all/vendor-config-onl/src/python/onl/platform/base.py +++ b/packages/base/all/vendor-config-onl/src/python/onl/platform/base.py @@ -309,3 +309,7 @@ class OnlPlatformPortConfig_32x40(object): class OnlPlatformPortConfig_32x100(object): PORT_COUNT=32 PORT_CONFIG="32x100" + +class OnlPlatformPortConfig_24x1_4x10(object): + PORT_COUNT=28 + PORT_CONFIG="24x1 + 4x10" diff --git a/packages/base/any/kernels/3.2.71-1+deb7/configs/arm-iproc-all/arm-iproc-all.config b/packages/base/any/kernels/3.2.71-1+deb7/configs/arm-iproc-all/arm-iproc-all.config index 0cd2c429..982c546d 100644 --- a/packages/base/any/kernels/3.2.71-1+deb7/configs/arm-iproc-all/arm-iproc-all.config +++ b/packages/base/any/kernels/3.2.71-1+deb7/configs/arm-iproc-all/arm-iproc-all.config @@ -864,6 +864,7 @@ CONFIG_MISC_DEVICES=y CONFIG_EEPROM_CLASS=y CONFIG_EEPROM_AT24=y CONFIG_EEPROM_AT25=y +CONFIG_EEPROM_ACCTON_AS4610_SFP=y # CONFIG_EEPROM_LEGACY is not set # CONFIG_EEPROM_MAX6875 is not set # CONFIG_EEPROM_93CX6 is not set @@ -1435,7 +1436,7 @@ CONFIG_SENSORS_ADM1021=y # CONFIG_SENSORS_LM70 is not set # CONFIG_SENSORS_LM73 is not set CONFIG_SENSORS_LM75=y -# CONFIG_SENSORS_LM77 is not set +CONFIG_SENSORS_LM77=y # CONFIG_SENSORS_LM78 is not set # CONFIG_SENSORS_LM80 is not set # CONFIG_SENSORS_LM83 is not set @@ -1499,6 +1500,10 @@ 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_FAN=y +CONFIG_SENSORS_ACCTON_AS4610_PSU=y +CONFIG_SENSORS_YM2651Y=y CONFIG_THERMAL=y CONFIG_THERMAL_HWMON=y # CONFIG_WATCHDOG is not set @@ -1802,7 +1807,28 @@ CONFIG_MMC_SDHCI_PLTFM=y # CONFIG_MMC_VUB300 is not set # CONFIG_MMC_USHC is not set # CONFIG_MEMSTICK is not set -# CONFIG_NEW_LEDS is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +CONFIG_LEDS_ACCTON_AS4610=y +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_RENESAS_TPU is not set +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_TRIGGERS is not set + # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set CONFIG_RTC_LIB=y diff --git a/packages/base/any/kernels/3.2.71-1+deb7/patches/platform-accton-as4610-device-drivers.patch b/packages/base/any/kernels/3.2.71-1+deb7/patches/platform-accton-as4610-device-drivers.patch new file mode 100644 index 00000000..027d3693 --- /dev/null +++ b/packages/base/any/kernels/3.2.71-1+deb7/patches/platform-accton-as4610-device-drivers.patch @@ -0,0 +1,3946 @@ +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 ++++ b/drivers/hwmon/Kconfig +@@ -1412,6 +1412,43 @@ config SENSORS_MC13783_ADC + help + Support for the A/D converter on MC13783 PMIC. + ++config SENSORS_ACCTON_I2C_CPLD ++ tristate "Accton i2c cpld" ++ depends on I2C ++ help ++ If you say yes here you get support for Accton i2c cpld. ++ ++ This driver can also be built as a module. If so, the module will ++ be called accton_i2c_cpld. ++ ++config SENSORS_ACCTON_AS4610_FAN ++ tristate "Accton as4610 fan" ++ depends on I2C && SENSORS_ACCTON_I2C_CPLD ++ help ++ If you say yes here you get support for Accton as4610 fan. ++ ++ This driver can also be built as a module. If so, the module will ++ be called accton_as4610_fan. ++ ++config SENSORS_ACCTON_AS4610_PSU ++ tristate "Accton as4610 psu" ++ depends on I2C && SENSORS_ACCTON_I2C_CPLD ++ help ++ If you say yes here you get support for Accton as4610 psu. ++ ++ This driver can also be built as a module. If so, the module will ++ be called accton_as4610_psu. ++ ++config SENSORS_YM2651Y ++ tristate "3Y Power (YM-2651Y, YM1921Y) Power Module" ++ depends on I2C ++ help ++ If you say yes here you get support for 3Y Power YM-2651Y and YM1921Y ++ Power Module. ++ ++ This driver can also be built as a module. If so, the module will ++ be called ym2651y. ++ + if ACPI + + comment "ACPI drivers" +diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile +index ff3a18e..39c9888 100644 +--- a/drivers/hwmon/Makefile ++++ b/drivers/hwmon/Makefile +@@ -21,6 +21,9 @@ obj-$(CONFIG_SENSORS_W83791D) += w83791d.o + + 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_FAN) += accton_as4610_fan.o ++obj-$(CONFIG_SENSORS_ACCTON_AS4610_PSU) += accton_as4610_psu.o + obj-$(CONFIG_SENSORS_AD7314) += ad7314.o + obj-$(CONFIG_SENSORS_AD7414) += ad7414.o + obj-$(CONFIG_SENSORS_AD7418) += ad7418.o +@@ -130,6 +133,7 @@ obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o + obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o + obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o + obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o ++obj-$(CONFIG_SENSORS_YM2651Y) += ym2651y.o + + obj-$(CONFIG_PMBUS) += pmbus/ + +diff --git a/drivers/hwmon/accton_as4610_fan.c b/drivers/hwmon/accton_as4610_fan.c +new file mode 100644 +index 0000000..3934bcd +--- /dev/null ++++ b/drivers/hwmon/accton_as4610_fan.c +@@ -0,0 +1,344 @@ ++/* ++ * A hwmon driver for the Accton as4610 fan ++ * ++ * Copyright (C) 2016 Accton Technology Corporation. ++ * Brandon Chuang ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRVNAME "as4610_fan" ++ ++static struct as4610_fan_data *as4610_fan_update_device(struct device *dev); ++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); ++ ++/* fan related data, the index should match sysfs_fan_attributes ++ */ ++static const u8 fan_reg[] = { ++ 0x2B, /* fan PWM(for all fan) */ ++ 0x2C, /* fan 1 speed(rpm) */ ++ 0x2D, /* fan 2 speed(rpm) */ ++ 0x11, /* fan1-2 operating status */ ++}; ++ ++static struct as4610_fan_data *fan_data = NULL; ++ ++/* Each client has this additional data */ ++struct as4610_fan_data { ++ struct platform_device *pdev; ++ struct device *hwmon_dev; ++ struct mutex update_lock; ++ char valid; /* != 0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ ++}; ++ ++enum fan_id { ++ FAN1_ID, ++ FAN2_ID ++}; ++ ++enum sysfs_fan_attributes { ++ FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */ ++ FAN1_SPEED_RPM, ++ FAN2_SPEED_RPM, ++ FAN_FAULT, ++ FAN1_FAULT, ++ FAN2_FAULT ++}; ++ ++/* Define attributes ++ */ ++#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \ ++ static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) ++#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.dev_attr.attr ++ ++#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ ++ static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE) ++#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr ++ ++#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \ ++ static SENSOR_DEVICE_ATTR(fan##index##_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_SPEED_RPM) ++#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_speed_rpm.dev_attr.attr ++ ++/* fan fault attributes in this platform */ ++DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1); ++DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2); ++/* fan speed(rpm) attributes in this platform */ ++DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1); ++DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2); ++/* 1 fan duty cycle attribute in this platform */ ++DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(); ++ ++static struct attribute *as4610_fan_attributes[] = { ++ /* fan related attributes */ ++ DECLARE_FAN_FAULT_ATTR(1), ++ DECLARE_FAN_FAULT_ATTR(2), ++ DECLARE_FAN_SPEED_RPM_ATTR(1), ++ DECLARE_FAN_SPEED_RPM_ATTR(2), ++ DECLARE_FAN_DUTY_CYCLE_ATTR(), ++ NULL ++}; ++ ++#define FAN_DUTY_CYCLE_REG_MASK 0xF ++#define FAN_MAX_DUTY_CYCLE 100 ++#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100 ++ ++static int as4610_fan_read_value(u8 reg) ++{ ++ return accton_i2c_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); ++} ++ ++/* 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); ++} ++ ++static u8 duty_cycle_to_reg_val(u8 duty_cycle) ++{ ++ 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; ++} ++ ++static u8 is_fan_fault(struct as4610_fan_data *data, enum fan_id id) ++{ ++ u8 mask = (id == FAN1_ID) ? 0x10 : 0x20; ++ ++ 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; ++ ++ error = kstrtoint(buf, 10, &value); ++ if (error) ++ return error; ++ ++ 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; ++} ++ ++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; ++ ++ 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; ++} ++ ++static const struct attribute_group as4610_fan_group = { ++ .attrs = as4610_fan_attributes, ++}; ++ ++static struct as4610_fan_data *as4610_fan_update_device(struct device *dev) ++{ ++ mutex_lock(&fan_data->update_lock); ++ ++ 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; ++ ++ /* 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; ++ } ++ } ++ ++ fan_data->last_updated = jiffies; ++ fan_data->valid = 1; ++ } ++ ++ mutex_unlock(&fan_data->update_lock); ++ ++ return fan_data; ++} ++ ++static int as4610_fan_probe(struct platform_device *pdev) ++{ ++ int status = -1; ++ ++ /* 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; ++ } ++ ++ dev_info(&pdev->dev, "accton_as5712_54x_fan\n"); ++ ++ return 0; ++ ++exit_remove: ++ sysfs_remove_group(&pdev->dev.kobj, &as4610_fan_group); ++exit: ++ 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); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id as4610_fan_id[] = { ++ { "as4610_fan", 0 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, as4610_fan_id); ++ ++static struct platform_driver as4610_fan_driver = { ++ .probe = as4610_fan_probe, ++ .remove = as4610_fan_remove, ++ .driver = { ++ .name = DRVNAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init as4610_fan_init(void) ++{ ++ int ret; ++ ++ if (as4610_number_of_system_fan() == 0) { ++ return -ENODEV; ++ } ++ ++ 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; ++ } ++ ++ 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; ++ } ++ ++exit: ++ return ret; ++} ++ ++static void __exit as4610_fan_exit(void) ++{ ++ if (!fan_data) { ++ return; ++ } ++ ++ platform_device_unregister(fan_data->pdev); ++ platform_driver_unregister(&as4610_fan_driver); ++ kfree(fan_data); ++} ++ ++late_initcall(as4610_fan_init); ++module_exit(as4610_fan_exit); ++ ++MODULE_AUTHOR("Brandon Chuang "); ++MODULE_DESCRIPTION("as4610_fan driver"); ++MODULE_LICENSE("GPL"); ++ +diff --git a/drivers/hwmon/accton_as4610_psu.c b/drivers/hwmon/accton_as4610_psu.c +new file mode 100644 +index 0000000..1f0d79d +--- /dev/null ++++ b/drivers/hwmon/accton_as4610_psu.c +@@ -0,0 +1,286 @@ ++/* ++ * An hwmon driver for accton as4610 Power Module ++ * ++ * Copyright (C) 2016 Accton Technology Corporation. ++ * Brandon Chuang ++ * ++ * Based on ad7414.c ++ * Copyright 2006 Stefan Roese , DENX Software Engineering ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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); ++ ++/* Addresses scanned ++ */ ++static const unsigned short normal_i2c[] = { 0x50, 0x53, I2C_CLIENT_END }; ++ ++/* Each client has this additional data ++ */ ++struct as4610_psu_data { ++ struct device *hwmon_dev; ++ struct mutex update_lock; ++ char valid; /* !=0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ u8 index; /* PSU index */ ++ u8 status; /* Status(present/power_good) register read from CPLD */ ++ char model_name[9]; /* Model name, read from eeprom */ ++}; ++ ++static struct as4610_psu_data *as4610_psu_update_device(struct device *dev); ++ ++enum as4610_psu_sysfs_attributes { ++ PSU_PRESENT, ++ PSU_MODEL_NAME, ++ PSU_POWER_GOOD ++}; ++ ++/* sysfs attributes for hwmon ++ */ ++static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT); ++static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_model_name,NULL, PSU_MODEL_NAME); ++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 ++}; ++ ++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; ++ ++ 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); ++} ++ ++static ssize_t show_model_name(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct as4610_psu_data *data = as4610_psu_update_device(dev); ++ ++ return sprintf(buf, "%s\n", data->model_name); ++} ++ ++static const struct attribute_group as4610_psu_group = { ++ .attrs = as4610_psu_attributes, ++}; ++ ++static int as4610_psu_probe(struct i2c_client *client, ++ const struct i2c_device_id *dev_id) ++{ ++ struct as4610_psu_data *data; ++ int status; ++ ++ 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; ++ } ++ ++ 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"); ++ ++ /* 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; ++ } ++ ++ dev_info(&client->dev, "%s: psu '%s'\n", ++ dev_name(data->hwmon_dev), client->name); ++ ++ return 0; ++ ++exit_remove: ++ sysfs_remove_group(&client->dev.kobj, &as4610_psu_group); ++exit_free: ++ kfree(data); ++exit: ++ ++ return status; ++} ++ ++static int as4610_psu_remove(struct i2c_client *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); ++ ++ return 0; ++} ++ ++enum psu_index ++{ ++ as4610_psu1, ++ as4610_psu2 ++}; ++ ++static const struct i2c_device_id as4610_psu_id[] = { ++ { "as4610_psu1", as4610_psu1 }, ++ { "as4610_psu2", as4610_psu2 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, as4610_psu_id); ++ ++static struct i2c_driver as4610_psu_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "as4610_psu", ++ }, ++ .probe = as4610_psu_probe, ++ .remove = as4610_psu_remove, ++ .id_table = as4610_psu_id, ++ .address_list = normal_i2c, ++}; ++ ++static int as4610_psu_read_data(struct i2c_client *client, u8 command, u8 *data, ++ int count) ++{ ++ int status = 0; ++ ++ while (count) { ++ status = i2c_smbus_read_byte_data(client, command); ++ if (unlikely(status < 0)) { ++ break; ++ } ++ ++ *data = (u8)status; ++ data += 1; ++ command += 1; ++ count -= 1; ++ } ++ ++ 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); ++ ++ mutex_lock(&data->update_lock); ++ ++ 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"); ++ ++ /* Read psu status */ ++ status = accton_i2c_cpld_read(0x30, 0x11); ++ ++ 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); ++ ++ 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); ++ ++ 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; ++ } ++ ++exit: ++ mutex_unlock(&data->update_lock); ++ ++ return data; ++} ++ ++static int __init as4610_psu_init(void) ++{ ++ return i2c_add_driver(&as4610_psu_driver); ++} ++ ++static void __exit as4610_psu_exit(void) ++{ ++ i2c_del_driver(&as4610_psu_driver); ++} ++ ++module_init(as4610_psu_init); ++module_exit(as4610_psu_exit); ++ ++MODULE_AUTHOR("Brandon Chuang "); ++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 ++++ b/drivers/hwmon/lm77.c +@@ -36,7 +36,7 @@ + #include + + /* Addresses to scan */ +-static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, ++static const unsigned short normal_i2c[] = { /*0x48,*/ 0x49, 0x4a, 0x4b, + I2C_CLIENT_END }; + + /* The LM77 registers */ +diff --git a/drivers/hwmon/ym2651y.c b/drivers/hwmon/ym2651y.c +new file mode 100644 +index 0000000..e761a74 +--- /dev/null ++++ b/drivers/hwmon/ym2651y.c +@@ -0,0 +1,651 @@ ++/* ++ * An hwmon driver for the 3Y Power YM-2651Y Power Module ++ * ++ * 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 ++ ++#define USE_I2C_BLOCK_READ 0 ++#if USE_I2C_BLOCK_READ ++ #define I2C_FUNCTION (I2C_FUNC_SMBUS_BYTE_DATA | \ ++ I2C_FUNC_SMBUS_WORD_DATA | \ ++ I2C_FUNC_SMBUS_I2C_BLOCK) ++#else ++ #define I2C_FUNCTION (I2C_FUNC_SMBUS_BYTE_DATA | \ ++ I2C_FUNC_SMBUS_WORD_DATA) ++#endif ++ ++#define MAX_FAN_DUTY_CYCLE 100 ++ ++/* Addresses scanned ++ */ ++static const unsigned short normal_i2c[] = { 0x58, 0x5b, I2C_CLIENT_END }; ++ ++/* Each client has this additional data ++ */ ++struct ym2651y_data { ++ struct device *hwmon_dev; ++ struct mutex update_lock; ++ char valid; /* !=0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ u8 capability; /* Register value */ ++ u16 status_word; /* Register value */ ++ u8 fan_fault; /* Register value */ ++ u8 over_temp; /* Register value */ ++ u16 v_out; /* Register value */ ++ u16 i_out; /* Register value */ ++ u16 p_out; /* Register value */ ++ u16 temp; /* Register value */ ++ u16 fan_speed; /* Register value */ ++ u16 fan_duty_cycle[2]; /* Register value */ ++ u8 pmbus_revision; /* Register value */ ++ u16 mfr_vin_min; /* Register value */ ++ u16 mfr_vin_max; /* Register value */ ++ u16 mfr_iin_max; /* Register value */ ++ u16 mfr_iout_max; /* Register value */ ++ u16 mfr_pin_max; /* Register value */ ++ u16 mfr_pout_max; /* Register value */ ++ u16 mfr_vout_min; /* Register value */ ++ u16 mfr_vout_max; /* Register value */ ++#if USE_I2C_BLOCK_READ ++ u8 fan_dir[4]; /* Register value */ ++ u8 mfr_id[10]; /* Register value */ ++ u8 mfr_model[10]; /* Register value */ ++ u8 mfr_revsion[3]; /* Register value */ ++#endif ++ ++}; ++ ++static ssize_t show_byte(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_word(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_linear(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, ++ char *buf); ++static ssize_t show_ascii(struct device *dev, struct device_attribute *da, ++ char *buf); ++static struct ym2651y_data *ym2651y_update_device(struct device *dev); ++static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count); ++static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value); ++ ++enum ym2651y_sysfs_attributes { ++ PSU_POWER_ON = 0, ++ PSU_TEMP_FAULT, ++ PSU_POWER_GOOD, ++ PSU_FAN1_FAULT, ++ PSU_FAN_DIRECTION, ++ PSU_OVER_TEMP, ++ PSU_V_OUT, ++ PSU_I_OUT, ++ PSU_P_OUT, ++ PSU_TEMP1_INPUT, ++ PSU_FAN1_SPEED, ++ PSU_FAN1_DUTY_CYCLE, ++ PSU_PMBUS_REVISION, ++ PSU_MFR_ID, ++ PSU_MFR_MODEL, ++ PSU_MFR_REVISION, ++ PSU_MFR_VIN_MIN, ++ PSU_MFR_VIN_MAX, ++ PSU_MFR_VOUT_MIN, ++ PSU_MFR_VOUT_MAX, ++ PSU_MFR_IIN_MAX, ++ PSU_MFR_IOUT_MAX, ++ PSU_MFR_PIN_MAX, ++ PSU_MFR_POUT_MAX ++}; ++ ++/* sysfs attributes for hwmon ++ */ ++static SENSOR_DEVICE_ATTR(psu_power_on, S_IRUGO, show_word, NULL, PSU_POWER_ON); ++static SENSOR_DEVICE_ATTR(psu_temp_fault, S_IRUGO, show_word, NULL, PSU_TEMP_FAULT); ++static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_word, NULL, PSU_POWER_GOOD); ++static SENSOR_DEVICE_ATTR(psu_fan1_fault, S_IRUGO, show_fan_fault, NULL, PSU_FAN1_FAULT); ++static SENSOR_DEVICE_ATTR(psu_over_temp, S_IRUGO, show_over_temp, NULL, PSU_OVER_TEMP); ++static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, show_linear, NULL, PSU_V_OUT); ++static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, show_linear, NULL, PSU_I_OUT); ++static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, show_linear, NULL, PSU_P_OUT); ++static SENSOR_DEVICE_ATTR(psu_temp1_input, S_IRUGO, show_linear, NULL, PSU_TEMP1_INPUT); ++static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, S_IRUGO, show_linear, NULL, PSU_FAN1_SPEED); ++static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUSR | S_IRUGO, show_linear, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); ++static SENSOR_DEVICE_ATTR(psu_pmbus_revision, S_IRUGO, show_byte, NULL, PSU_PMBUS_REVISION); ++static SENSOR_DEVICE_ATTR(psu_mfr_vin_min, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MIN); ++static SENSOR_DEVICE_ATTR(psu_mfr_vin_max, S_IRUGO, show_linear, NULL, PSU_MFR_VIN_MAX); ++static SENSOR_DEVICE_ATTR(psu_mfr_vout_min, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MIN); ++static SENSOR_DEVICE_ATTR(psu_mfr_vout_max, S_IRUGO, show_linear, NULL, PSU_MFR_VOUT_MAX); ++static SENSOR_DEVICE_ATTR(psu_mfr_iin_max, S_IRUGO, show_linear, NULL, PSU_MFR_IIN_MAX); ++static SENSOR_DEVICE_ATTR(psu_mfr_iout_max, S_IRUGO, show_linear, NULL, PSU_MFR_IOUT_MAX); ++static SENSOR_DEVICE_ATTR(psu_mfr_pin_max, S_IRUGO, show_linear, NULL, PSU_MFR_PIN_MAX); ++static SENSOR_DEVICE_ATTR(psu_mfr_pout_max, S_IRUGO, show_linear, NULL, PSU_MFR_POUT_MAX); ++#if USE_I2C_BLOCK_READ ++static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_ascii, NULL, PSU_FAN_DIRECTION); ++static SENSOR_DEVICE_ATTR(psu_mfr_id, S_IRUGO, show_ascii, NULL, PSU_MFR_ID); ++static SENSOR_DEVICE_ATTR(psu_mfr_model, S_IRUGO, show_ascii, NULL, PSU_MFR_MODEL); ++static SENSOR_DEVICE_ATTR(psu_mfr_revision, S_IRUGO, show_ascii, NULL, PSU_MFR_REVISION); ++#endif ++ ++ ++static struct attribute *ym2651y_attributes[] = { ++ &sensor_dev_attr_psu_power_on.dev_attr.attr, ++ &sensor_dev_attr_psu_temp_fault.dev_attr.attr, ++ &sensor_dev_attr_psu_power_good.dev_attr.attr, ++ &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, ++ &sensor_dev_attr_psu_over_temp.dev_attr.attr, ++ &sensor_dev_attr_psu_v_out.dev_attr.attr, ++ &sensor_dev_attr_psu_i_out.dev_attr.attr, ++ &sensor_dev_attr_psu_p_out.dev_attr.attr, ++ &sensor_dev_attr_psu_temp1_input.dev_attr.attr, ++ &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, ++ &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, ++ &sensor_dev_attr_psu_pmbus_revision.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_vin_min.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_vin_max.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_pout_max.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_iin_max.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_pin_max.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_vout_min.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_vout_max.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_iout_max.dev_attr.attr, ++#if USE_I2C_BLOCK_READ ++ &sensor_dev_attr_psu_fan_dir.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_id.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_model.dev_attr.attr, ++ &sensor_dev_attr_psu_mfr_revision.dev_attr.attr, ++#endif ++ NULL ++}; ++ ++static ssize_t show_byte(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ return (attr->index == PSU_PMBUS_REVISION) ? sprintf(buf, "%d\n", data->pmbus_revision) : ++ sprintf(buf, "0\n"); ++} ++ ++static ssize_t show_word(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ u16 status = 0; ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ switch (attr->index) { ++ case PSU_POWER_ON: /* psu_power_on, low byte bit 6 of status_word, 0=>ON, 1=>OFF */ ++ status = (data->status_word & 0x40) ? 0 : 1; ++ break; ++ case PSU_TEMP_FAULT: /* psu_temp_fault, low byte bit 2 of status_word, 0=>Normal, 1=>temp fault */ ++ status = (data->status_word & 0x4) >> 2; ++ break; ++ case PSU_POWER_GOOD: /* psu_power_good, high byte bit 3 of status_word, 0=>OK, 1=>FAIL */ ++ status = (data->status_word & 0x800) ? 0 : 1; ++ break; ++ } ++ ++ return sprintf(buf, "%d\n", status); ++} ++ ++static int two_complement_to_int(u16 data, u8 valid_bit, int mask) ++{ ++ u16 valid_data = data & mask; ++ bool is_negative = valid_data >> (valid_bit - 1); ++ ++ return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; ++} ++ ++static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct i2c_client *client = to_i2c_client(dev); ++ struct ym2651y_data *data = i2c_get_clientdata(client); ++ int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; ++ long speed; ++ int error; ++ ++ error = kstrtol(buf, 10, &speed); ++ if (error) ++ return error; ++ ++ if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) ++ return -EINVAL; ++ ++ mutex_lock(&data->update_lock); ++ data->fan_duty_cycle[nr] = speed; ++ ym2651y_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); ++ mutex_unlock(&data->update_lock); ++ ++ return count; ++} ++ ++static ssize_t show_linear(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ ++ u16 value = 0; ++ int exponent, mantissa; ++ int multiplier = 1000; ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ switch (attr->index) { ++ case PSU_V_OUT: ++ value = data->v_out; ++ break; ++ case PSU_I_OUT: ++ value = data->i_out; ++ break; ++ case PSU_P_OUT: ++ value = data->p_out; ++ break; ++ case PSU_TEMP1_INPUT: ++ value = data->temp; ++ break; ++ case PSU_FAN1_SPEED: ++ value = data->fan_speed; ++ multiplier = 1; ++ break; ++ case PSU_FAN1_DUTY_CYCLE: ++ value = data->fan_duty_cycle[0]; ++ multiplier = 1; ++ break; ++ case PSU_MFR_VIN_MIN: ++ value = data->mfr_vin_min; ++ break; ++ case PSU_MFR_VIN_MAX: ++ value = data->mfr_vin_max; ++ break; ++ case PSU_MFR_VOUT_MIN: ++ value = data->mfr_vout_min; ++ break; ++ case PSU_MFR_VOUT_MAX: ++ value = data->mfr_vout_max; ++ break; ++ case PSU_MFR_PIN_MAX: ++ value = data->mfr_pin_max; ++ break; ++ case PSU_MFR_POUT_MAX: ++ value = data->mfr_pout_max; ++ break; ++ case PSU_MFR_IOUT_MAX: ++ value = data->mfr_iout_max; ++ break; ++ case PSU_MFR_IIN_MAX: ++ value = data->mfr_iin_max; ++ break; ++ } ++ ++ exponent = two_complement_to_int(value >> 11, 5, 0x1f); ++ mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); ++ ++ return (exponent >= 0) ? sprintf(buf, "%d\n", (mantissa << exponent) * multiplier) : ++ sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); ++} ++ ++static ssize_t show_fan_fault(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ ++ u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ return sprintf(buf, "%d\n", data->fan_fault >> shift); ++} ++ ++static ssize_t show_over_temp(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ return sprintf(buf, "%d\n", data->over_temp >> 7); ++} ++ ++#if USE_I2C_BLOCK_READ ++static ssize_t show_ascii(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct ym2651y_data *data = ym2651y_update_device(dev); ++ u8 *ptr = NULL; ++ ++ if (!data->valid) { ++ return 0; ++ } ++ ++ switch (attr->index) { ++ case PSU_FAN_DIRECTION: /* psu_fan_dir */ ++ ptr = data->fan_dir; ++ break; ++ case PSU_MFR_ID: /* psu_mfr_id */ ++ ptr = data->mfr_id; ++ break; ++ case PSU_MFR_MODEL: /* psu_mfr_model */ ++ ptr = data->mfr_model; ++ break; ++ case PSU_MFR_REVISION: /* psu_mfr_revision */ ++ ptr = data->mfr_revsion; ++ break; ++ default: ++ return 0; ++ } ++ ++ return sprintf(buf, "%s\n", ptr); ++} ++#endif ++ ++static const struct attribute_group ym2651y_group = { ++ .attrs = ym2651y_attributes, ++}; ++ ++static int ym2651y_probe(struct i2c_client *client, ++ const struct i2c_device_id *dev_id) ++{ ++ struct ym2651y_data *data; ++ int status; ++ ++ if (!i2c_check_functionality(client->adapter, I2C_FUNCTION)) { ++ status = -EIO; ++ goto exit; ++ } ++ ++ data = kzalloc(sizeof(struct ym2651y_data), GFP_KERNEL); ++ if (!data) { ++ status = -ENOMEM; ++ goto exit; ++ } ++ ++ i2c_set_clientdata(client, data); ++ mutex_init(&data->update_lock); ++ ++ dev_info(&client->dev, "chip found\n"); ++ ++ /* Register sysfs hooks */ ++ status = sysfs_create_group(&client->dev.kobj, &ym2651y_group); ++ if (status) { ++ goto exit_free; ++ } ++ ++ data->hwmon_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ status = PTR_ERR(data->hwmon_dev); ++ goto exit_remove; ++ } ++ ++ dev_info(&client->dev, "%s: psu '%s'\n", ++ dev_name(data->hwmon_dev), client->name); ++ ++ return 0; ++ ++exit_remove: ++ sysfs_remove_group(&client->dev.kobj, &ym2651y_group); ++exit_free: ++ kfree(data); ++exit: ++ ++ return status; ++} ++ ++static int ym2651y_remove(struct i2c_client *client) ++{ ++ struct ym2651y_data *data = i2c_get_clientdata(client); ++ ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &ym2651y_group); ++ kfree(data); ++ ++ return 0; ++} ++ ++static const struct i2c_device_id ym2651y_id[] = { ++ { "ym2651", 0 }, ++ { "ym1921", 1 }, ++ {} ++}; ++MODULE_DEVICE_TABLE(i2c, ym2651y_id); ++ ++static struct i2c_driver ym2651y_driver = { ++ .class = I2C_CLASS_HWMON, ++ .driver = { ++ .name = "ym2651", ++ }, ++ .probe = ym2651y_probe, ++ .remove = ym2651y_remove, ++ .id_table = ym2651y_id, ++ .address_list = normal_i2c, ++}; ++ ++static int ym2651y_read_byte(struct i2c_client *client, u8 reg) ++{ ++ return i2c_smbus_read_byte_data(client, reg); ++} ++ ++static int ym2651y_read_word(struct i2c_client *client, u8 reg) ++{ ++ return i2c_smbus_read_word_data(client, reg); ++} ++ ++static int ym2651y_write_word(struct i2c_client *client, u8 reg, u16 value) ++{ ++ return i2c_smbus_write_word_data(client, reg, value); ++} ++ ++#if USE_I2C_BLOCK_READ ++static int ym2651y_read_block(struct i2c_client *client, u8 command, u8 *data, ++ int data_len) ++{ ++ int result = i2c_smbus_read_i2c_block_data(client, command, data_len, data); ++ ++ if (unlikely(result < 0)) ++ goto abort; ++ if (unlikely(result != data_len)) { ++ result = -EIO; ++ goto abort; ++ } ++ ++ result = 0; ++ ++abort: ++ return result; ++} ++#endif ++ ++struct reg_data_byte { ++ u8 reg; ++ u8 *value; ++}; ++ ++struct reg_data_word { ++ u8 reg; ++ u16 *value; ++}; ++ ++static struct ym2651y_data *ym2651y_update_device(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct ym2651y_data *data = i2c_get_clientdata(client); ++ ++ mutex_lock(&data->update_lock); ++ ++ if (time_after(jiffies, data->last_updated + HZ + HZ / 2) ++ || !data->valid) { ++ int i, status; ++ u8 command; ++ u8 fan_dir[5] = {0}; ++ struct reg_data_byte regs_byte[] = { {0x19, &data->capability}, ++ {0x7d, &data->over_temp}, ++ {0x81, &data->fan_fault}, ++ {0x98, &data->pmbus_revision}}; ++ struct reg_data_word regs_word[] = { {0x79, &data->status_word}, ++ {0x8b, &data->v_out}, ++ {0x8c, &data->i_out}, ++ {0x96, &data->p_out}, ++ {0x8d, &data->temp}, ++ {0x3b, &(data->fan_duty_cycle[0])}, ++ {0x3c, &(data->fan_duty_cycle[1])}, ++ {0x90, &data->fan_speed}, ++ {0xa0, &data->mfr_vin_min}, ++ {0xa1, &data->mfr_vin_max}, ++ {0xa2, &data->mfr_iin_max}, ++ {0xa3, &data->mfr_pin_max}, ++ {0xa4, &data->mfr_vout_min}, ++ {0xa5, &data->mfr_vout_max}, ++ {0xa6, &data->mfr_iout_max}, ++ {0xa7, &data->mfr_pout_max}}; ++ ++ dev_dbg(&client->dev, "Starting ym2651 update\n"); ++ data->valid = 0; ++ ++ /* Read byte data */ ++ for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { ++ status = ym2651y_read_byte(client, regs_byte[i].reg); ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", regs_byte[i].reg, status); ++ goto exit; ++ } ++ else { ++ *(regs_byte[i].value) = status; ++ } ++ } ++ ++ /* Read word data */ ++ for (i = 0; i < ARRAY_SIZE(regs_word); i++) { ++ status = ym2651y_read_word(client, regs_word[i].reg); ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", regs_word[i].reg, status); ++ goto exit; ++ } ++ else { ++ *(regs_word[i].value) = status; ++ } ++ } ++ ++#if USE_I2C_BLOCK_READ ++ /* Read fan_direction */ ++ command = 0xC3; ++ status = ym2651y_read_block(client, command, fan_dir, ARRAY_SIZE(fan_dir)-1); ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", command, status); ++ goto exit; ++ } ++ ++ strncpy(data->fan_dir, fan_dir+1, ARRAY_SIZE(data->fan_dir)-1); ++ data->fan_dir[ARRAY_SIZE(data->fan_dir)-1] = '\0'; ++ ++ /* Read mfr_id */ ++ command = 0x99; ++ status = ym2651y_read_block(client, command, data->mfr_id, ++ ARRAY_SIZE(data->mfr_id)-1); ++ data->mfr_id[ARRAY_SIZE(data->mfr_id)-1] = '\0'; ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", command, status); ++ goto exit; ++ } ++ ++ /* Read mfr_model */ ++ command = 0x9a; ++ status = ym2651y_read_block(client, command, data->mfr_model, ++ ARRAY_SIZE(data->mfr_model)-1); ++ data->mfr_model[ARRAY_SIZE(data->mfr_model)-1] = '\0'; ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", command, status); ++ goto exit; ++ } ++ ++ /* Read mfr_revsion */ ++ command = 0x9b; ++ status = ym2651y_read_block(client, command, data->mfr_revsion, ++ ARRAY_SIZE(data->mfr_revsion)-1); ++ data->mfr_revsion[ARRAY_SIZE(data->mfr_revsion)-1] = '\0'; ++ ++ if (status < 0) { ++ dev_dbg(&client->dev, "reg %d, err %d\n", command, status); ++ goto exit; ++ } ++#endif ++ ++ data->last_updated = jiffies; ++ data->valid = 1; ++ } ++ ++exit: ++ mutex_unlock(&data->update_lock); ++ ++ return data; ++} ++ ++static int __init ym2651y_init(void) ++{ ++ return i2c_add_driver(&ym2651y_driver); ++} ++ ++static void __exit ym2651y_exit(void) ++{ ++ i2c_del_driver(&ym2651y_driver); ++} ++ ++MODULE_AUTHOR("Brandon Chuang "); ++MODULE_DESCRIPTION("3Y Power YM-2651Y driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(ym2651y_init); ++module_exit(ym2651y_exit); ++ +diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig +index ff203a4..97d4d54 100644 +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -387,6 +387,13 @@ config LEDS_RENESAS_TPU + pin function. The latter to support brightness control. + Brightness control is supported but hardware blinking is not. + ++config LEDS_ACCTON_AS4610 ++ tristate "LED support for the Accton as4610" ++ depends on LEDS_CLASS && SENSORS_ACCTON_I2C_CPLD ++ help ++ This option enables support for the LEDs on the Accton as4610. ++ Say Y to enable LEDs on the Accton as4610. ++ + config LEDS_TRIGGERS + bool "LED Trigger support" + depends on LEDS_CLASS +diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile +index e4f6bf5..db2dab8 100644 +--- a/drivers/leds/Makefile ++++ b/drivers/leds/Makefile +@@ -43,6 +43,7 @@ obj-$(CONFIG_LEDS_NS2) += leds-ns2.o + obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o + obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o + obj-$(CONFIG_LEDS_RENESAS_TPU) += leds-renesas-tpu.o ++obj-$(CONFIG_LEDS_ACCTON_AS4610) += leds-accton_as4610.o + + # LED SPI Drivers + 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..6f20735 +--- /dev/null ++++ b/drivers/leds/leds-accton_as4610.c +@@ -0,0 +1,719 @@ ++/* ++ * A LED driver for the accton_as4610_led ++ * ++ * Copyright (C) 2016 Accton Technology Corporation. ++ * Brandon Chuang ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++/*#define DEBUG*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#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 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 "as4610_led" ++ ++struct as4610_led_data { ++ struct platform_device *pdev; ++ struct mutex update_lock; ++ char valid; /* != 0 if registers are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ u8 num_of_led; ++ u8 reg_val[5]; /* Register value, 0 = (0x1A) Blinking function ++ 1 = (0x30) 7-seg 2 ++ 2 = (0x31) 7-seg 1 ++ 3 = (0x32) SYS/PRI/PSU1-2 LED ++ 4 = (0x33) STK1-2/Fan/PoE LED */ ++}; ++ ++static struct as4610_led_data *ledctl = NULL; ++ ++/* LED related data ++ */ ++#define LED_7SEG_REG_MASK 0x0F ++#define LED_7SEG_POINT_REG_MASK 0x10 ++ ++#define LED_NORMAL_MASK 0x03 ++#define LED_NORMAL_GREEN_VALUE 0x02 ++#define LED_NORMAL_AMBER_VALUE 0x01 ++#define LED_NORMAL_OFF_VALUE 0x00 ++ ++#define LED_TYPE_SYS_REG_MASK 0xC0 ++#define LED_MODE_SYS_GREEN_MASK 0x80 ++#define LED_MODE_SYS_AMBER_MASK 0x40 ++#define LED_MODE_SYS_OFF_MASK 0x00 ++#define LED_MODE_SYS_BLINK_MASK 0x80 ++ ++#define LED_TYPE_PRI_REG_MASK 0x30 ++#define LED_MODE_PRI_GREEN_MASK 0x20 ++#define LED_MODE_PRI_AMBER_MASK 0x10 ++#define LED_MODE_PRI_OFF_MASK 0x00 ++#define LED_MODE_PRI_BLINK_MASK 0x40 ++ ++#define LED_TYPE_PSU1_REG_MASK 0x0C ++#define LED_MODE_PSU1_BLINK_MASK 0x20 ++ ++#define LED_TYPE_PSU2_REG_MASK 0x03 ++#define LED_MODE_PSU2_BLINK_MASK 0x10 ++ ++#define LED_TYPE_STK1_REG_MASK 0xC0 ++#define LED_MODE_STK1_GREEN_MASK 0x80 ++#define LED_MODE_STK1_AMBER_MASK 0x40 ++#define LED_MODE_STK1_OFF_MASK 0x00 ++#define LED_MODE_STK1_BLINK_MASK 0x08 ++ ++#define LED_TYPE_STK2_REG_MASK 0x30 ++#define LED_MODE_STK2_GREEN_MASK 0x20 ++#define LED_MODE_STK2_AMBER_MASK 0x10 ++#define LED_MODE_STK2_OFF_MASK 0x00 ++#define LED_MODE_STK2_BLINK_MASK 0x04 ++ ++#define LED_TYPE_FAN_REG_MASK 0x0C ++#define LED_MODE_FAN_BLINK_MASK 0x02 ++ ++#define LED_TYPE_POE_REG_MASK 0x03 ++#define LED_MODE_POE_GREEN_MASK 0x02 ++#define LED_MODE_POE_AMBER_MASK 0x01 ++#define LED_MODE_POE_OFF_MASK 0x00 ++#define LED_MODE_POE_BLINK_MASK 0x01 ++ ++static const u8 led_reg[] = { ++ 0x1A, /* Blinking function */ ++ 0x30, /* 7-seg 1 */ ++ 0x31, /* 7-seg 2 */ ++ 0x32, /* SYS/PRI/PSU1-2 LED */ ++ 0x33, /* STK1-2/Fan/PoE LED */ ++}; ++ ++enum led_type { ++ LED_TYPE_SYS, ++ LED_TYPE_PRI, ++ LED_TYPE_PSU1, ++ LED_TYPE_PSU2, ++ LED_TYPE_STK1, ++ LED_TYPE_STK2, ++ LED_TYPE_7SEG_TENS, ++ LED_TYPE_7SEG_TENS_POINT, ++ LED_TYPE_7SEG_DIGITS, ++ LED_TYPE_7SEG_DIGITS_POINT, ++ LED_TYPE_FAN, ++ LED_TYPE_POE ++}; ++ ++enum led_light_mode { ++ LED_MODE_OFF = 0, ++ LED_MODE_GREEN, ++ LED_MODE_GREEN_BLINK, ++ LED_MODE_AMBER, ++ LED_MODE_AMBER_BLINK, ++ LED_MODE_RED, ++ LED_MODE_RED_BLINK, ++ LED_MODE_BLUE, ++ LED_MODE_BLUE_BLINK, ++ LED_MODE_AUTO, ++ LED_MODE_AUTO_BLINKING, ++ LED_MODE_UNKNOWN, ++ LED_MODE_SEVEN_SEGMENT_MAX = 9, ++}; ++ ++static int as4610_led_read_value(u8 reg) ++{ ++ return accton_i2c_cpld_read(0x30, reg); ++} ++ ++static int as4610_led_write_value(u8 reg, u8 value) ++{ ++ return accton_i2c_cpld_write(0x30, reg, value); ++} ++ ++static void as4610_led_update(void) ++{ ++ mutex_lock(&ledctl->update_lock); ++ ++ if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) ++ || !ledctl->valid) { ++ int i; ++ ++ dev_dbg(&ledctl->pdev->dev, "Starting as4610_led update\n"); ++ ++ /* Update LED data ++ */ ++ for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { ++ int status = as4610_led_read_value(led_reg[i]); ++ ++ if (status < 0) { ++ ledctl->valid = 0; ++ dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg[i], status); ++ goto exit; ++ } ++ else ++ { ++ ledctl->reg_val[i] = status; ++ } ++ } ++ ++ ledctl->last_updated = jiffies; ++ ledctl->valid = 1; ++ } ++ ++exit: ++ mutex_unlock(&ledctl->update_lock); ++} ++ ++static enum led_brightness seven_segment_get(struct led_classdev *cdev, u8 reg_id) ++{ ++ as4610_led_update(); ++ return (ledctl->reg_val[reg_id] & LED_7SEG_REG_MASK); ++#if 0 ++ as4610_led_update(); ++ ++ return (ledctl->reg_val[2] & LED_7SEG_REG_MASK) * 10 + ++ (ledctl->reg_val[1] & LED_7SEG_REG_MASK); ++#endif ++} ++ ++static void seven_segment_set(struct led_classdev *cdev, enum led_brightness mode, u8 reg_id) ++{ ++ if (mode > cdev->max_brightness) { ++ return; ++ } ++ ++ ledctl->reg_val[reg_id] &= 0xF0; ++ ledctl->reg_val[reg_id] |= mode; ++ as4610_led_write_value(led_reg[reg_id], ledctl->reg_val[reg_id]); ++ ++#if 0 ++ u8 digits, tens; ++ ++ if (mode > LED_MODE_SEVEN_SEGMENT_MAX) { ++ return; ++ } ++ ++ digits = mode % 10; ++ tens = mode / 10; ++ ledctl->reg_val[1] &= 0xF0; ++ ledctl->reg_val[1] |= digits; ++ ledctl->reg_val[2] &= 0xF0; ++ ledctl->reg_val[2] |= tens; ++ as4610_led_write_value(led_reg[1], ledctl->reg_val[1]); ++ as4610_led_write_value(led_reg[2], ledctl->reg_val[2]); ++#endif ++} ++ ++static enum led_brightness seven_segment_digits_get(struct led_classdev *cdev) ++{ ++ return seven_segment_get(cdev, 1); ++} ++ ++static void seven_segment_digits_set(struct led_classdev *cdev, enum led_brightness mode) ++{ ++ seven_segment_set(cdev, mode, 1); ++} ++ ++static enum led_brightness seven_segment_tens_get(struct led_classdev *cdev) ++{ ++ return seven_segment_get(cdev, 2); ++} ++ ++static void seven_segment_tens_set(struct led_classdev *cdev, enum led_brightness mode) ++{ ++ seven_segment_set(cdev, mode, 2); ++} ++ ++static enum led_brightness seven_segment_point_get(struct led_classdev *cdev, u8 reg_id) ++{ ++ as4610_led_update(); ++ return (ledctl->reg_val[reg_id] & LED_7SEG_POINT_REG_MASK) ? LED_MODE_GREEN : LED_MODE_OFF; ++} ++ ++static void seven_segment_point_set(struct led_classdev *cdev, ++ enum led_brightness mode, u8 reg_id) ++{ ++ /* Validate brightness */ ++ if ((int)mode < LED_MODE_OFF || mode > cdev->max_brightness) { ++ return; ++ } ++ ++ if ((int)mode == (int)LED_MODE_OFF) { ++ ledctl->reg_val[reg_id] &= ~LED_7SEG_POINT_REG_MASK; ++ } ++ else { /* LED_MODE_GREEN */ ++ ledctl->reg_val[reg_id] |= LED_7SEG_POINT_REG_MASK; ++ } ++ ++ as4610_led_write_value(led_reg[reg_id], ledctl->reg_val[reg_id]); ++} ++ ++static enum led_brightness seven_segment_tens_point_get(struct led_classdev *cdev) ++{ ++ return seven_segment_point_get(cdev, 2); ++} ++ ++static void seven_segment_tens_point_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ seven_segment_point_set(cdev, mode, 2); ++} ++ ++static enum led_brightness seven_segment_digits_point_get(struct led_classdev *cdev) ++{ ++ return seven_segment_point_get(cdev, 1); ++} ++ ++static void seven_segment_digits_point_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ seven_segment_point_set(cdev, mode, 1); ++} ++ ++static u8 led_is_blinking_mode(enum led_brightness mode) ++{ ++ return ((int)mode == (int)LED_MODE_GREEN_BLINK || ++ (int)mode == (int)LED_MODE_AMBER_BLINK || ++ (int)mode == (int)LED_MODE_AUTO_BLINKING); ++} ++ ++static enum led_brightness as4610_led_auto_get(u8 blink_mask) ++{ ++ as4610_led_update(); ++ return (ledctl->reg_val[0] & blink_mask) ? LED_MODE_AUTO_BLINKING : LED_MODE_AUTO; ++} ++ ++static void as4610_led_auto_set(struct led_classdev *cdev, ++ enum led_brightness mode, u8 blink_mask) ++{ ++ /* Validate brightness */ ++ if ((int)mode < (int)LED_MODE_AUTO || mode > cdev->max_brightness) { ++ return; ++ } ++ ++ /* Set blinking */ ++ if (led_is_blinking_mode(mode)) { ++ ledctl->reg_val[0] |= blink_mask; ++ } ++ else { ++ ledctl->reg_val[0] &= ~blink_mask; ++ } ++ as4610_led_write_value(led_reg[0], ledctl->reg_val[0]); ++} ++ ++static enum led_brightness as4610_led_psu1_get(struct led_classdev *cdev) ++{ ++ return as4610_led_auto_get(LED_MODE_PSU1_BLINK_MASK); ++} ++ ++static void as4610_led_psu1_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_auto_set(cdev, mode, LED_MODE_PSU1_BLINK_MASK); ++} ++ ++static enum led_brightness as4610_led_psu2_get(struct led_classdev *cdev) ++{ ++ return as4610_led_auto_get(LED_MODE_PSU2_BLINK_MASK); ++} ++ ++static void as4610_led_psu2_set(struct led_classdev *led_cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_auto_set(led_cdev, mode, LED_MODE_PSU2_BLINK_MASK); ++} ++ ++static enum led_brightness as4610_led_fan_get(struct led_classdev *cdev) ++{ ++ return as4610_led_auto_get(LED_MODE_FAN_BLINK_MASK); ++} ++ ++static void as4610_led_fan_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_auto_set(cdev, mode, LED_MODE_FAN_BLINK_MASK); ++} ++ ++static u8 led_normal_light_mode_to_reg_val(enum led_brightness mode) ++{ ++ if (led_is_blinking_mode(mode)) { ++ mode -= 1; /* convert blinking mode to non-blinking mode */ ++ } ++ ++ if ((int)mode == (int)LED_MODE_GREEN) { ++ return LED_NORMAL_GREEN_VALUE; ++ } ++ else if ((int)mode == (int)LED_MODE_AMBER) { ++ return LED_NORMAL_AMBER_VALUE; ++ } ++ ++ return LED_NORMAL_OFF_VALUE; ++} ++ ++static enum led_brightness led_normal_reg_val_to_light_mode(u8 reg_val) ++{ ++ reg_val &= LED_NORMAL_MASK; ++ ++ if (reg_val & LED_NORMAL_GREEN_VALUE) { ++ return LED_MODE_GREEN; ++ } ++ else if (reg_val & LED_NORMAL_AMBER_VALUE) { ++ return LED_MODE_AMBER; ++ } ++ ++ return LED_MODE_OFF; ++} ++ ++static void as4610_led_normal_set(struct led_classdev *cdev, ++ enum led_brightness mode, u8 blink_mask, u8 reg_id, u8 reg_mask, u8 shift) ++{ ++ /* Validate brightness */ ++ if (mode > cdev->max_brightness) { ++ return; ++ } ++ ++ /* Set blinking */ ++ if (led_is_blinking_mode(mode)) { ++ ledctl->reg_val[0] |= blink_mask; ++ } ++ else { ++ ledctl->reg_val[0] &= ~blink_mask; ++ } ++ as4610_led_write_value(led_reg[0], ledctl->reg_val[0]); ++ ++ /* Set color */ ++ ledctl->reg_val[reg_id] &= ~reg_mask; ++ ledctl->reg_val[reg_id] |= (led_normal_light_mode_to_reg_val(mode) << shift); ++ as4610_led_write_value(led_reg[reg_id], ledctl->reg_val[reg_id]); ++} ++ ++static enum led_brightness as4610_led_normal_get(u8 reg_id, u8 blink_mask, u8 shift) ++{ ++ u8 blinking = 0; ++ enum led_brightness mode; ++ ++ as4610_led_update(); ++ ++ mode = led_normal_reg_val_to_light_mode(ledctl->reg_val[reg_id] >> shift); ++ if ((int)mode == (int)LED_MODE_OFF) { ++ return mode; ++ } ++ ++ /* Checking blinking */ ++ if (ledctl->reg_val[0] & blink_mask) { ++ blinking = 1; ++ } ++ ++ return blinking ? (mode+1) : mode; ++} ++ ++static void as4610_led_sys_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_normal_set(cdev, mode, LED_MODE_SYS_BLINK_MASK, ++ 3, LED_TYPE_SYS_REG_MASK, 6); ++} ++ ++static enum led_brightness as4610_led_sys_get(struct led_classdev *cdev) ++{ ++ return as4610_led_normal_get(3, LED_MODE_SYS_BLINK_MASK, 6); ++} ++ ++static void as4610_led_pri_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_normal_set(cdev, mode, LED_MODE_PRI_BLINK_MASK, ++ 3, LED_TYPE_PRI_REG_MASK, 4); ++} ++ ++static enum led_brightness as4610_led_pri_get(struct led_classdev *cdev) ++{ ++ return as4610_led_normal_get(3, LED_MODE_PRI_BLINK_MASK, 4); ++} ++ ++static void as4610_led_poe_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_normal_set(cdev, mode, LED_MODE_POE_BLINK_MASK, ++ 4, LED_TYPE_POE_REG_MASK, 0); ++} ++ ++static enum led_brightness as4610_led_poe_get(struct led_classdev *cdev) ++{ ++ return as4610_led_normal_get(4, LED_MODE_POE_BLINK_MASK, 0); ++} ++ ++static void as4610_led_stk1_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_normal_set(cdev, mode, LED_MODE_STK1_BLINK_MASK, ++ 4, LED_TYPE_STK1_REG_MASK, 6); ++} ++ ++static enum led_brightness as4610_led_stk1_get(struct led_classdev *cdev) ++{ ++ return as4610_led_normal_get(4, LED_MODE_STK1_BLINK_MASK, 6); ++} ++ ++static void as4610_led_stk2_set(struct led_classdev *cdev, ++ enum led_brightness mode) ++{ ++ as4610_led_normal_set(cdev, mode, LED_MODE_STK2_BLINK_MASK, ++ 4, LED_TYPE_STK2_REG_MASK, 4); ++} ++ ++static enum led_brightness as4610_led_stk2_get(struct led_classdev *cdev) ++{ ++ return as4610_led_normal_get(4, LED_MODE_STK2_BLINK_MASK, 4); ++} ++ ++static struct led_classdev as4610_leds[] = { ++ [LED_TYPE_SYS] = { ++ .name = "as4610::sys", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_sys_set, ++ .brightness_get = as4610_led_sys_get, ++ .flags = LED_CORE_SUSPENDRESUME, ++ .max_brightness = LED_MODE_AMBER_BLINK, ++ }, ++ [LED_TYPE_PRI] = { ++ .name = "as4610::pri", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_pri_set, ++ .brightness_get = as4610_led_pri_get, ++ .flags = LED_CORE_SUSPENDRESUME, ++ .max_brightness = LED_MODE_AMBER_BLINK, ++ }, ++ [LED_TYPE_PSU1] = { ++ .name = "as4610::psu1", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_psu1_set, ++ .brightness_get = as4610_led_psu1_get, ++ .flags = LED_CORE_SUSPENDRESUME, ++ .max_brightness = LED_MODE_AUTO_BLINKING, ++ }, ++ [LED_TYPE_PSU2] = { ++ .name = "as4610::psu2", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_psu2_set, ++ .brightness_get = as4610_led_psu2_get, ++ .flags = LED_CORE_SUSPENDRESUME, ++ .max_brightness = LED_MODE_AUTO_BLINKING, ++ }, ++ [LED_TYPE_STK1] = { ++ .name = "as4610::stk1", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_stk1_set, ++ .brightness_get = as4610_led_stk1_get, ++ .flags = LED_CORE_SUSPENDRESUME, ++ .max_brightness = LED_MODE_AMBER_BLINK, ++ }, ++ [LED_TYPE_STK2] = { ++ .name = "as4610::stk2", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_stk2_set, ++ .brightness_get = as4610_led_stk2_get, ++ .flags = LED_CORE_SUSPENDRESUME, ++ .max_brightness = LED_MODE_AMBER_BLINK, ++ }, ++ [LED_TYPE_7SEG_TENS] = { ++ .name = "as4610::7seg_tens", ++ .default_trigger = "unused", ++ .brightness_set = seven_segment_tens_set, ++ .brightness_get = seven_segment_tens_get, ++ .flags = LED_CORE_SUSPENDRESUME, ++ .max_brightness = LED_MODE_SEVEN_SEGMENT_MAX, ++ }, ++ [LED_TYPE_7SEG_TENS_POINT] = { ++ .name = "as4610::7seg_tens_point", ++ .default_trigger = "unused", ++ .brightness_set = seven_segment_tens_point_set, ++ .brightness_get = seven_segment_tens_point_get, ++ .flags = LED_CORE_SUSPENDRESUME, ++ .max_brightness = LED_MODE_GREEN, ++ }, ++ [LED_TYPE_7SEG_DIGITS] = { ++ .name = "as4610::7seg_digits", ++ .default_trigger = "unused", ++ .brightness_set = seven_segment_digits_set, ++ .brightness_get = seven_segment_digits_get, ++ .flags = LED_CORE_SUSPENDRESUME, ++ .max_brightness = LED_MODE_SEVEN_SEGMENT_MAX, ++ }, ++ [LED_TYPE_7SEG_DIGITS_POINT] = { ++ .name = "as4610::7seg_digits_point", ++ .default_trigger = "unused", ++ .brightness_set = seven_segment_digits_point_set, ++ .brightness_get = seven_segment_digits_point_get, ++ .flags = LED_CORE_SUSPENDRESUME, ++ .max_brightness = LED_MODE_GREEN, ++ }, ++ [LED_TYPE_FAN] = { ++ .name = "as4610::fan", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_fan_set, ++ .brightness_get = as4610_led_fan_get, ++ .flags = LED_CORE_SUSPENDRESUME, ++ .max_brightness = LED_MODE_AUTO_BLINKING, ++ }, ++ [LED_TYPE_POE] = { ++ .name = "as4610::poe", ++ .default_trigger = "unused", ++ .brightness_set = as4610_led_poe_set, ++ .brightness_get = as4610_led_poe_get, ++ .flags = LED_CORE_SUSPENDRESUME, ++ .max_brightness = LED_MODE_AMBER_BLINK, ++ }, ++}; ++ ++static int as4610_led_suspend(struct platform_device *dev, ++ pm_message_t state) ++{ ++ int i = 0; ++ ++ for (i = 0; i < ledctl->num_of_led; i++) { ++ led_classdev_suspend(&as4610_leds[i]); ++ } ++ ++ return 0; ++} ++ ++static int as4610_led_resume(struct platform_device *dev) ++{ ++ int i = 0; ++ ++ for (i = 0; i < ledctl->num_of_led; i++) { ++ led_classdev_resume(&as4610_leds[i]); ++ } ++ ++ return 0; ++} ++ ++static int as4610_led_probe(struct platform_device *pdev) ++{ ++ int ret = 0, i; ++ ++ for (i = 0; i < ledctl->num_of_led; i++) { ++ ret = led_classdev_register(&pdev->dev, &as4610_leds[i]); ++ ++ if (ret < 0) ++ break; ++ } ++ ++ /* Check if all LEDs were successfully registered */ ++ if (i != ledctl->num_of_led){ ++ int j; ++ ++ /* only unregister the LEDs that were successfully registered */ ++ for (j = 0; j < i; j++) { ++ led_classdev_unregister(&as4610_leds[i]); ++ } ++ } ++ ++ return ret; ++} ++ ++static int as4610_led_remove(struct platform_device *pdev) ++{ ++ int i; ++ ++ for (i = 0; i < ledctl->num_of_led; i++) { ++ led_classdev_unregister(&as4610_leds[i]); ++ } ++ ++ return 0; ++} ++ ++static struct platform_driver as4610_led_driver = { ++ .probe = as4610_led_probe, ++ .remove = as4610_led_remove, ++ .suspend = as4610_led_suspend, ++ .resume = as4610_led_resume, ++ .driver = { ++ .name = DRVNAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init as4610_led_init(void) ++{ ++ int ret; ++ ++ if (as4610_product_id() == PID_UNKNOWN) { ++ return -ENODEV; ++ } ++ ++ ret = platform_driver_register(&as4610_led_driver); ++ if (ret < 0) { ++ goto exit; ++ } ++ ++ ledctl = kzalloc(sizeof(struct as4610_led_data), GFP_KERNEL); ++ if (!ledctl) { ++ ret = -ENOMEM; ++ platform_driver_unregister(&as4610_led_driver); ++ goto exit; ++ } ++ ++ if (as4610_is_poe_system()) { ++ ledctl->num_of_led = LED_TYPE_POE - LED_TYPE_SYS + 1; ++ } ++ else { ++ ledctl->num_of_led = LED_TYPE_7SEG_DIGITS_POINT - LED_TYPE_SYS + 1; ++ } ++ ++ mutex_init(&ledctl->update_lock); ++ ++ ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); ++ if (IS_ERR(ledctl->pdev)) { ++ ret = PTR_ERR(ledctl->pdev); ++ platform_driver_unregister(&as4610_led_driver); ++ kfree(ledctl); ++ goto exit; ++ } ++ ++exit: ++ return ret; ++} ++ ++static void __exit as4610_led_exit(void) ++{ ++ if (!ledctl) { ++ return; ++ } ++ ++ platform_device_unregister(ledctl->pdev); ++ platform_driver_unregister(&as4610_led_driver); ++ kfree(ledctl); ++} ++ ++late_initcall(as4610_led_init); ++module_exit(as4610_led_exit); ++ ++MODULE_AUTHOR("Brandon Chuang "); ++MODULE_DESCRIPTION("as4610_led driver"); ++MODULE_LICENSE("GPL"); ++ +diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig +index 7c7b208..1c62b33 100644 +--- a/drivers/misc/eeprom/Kconfig ++++ b/drivers/misc/eeprom/Kconfig +@@ -117,5 +117,14 @@ config EEPROM_SFF_8436 + + 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 ++ help ++ If you say yes here you get support for Accton as4610 sfp. ++ ++ This driver can also be built as a module. If so, the module will ++ be called accton_as4610_sfp. + + endmenu +diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile +index 9edd559..12f7cae 100644 +--- a/drivers/misc/eeprom/Makefile ++++ b/drivers/misc/eeprom/Makefile +@@ -7,3 +7,4 @@ obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o + 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 +new file mode 100644 +index 0000000..51488b4 +--- /dev/null ++++ b/drivers/misc/eeprom/accton_as4610_sfp.c +@@ -0,0 +1,1265 @@ ++/* ++ * SFP driver for accton as4610 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 "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 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)) { ++ 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 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 -ENODEV; ++ } ++ ++ 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) ? 1 : 0; ++ break; ++ 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_DISABLE: ++ val = (data->qsfp->status[1] & 0xF) ? 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_LOS: ++ val = (data->qsfp->status[0] & 0xF) ? 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 (attr->index == TX_DISABLE) { ++ if (disable) { ++ data->qsfp->status[1] |= 0xF; ++ } ++ else { ++ data->qsfp->status[1] &= ~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) ? 1 : 0); ++} ++ ++/* 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; ++#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 (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); ++ } ++ } ++ 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); ++ } ++ } ++ ++ 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[] = { SFP_EEPROM_A0_I2C_ADDR, SFP_EEPROM_A2_I2C_ADDR, 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 as4610_sfp driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(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..3f13209 +--- /dev/null ++++ b/include/linux/accton_i2c_cpld.h +@@ -0,0 +1,53 @@ ++/* ++ * A hwmon driver for the accton_i2c_cpld ++ * ++ * Copyright (C) 2016 Accton Technology Corporation. ++ * Brandon Chuang ++ * ++ * 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. ++ */ ++ ++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); ++ ++#define AS4610_CPLD_SLAVE_ADDR 0x30 ++#define AS4610_CPLD_PID_OFFSET 0x01 /* Product ID offset */ ++ ++enum as4610_product_id_e { ++ PID_AS4610_30T, ++ PID_AS4610_30P, ++ PID_AS4610_54T, ++ PID_AS4610_54P, ++ PID_UNKNOWN ++}; ++ ++static inline int as4610_product_id(void) ++{ ++ int pid = accton_i2c_cpld_read(AS4610_CPLD_SLAVE_ADDR, AS4610_CPLD_PID_OFFSET); ++ pid &= 0xF; ++ return (pid < PID_AS4610_30T || pid > PID_AS4610_54P) ? PID_UNKNOWN : pid; ++} ++ ++static inline int as4610_is_poe_system(void) ++{ ++ int pid = as4610_product_id(); ++ return (pid == PID_AS4610_30P || pid == PID_AS4610_54P); ++} ++ ++static inline int as4610_number_of_system_fan(void) ++{ ++ return as4610_is_poe_system() ? 1 : 0; ++} ++ + diff --git a/packages/base/any/kernels/3.2.71-1+deb7/patches/series b/packages/base/any/kernels/3.2.71-1+deb7/patches/series index 4ba1b885..f0567595 100644 --- a/packages/base/any/kernels/3.2.71-1+deb7/patches/series +++ b/packages/base/any/kernels/3.2.71-1+deb7/patches/series @@ -1,2 +1,3 @@ prepare.sh kernel-3.2.71.patch +platform-accton-as4610-device-drivers.patch diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/lib/arm_accton_as4610_54.mk b/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/lib/arm_accton_as4610_54.mk deleted file mode 100644 index fb559c69..00000000 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/lib/arm_accton_as4610_54.mk +++ /dev/null @@ -1,10 +0,0 @@ - -############################################################################### -# -# Inclusive Makefile for the arm_accton_as4610_54 module. -# -# Autogenerated 2016-04-03 19:55:05.384384 -# -############################################################################### -arm_accton_as4610_54_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) - diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/.gitignore b/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/.gitignore deleted file mode 100644 index 1c192e04..00000000 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/arm_accton_as4610_54.mk -/doc diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/.module b/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/.module deleted file mode 100644 index 5d4aa1c0..00000000 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/.module +++ /dev/null @@ -1 +0,0 @@ -name: arm_accton_as4610_54 diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_config.c b/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_config.c deleted file mode 100644 index 0d133448..00000000 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_config.c +++ /dev/null @@ -1,101 +0,0 @@ -/************************************************************ - * - * - * Copyright 2014, 2015 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 - -/* */ -#define __arm_accton_as4610_54_config_STRINGIFY_NAME(_x) #_x -#define __arm_accton_as4610_54_config_STRINGIFY_VALUE(_x) __arm_accton_as4610_54_config_STRINGIFY_NAME(_x) -arm_accton_as4610_54_config_settings_t arm_accton_as4610_54_config_settings[] = -{ -#ifdef ONLPSIM_CONFIG_INCLUDE_LOGGING - { __arm_accton_as4610_54_config_STRINGIFY_NAME(ONLPSIM_CONFIG_INCLUDE_LOGGING), __arm_accton_as4610_54_config_STRINGIFY_VALUE(ONLPSIM_CONFIG_INCLUDE_LOGGING) }, -#else -{ ONLPSIM_CONFIG_INCLUDE_LOGGING(__arm_accton_as4610_54_config_STRINGIFY_NAME), "__undefined__" }, -#endif -#ifdef ONLPSIM_CONFIG_LOG_OPTIONS_DEFAULT - { __arm_accton_as4610_54_config_STRINGIFY_NAME(ONLPSIM_CONFIG_LOG_OPTIONS_DEFAULT), __arm_accton_as4610_54_config_STRINGIFY_VALUE(ONLPSIM_CONFIG_LOG_OPTIONS_DEFAULT) }, -#else -{ ONLPSIM_CONFIG_LOG_OPTIONS_DEFAULT(__arm_accton_as4610_54_config_STRINGIFY_NAME), "__undefined__" }, -#endif -#ifdef ONLPSIM_CONFIG_LOG_BITS_DEFAULT - { __arm_accton_as4610_54_config_STRINGIFY_NAME(ONLPSIM_CONFIG_LOG_BITS_DEFAULT), __arm_accton_as4610_54_config_STRINGIFY_VALUE(ONLPSIM_CONFIG_LOG_BITS_DEFAULT) }, -#else -{ ONLPSIM_CONFIG_LOG_BITS_DEFAULT(__arm_accton_as4610_54_config_STRINGIFY_NAME), "__undefined__" }, -#endif -#ifdef ONLPSIM_CONFIG_LOG_CUSTOM_BITS_DEFAULT - { __arm_accton_as4610_54_config_STRINGIFY_NAME(ONLPSIM_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __arm_accton_as4610_54_config_STRINGIFY_VALUE(ONLPSIM_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, -#else -{ ONLPSIM_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__arm_accton_as4610_54_config_STRINGIFY_NAME), "__undefined__" }, -#endif -#ifdef ONLPSIM_CONFIG_PORTING_STDLIB - { __arm_accton_as4610_54_config_STRINGIFY_NAME(ONLPSIM_CONFIG_PORTING_STDLIB), __arm_accton_as4610_54_config_STRINGIFY_VALUE(ONLPSIM_CONFIG_PORTING_STDLIB) }, -#else -{ ONLPSIM_CONFIG_PORTING_STDLIB(__arm_accton_as4610_54_config_STRINGIFY_NAME), "__undefined__" }, -#endif -#ifdef ONLPSIM_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS - { __arm_accton_as4610_54_config_STRINGIFY_NAME(ONLPSIM_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __arm_accton_as4610_54_config_STRINGIFY_VALUE(ONLPSIM_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, -#else -{ ONLPSIM_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__arm_accton_as4610_54_config_STRINGIFY_NAME), "__undefined__" }, -#endif -#ifdef ONLPSIM_CONFIG_INCLUDE_UCLI - { __arm_accton_as4610_54_config_STRINGIFY_NAME(ONLPSIM_CONFIG_INCLUDE_UCLI), __arm_accton_as4610_54_config_STRINGIFY_VALUE(ONLPSIM_CONFIG_INCLUDE_UCLI) }, -#else -{ ONLPSIM_CONFIG_INCLUDE_UCLI(__arm_accton_as4610_54_config_STRINGIFY_NAME), "__undefined__" }, -#endif -#ifdef ONLPSIM_CONFIG_SFP_COUNT - { __arm_accton_as4610_54_config_STRINGIFY_NAME(ONLPSIM_CONFIG_SFP_COUNT), __arm_accton_as4610_54_config_STRINGIFY_VALUE(ONLPSIM_CONFIG_SFP_COUNT) }, -#else -{ ONLPSIM_CONFIG_SFP_COUNT(__arm_accton_as4610_54_config_STRINGIFY_NAME), "__undefined__" }, -#endif - { NULL, NULL } -}; -#undef __arm_accton_as4610_54_config_STRINGIFY_VALUE -#undef __arm_accton_as4610_54_config_STRINGIFY_NAME - -const char* -arm_accton_as4610_54_config_lookup(const char* setting) -{ - int i; - for(i = 0; arm_accton_as4610_54_config_settings[i].name; i++) { - if(strcmp(arm_accton_as4610_54_config_settings[i].name, setting)) { - return arm_accton_as4610_54_config_settings[i].value; - } - } - return NULL; -} - -int -arm_accton_as4610_54_config_show(struct aim_pvs_s* pvs) -{ - int i; - for(i = 0; arm_accton_as4610_54_config_settings[i].name; i++) { - aim_printf(pvs, "%s = %s\n", arm_accton_as4610_54_config_settings[i].name, arm_accton_as4610_54_config_settings[i].value); - } - return i; -} - -/* */ - diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/fani.c b/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/fani.c deleted file mode 100644 index 5cfc57c3..00000000 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/fani.c +++ /dev/null @@ -1,35 +0,0 @@ -/************************************************************ - * - * - * Copyright 2014, 2015 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. - * - * - ************************************************************ - * - * Fan Platform Implementation Defaults. - * - ***********************************************************/ -#include -#include "arm_accton_as4610_54_int.h" - -/* - * This function will be called prior to all of onlp_fani_* functions. - */ -int -onlp_fani_init(void) -{ - return ONLP_STATUS_OK; -} diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/ledi.c b/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/ledi.c deleted file mode 100644 index 3a405318..00000000 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/ledi.c +++ /dev/null @@ -1,31 +0,0 @@ -/************************************************************ - * - * - * Copyright 2014, 2015 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 "arm_accton_as4610_54_int.h" - -int -onlp_ledi_init(void) -{ - return ONLP_STATUS_OK; -} diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/psui.c b/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/psui.c deleted file mode 100644 index 7668d031..00000000 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/psui.c +++ /dev/null @@ -1,32 +0,0 @@ -/************************************************************ - * - * - * Copyright 2014, 2015 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 "arm_accton_as4610_54_int.h" - -int -onlp_psui_init(void) -{ - return ONLP_STATUS_OK; -} diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/sfpi.c b/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/sfpi.c deleted file mode 100644 index ca1a421d..00000000 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/sfpi.c +++ /dev/null @@ -1,76 +0,0 @@ -/************************************************************ - * - * - * Copyright 2014, 2015 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 "arm_accton_as4610_54_log.h" - -static int sfp_count__ = ONLPSIM_CONFIG_SFP_COUNT; - -int -onlp_sfpi_init(void) -{ - return ONLP_STATUS_OK; -} - -int -onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) -{ - int p; - for(p = 0; p < sfp_count__; p++) { - AIM_BITMAP_SET(bmap, p); - } - return ONLP_STATUS_OK; -} - -int -onlp_sfpi_is_present(int port) -{ - return 0; -} - -int -onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) -{ - AIM_BITMAP_CLR_ALL(dst); - 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]) -{ - return ONLP_STATUS_E_MISSING; -} - -/* - * De-initialize the SFPI subsystem. - */ -int -onlp_sfpi_denit(void) -{ - return ONLP_STATUS_OK; -} diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/sysi.c b/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/sysi.c deleted file mode 100644 index 0a89b596..00000000 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/sysi.c +++ /dev/null @@ -1,77 +0,0 @@ -/************************************************************ - * - * - * Copyright 2014, 2015 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 "arm_accton_as4610_54_log.h" -#include - - -const char* -onlp_sysi_platform_get(void) -{ - return "arm-accton-as4610-54-r0"; -} - -int -onlp_sysi_init(void) -{ - return ONLP_STATUS_OK; -} - -int -onlp_sysi_onie_data_get(uint8_t** data, int* size) -{ -#define IDPROM_PATH "/sys/devices/1803b000.i2c/i2c-1/i2c-9/9-0050/eeprom" - - 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; - } - } - aim_free(rdata); - *size = 0; - return ONLP_STATUS_E_INTERNAL; -} - -void -onlp_sysi_onie_data_free(uint8_t* data) -{ - aim_free(data); -} - -void -onlp_sysi_platform_manage(void) -{ -} - -int -onlp_sysi_oids_get(onlp_oid_t* table, int max) -{ - memset(table, 0, max*sizeof(onlp_oid_t)); - return 0; -} diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/thermali.c b/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/thermali.c deleted file mode 100644 index 02f0593b..00000000 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/thermali.c +++ /dev/null @@ -1,32 +0,0 @@ -/************************************************************ - * - * - * Copyright 2014, 2015 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. - * - * - ************************************************************ - * - * Thermal Sensor Platform Implementation. - * - ***********************************************************/ -#include -#include "arm_accton_as4610_54_log.h" - -int -onlp_thermali_init(void) -{ - return ONLP_STATUS_OK; -} diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/.gitignore b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/.gitignore similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610-54/.gitignore rename to packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/.gitignore diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/Makefile similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610-54/Makefile rename to packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/Makefile diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/onlp/Makefile similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/Makefile rename to packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/onlp/Makefile diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/onlp/PKG.yml b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/onlp/PKG.yml new file mode 100644 index 00000000..2c50976c --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=arm-accton-as4610-30 ARCH=armel TOOLCHAIN=arm-linux-gnueabi diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/Makefile similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/Makefile rename to packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/Makefile diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/lib/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/lib/Makefile new file mode 100644 index 00000000..3405739a --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/lib/Makefile @@ -0,0 +1,44 @@ +############################################################ +# +# +# 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.armel.mk + +MODULE := libonlp-arm-accton-as4610-30 +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF arm_accton_as4610 onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-arm-accton-as4610-30.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/accton/armel/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/lib/libonlp-arm-accton-as4610-30.mk b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/lib/libonlp-arm-accton-as4610-30.mk new file mode 100644 index 00000000..3c9f70fa --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/lib/libonlp-arm-accton-as4610-30.mk @@ -0,0 +1,10 @@ + +############################################################################### +# +# Inclusive Makefile for the libonlp-arm-accton-as4610-30 module. +# +# Autogenerated 2016-07-20 18:29:31.706331 +# +############################################################################### +libonlp-arm-accton-as4610-30_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/onlpdump/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/onlpdump/Makefile similarity index 91% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/onlpdump/Makefile rename to packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/onlpdump/Makefile index 10450f8c..f6a0f5dc 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/onlpdump/Makefile +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/onlp/builds/onlpdump/Makefile @@ -29,7 +29,7 @@ include $(ONL)/make/config.armel.mk MODULE := onlpdump include $(BUILDER)/standardinit.mk -DEPENDMODULES := AIM IOF onlp arm_accton_as4610_54 onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS +DEPENDMODULES := AIM IOF onlp arm_accton_as4610 onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS include $(BUILDER)/dependmodules.mk diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/platform-config/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/Makefile similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610-54/platform-config/Makefile rename to packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/Makefile diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/platform-config/r0/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/Makefile similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610-54/platform-config/r0/Makefile rename to packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/Makefile diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/PKG.yml b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/PKG.yml new file mode 100644 index 00000000..e1444152 --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=armel VENDOR=accton PLATFORM=arm-accton-as4610-30-r0 diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/lib/arm-accton-as4610-30-r0.yml b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/lib/arm-accton-as4610-30-r0.yml new file mode 100644 index 00000000..64507ab6 --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/lib/arm-accton-as4610-30-r0.yml @@ -0,0 +1,29 @@ +--- + +###################################################################### +# +# platform-config for AS4610-30 +# +###################################################################### + +arm-accton-as4610-30-r0: + flat_image_tree: + kernel: + <<: *arm-iproc-kernel + dtb: + =: accton_as4610_54.dtb + <<: *arm-iproc-kernel-package + itb: + <<: *arm-itb + + loader: + device: /dev/sda + ##partition: /dev/sda1 + loadaddr: 0x70000000 + nos_bootcmds: *usb2_bootcmds + + environment: + - device: /dev/mtd2 + env_offset: 0x00000000 + env_size: 0x00002000 + sector_size: 0x00010000 diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py new file mode 100644 index 00000000..e43c847e --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-30/platform-config/r0/src/python/arm_accton_as4610_30_r0/__init__.py @@ -0,0 +1,8 @@ +from onl.platform.base import * +from onl.platform.accton import * + +class OnlPlatform_arm_accton_as4610_30_r0(OnlPlatformAccton, + OnlPlatformPortConfig_24x1_4x10): + PLATFORM='arm-accton-as4610-30-r0' + MODEL="AS4610-30" + SYS_OBJECT_ID=".4610.30" diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/.gitignore b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/.gitignore new file mode 100644 index 00000000..4d978b36 --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/.gitignore @@ -0,0 +1,2 @@ +*x86*64*cel*redstone*xp*.mk +onlpdump.mk diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/onlp/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/onlp/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/PKG.yml b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/onlp/PKG.yml similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/PKG.yml rename to packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/onlp/PKG.yml diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/Makefile new file mode 100644 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/lib/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/lib/Makefile similarity index 96% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/lib/Makefile rename to packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/lib/Makefile index 40095f96..cdadc9bd 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/lib/Makefile +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/lib/Makefile @@ -26,7 +26,7 @@ include $(ONL)/make/config.armel.mk MODULE := libonlp-arm-accton-as4610-54 include $(BUILDER)/standardinit.mk -DEPENDMODULES := AIM IOF arm_accton_as4610_54 onlplib +DEPENDMODULES := AIM IOF arm_accton_as4610 onlplib DEPENDMODULE_HEADERS := sff include $(BUILDER)/dependmodules.mk diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/lib/libonlp-arm-accton-as4610-54.mk b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/lib/libonlp-arm-accton-as4610-54.mk similarity index 88% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/lib/libonlp-arm-accton-as4610-54.mk rename to packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/lib/libonlp-arm-accton-as4610-54.mk index a2b5c7a9..71f6d993 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/lib/libonlp-arm-accton-as4610-54.mk +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/lib/libonlp-arm-accton-as4610-54.mk @@ -3,7 +3,7 @@ # # Inclusive Makefile for the libonlp-arm-accton-as4610-54 module. # -# Autogenerated 2016-04-03 19:55:05.365431 +# Autogenerated 2016-07-20 18:27:47.344268 # ############################################################################### libonlp-arm-accton-as4610-54_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/onlpdump/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/onlp/builds/onlpdump/Makefile new file mode 100644 index 00000000..f6a0f5dc --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/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.armel.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp arm_accton_as4610 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/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/platform-config/r0/PKG.yml b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/PKG.yml similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610-54/platform-config/r0/PKG.yml rename to packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/PKG.yml diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/platform-config/r0/src/lib/arm-accton-as4610-54-r0.yml b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/lib/arm-accton-as4610-54-r0.yml similarity index 100% rename from packages/platforms/accton/armel/arm-accton-as4610-54/platform-config/r0/src/lib/arm-accton-as4610-54-r0.yml rename to packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/lib/arm-accton-as4610-54-r0.yml diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py similarity index 90% rename from packages/platforms/accton/armel/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py rename to packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py index f2a47419..a4cf2289 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py +++ b/packages/platforms/accton/armel/arm-accton-as4610/arm-accton-as4610-54/platform-config/r0/src/python/arm_accton_as4610_54_r0/__init__.py @@ -5,4 +5,4 @@ class OnlPlatform_arm_accton_as4610_54_r0(OnlPlatformAccton, OnlPlatformPortConfig_48x1_4x10): PLATFORM='arm-accton-as4610-54-r0' MODEL="AS4610-54" - SYS_OBJECT_ID=".4610" + SYS_OBJECT_ID=".4610.54" diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/.gitignore b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/.gitignore new file mode 100644 index 00000000..f663e0ad --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/.gitignore @@ -0,0 +1,2 @@ +/arm_accton_as4610.mk +/doc diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/.module b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/.module new file mode 100644 index 00000000..211d3d67 --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/.module @@ -0,0 +1 @@ +name: arm_accton_as4610 diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/Makefile similarity index 93% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/Makefile rename to packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/Makefile index 2cc4c5e4..e9180def 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/Makefile +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/Makefile @@ -23,6 +23,6 @@ # ############################################################ include $(ONL)/make/config.mk -MODULE := arm_accton_as4610_54 -AUTOMODULE := arm_accton_as4610_54 +MODULE := arm_accton_as4610 +AUTOMODULE := arm_accton_as4610 include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/arm_accton_as4610_54.doxy b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/arm_accton_as4610.doxy similarity index 99% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/arm_accton_as4610_54.doxy rename to packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/arm_accton_as4610.doxy index 10f2bc49..14370eab 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/arm_accton_as4610_54.doxy +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/arm_accton_as4610.doxy @@ -26,7 +26,7 @@ DOXYFILE_ENCODING = UTF-8 # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. -PROJECT_NAME = "arm_accton_as4610_54" +PROJECT_NAME = "arm_accton_as4610" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/auto/arm_accton_as4610_54.yml b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/auto/arm_accton_as4610.yml similarity index 95% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/auto/arm_accton_as4610_54.yml rename to packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/auto/arm_accton_as4610.yml index 5970cda3..3c684974 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/auto/arm_accton_as4610_54.yml +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/auto/arm_accton_as4610.yml @@ -19,7 +19,7 @@ # ############################################################ # -# arm_accton_as4610_54 Autogeneration Definitions. +# arm_accton_as4610 Autogeneration Definitions. # ############################################################ @@ -53,7 +53,7 @@ definitions: cdefs: ONLPSIM_CONFIG_HEADER: defs: *cdefs - basename: arm_accton_as4610_54_config + basename: arm_accton_as4610_config portingmacro: ONLPSIM: diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/auto/make.mk b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/auto/make.mk similarity index 82% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/auto/make.mk rename to packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/auto/make.mk index ebbb4623..01d86621 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/auto/make.mk +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/auto/make.mk @@ -19,11 +19,11 @@ # ############################################################ # -# arm_accton_as4610_54 Autogeneration +# arm_accton_as4610 Autogeneration # ############################################################ -arm_accton_as4610_54_AUTO_DEFS := module/auto/arm_accton_as4610_54.yml -arm_accton_as4610_54_AUTO_DIRS := module/inc/arm_accton_as4610_54 module/src +arm_accton_as4610_AUTO_DEFS := module/auto/arm_accton_as4610.yml +arm_accton_as4610_AUTO_DIRS := module/inc/arm_accton_as4610 module/src include $(BUILDER)/auto.mk diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/inc/arm_accton_as4610_54/arm_accton_as4610_54.x b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610.x similarity index 94% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/inc/arm_accton_as4610_54/arm_accton_as4610_54.x rename to packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610.x index fe057311..359a8f9f 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/inc/arm_accton_as4610_54/arm_accton_as4610_54.x +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610.x @@ -23,7 +23,7 @@ * ***********************************************************/ -#include +#include /* <--auto.start.xmacro(ALL).define> */ /* */ diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/inc/arm_accton_as4610_54/arm_accton_as4610_54_config.h b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_config.h similarity index 85% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/inc/arm_accton_as4610_54/arm_accton_as4610_54_config.h rename to packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_config.h index 57e1b001..09c084d9 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/inc/arm_accton_as4610_54/arm_accton_as4610_54_config.h +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_config.h @@ -26,9 +26,9 @@ /**************************************************************************//** * * @file - * @brief arm_accton_as4610_54 Configuration Header + * @brief arm_accton_as4610 Configuration Header * - * @addtogroup arm_accton_as4610_54-config + * @addtogroup arm_accton_as4610-config * @{ * *****************************************************************************/ @@ -39,7 +39,7 @@ #include #endif #ifdef ONLPSIM_INCLUDE_CUSTOM_CONFIG -#include +#include #endif /* */ @@ -131,32 +131,32 @@ */ /** Configuration settings structure. */ -typedef struct arm_accton_as4610_54_config_settings_s { +typedef struct arm_accton_as4610_config_settings_s { /** name */ const char* name; /** value */ const char* value; -} arm_accton_as4610_54_config_settings_t; +} arm_accton_as4610_config_settings_t; /** Configuration settings table. */ -/** arm_accton_as4610_54_config_settings table. */ -extern arm_accton_as4610_54_config_settings_t arm_accton_as4610_54_config_settings[]; +/** arm_accton_as4610_config_settings table. */ +extern arm_accton_as4610_config_settings_t arm_accton_as4610_config_settings[]; /** * @brief Lookup a configuration setting. * @param setting The name of the configuration option to lookup. */ -const char* arm_accton_as4610_54_config_lookup(const char* setting); +const char* arm_accton_as4610_config_lookup(const char* setting); /** * @brief Show the compile-time configuration. * @param pvs The output stream. */ -int arm_accton_as4610_54_config_show(struct aim_pvs_s* pvs); +int arm_accton_as4610_config_show(struct aim_pvs_s* pvs); /* */ -#include "arm_accton_as4610_54_porting.h" +#include "arm_accton_as4610_porting.h" #endif /* __ONLPSIM_CONFIG_H__ */ /* @} */ diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/inc/arm_accton_as4610_54/arm_accton_as4610_54_dox.h b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_dox.h similarity index 79% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/inc/arm_accton_as4610_54/arm_accton_as4610_54_dox.h rename to packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_dox.h index 176c9608..8a83adb6 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/inc/arm_accton_as4610_54/arm_accton_as4610_54_dox.h +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_dox.h @@ -25,14 +25,14 @@ /********************************************************//** * - * arm_accton_as4610_54 Doxygen Header + * arm_accton_as4610 Doxygen Header * ***********************************************************/ #ifndef __ONLPSIM_DOX_H__ #define __ONLPSIM_DOX_H__ /** - * @defgroup arm_accton_as4610_54 arm_accton_as4610_54 - onlpsim Description + * @defgroup arm_accton_as4610 arm_accton_as4610 - onlpsim Description * The documentation overview for this module should go here. @@ -40,9 +40,9 @@ The documentation overview for this module should go here. * * @{ * - * @defgroup arm_accton_as4610_54-arm_accton_as4610_54 Public Interface - * @defgroup arm_accton_as4610_54-config Compile Time Configuration - * @defgroup arm_accton_as4610_54-porting Porting Macros + * @defgroup arm_accton_as4610-arm_accton_as4610 Public Interface + * @defgroup arm_accton_as4610-config Compile Time Configuration + * @defgroup arm_accton_as4610-porting Porting Macros * * @} * diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/inc/arm_accton_as4610_54/arm_accton_as4610_54_porting.h b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_porting.h similarity index 97% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/inc/arm_accton_as4610_54/arm_accton_as4610_54_porting.h rename to packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_porting.h index aba25043..e29b8611 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/inc/arm_accton_as4610_54/arm_accton_as4610_54_porting.h +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/inc/arm_accton_as4610/arm_accton_as4610_porting.h @@ -26,9 +26,9 @@ /********************************************************//** * * @file - * @brief arm_accton_as4610_54 Porting Macros. + * @brief arm_accton_as4610 Porting Macros. * - * @addtogroup arm_accton_as4610_54-porting + * @addtogroup arm_accton_as4610-porting * @{ * ***********************************************************/ diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/make.mk b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/make.mk similarity index 81% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/make.mk rename to packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/make.mk index 90cb2cea..1e6c405a 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/make.mk +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/make.mk @@ -23,7 +23,7 @@ # ############################################################ THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) -arm_accton_as4610_54_INCLUDES := -I $(THIS_DIR)inc -arm_accton_as4610_54_INTERNAL_INCLUDES := -I $(THIS_DIR)src -arm_accton_as4610_54_DEPENDMODULE_ENTRIES := init:arm_accton_as4610_54 ucli:arm_accton_as4610_54 +arm_accton_as4610_INCLUDES := -I $(THIS_DIR)inc +arm_accton_as4610_INTERNAL_INCLUDES := -I $(THIS_DIR)src +arm_accton_as4610_DEPENDMODULE_ENTRIES := init:arm_accton_as4610 ucli:arm_accton_as4610 diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/Makefile b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/Makefile similarity index 92% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/Makefile rename to packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/Makefile index 998b5874..8c35e1a0 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/Makefile +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/Makefile @@ -26,5 +26,5 @@ include ../../../../init.mk ucli: - $(SUBMODULE_BIGCODE)/tools/uclihandlers.py arm_accton_as4610_54_ucli.c + $(SUBMODULE_BIGCODE)/tools/uclihandlers.py arm_accton_as4610_ucli.c diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_config.c b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_config.c new file mode 100644 index 00000000..ba06f213 --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_config.c @@ -0,0 +1,101 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 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 + +/* */ +#define __arm_accton_as4610_config_STRINGIFY_NAME(_x) #_x +#define __arm_accton_as4610_config_STRINGIFY_VALUE(_x) __arm_accton_as4610_config_STRINGIFY_NAME(_x) +arm_accton_as4610_config_settings_t arm_accton_as4610_config_settings[] = +{ +#ifdef ONLPSIM_CONFIG_INCLUDE_LOGGING + { __arm_accton_as4610_config_STRINGIFY_NAME(ONLPSIM_CONFIG_INCLUDE_LOGGING), __arm_accton_as4610_config_STRINGIFY_VALUE(ONLPSIM_CONFIG_INCLUDE_LOGGING) }, +#else +{ ONLPSIM_CONFIG_INCLUDE_LOGGING(__arm_accton_as4610_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef ONLPSIM_CONFIG_LOG_OPTIONS_DEFAULT + { __arm_accton_as4610_config_STRINGIFY_NAME(ONLPSIM_CONFIG_LOG_OPTIONS_DEFAULT), __arm_accton_as4610_config_STRINGIFY_VALUE(ONLPSIM_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ ONLPSIM_CONFIG_LOG_OPTIONS_DEFAULT(__arm_accton_as4610_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef ONLPSIM_CONFIG_LOG_BITS_DEFAULT + { __arm_accton_as4610_config_STRINGIFY_NAME(ONLPSIM_CONFIG_LOG_BITS_DEFAULT), __arm_accton_as4610_config_STRINGIFY_VALUE(ONLPSIM_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ ONLPSIM_CONFIG_LOG_BITS_DEFAULT(__arm_accton_as4610_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef ONLPSIM_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __arm_accton_as4610_config_STRINGIFY_NAME(ONLPSIM_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __arm_accton_as4610_config_STRINGIFY_VALUE(ONLPSIM_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ ONLPSIM_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__arm_accton_as4610_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef ONLPSIM_CONFIG_PORTING_STDLIB + { __arm_accton_as4610_config_STRINGIFY_NAME(ONLPSIM_CONFIG_PORTING_STDLIB), __arm_accton_as4610_config_STRINGIFY_VALUE(ONLPSIM_CONFIG_PORTING_STDLIB) }, +#else +{ ONLPSIM_CONFIG_PORTING_STDLIB(__arm_accton_as4610_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef ONLPSIM_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __arm_accton_as4610_config_STRINGIFY_NAME(ONLPSIM_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __arm_accton_as4610_config_STRINGIFY_VALUE(ONLPSIM_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ ONLPSIM_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__arm_accton_as4610_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef ONLPSIM_CONFIG_INCLUDE_UCLI + { __arm_accton_as4610_config_STRINGIFY_NAME(ONLPSIM_CONFIG_INCLUDE_UCLI), __arm_accton_as4610_config_STRINGIFY_VALUE(ONLPSIM_CONFIG_INCLUDE_UCLI) }, +#else +{ ONLPSIM_CONFIG_INCLUDE_UCLI(__arm_accton_as4610_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef ONLPSIM_CONFIG_SFP_COUNT + { __arm_accton_as4610_config_STRINGIFY_NAME(ONLPSIM_CONFIG_SFP_COUNT), __arm_accton_as4610_config_STRINGIFY_VALUE(ONLPSIM_CONFIG_SFP_COUNT) }, +#else +{ ONLPSIM_CONFIG_SFP_COUNT(__arm_accton_as4610_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __arm_accton_as4610_config_STRINGIFY_VALUE +#undef __arm_accton_as4610_config_STRINGIFY_NAME + +const char* +arm_accton_as4610_config_lookup(const char* setting) +{ + int i; + for(i = 0; arm_accton_as4610_config_settings[i].name; i++) { + if(strcmp(arm_accton_as4610_config_settings[i].name, setting)) { + return arm_accton_as4610_config_settings[i].value; + } + } + return NULL; +} + +int +arm_accton_as4610_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; arm_accton_as4610_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", arm_accton_as4610_config_settings[i].name, arm_accton_as4610_config_settings[i].value); + } + return i; +} + +/* */ + diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_enums.c b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_enums.c similarity index 93% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_enums.c rename to packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_enums.c index a4044272..06249bee 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_enums.c +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_enums.c @@ -23,7 +23,7 @@ * ***********************************************************/ -#include +#include /* <--auto.start.enum(ALL).source> */ /* */ diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_int.h b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_int.h similarity index 93% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_int.h rename to packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_int.h index 94956e01..07f4fb00 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_int.h +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_int.h @@ -26,7 +26,7 @@ #ifndef __ONLPSIM_INT_H__ #define __ONLPSIM_INT_H__ -#include +#include #endif /* __ONLPSIM_INT_H__ */ diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_log.c b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_log.c similarity index 89% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_log.c rename to packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_log.c index 5db95d2b..c05e6cef 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_log.c +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_log.c @@ -23,11 +23,11 @@ * ***********************************************************/ -#include +#include -#include "arm_accton_as4610_54_log.h" +#include "arm_accton_as4610_log.h" /* - * arm_accton_as4610_54 log struct. + * arm_accton_as4610 log struct. */ AIM_LOG_STRUCT_DEFINE( ONLPSIM_CONFIG_LOG_OPTIONS_DEFAULT, diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_log.h b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_log.h similarity index 95% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_log.h rename to packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_log.h index 5936ec81..44cc9bd4 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_log.h +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_log.h @@ -26,7 +26,7 @@ #ifndef __ONLPSIM_LOG_H__ #define __ONLPSIM_LOG_H__ -#define AIM_LOG_MODULE_NAME arm_accton_as4610_54 +#define AIM_LOG_MODULE_NAME arm_accton_as4610 #include #endif /* __ONLPSIM_LOG_H__ */ diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_module.c b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_module.c similarity index 85% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_module.c rename to packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_module.c index df470cd6..11bb2b47 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_module.c +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_module.c @@ -23,19 +23,19 @@ * ***********************************************************/ -#include +#include -#include "arm_accton_as4610_54_log.h" +#include "arm_accton_as4610_log.h" static int datatypes_init__(void) { #define ONLPSIM_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); -#include +#include return 0; } -void __arm_accton_as4610_54_module_init__(void) +void __arm_accton_as4610_module_init__(void) { AIM_LOG_STRUCT_REGISTER(); datatypes_init__(); diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_ucli.c b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_ucli.c similarity index 71% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_ucli.c rename to packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_ucli.c index 7af18c7d..39483bbb 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/arm_accton_as4610_54_ucli.c +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/arm_accton_as4610_ucli.c @@ -23,7 +23,7 @@ * ***********************************************************/ -#include +#include #if ONLPSIM_CONFIG_INCLUDE_UCLI == 1 @@ -32,9 +32,9 @@ #include static ucli_status_t -arm_accton_as4610_54_ucli_ucli__config__(ucli_context_t* uc) +arm_accton_as4610_ucli_ucli__config__(ucli_context_t* uc) { - UCLI_HANDLER_MACRO_MODULE_CONFIG(arm_accton_as4610_54) + UCLI_HANDLER_MACRO_MODULE_CONFIG(arm_accton_as4610) } /* */ @@ -44,37 +44,37 @@ arm_accton_as4610_54_ucli_ucli__config__(ucli_context_t* uc) * source file. * *****************************************************************************/ -static ucli_command_handler_f arm_accton_as4610_54_ucli_ucli_handlers__[] = +static ucli_command_handler_f arm_accton_as4610_ucli_ucli_handlers__[] = { - arm_accton_as4610_54_ucli_ucli__config__, + arm_accton_as4610_ucli_ucli__config__, NULL }; /******************************************************************************/ /* */ static ucli_module_t -arm_accton_as4610_54_ucli_module__ = +arm_accton_as4610_ucli_module__ = { - "arm_accton_as4610_54_ucli", + "arm_accton_as4610_ucli", NULL, - arm_accton_as4610_54_ucli_ucli_handlers__, + arm_accton_as4610_ucli_ucli_handlers__, NULL, NULL, }; ucli_node_t* -arm_accton_as4610_54_ucli_node_create(void) +arm_accton_as4610_ucli_node_create(void) { ucli_node_t* n; - ucli_module_init(&arm_accton_as4610_54_ucli_module__); - n = ucli_node_create("arm_accton_as4610_54", NULL, &arm_accton_as4610_54_ucli_module__); - ucli_node_subnode_add(n, ucli_module_log_node_create("arm_accton_as4610_54")); + ucli_module_init(&arm_accton_as4610_ucli_module__); + n = ucli_node_create("arm_accton_as4610", NULL, &arm_accton_as4610_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("arm_accton_as4610")); return n; } #else void* -arm_accton_as4610_54_ucli_node_create(void) +arm_accton_as4610_ucli_node_create(void) { return NULL; } diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/fani.c b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/fani.c new file mode 100644 index 00000000..e6b63b14 --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/fani.c @@ -0,0 +1,345 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * Copyright 2016 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. + * + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include +#include +#include +#include "platform_lib.h" +#include "arm_accton_as4610_int.h" + +#define PREFIX_PATH_ON_MAIN_BOARD "/sys/devices/platform/as4610_fan/" +#define PREFIX_PATH_ON_PSU "/sys/bus/i2c/devices/" + +#define MAX_FAN_SPEED 13000 +#define MAX_PSU_FAN_SPEED 25500 + +#define FILE_NAME_LEN 80 + +enum onlp_fan_id +{ + FAN_RESERVED = 0, + FAN_1_ON_MAIN_BOARD, + FAN_1_ON_PSU1, + FAN_1_ON_PSU2 +}; + +typedef struct fan_path_S +{ + char status[FILE_NAME_LEN]; + char speed[FILE_NAME_LEN]; + char ctrl_speed[FILE_NAME_LEN]; +}fan_path_T; + +#define _MAKE_FAN_PATH_ON_MAIN_BOARD(id) \ + { "fan"#id"_fault", "fan"#id"_speed_rpm", "fan_duty_cycle_percentage"} + +#define MAKE_FAN_PATH_ON_MAIN_BOARD(id) _MAKE_FAN_PATH_ON_MAIN_BOARD(id) + +#define MAKE_FAN_PATH_ON_PSU(folder) \ + {#folder"/psu_fan1_fault", #folder"/psu_fan1_speed_rpm", \ + #folder"/psu_fan1_duty_cycle_percentage",} + +static fan_path_T fan_path[] = /* must map with onlp_fan_id */ +{ + { }, /* Not used */ + MAKE_FAN_PATH_ON_MAIN_BOARD(2), + MAKE_FAN_PATH_ON_PSU(8-0058), + MAKE_FAN_PATH_ON_PSU(8-0059) +}; + +#define MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(id) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##id##_ON_MAIN_BOARD), "Chassis Fan "#id, 0 }, \ + ONLP_FAN_STATUS_F2B | ONLP_FAN_STATUS_PRESENT, \ + (ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ + 0, \ + 0, \ + ONLP_FAN_MODE_INVALID, \ + } + +#define MAKE_FAN_INFO_NODE_ON_PSU(psu_id, fan_id) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fan_id##_ON_PSU##psu_id), "Chassis PSU-"#psu_id " Fan "#fan_id, 0 }, \ + ONLP_FAN_STATUS_F2B | ONLP_FAN_STATUS_PRESENT, \ + (ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ + 0, \ + 0, \ + ONLP_FAN_MODE_INVALID, \ + } + +/* Static fan information */ +onlp_fan_info_t linfo[] = { + { }, /* Not used */ + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(1), + MAKE_FAN_INFO_NODE_ON_PSU(1,1), + MAKE_FAN_INFO_NODE_ON_PSU(2,1), +}; + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +#define OPEN_READ_FILE(fd,fullpath,data,nbytes,len) \ + DEBUG_PRINT("[Debug][%s][%d][openfile: %s]\n", __FUNCTION__, __LINE__, fullpath); \ + if ((fd = open(fullpath, O_RDONLY)) == -1) \ + return ONLP_STATUS_E_INTERNAL; \ + if ((len = read(fd, r_data, nbytes)) <= 0){ \ + close(fd); \ + return ONLP_STATUS_E_INTERNAL;} \ + DEBUG_PRINT("[Debug][%s][%d][read data: %s]\n", __FUNCTION__, __LINE__, r_data); \ + if (close(fd) == -1) \ + return ONLP_STATUS_E_INTERNAL + +static int +_onlp_fani_info_get_fan(int local_id, onlp_fan_info_t* info) +{ + int fd, len, nbytes = 10; + char r_data[10] = {0}; + char fullpath[65] = {0}; + + /* get fan fault status (turn on when any one fails) + */ + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, fan_path[local_id].status); + OPEN_READ_FILE(fd, fullpath, r_data, nbytes, len); + if (atoi(r_data) > 0) { + info->status |= ONLP_FAN_STATUS_FAILED; + return ONLP_STATUS_OK; + } + + /* get fan speed + */ + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, fan_path[local_id].speed); + OPEN_READ_FILE(fd, fullpath, r_data, nbytes, len); + info->rpm = atoi(r_data); + + /* get speed percentage from rpm */ + info->percentage = (info->rpm * 100) / MAX_FAN_SPEED; + + return ONLP_STATUS_OK; +} + +static int +_onlp_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info) +{ + int psu_id; + int fd, len, nbytes = 10; + char r_data[10] = {0}; + char fullpath[80] = {0}; + psu_type_t psu_type; + + /* get fan fault status + */ + psu_id = (local_id - FAN_1_ON_PSU1) + 1; + DEBUG_PRINT("[Debug][%s][%d][psu_id: %d]\n", __FUNCTION__, __LINE__, psu_id); + + psu_type = get_psu_type(psu_id, NULL, 0); /* psu_id = 1 , present PSU1. pus_id =2 , present PSU2 */ + DEBUG_PRINT("[Debug][%s][%d][psu_type: %d]\n", __FUNCTION__, __LINE__, psu_type); + + switch (psu_type) { + case PSU_TYPE_AC_F2B: + info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_F2B); + break; + case PSU_TYPE_AC_B2F: + info->status |= (ONLP_FAN_STATUS_PRESENT | ONLP_FAN_STATUS_B2F); + break; + default: + return ONLP_STATUS_E_UNSUPPORTED; + } + + /* get fan fault status + */ + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, fan_path[local_id].status); + OPEN_READ_FILE(fd, fullpath, r_data, nbytes, len); + if (atoi(r_data) > 0) { + info->status |= ONLP_FAN_STATUS_FAILED; + return ONLP_STATUS_OK; + } + + /* get fan speed + */ + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, fan_path[local_id].speed); + OPEN_READ_FILE(fd, fullpath, r_data, nbytes, len); + info->rpm = atoi(r_data); + + /* get speed percentage from rpm */ + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + + return ONLP_STATUS_OK; +} + +/* + * 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 rc = 0; + int local_id; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + if (chassis_fan_count() == 0) { + local_id += 1; + } + + *info = linfo[local_id]; + + switch (local_id) + { + case FAN_1_ON_PSU1: + case FAN_1_ON_PSU2: + rc = _onlp_fani_info_get_fan_on_psu(local_id, info); + break; + case FAN_1_ON_MAIN_BOARD: + rc =_onlp_fani_info_get_fan(local_id, info); + break; + default: + rc = ONLP_STATUS_E_INVALID; + break; + } + + return rc; +} + +/* + * 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) +{ + int fd, len, nbytes=10, local_id; + char data[10] = {0}; + char fullpath[70] = {0}; + + VALIDATE(id); + + if (chassis_fan_count() == 0) { + return ONLP_STATUS_E_INVALID; + } + + local_id = ONLP_OID_ID_GET(id); + + /* reject p=0 (p=0, stop fan) */ + if (p == 0){ + return ONLP_STATUS_E_INVALID; + } + + /* get fullpath */ + switch (local_id) + { + case FAN_1_ON_PSU1: + case FAN_1_ON_PSU2: + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_PSU, fan_path[local_id].ctrl_speed); + break; + case FAN_1_ON_MAIN_BOARD: + sprintf(fullpath, "%s%s", PREFIX_PATH_ON_MAIN_BOARD, fan_path[local_id].ctrl_speed); + break; + default: + return ONLP_STATUS_E_INVALID; + } + sprintf(data, "%d", p); + DEBUG_PRINT("[Debug][%s][%d][openfile: %s][data=%s]\n", __FUNCTION__, __LINE__, fullpath, data); + + /* Create output file descriptor */ + fd = open(fullpath, O_WRONLY, 0644); + if (fd == -1){ + return ONLP_STATUS_E_INTERNAL; + } + + len = write (fd, data, (ssize_t) nbytes); + if (len != nbytes) { + close(fd); + return ONLP_STATUS_E_INTERNAL; + } + + close(fd); + return ONLP_STATUS_OK; +} + + +/* + * 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/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/ledi.c b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/ledi.c new file mode 100644 index 00000000..b63722c2 --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/ledi.c @@ -0,0 +1,422 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * Copyright 2016 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 +#include +#include + +#include +#include "platform_lib.h" +#include "arm_accton_as4610_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 { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_GREEN_BLINKING, + LED_MODE_AMBER, + LED_MODE_AMBER_BLINKING, + LED_MODE_RED, + LED_MODE_RED_BLINKING, + LED_MODE_BLUE, + LED_MODE_BLUE_BLINKING, + LED_MODE_AUTO, + LED_MODE_AUTO_BLINKING, + LED_MODE_UNKNOWN, + LED_MODE_SEVEN_SEGMENT_MAX = 9, +}; + + +#define led_prefix_path "/sys/class/leds/as4610::" +#define led_filename "brightness" + +typedef enum onlp_led_id +{ + LED_RESERVED = 0, + LED_7SEG_DIG1, + LED_7SEG_DP1, + LED_7SEG_DIG2, + LED_7SEG_DP2, + LED_SYS, + LED_PRI, + LED_PSU1, + LED_PSU2, + LED_STK1, + LED_STK2, + LED_FAN, + LED_POE +} onlp_led_id_t; + +static char onlp_led_node_subname[][20] = /* must map with onlp_led_id */ +{ + "reserved", + "7seg_tens", + "7seg_tens_point", + "7seg_digits", + "7seg_digits_point", + "sys", + "pri", + "psu1", + "psu2", + "stk1", + "stk2", + "fan", + "poe" +}; + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t linfo[] = +{ + { }, /* Not used */ + { + { ONLP_LED_ID_CREATE(LED_7SEG_DIG1), "7-segment digit 1", 0 }, + ONLP_LED_STATUS_PRESENT, ONLP_LED_CAPS_CHAR, ONLP_LED_MODE_ON, + }, + { + { ONLP_LED_ID_CREATE(LED_7SEG_DP1), "7-segment dot 1", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN, + }, + { + { ONLP_LED_ID_CREATE(LED_7SEG_DIG2), "7-segment digit 2", 0 }, + ONLP_LED_STATUS_PRESENT, ONLP_LED_CAPS_CHAR, ONLP_LED_MODE_ON, + }, + { + { ONLP_LED_ID_CREATE(LED_7SEG_DP2), "7-segment dot 2", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN, + }, + { + { ONLP_LED_ID_CREATE(LED_SYS), "sys", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN_BLINKING | + ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_PRI), "pri", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN_BLINKING | + ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU1), "psu1", 0 }, + ONLP_LED_STATUS_PRESENT, ONLP_LED_CAPS_AUTO | ONLP_LED_CAPS_AUTO_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU2), "psu2", 0 }, + ONLP_LED_STATUS_PRESENT, ONLP_LED_CAPS_AUTO | ONLP_LED_CAPS_AUTO_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_STK1), "stk1", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN_BLINKING | + ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_STK2), "stk2", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN_BLINKING | + ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_FAN), "fan", 0 }, + ONLP_LED_STATUS_PRESENT, ONLP_LED_CAPS_AUTO | ONLP_LED_CAPS_AUTO_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_POE), "poe", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN_BLINKING | + ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING, + }, +}; + +static int conver_led_light_mode_to_onl(uint32_t id, int led_ligth_mode) +{ + switch (id) { + case LED_SYS: + case LED_PRI: + case LED_STK1: + case LED_STK2: + case LED_POE: + case LED_7SEG_DP1: + case LED_7SEG_DP2: + switch (led_ligth_mode) { + case LED_MODE_OFF: return ONLP_LED_MODE_OFF; + case LED_MODE_GREEN: return ONLP_LED_MODE_GREEN; + case LED_MODE_GREEN_BLINKING: return ONLP_LED_MODE_GREEN_BLINKING; + case LED_MODE_AMBER: return ONLP_LED_MODE_ORANGE; + case LED_MODE_AMBER_BLINKING: return ONLP_LED_MODE_ORANGE_BLINKING; + default: return ONLP_LED_MODE_OFF; + } + case LED_PSU1: + case LED_PSU2: + case LED_FAN: + switch (led_ligth_mode) { + case LED_MODE_AUTO: return ONLP_LED_MODE_AUTO; + case LED_MODE_AUTO_BLINKING: return ONLP_LED_MODE_AUTO_BLINKING; + default: return ONLP_LED_MODE_OFF; + } + } + + return ONLP_LED_MODE_OFF; +} + +static int conver_onlp_led_light_mode_to_driver(uint32_t id, int led_ligth_mode) +{ + switch (id) { + case LED_SYS: + case LED_PRI: + case LED_STK1: + case LED_STK2: + case LED_POE: + case LED_7SEG_DP1: + case LED_7SEG_DP2: + switch (led_ligth_mode) { + case ONLP_LED_MODE_OFF: return LED_MODE_OFF; + case ONLP_LED_MODE_GREEN: return LED_MODE_GREEN; + case ONLP_LED_MODE_GREEN_BLINKING: return LED_MODE_GREEN_BLINKING; + case ONLP_LED_MODE_ORANGE: return LED_MODE_AMBER; + case ONLP_LED_MODE_ORANGE_BLINKING: return LED_MODE_AMBER_BLINKING; + default: return LED_MODE_OFF; + } + case LED_PSU1: + case LED_PSU2: + case LED_FAN: + switch (led_ligth_mode) { + case ONLP_LED_MODE_AUTO: return LED_MODE_AUTO; + case ONLP_LED_MODE_AUTO_BLINKING: return LED_MODE_AUTO_BLINKING; + default: return ONLP_LED_MODE_OFF; + } + } + + return ONLP_LED_MODE_OFF; +} + +/* + * This function will be called prior to any other onlp_ledi_* functions. + */ +int +onlp_ledi_init(void) +{ + return ONLP_STATUS_OK; +} + +/** Set the character */ +int onlp_ledi_char_set(onlp_oid_t id, char c) +{ + int fd, len, nbytes=1; + char data[2] = {0}; + char fullpath[50] = {0}; + int lid = ONLP_OID_ID_GET(id); + + VALIDATE(id); + + if (!(linfo[lid].caps & ONLP_LED_CAPS_CHAR)) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + sprintf(fullpath, "%s%s/%s", led_prefix_path, onlp_led_node_subname[lid], led_filename); + + data[0] = c; + + /* Create output file descriptor */ + fd = open(fullpath, O_WRONLY | O_CREAT, 0644); + if(fd == -1){ + return ONLP_STATUS_E_INTERNAL; + } + + len = write(fd, data, (ssize_t) nbytes); + if(len != nbytes){ + close(fd); + return ONLP_STATUS_E_INTERNAL; + } + + close(fd); + return ONLP_STATUS_OK; +} + +/** Get the current character */ +int onlp_ledi_char_get(onlp_oid_t id, char* c) +{ + int fd, len; + char data = 0; + char fullpath[50] = {0}; + int lid = ONLP_OID_ID_GET(id); + + VALIDATE(id); + + if (!(linfo[lid].caps & ONLP_LED_CAPS_CHAR)) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + sprintf(fullpath, "%s%s/%s", led_prefix_path, onlp_led_node_subname[lid], led_filename); + + /* Set current char */ + if ((fd = open(fullpath, O_RDONLY)) == -1) { + return ONLP_STATUS_E_INTERNAL; + } + + if ((len = read(fd, &data, sizeof(data))) < 0) { + close(fd); + return ONLP_STATUS_E_INTERNAL; + } + + /* If the read byte count is less, the format is different and calc will be wrong*/ + if ((close(fd) == -1) || (len != sizeof(data))) { + return ONLP_STATUS_E_INTERNAL; + } + + *c = data; + return ONLP_STATUS_OK; +} + +int +onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int fd, len, nbytes=1; + char data[2] = {0}; + char fullpath[50] = {0}; + int lid = ONLP_OID_ID_GET(id); + + VALIDATE(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[ONLP_OID_ID_GET(id)]; + + if (linfo[lid].caps & ONLP_LED_CAPS_CHAR) { + return onlp_ledi_char_get(id, &info->character); + } + else { + sprintf(fullpath, "%s%s/%s", led_prefix_path, onlp_led_node_subname[ONLP_OID_ID_GET(id)], led_filename); + + /* Set current mode */ + if ((fd = open(fullpath, O_RDONLY)) == -1) { + return ONLP_STATUS_E_INTERNAL; + } + + if ((len = read(fd, data, nbytes)) < 0) { + close(fd); + return ONLP_STATUS_E_INTERNAL; + } + + /* If the read byte count is less, the format is different and calc will be wrong*/ + if ((close(fd) == -1) || (len != nbytes)) { + return ONLP_STATUS_E_INTERNAL; + } + + info->mode = conver_led_light_mode_to_onl(ONLP_OID_ID_GET(id),atoi(data)); + + /* Set the on/off status */ + if (info->mode != ONLP_LED_MODE_OFF) { + info->status |= ONLP_LED_STATUS_ON; + } + } + + return ONLP_STATUS_OK; +} + +/* + * Turn an LED on or off. + * + * This function will only be called if the LED OID supports the ONOFF + * capability. + * + * What 'on' means in terms of colors or modes for multimode LEDs is + * up to the platform to decide. This is intended as baseline toggle mechanism. + */ +int +onlp_ledi_set(onlp_oid_t id, int on_or_off) +{ + VALIDATE(id); + + if (!on_or_off) { + return onlp_ledi_mode_set(id, ONLP_LED_MODE_OFF); + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function puts the LED into the given mode. It is a more functional + * interface for multimode LEDs. + * + * Only modes reported in the LED's capabilities will be attempted. + */ +int +onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) +{ + int fd, len, driver_mode, nbytes=1; + char data[2] = {0}; + char fullpath[50] = {0}; + int lid = ONLP_OID_ID_GET(id); + + VALIDATE(id); + + if (linfo[lid].caps & ONLP_LED_CAPS_CHAR) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + sprintf(fullpath, "%s%s/%s", led_prefix_path, onlp_led_node_subname[ONLP_OID_ID_GET(id)], led_filename); + + driver_mode = conver_onlp_led_light_mode_to_driver(ONLP_OID_ID_GET(id),mode); + sprintf(data, "%d", driver_mode); + + /* Create output file descriptor */ + fd = open(fullpath, O_WRONLY | O_CREAT, 0644); + if(fd == -1){ + return ONLP_STATUS_E_INTERNAL; + } + + len = write(fd, data, (ssize_t) nbytes); + if(len != nbytes){ + close(fd); + return ONLP_STATUS_E_INTERNAL; + } + + close(fd); + return ONLP_STATUS_OK; +} + +/* + * Generic LED ioctl interface. + */ +int +onlp_ledi_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/make.mk b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/make.mk similarity index 96% rename from packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/make.mk rename to packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/make.mk index d4abed54..699a893a 100644 --- a/packages/platforms/accton/armel/arm-accton-as4610-54/onlp/builds/src/arm_accton_as4610_54/module/src/make.mk +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/make.mk @@ -23,7 +23,7 @@ # ############################################################ -LIBRARY := arm_accton_as4610_54 +LIBRARY := arm_accton_as4610 $(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) #$(LIBRARY)_LAST := 1 include $(BUILDER)/lib.mk diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/platform_lib.c b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/platform_lib.c new file mode 100644 index 00000000..5d0909bb --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/platform_lib.c @@ -0,0 +1,170 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * Copyright 2016 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 +#include +#include +#include +#include +#include "platform_lib.h" + +int deviceNodeWrite(char *filename, char *buffer, int buf_size, int data_len) +{ + int fd; + int len; + + if ((buffer == NULL) || (buf_size < 0)) { + return -1; + } + + if ((fd = open(filename, O_WRONLY, S_IWUSR)) == -1) { + return -1; + } + + if ((len = write(fd, buffer, buf_size)) < 0) { + close(fd); + return -1; + } + + if ((close(fd) == -1)) { + return -1; + } + + if ((len > buf_size) || (data_len != 0 && len != data_len)) { + return -1; + } + + return 0; +} + +int deviceNodeWriteInt(char *filename, int value, int data_len) +{ + char buf[8] = {0}; + sprintf(buf, "%d", value); + + return deviceNodeWrite(filename, buf, sizeof(buf)-1, data_len); +} + +int deviceNodeReadBinary(char *filename, char *buffer, int buf_size, int data_len) +{ + int fd; + int len; + + if ((buffer == NULL) || (buf_size < 0)) { + return -1; + } + + if ((fd = open(filename, O_RDONLY)) == -1) { + return -1; + } + + if ((len = read(fd, buffer, buf_size)) < 0) { + close(fd); + return -1; + } + + if ((close(fd) == -1)) { + return -1; + } + + if ((len > buf_size) || (data_len != 0 && len != data_len)) { + return -1; + } + + return 0; +} + +int deviceNodeReadString(char *filename, char *buffer, int buf_size, int data_len) +{ + int ret; + + if (data_len >= buf_size) { + return -1; + } + + ret = deviceNodeReadBinary(filename, buffer, buf_size-1, data_len); + + if (ret == 0) { + buffer[buf_size-1] = '\0'; + } + + return ret; +} + +#define I2C_PSU_MODEL_NAME_LEN 8 + +psu_type_t get_psu_type(int id, char* modelname, int modelname_len) +{ + char *node = NULL; + char model_name[I2C_PSU_MODEL_NAME_LEN + 1] = {0}; + + /* Check AC model name */ + node = (id == PSU1_ID) ? PSU1_AC_EEPROM_NODE(psu_model_name) : PSU2_AC_EEPROM_NODE(psu_model_name); + + if (deviceNodeReadString(node, model_name, sizeof(model_name), 0) == 0) { + if (strncmp(model_name, "YM-1921A", strlen("YM-1921A")) == 0 || + strncmp(model_name, "YM-1151D", strlen("YM-1151D")) == 0 || + strncmp(model_name, "YM-1601A", strlen("YM-1601A")) == 0) { + if (modelname) { + strncpy(modelname, model_name, modelname_len-1); + } + return PSU_TYPE_AC_F2B; + } + } + + return PSU_TYPE_UNKNOWN; +} + +enum as4610_product_id get_product_id(void) +{ + char *node = "/sys/bus/i2c/devices/0-0030/product_id"; + char buf[3] = {0}; + int pid = PID_UNKNOWN; + + if (deviceNodeReadString(node, buf, sizeof(buf), 0) != 0) { + return PID_UNKNOWN; + } + + pid = atoi(buf); + if (pid >= PID_UNKNOWN || pid < PID_AS4610_30T) { + return PID_UNKNOWN; + } + + return pid; +} + +int chassis_fan_count(void) +{ + enum as4610_product_id pid = get_product_id(); + return (pid == PID_AS4610_30P || pid == PID_AS4610P) ? 1 : 0; +} + +int chassis_led_count(void) +{ + enum as4610_product_id pid = get_product_id(); + return (pid == PID_AS4610_30P || pid == PID_AS4610P) ? 12 : 10; +} diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/platform_lib.h b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/platform_lib.h new file mode 100644 index 00000000..0beab750 --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/platform_lib.h @@ -0,0 +1,98 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * Copyright 2016 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. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#ifndef __PLATFORM_LIB_H__ +#define __PLATFORM_LIB_H__ + +#include "arm_accton_as4610_log.h" + +#define CHASSIS_THERMAL_COUNT 1 +#define CHASSIS_PSU_COUNT 2 + +#define PSU1_ID 1 +#define PSU2_ID 2 + +#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/8-0058/" +#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/8-0059/" + +#define PSU1_AC_PMBUS_NODE(node) PSU1_AC_PMBUS_PREFIX#node +#define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node + +#define PSU1_AC_EEPROM_PREFIX "/sys/bus/i2c/devices/8-0050/" +#define PSU2_AC_EEPROM_PREFIX "/sys/bus/i2c/devices/8-0051/" + +#define PSU1_AC_EEPROM_NODE(node) PSU1_AC_EEPROM_PREFIX#node +#define PSU2_AC_EEPROM_NODE(node) PSU2_AC_EEPROM_PREFIX#node + +#define IDPROM_PATH "/sys/devices/1803b000.i2c/i2c-1/i2c-9/9-0050/eeprom" + +int deviceNodeWriteInt(char *filename, int value, int data_len); +int deviceNodeReadBinary(char *filename, char *buffer, int buf_size, int data_len); +int deviceNodeReadString(char *filename, char *buffer, int buf_size, int data_len); + +typedef enum psu_type { + PSU_TYPE_UNKNOWN, + PSU_TYPE_AC_F2B, + PSU_TYPE_AC_B2F +} psu_type_t; + +psu_type_t get_psu_type(int id, char* modelname, int modelname_len); + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(format, ...) printf(format, __VA_ARGS__) +#else + #define DEBUG_PRINT(format, ...) +#endif + +enum onlp_fan_duty_cycle_percentage +{ + FAN_PERCENTAGE_LOW = 13, + FAN_PERCENTAGE_HIGH = 75 +}; + +enum as4610_product_id { + PID_AS4610_30T = 0, + PID_AS4610_30P, + PID_AS4610T, + PID_AS4610P, + PID_UNKNOWN +}; + +enum as4610_product_id get_product_id(void); +int chassis_fan_count(void); +int chassis_led_count(void); + +typedef enum platform_id_e { + PLATFORM_ID_UNKNOWN, + PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0, + PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0, +} platform_id_t; + +extern platform_id_t platform_id; + +#endif /* __PLATFORM_LIB_H__ */ + diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/psui.c b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/psui.c new file mode 100644 index 00000000..4ddb2b37 --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/psui.c @@ -0,0 +1,153 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * Copyright 2016 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 +#include +#include "platform_lib.h" +#include "arm_accton_as4610_int.h" + +#define PSU_STATUS_PRESENT 1 +#define PSU_STATUS_POWER_GOOD 1 + +#define PSU_NODE_MAX_INT_LEN 8 +#define PSU_NODE_MAX_PATH_LEN 64 + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +psu_status_info_get(int id, char *node, int *value) +{ + int ret = 0; + char buf[PSU_NODE_MAX_INT_LEN + 1] = {0}; + char node_path[PSU_NODE_MAX_PATH_LEN] = {0}; + + *value = 0; + + if (PSU1_ID == id) { + sprintf(node_path, "%s%s", PSU1_AC_EEPROM_PREFIX, node); + } + else if (PSU2_ID == id) { + sprintf(node_path, "%s%s", PSU2_AC_EEPROM_PREFIX, node); + } + + ret = deviceNodeReadString(node_path, buf, sizeof(buf), 0); + + if (ret == 0) { + *value = atoi(buf); + } + + return ret; +} + +int +onlp_psui_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * Get all information about the given PSU oid. + */ +static onlp_psu_info_t pinfo[] = +{ + { }, /* Not used */ + { + { ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0 }, + }, + { + { ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0 }, + } +}; + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int val = 0; + int ret = ONLP_STATUS_OK; + int index = ONLP_OID_ID_GET(id); + psu_type_t psu_type; + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_psu_info_t)); + *info = pinfo[index]; /* Set the onlp_oid_hdr_t */ + + /* Get the present state */ + if (psu_status_info_get(index, "psu_present", &val) != 0) { + printf("Unable to read PSU(%d) node(psu_present)\r\n", index); + } + + if (val != PSU_STATUS_PRESENT) { + info->status &= ~ONLP_PSU_STATUS_PRESENT; + return ONLP_STATUS_OK; + } + info->status |= ONLP_PSU_STATUS_PRESENT; + + + /* Get power good status */ + if (psu_status_info_get(index, "psu_power_good", &val) != 0) { + printf("Unable to read PSU(%d) node(psu_power_good)\r\n", index); + } + + if (val != PSU_STATUS_POWER_GOOD) { + info->status |= ONLP_PSU_STATUS_FAILED; + } + + /* Get PSU type + */ + psu_type = get_psu_type(index, info->model, sizeof(info->model)); + + switch (psu_type) { + case PSU_TYPE_AC_F2B: + case PSU_TYPE_AC_B2F: + info->caps = ONLP_PSU_CAPS_AC; + ret = ONLP_STATUS_OK; + break; + case PSU_TYPE_UNKNOWN: /* User insert a unknown PSU or unplugged.*/ + info->status |= ONLP_PSU_STATUS_UNPLUGGED; + info->status &= ~ONLP_PSU_STATUS_FAILED; + ret = ONLP_STATUS_OK; + break; + default: + ret = ONLP_STATUS_E_UNSUPPORTED; + break; + } + + return ret; +} + +int +onlp_psui_ioctl(onlp_oid_t pid, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + 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 new file mode 100644 index 00000000..7199a31a --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/sfpi.c @@ -0,0 +1,338 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * Copyright 2016 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 "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) + +static int +sfp_node_read_int(char *node_path, int *value, int data_len) +{ + 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; +} + +static char* +sfp_get_port_path_addr(int port, int addr, char *node_name) +{ + 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); +} + +/************************************************************ + * + * SFPI Entry Points + * + ***********************************************************/ +int +onlp_sfpi_init(void) +{ + /* Called at initialization time */ + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + int p; + int start_port, end_port; + + if(platform_id == PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0) + { + start_port = 24; + end_port = 30; + } + else /*PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0*/ + { + start_port = 48; + end_port = 54; + } + + for(p = start_port; p < end_port; p++) { + AIM_BITMAP_SET(bmap, p); + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_present(int port) +{ + /* + * Return 1 if present. + * Return 0 if not present. + * 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_ERROR("Unable to read present status from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return present; +} + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + uint32_t byte; + char* path; + FILE* fp; + int port; + + AIM_BITMAP_CLR_ALL(dst); + + if(platform_id == PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0) + port = 24; + else /*PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0*/ + port = 48; + + path = sfp_get_port_path(port, "sfp_is_present_all"); + fp = fopen(path, "r"); + + 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", &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."); + return ONLP_STATUS_E_INTERNAL; + } + + /* Convert to 64 bit integer in port order */ + int i = 0; + uint64_t presence_all = byte; + presence_all <<= port; + + /* Populate bitmap */ + for(i = 0; presence_all; i++) { + AIM_BITMAP_MOD(dst, i, (presence_all & 1)); + presence_all >>= 1; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + uint32_t byte; + char* path; + FILE* fp; + int port; + + if(platform_id == PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0) + port = 24; + else /*PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0*/ + port = 48; + + path = sfp_get_port_path(port, "sfp_rx_los_all"); + fp = fopen(path, "r"); + 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", &byte); + fclose(fp); + if(count != 1) { + AIM_LOG_ERROR("Unable to read all fields from the sfp_rx_los_all device file."); + return ONLP_STATUS_E_INTERNAL; + } + + /* Convert to 64 bit integer in port order */ + int i = 0; + uint64_t rx_los_all = byte; + rx_los_all <<= port; + + /* Populate bitmap */ + for(i = 0; rx_los_all; i++) { + AIM_BITMAP_MOD(dst, i, (rx_los_all & 1)); + rx_los_all >>= 1; + } + + return ONLP_STATUS_OK; +} + +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 + */ + memset(data, 0, 256); + + if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\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); + + if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) { + AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", 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; + + 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; +} + +int +onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) +{ + int rv; + char* path = NULL; + + 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) { + AIM_LOG_ERROR("Unable to read rx_los status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + break; + } + + case ONLP_SFP_CONTROL_TX_FAULT: + { + path = sfp_get_port_path(port, "sfp_tx_fault"); + + if (sfp_node_read_int(path, value, 0) != 0) { + AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else { + rv = ONLP_STATUS_OK; + } + 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; + } + + return rv; +} + + +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/sysi.c b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/sysi.c new file mode 100644 index 00000000..16471bef --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/sysi.c @@ -0,0 +1,208 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * Copyright 2016 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 +#include +#include +#include +#include +#include + +#include "arm_accton_as4610_int.h" +#include "arm_accton_as4610_log.h" + +#include "platform_lib.h" + +#define OPEN_READ_FILE(fd,fullpath,data,nbytes,len) \ + DEBUG_PRINT("[Debug][%s][%d][openfile: %s]\n", __FUNCTION__, __LINE__, fullpath); \ + if ((fd = open(fullpath, O_RDONLY)) == -1) \ + return ONLP_STATUS_E_INTERNAL; \ + if ((len = read(fd, r_data, nbytes)) <= 0){ \ + close(fd); \ + return ONLP_STATUS_E_INTERNAL;} \ + DEBUG_PRINT("[Debug][%s][%d][read data: %s]\n", __FUNCTION__, __LINE__, r_data); \ + if (close(fd) == -1) \ + return ONLP_STATUS_E_INTERNAL + +platform_id_t platform_id = PLATFORM_ID_UNKNOWN; + +const char* +onlp_sysi_platform_get(void) +{ + return "arm-accton-as4610"; +} + +int +onlp_sysi_platform_set(const char* platform) +{ + if(strstr(platform, "arm-accton-as4610-30-r0")) { + platform_id = PLATFORM_ID_POWERPC_ACCTON_AS4610_30_R0; + return ONLP_STATUS_OK; + } + if(strstr(platform, "arm-accton-as4610-54-r0")) { + platform_id = PLATFORM_ID_POWERPC_ACCTON_AS4610_54_R0; + return ONLP_STATUS_OK; + } + AIM_LOG_ERROR("No support for platform '%s'", platform); + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + int v; + int fd, len, nbytes = 10; + char r_data[10] = {0}; + char fullpath[65] = {0}; + + sprintf(fullpath, "/sys/bus/i2c/devices/0-0030/version"); + OPEN_READ_FILE(fd, fullpath, r_data, nbytes, len); + v = atoi(r_data); + + pi->cpld_versions = aim_fstrdup("%d", v); + + return 0; +} + +int +onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ + 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; + } + } + aim_free(rdata); + *size = 0; + return ONLP_STATUS_E_INTERNAL; +} + +void +onlp_sysi_onie_data_free(uint8_t* data) +{ + aim_free(data); +} + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + int i; + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + + /* 1 Thermal sensors on the chassis */ + for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* LEDs on the chassis */ + for (i = 1; i <= chassis_led_count(); i++) { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* 1 Fans on the chassis */ + for (i = 1; i <= chassis_fan_count(); i++) { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + /* 2 PSUs on the chassis */ + for (i = 1; i <= CHASSIS_PSU_COUNT; i++) { + *e++ = ONLP_PSU_ID_CREATE(i); + } + + return 0; +} + +int +onlp_sysi_platform_manage_fans(void) +{ + int rc, oldP, newP = 0; + onlp_thermal_info_t ti; + int fd, len; + char buf[10] = {0}; + char path[70] = "/sys/devices/platform/as4610_fan/fan_duty_cycle_percentage"; + + if (chassis_fan_count() == 0) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + /* Get fan duty cycle */ + fd = open(path, O_RDWR, 0644); + if (fd == -1){ + return ONLP_STATUS_E_INTERNAL; + } + + len = read(fd, buf, sizeof(buf)); + if (len <= 0){ + close(fd); + return ONLP_STATUS_E_INTERNAL; + } + + if (close(fd) == -1) { + return ONLP_STATUS_E_INTERNAL; + } + + DEBUG_PRINT("[Debug][%s][%d][read data: %s]\n", __FUNCTION__, __LINE__, buf); + oldP = atoi(buf); + + /* Get temperature */ + rc = onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(1), &ti); + if (rc != ONLP_STATUS_OK) { + return rc; + } + + /* Bring fan speed to high if current speed is unexpected + */ + if (oldP != FAN_PERCENTAGE_LOW && oldP != FAN_PERCENTAGE_HIGH) { + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_PERCENTAGE_HIGH); + return ONLP_STATUS_OK; + } + + if (oldP == FAN_PERCENTAGE_LOW && ti.mcelsius >= 61000) { + newP = FAN_PERCENTAGE_HIGH; + + } + else if (oldP == FAN_PERCENTAGE_HIGH && ti.mcelsius <= 49000) { + newP = FAN_PERCENTAGE_LOW; + } + + if (newP) { + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), newP); + } + + return ONLP_STATUS_OK; +} + +int +onlp_sysi_platform_manage_leds(void) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} diff --git a/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/thermali.c b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/thermali.c new file mode 100644 index 00000000..d9beebec --- /dev/null +++ b/packages/platforms/accton/armel/arm-accton-as4610/src/arm_accton_as4610/module/src/thermali.c @@ -0,0 +1,130 @@ +/************************************************************ + * + * + * Copyright 2014, 2015 Big Switch Networks, Inc. + * Copyright 2016 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. + * + * + ************************************************************ + * + * Thermal Sensor Platform Implementation. + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include "platform_lib.h" +#include "arm_accton_as4610_log.h" + +#define prefix_path "/sys/bus/i2c/devices/" +#define LOCAL_DEBUG 0 + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +#define OPEN_READ_FILE(fd,fullpath,data,nbytes,len) \ + DEBUG_PRINT("[Debug][%s][%d][openfile: %s]\n", __FUNCTION__, __LINE__, fullpath); \ + if ((fd = open(fullpath, O_RDONLY)) == -1) \ + return ONLP_STATUS_E_INTERNAL; \ + if ((len = read(fd, r_data, nbytes)) <= 0){ \ + close(fd); \ + return ONLP_STATUS_E_INTERNAL;} \ + DEBUG_PRINT("[Debug][%s][%d][read data: %s]\n", __FUNCTION__, __LINE__, r_data); \ + if (close(fd) == -1) \ + return ONLP_STATUS_E_INTERNAL + +enum onlp_thermal_id +{ + THERMAL_RESERVED = 0, + THERMAL_1_ON_MAIN_BROAD, + THERMAL_1_ON_PSU1, + THERMAL_1_ON_PSU2, +}; + +static char* last_path[] = /* must map with onlp_thermal_id */ +{ + "reserved", + "9-0048/temp1_input", + "8-0058/psu_temp1_input", + "8-0059/psu_temp1_input", +}; + +/* Static values */ +static onlp_thermal_info_t linfo[] = { + { }, /* Not used */ + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "Chassis Thermal Sensor 1", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(1)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), "PSU-2 Thermal Sensor 1", ONLP_PSU_ID_CREATE(2)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + } +}; + +/* + * 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 fd, len, nbytes = 10, temp_base=1, local_id; + char r_data[10] = {0}; + char fullpath[50] = {0}; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + DEBUG_PRINT("\n[Debug][%s][%d][local_id: %d]", __FUNCTION__, __LINE__, local_id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[local_id]; + + /* get fullpath */ + sprintf(fullpath, "%s%s", prefix_path, last_path[local_id]); + + OPEN_READ_FILE(fd, fullpath, r_data, nbytes, len); + info->mcelsius = atoi(r_data) / temp_base; + DEBUG_PRINT("\n[Debug][%s][%d][save data: %d]\n", __FUNCTION__, __LINE__, info->mcelsius); + + return ONLP_STATUS_OK; +} +