diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/.gitignore b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/.gitignore new file mode 100755 index 00000000..f34c03c4 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/.gitignore @@ -0,0 +1,3 @@ +*x86*64*accton*asgvolt64*.mk +onlpdump.mk + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/PKG.yml new file mode 100755 index 00000000..506a275e --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=accton BASENAME=x86-64-accton-asgvolt64 ARCH=amd64 KERNELS="onl-kernel-4.14-lts-x86-64-all:amd64" diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/.gitignore b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/.gitignore new file mode 100755 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/Makefile new file mode 100755 index 00000000..2d44f24f --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-4.14-lts-x86-64-all:amd64 +KMODULES := $(wildcard *.c) +VENDOR := accton +BASENAME := x86-64-accton-asgvolt64 +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-cpld.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-cpld.c new file mode 100755 index 00000000..f79800ac --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-cpld.c @@ -0,0 +1,1644 @@ +/* + * Copyright (C) Jostar yang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton asgvolt64 CPLD + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ +#define FAN_DUTY_CYCLE_REG_MASK 0x1F +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 114 // R.P.M value = read value x3.79*60/2 + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + asgvolt64_cpld1, + asgvolt64_cpld2, + asgvolt64_cpld3 +}; + +struct asgvolt64_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ +}; + +static const struct i2c_device_id asgvolt64_cpld_id[] = { + { "asgvlot64_cpld1", asgvolt64_cpld1}, + { "asgvlot64_cpld2", asgvolt64_cpld2}, + { "asgvlot64_cpld3", asgvolt64_cpld3}, + { } +}; +MODULE_DEVICE_TABLE(i2c, asgvolt64_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index + + +enum asgvolt64_cpld_sysfs_attributes { + CPLD_VERSION, + ACCESS, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(1), + TRANSCEIVER_PRESENT_ATTR_ID(2), + TRANSCEIVER_PRESENT_ATTR_ID(3), + TRANSCEIVER_PRESENT_ATTR_ID(4), + TRANSCEIVER_PRESENT_ATTR_ID(5), + TRANSCEIVER_PRESENT_ATTR_ID(6), + TRANSCEIVER_PRESENT_ATTR_ID(7), + TRANSCEIVER_PRESENT_ATTR_ID(8), + TRANSCEIVER_PRESENT_ATTR_ID(9), + TRANSCEIVER_PRESENT_ATTR_ID(10), + TRANSCEIVER_PRESENT_ATTR_ID(11), + TRANSCEIVER_PRESENT_ATTR_ID(12), + TRANSCEIVER_PRESENT_ATTR_ID(13), + TRANSCEIVER_PRESENT_ATTR_ID(14), + TRANSCEIVER_PRESENT_ATTR_ID(15), + TRANSCEIVER_PRESENT_ATTR_ID(16), + TRANSCEIVER_PRESENT_ATTR_ID(17), + TRANSCEIVER_PRESENT_ATTR_ID(18), + TRANSCEIVER_PRESENT_ATTR_ID(19), + TRANSCEIVER_PRESENT_ATTR_ID(20), + TRANSCEIVER_PRESENT_ATTR_ID(21), + TRANSCEIVER_PRESENT_ATTR_ID(22), + TRANSCEIVER_PRESENT_ATTR_ID(23), + TRANSCEIVER_PRESENT_ATTR_ID(24), + TRANSCEIVER_PRESENT_ATTR_ID(25), + TRANSCEIVER_PRESENT_ATTR_ID(26), + TRANSCEIVER_PRESENT_ATTR_ID(27), + TRANSCEIVER_PRESENT_ATTR_ID(28), + TRANSCEIVER_PRESENT_ATTR_ID(29), + TRANSCEIVER_PRESENT_ATTR_ID(30), + TRANSCEIVER_PRESENT_ATTR_ID(31), + TRANSCEIVER_PRESENT_ATTR_ID(32), + TRANSCEIVER_PRESENT_ATTR_ID(33), + TRANSCEIVER_PRESENT_ATTR_ID(34), + TRANSCEIVER_PRESENT_ATTR_ID(35), + TRANSCEIVER_PRESENT_ATTR_ID(36), + TRANSCEIVER_PRESENT_ATTR_ID(37), + TRANSCEIVER_PRESENT_ATTR_ID(38), + TRANSCEIVER_PRESENT_ATTR_ID(39), + TRANSCEIVER_PRESENT_ATTR_ID(40), + TRANSCEIVER_PRESENT_ATTR_ID(41), + TRANSCEIVER_PRESENT_ATTR_ID(42), + TRANSCEIVER_PRESENT_ATTR_ID(43), + TRANSCEIVER_PRESENT_ATTR_ID(44), + TRANSCEIVER_PRESENT_ATTR_ID(45), + TRANSCEIVER_PRESENT_ATTR_ID(46), + TRANSCEIVER_PRESENT_ATTR_ID(47), + TRANSCEIVER_PRESENT_ATTR_ID(48), + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_PRESENT_ATTR_ID(55), + TRANSCEIVER_PRESENT_ATTR_ID(56), + TRANSCEIVER_PRESENT_ATTR_ID(57), + TRANSCEIVER_PRESENT_ATTR_ID(58), + TRANSCEIVER_PRESENT_ATTR_ID(59), + TRANSCEIVER_PRESENT_ATTR_ID(60), + TRANSCEIVER_PRESENT_ATTR_ID(61), + TRANSCEIVER_PRESENT_ATTR_ID(62), + TRANSCEIVER_PRESENT_ATTR_ID(63), + TRANSCEIVER_PRESENT_ATTR_ID(64), + TRANSCEIVER_PRESENT_ATTR_ID(65), + TRANSCEIVER_PRESENT_ATTR_ID(66), + TRANSCEIVER_PRESENT_ATTR_ID(67), + TRANSCEIVER_PRESENT_ATTR_ID(68), + TRANSCEIVER_PRESENT_ATTR_ID(69), + TRANSCEIVER_PRESENT_ATTR_ID(70), + TRANSCEIVER_PRESENT_ATTR_ID(71), + TRANSCEIVER_PRESENT_ATTR_ID(72), + TRANSCEIVER_PRESENT_ATTR_ID(73), + TRANSCEIVER_PRESENT_ATTR_ID(74), + + TRANSCEIVER_RXLOS_ATTR_ID(67), + TRANSCEIVER_RXLOS_ATTR_ID(68), + TRANSCEIVER_RXLOS_ATTR_ID(69), + TRANSCEIVER_RXLOS_ATTR_ID(70), + TRANSCEIVER_RXLOS_ATTR_ID(71), + TRANSCEIVER_RXLOS_ATTR_ID(72), + TRANSCEIVER_RXLOS_ATTR_ID(73), + TRANSCEIVER_RXLOS_ATTR_ID(74), + + TRANSCEIVER_TXFAULT_ATTR_ID(1), + TRANSCEIVER_TXFAULT_ATTR_ID(2), + TRANSCEIVER_TXFAULT_ATTR_ID(3), + TRANSCEIVER_TXFAULT_ATTR_ID(4), + TRANSCEIVER_TXFAULT_ATTR_ID(5), + TRANSCEIVER_TXFAULT_ATTR_ID(6), + TRANSCEIVER_TXFAULT_ATTR_ID(7), + TRANSCEIVER_TXFAULT_ATTR_ID(8), + TRANSCEIVER_TXFAULT_ATTR_ID(9), + TRANSCEIVER_TXFAULT_ATTR_ID(10), + TRANSCEIVER_TXFAULT_ATTR_ID(11), + TRANSCEIVER_TXFAULT_ATTR_ID(12), + TRANSCEIVER_TXFAULT_ATTR_ID(13), + TRANSCEIVER_TXFAULT_ATTR_ID(14), + TRANSCEIVER_TXFAULT_ATTR_ID(15), + TRANSCEIVER_TXFAULT_ATTR_ID(16), + TRANSCEIVER_TXFAULT_ATTR_ID(17), + TRANSCEIVER_TXFAULT_ATTR_ID(18), + TRANSCEIVER_TXFAULT_ATTR_ID(19), + TRANSCEIVER_TXFAULT_ATTR_ID(20), + TRANSCEIVER_TXFAULT_ATTR_ID(21), + TRANSCEIVER_TXFAULT_ATTR_ID(22), + TRANSCEIVER_TXFAULT_ATTR_ID(23), + TRANSCEIVER_TXFAULT_ATTR_ID(24), + TRANSCEIVER_TXFAULT_ATTR_ID(25), + TRANSCEIVER_TXFAULT_ATTR_ID(26), + TRANSCEIVER_TXFAULT_ATTR_ID(27), + TRANSCEIVER_TXFAULT_ATTR_ID(28), + TRANSCEIVER_TXFAULT_ATTR_ID(29), + TRANSCEIVER_TXFAULT_ATTR_ID(30), + TRANSCEIVER_TXFAULT_ATTR_ID(31), + TRANSCEIVER_TXFAULT_ATTR_ID(32), + TRANSCEIVER_TXFAULT_ATTR_ID(33), + TRANSCEIVER_TXFAULT_ATTR_ID(34), + TRANSCEIVER_TXFAULT_ATTR_ID(35), + TRANSCEIVER_TXFAULT_ATTR_ID(36), + TRANSCEIVER_TXFAULT_ATTR_ID(37), + TRANSCEIVER_TXFAULT_ATTR_ID(38), + TRANSCEIVER_TXFAULT_ATTR_ID(39), + TRANSCEIVER_TXFAULT_ATTR_ID(40), + TRANSCEIVER_TXFAULT_ATTR_ID(41), + TRANSCEIVER_TXFAULT_ATTR_ID(42), + TRANSCEIVER_TXFAULT_ATTR_ID(43), + TRANSCEIVER_TXFAULT_ATTR_ID(44), + TRANSCEIVER_TXFAULT_ATTR_ID(45), + TRANSCEIVER_TXFAULT_ATTR_ID(46), + TRANSCEIVER_TXFAULT_ATTR_ID(47), + TRANSCEIVER_TXFAULT_ATTR_ID(48), + TRANSCEIVER_TXFAULT_ATTR_ID(49), + TRANSCEIVER_TXFAULT_ATTR_ID(50), + TRANSCEIVER_TXFAULT_ATTR_ID(51), + TRANSCEIVER_TXFAULT_ATTR_ID(52), + TRANSCEIVER_TXFAULT_ATTR_ID(53), + TRANSCEIVER_TXFAULT_ATTR_ID(54), + TRANSCEIVER_TXFAULT_ATTR_ID(55), + TRANSCEIVER_TXFAULT_ATTR_ID(56), + TRANSCEIVER_TXFAULT_ATTR_ID(57), + TRANSCEIVER_TXFAULT_ATTR_ID(58), + TRANSCEIVER_TXFAULT_ATTR_ID(59), + TRANSCEIVER_TXFAULT_ATTR_ID(60), + TRANSCEIVER_TXFAULT_ATTR_ID(61), + TRANSCEIVER_TXFAULT_ATTR_ID(62), + TRANSCEIVER_TXFAULT_ATTR_ID(63), + TRANSCEIVER_TXFAULT_ATTR_ID(64), + TRANSCEIVER_TXFAULT_ATTR_ID(67), + TRANSCEIVER_TXFAULT_ATTR_ID(68), + TRANSCEIVER_TXFAULT_ATTR_ID(69), + TRANSCEIVER_TXFAULT_ATTR_ID(70), + TRANSCEIVER_TXFAULT_ATTR_ID(71), + TRANSCEIVER_TXFAULT_ATTR_ID(72), + TRANSCEIVER_TXFAULT_ATTR_ID(73), + TRANSCEIVER_TXFAULT_ATTR_ID(74), + + TRANSCEIVER_TXDISABLE_ATTR_ID(1), + TRANSCEIVER_TXDISABLE_ATTR_ID(2), + TRANSCEIVER_TXDISABLE_ATTR_ID(3), + TRANSCEIVER_TXDISABLE_ATTR_ID(4), + TRANSCEIVER_TXDISABLE_ATTR_ID(5), + TRANSCEIVER_TXDISABLE_ATTR_ID(6), + TRANSCEIVER_TXDISABLE_ATTR_ID(7), + TRANSCEIVER_TXDISABLE_ATTR_ID(8), + TRANSCEIVER_TXDISABLE_ATTR_ID(9), + TRANSCEIVER_TXDISABLE_ATTR_ID(10), + TRANSCEIVER_TXDISABLE_ATTR_ID(11), + TRANSCEIVER_TXDISABLE_ATTR_ID(12), + TRANSCEIVER_TXDISABLE_ATTR_ID(13), + TRANSCEIVER_TXDISABLE_ATTR_ID(14), + TRANSCEIVER_TXDISABLE_ATTR_ID(15), + TRANSCEIVER_TXDISABLE_ATTR_ID(16), + TRANSCEIVER_TXDISABLE_ATTR_ID(17), + TRANSCEIVER_TXDISABLE_ATTR_ID(18), + TRANSCEIVER_TXDISABLE_ATTR_ID(19), + TRANSCEIVER_TXDISABLE_ATTR_ID(20), + TRANSCEIVER_TXDISABLE_ATTR_ID(21), + TRANSCEIVER_TXDISABLE_ATTR_ID(22), + TRANSCEIVER_TXDISABLE_ATTR_ID(23), + TRANSCEIVER_TXDISABLE_ATTR_ID(24), + TRANSCEIVER_TXDISABLE_ATTR_ID(25), + TRANSCEIVER_TXDISABLE_ATTR_ID(26), + TRANSCEIVER_TXDISABLE_ATTR_ID(27), + TRANSCEIVER_TXDISABLE_ATTR_ID(28), + TRANSCEIVER_TXDISABLE_ATTR_ID(29), + TRANSCEIVER_TXDISABLE_ATTR_ID(30), + TRANSCEIVER_TXDISABLE_ATTR_ID(31), + TRANSCEIVER_TXDISABLE_ATTR_ID(32), + TRANSCEIVER_TXDISABLE_ATTR_ID(33), + TRANSCEIVER_TXDISABLE_ATTR_ID(34), + TRANSCEIVER_TXDISABLE_ATTR_ID(35), + TRANSCEIVER_TXDISABLE_ATTR_ID(36), + TRANSCEIVER_TXDISABLE_ATTR_ID(37), + TRANSCEIVER_TXDISABLE_ATTR_ID(38), + TRANSCEIVER_TXDISABLE_ATTR_ID(39), + TRANSCEIVER_TXDISABLE_ATTR_ID(40), + TRANSCEIVER_TXDISABLE_ATTR_ID(41), + TRANSCEIVER_TXDISABLE_ATTR_ID(42), + TRANSCEIVER_TXDISABLE_ATTR_ID(43), + TRANSCEIVER_TXDISABLE_ATTR_ID(44), + TRANSCEIVER_TXDISABLE_ATTR_ID(45), + TRANSCEIVER_TXDISABLE_ATTR_ID(46), + TRANSCEIVER_TXDISABLE_ATTR_ID(47), + TRANSCEIVER_TXDISABLE_ATTR_ID(48), + TRANSCEIVER_TXDISABLE_ATTR_ID(49), + TRANSCEIVER_TXDISABLE_ATTR_ID(50), + TRANSCEIVER_TXDISABLE_ATTR_ID(51), + TRANSCEIVER_TXDISABLE_ATTR_ID(52), + TRANSCEIVER_TXDISABLE_ATTR_ID(53), + TRANSCEIVER_TXDISABLE_ATTR_ID(54), + TRANSCEIVER_TXDISABLE_ATTR_ID(55), + TRANSCEIVER_TXDISABLE_ATTR_ID(56), + TRANSCEIVER_TXDISABLE_ATTR_ID(57), + TRANSCEIVER_TXDISABLE_ATTR_ID(58), + TRANSCEIVER_TXDISABLE_ATTR_ID(59), + TRANSCEIVER_TXDISABLE_ATTR_ID(60), + TRANSCEIVER_TXDISABLE_ATTR_ID(61), + TRANSCEIVER_TXDISABLE_ATTR_ID(62), + TRANSCEIVER_TXDISABLE_ATTR_ID(63), + TRANSCEIVER_TXDISABLE_ATTR_ID(64), + TRANSCEIVER_TXDISABLE_ATTR_ID(67), + TRANSCEIVER_TXDISABLE_ATTR_ID(68), + TRANSCEIVER_TXDISABLE_ATTR_ID(69), + TRANSCEIVER_TXDISABLE_ATTR_ID(70), + TRANSCEIVER_TXDISABLE_ATTR_ID(71), + TRANSCEIVER_TXDISABLE_ATTR_ID(72), + TRANSCEIVER_TXDISABLE_ATTR_ID(73), + TRANSCEIVER_TXDISABLE_ATTR_ID(74), +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int asgvolt64_cpld_read_internal(struct i2c_client *client, u8 reg); +static int asgvolt64_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value); + +/* sfp transceiver attributes */ +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_TXFAULT_##index); + +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_present_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +/* qsfp transceiver attributes */ +#define DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index); + +#define DECLARE_QSFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_present_##index.dev_attr.attr + +/*gpon transceiver attributes*/ +#define DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_tx_disable, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_TXFAULT_##index); + +#define DECLARE_GPON_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_present_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); + + + +/* transceiver attributes */ +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(1); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(2); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(3); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(4); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(5); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(6); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(7); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(8); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(9); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(10); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(11); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(12); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(13); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(14); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(15); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(16); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(17); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(18); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(19); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(20); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(21); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(22); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(23); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(24); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(31); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(32); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(33); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(34); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(35); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(36); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(37); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(38); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(39); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(40); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(41); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(42); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(43); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(44); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(45); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(46); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(47); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(48); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(49); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(50); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(51); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(52); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(53); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(54); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(55); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(56); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(57); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(58); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(59); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(60); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(61); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(62); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(63); +DECLARE_GPON_TRANSCEIVER_SENSOR_DEVICE_ATTR(64); + +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(67); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(68); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(69); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(70); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(71); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(72); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(73); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(74); + +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(65); +DECLARE_QSFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(66); + +static struct attribute *asgvolt64_cpld1_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /*xfp*/ + DECLARE_GPON_TRANSCEIVER_ATTR(1), + DECLARE_GPON_TRANSCEIVER_ATTR(2), + DECLARE_GPON_TRANSCEIVER_ATTR(3), + DECLARE_GPON_TRANSCEIVER_ATTR(4), + DECLARE_GPON_TRANSCEIVER_ATTR(5), + DECLARE_GPON_TRANSCEIVER_ATTR(6), + DECLARE_GPON_TRANSCEIVER_ATTR(7), + DECLARE_GPON_TRANSCEIVER_ATTR(8), + DECLARE_GPON_TRANSCEIVER_ATTR(9), + DECLARE_GPON_TRANSCEIVER_ATTR(10), + DECLARE_GPON_TRANSCEIVER_ATTR(11), + DECLARE_GPON_TRANSCEIVER_ATTR(12), + DECLARE_GPON_TRANSCEIVER_ATTR(13), + DECLARE_GPON_TRANSCEIVER_ATTR(14), + DECLARE_GPON_TRANSCEIVER_ATTR(15), + DECLARE_GPON_TRANSCEIVER_ATTR(16), + DECLARE_GPON_TRANSCEIVER_ATTR(17), + DECLARE_GPON_TRANSCEIVER_ATTR(18), + DECLARE_GPON_TRANSCEIVER_ATTR(21), + DECLARE_GPON_TRANSCEIVER_ATTR(22), + DECLARE_GPON_TRANSCEIVER_ATTR(25), + DECLARE_GPON_TRANSCEIVER_ATTR(26), + /*100g qsfp*/ + DECLARE_QSFP_TRANSCEIVER_ATTR(65), + DECLARE_QSFP_TRANSCEIVER_ATTR(66), + NULL +}; + +static struct attribute *asgvolt64_cpld2_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /*xfp*/ + DECLARE_GPON_TRANSCEIVER_ATTR(19), + DECLARE_GPON_TRANSCEIVER_ATTR(20), + DECLARE_GPON_TRANSCEIVER_ATTR(23), + DECLARE_GPON_TRANSCEIVER_ATTR(24), + DECLARE_GPON_TRANSCEIVER_ATTR(26), + DECLARE_GPON_TRANSCEIVER_ATTR(27), + DECLARE_GPON_TRANSCEIVER_ATTR(28), + DECLARE_GPON_TRANSCEIVER_ATTR(29), + DECLARE_GPON_TRANSCEIVER_ATTR(30), + DECLARE_GPON_TRANSCEIVER_ATTR(31), + DECLARE_GPON_TRANSCEIVER_ATTR(32), + DECLARE_GPON_TRANSCEIVER_ATTR(33), + DECLARE_GPON_TRANSCEIVER_ATTR(34), + DECLARE_GPON_TRANSCEIVER_ATTR(37), + DECLARE_GPON_TRANSCEIVER_ATTR(38), + DECLARE_GPON_TRANSCEIVER_ATTR(41), + DECLARE_GPON_TRANSCEIVER_ATTR(42), + DECLARE_GPON_TRANSCEIVER_ATTR(44), + DECLARE_GPON_TRANSCEIVER_ATTR(45), + DECLARE_GPON_TRANSCEIVER_ATTR(46), + DECLARE_GPON_TRANSCEIVER_ATTR(47), + DECLARE_GPON_TRANSCEIVER_ATTR(48), + /*25g sfp*/ + DECLARE_SFP_TRANSCEIVER_ATTR(67), + DECLARE_SFP_TRANSCEIVER_ATTR(68), + DECLARE_SFP_TRANSCEIVER_ATTR(69), + DECLARE_SFP_TRANSCEIVER_ATTR(70), + DECLARE_SFP_TRANSCEIVER_ATTR(71), + DECLARE_SFP_TRANSCEIVER_ATTR(72), + DECLARE_SFP_TRANSCEIVER_ATTR(73), + DECLARE_SFP_TRANSCEIVER_ATTR(74), + + NULL +}; + +static struct attribute *asgvolt64_cpld3_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /*xfp*/ + DECLARE_GPON_TRANSCEIVER_ATTR(35), + DECLARE_GPON_TRANSCEIVER_ATTR(36), + DECLARE_GPON_TRANSCEIVER_ATTR(39), + DECLARE_GPON_TRANSCEIVER_ATTR(40), + DECLARE_GPON_TRANSCEIVER_ATTR(43), + DECLARE_GPON_TRANSCEIVER_ATTR(49), + DECLARE_GPON_TRANSCEIVER_ATTR(50), + DECLARE_GPON_TRANSCEIVER_ATTR(51), + DECLARE_GPON_TRANSCEIVER_ATTR(52), + DECLARE_GPON_TRANSCEIVER_ATTR(53), + DECLARE_GPON_TRANSCEIVER_ATTR(54), + DECLARE_GPON_TRANSCEIVER_ATTR(55), + DECLARE_GPON_TRANSCEIVER_ATTR(56), + DECLARE_GPON_TRANSCEIVER_ATTR(57), + DECLARE_GPON_TRANSCEIVER_ATTR(58), + DECLARE_GPON_TRANSCEIVER_ATTR(59), + DECLARE_GPON_TRANSCEIVER_ATTR(60), + DECLARE_GPON_TRANSCEIVER_ATTR(61), + DECLARE_GPON_TRANSCEIVER_ATTR(62), + DECLARE_GPON_TRANSCEIVER_ATTR(63), + DECLARE_GPON_TRANSCEIVER_ATTR(64), + NULL +}; + +static const struct attribute_group asgvolt64_cpld1_group = { + .attrs = asgvolt64_cpld1_attributes, +}; + + +static const struct attribute_group asgvolt64_cpld2_group = { + .attrs = asgvolt64_cpld2_attributes, +}; + +static const struct attribute_group asgvolt64_cpld3_group = { + .attrs = asgvolt64_cpld3_attributes, +}; + + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct asgvolt64_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, revert = 0, addr=0x60; + + switch (attr->index) + { + /*100g QSFP*/ + case MODULE_PRESENT_65 ... MODULE_PRESENT_66: + addr=0x60; + reg=0x34; + mask = 0x1 << (attr->index- MODULE_PRESENT_65); + break; + /*25g sfp*/ + case MODULE_PRESENT_67 ... MODULE_PRESENT_74: + addr=0x61; + reg=0x9; + mask = 0x1 << (attr->index- MODULE_PRESENT_67); + break; + case MODULE_TXFAULT_67 ... MODULE_TXFAULT_74: + addr=0x61; + reg=0x17; + mask = 0x1 << (attr->index- MODULE_TXFAULT_67); + break; + case MODULE_TXDISABLE_67 ... MODULE_TXDISABLE_74: + reg=0x25; + addr=0x61; + mask = 0x1 << (attr->index- MODULE_TXFAULT_67); + break; + case MODULE_RXLOS_67 ... MODULE_RXLOS_74: + reg=0x43; + addr=0x61; + mask = 0x1 << (attr->index- MODULE_RXLOS_67); + break; + + /*gpon*/ + /*cpld1:present_1, 0x3*/ + case MODULE_PRESENT_1 ... MODULE_PRESENT_2: + addr=0x60; + reg=0x3; + mask=0x1 << (attr->index-MODULE_PRESENT_1); + break; + case MODULE_PRESENT_5 ... MODULE_PRESENT_6: + addr=0x60; + reg=0x3; + mask=0x1 << (attr->index-MODULE_PRESENT_5 + 2); + break; + case MODULE_PRESENT_9 ... MODULE_PRESENT_10: + addr=0x60; + reg=0x3; + mask=0x1 << (attr->index-MODULE_PRESENT_9 + 4); + break; + case MODULE_PRESENT_13 ... MODULE_PRESENT_14: + addr=0x60; + reg=0x3; + mask=0x1 << (attr->index-MODULE_PRESENT_13 + 6); + break; + /*cpld1:present_2, 0x5, */ + case MODULE_PRESENT_15 ... MODULE_PRESENT_16: + addr=0x60; + reg=0x5; + mask=0x1 << ((attr->index==MODULE_PRESENT_15)?1:0); + break; + case MODULE_PRESENT_11 ... MODULE_PRESENT_12: + addr=0x60; + reg=0x5; + mask=0x1 << ((attr->index==MODULE_PRESENT_11)?3:2); + break; + case MODULE_PRESENT_7 ... MODULE_PRESENT_8: + addr=0x60; + reg=0x5; + mask=0x1 << ((attr->index==MODULE_PRESENT_7)?5:4); + break; + case MODULE_PRESENT_3 ... MODULE_PRESENT_4: + addr=0x60; + reg=0x5; + mask=0x1 << ((attr->index==MODULE_PRESENT_3)?7:6); + break; + /*cpld1:present_3, 0x7*/ + case MODULE_PRESENT_17 ... MODULE_PRESENT_18: + addr=0x60; + reg=0x7; + mask=0x1 << ((attr->index==MODULE_PRESENT_17)?0:1); + break; + case MODULE_PRESENT_21 ... MODULE_PRESENT_22: + addr=0x60; + reg=0x7; + mask=0x1 << ((attr->index==MODULE_PRESENT_21)?2:3); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_26: + addr=0x60; + reg=0x7; + mask=0x1 << ((attr->index==MODULE_PRESENT_25)?4:5); + break; + + /*cpld1:tx_fault_1,0x9*/ + case MODULE_TXFAULT_1 ... MODULE_TXFAULT_2: + addr=0x60; + reg=0x9; + mask=0x1 << (attr->index==MODULE_TXFAULT_1?0:1); + break; + case MODULE_TXFAULT_5 ... MODULE_TXFAULT_6: + addr=0x60; + reg=0x9; + mask=0x1 << (attr->index==MODULE_TXFAULT_5?2:3); + break; + case MODULE_TXFAULT_9 ... MODULE_TXFAULT_10: + addr=0x60; + reg=0x9; + mask=0x1 << (attr->index==MODULE_PRESENT_9?4:5); + break; + case MODULE_TXFAULT_13 ... MODULE_TXFAULT_14: + addr=0x60; + reg=0x9; + mask=0x1 << (attr->index==MODULE_TXFAULT_13?6:7); + break; + /*cpld1:tx_fault_2, 0x11*/ + case MODULE_TXFAULT_15 ... MODULE_TXFAULT_16: + addr=0x60; + reg=0x11; + mask=0x1 << ((attr->index==MODULE_TXFAULT_15)?1:0); + break; + case MODULE_TXFAULT_11 ... MODULE_TXFAULT_12: + addr=0x60; + reg=0x11; + mask=0x1 << ((attr->index==MODULE_TXFAULT_11)?3:2); + break; + case MODULE_TXFAULT_7 ... MODULE_TXFAULT_8: + addr=0x60; + reg=0x11; + mask=0x1 << ((attr->index==MODULE_TXFAULT_7)?5:4); + break; + case MODULE_TXFAULT_3 ... MODULE_TXFAULT_4: + addr=0x60; + reg=0x11; + mask=0x1 << ((attr->index==MODULE_TXFAULT_3)?7:6); + break; + /*cpld1:tx_fault_3, 0x13*/ + case MODULE_TXFAULT_17 ... MODULE_TXFAULT_18: + addr=0x60; + reg=0x13; + mask=0x1 << ((attr->index==MODULE_TXFAULT_17)?0:1); + break; + case MODULE_TXFAULT_21 ... MODULE_TXFAULT_22: + addr=0x60; + reg=0x13; + mask=0x1 << ((attr->index==MODULE_TXFAULT_21)?2:3); + break; + case MODULE_TXFAULT_25 ... MODULE_TXFAULT_26: + addr=0x60; + reg=0x13; + mask=0x1 << ((attr->index==MODULE_TXFAULT_25)?4:5); + break; + + /*cpld1:tx_disable_1,0x15*/ + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_2: + addr=0x60; + reg=0x15; + mask=0x1 << (attr->index==MODULE_TXDISABLE_1?0:1); + break; + case MODULE_TXDISABLE_5 ... MODULE_TXDISABLE_6: + addr=0x60; + reg=0x15; + mask=0x1 << (attr->index==MODULE_TXDISABLE_5?2:3); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_10: + addr=0x60; + reg=0x15; + mask=0x1 << (attr->index==MODULE_TXDISABLE_9?4:5); + break; + case MODULE_TXDISABLE_13 ... MODULE_TXDISABLE_14: + addr=0x60; + reg=0x15; + mask=0x1 << (attr->index==MODULE_TXDISABLE_13?6:7); + break; + /*cpld1:tx_disable_2, 0x17*/ + case MODULE_TXDISABLE_15 ... MODULE_TXDISABLE_16: + addr=0x60; + reg=0x17; + mask=0x1 << ((attr->index==MODULE_TXDISABLE_15)?1:0); + break; + case MODULE_TXDISABLE_11 ... MODULE_TXDISABLE_12: + addr=0x60; + reg=0x17; + mask=0x1 << ((attr->index==MODULE_TXDISABLE_11)?3:2); + break; + case MODULE_TXDISABLE_7 ... MODULE_TXDISABLE_8: + addr=0x60; + reg=0x17; + mask=0x1 << ((attr->index==MODULE_TXDISABLE_7)?5:4); + break; + case MODULE_TXDISABLE_3 ... MODULE_TXDISABLE_4: + addr=0x60; + reg=0x17; + mask=0x1 << ((attr->index==MODULE_TXDISABLE_3)?7:6); + break; + /*cpld1:tx_disable_3, 0x19*/ + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_18: + addr=0x60; + reg=0x19; + mask=0x1 << ((attr->index==MODULE_TXDISABLE_17)?0:1); + break; + case MODULE_TXDISABLE_21 ... MODULE_TXDISABLE_22: + addr=0x60; + reg=0x19; + mask=0x1 << ((attr->index==MODULE_TXDISABLE_21)?2:3); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_26: + addr=0x60; + reg=0x19; + mask=0x1 << ((attr->index==MODULE_TXDISABLE_25)?4:5); + break; + + /*cpld2:present_1, 0x3*/ + case MODULE_PRESENT_29 ... MODULE_PRESENT_30: + addr=0x61; + reg=0x3; + mask=0x1 << (attr->index==MODULE_PRESENT_29?0:1); + break; + case MODULE_PRESENT_31 ... MODULE_PRESENT_32: + addr=0x61; + reg=0x3; + mask=0x1 << (attr->index==MODULE_PRESENT_31?3:2); + break; + case MODULE_PRESENT_27 ... MODULE_PRESENT_28: + addr=0x61; + reg=0x3; + mask=0x1 << (attr->index==MODULE_PRESENT_27?5:4); + break; + case MODULE_PRESENT_23 ... MODULE_PRESENT_24: + addr=0x61; + reg=0x3; + mask=0x1 << (attr->index==MODULE_PRESENT_23?7:6); + break; + /*cpld2:present_2, 0x5*/ + case MODULE_PRESENT_19 ... MODULE_PRESENT_20: + addr=0x61; + reg=0x5; + mask=0x1 << (attr->index==MODULE_PRESENT_19?1:0); + break; + case MODULE_PRESENT_33 ... MODULE_PRESENT_34: + addr=0x61; + reg=0x5; + mask=0x1 << (attr->index==MODULE_PRESENT_33?2:3); + break; + case MODULE_PRESENT_37 ... MODULE_PRESENT_38: + addr=0x61; + reg=0x5; + mask=0x1 << (attr->index==MODULE_PRESENT_37?4:5); + break; + case MODULE_PRESENT_41 ... MODULE_PRESENT_42: + addr=0x61; + reg=0x5; + mask=0x1 << (attr->index==MODULE_PRESENT_41?6:7); + break; + /*cpld2:present_3, 0x7*/ + case MODULE_PRESENT_45 ... MODULE_PRESENT_46: + addr=0x61; + reg=0x7; + mask=0x1 << (attr->index==MODULE_PRESENT_45?0:1); + break; + case MODULE_PRESENT_47 ... MODULE_PRESENT_48: + addr=0x61; + reg=0x7; + mask=0x1 << (attr->index==MODULE_PRESENT_47?3:2); + break; + case MODULE_PRESENT_44: + addr=0x61; + reg=0x7; + mask=0x1 << 4; + break; + + /*cpld2:tx_fault_1, 0x11*/ + case MODULE_TXFAULT_29 ... MODULE_TXFAULT_30: + addr=0x61; + reg=0x11; + mask=0x1 << (attr->index==MODULE_TXFAULT_29?0:1); + break; + case MODULE_TXFAULT_31 ... MODULE_TXFAULT_32: + addr=0x61; + reg=0x11; + mask=0x1 << (attr->index==MODULE_TXFAULT_31?3:2); + break; + case MODULE_TXFAULT_27 ... MODULE_TXFAULT_28: + addr=0x61; + reg=0x11; + mask=0x1 << (attr->index==MODULE_TXFAULT_27?5:4); + break; + case MODULE_TXFAULT_23 ... MODULE_TXFAULT_24: + addr=0x61; + reg=0x11; + mask=0x1 << (attr->index==MODULE_TXFAULT_23?7:6); + break; + /*cpld2:tx_fault_2, 0x13*/ + case MODULE_TXFAULT_19 ... MODULE_TXFAULT_20: + addr=0x61; + reg=0x13; + mask=0x1 << (attr->index==MODULE_TXFAULT_19?1:0); + break; + case MODULE_TXFAULT_33 ... MODULE_TXFAULT_34: + addr=0x61; + reg=0x13; + mask=0x1 << (attr->index==MODULE_TXFAULT_33?2:3); + break; + case MODULE_TXFAULT_37 ... MODULE_TXFAULT_38: + addr=0x61; + reg=0x13; + mask=0x1 << (attr->index==MODULE_TXFAULT_37?4:5); + break; + case MODULE_TXFAULT_41 ... MODULE_TXFAULT_42: + addr=0x61; + reg=0x13; + mask=0x1 << (attr->index==MODULE_TXFAULT_41?6:7); + break; + /*cpld2:tx_fault_3, 0x15*/ + case MODULE_TXFAULT_45 ... MODULE_TXFAULT_46: + addr=0x61; + reg=0x15; + mask=0x1 << (attr->index==MODULE_TXFAULT_45?0:1); + break; + case MODULE_TXFAULT_47 ... MODULE_TXFAULT_48: + addr=0x61; + reg=0x15; + mask=0x1 << (attr->index==MODULE_TXFAULT_47?3:2); + break; + case MODULE_TXFAULT_44: + addr=0x61; + reg=0x15; + mask=0x1 << 4; + break; + + /*cpld2:tx_disable_1, 0x19*/ + case MODULE_TXDISABLE_29 ... MODULE_TXDISABLE_30: + addr=0x61; + reg=0x19; + mask=0x1 << (attr->index==MODULE_TXDISABLE_29?0:1); + break; + case MODULE_TXDISABLE_31 ... MODULE_TXDISABLE_32: + addr=0x61; + reg=0x19; + mask=0x1 << (attr->index==MODULE_TXDISABLE_31?3:2); + break; + case MODULE_TXDISABLE_27 ... MODULE_TXDISABLE_28: + addr=0x61; + reg=0x19; + mask=0x1 << (attr->index==MODULE_TXDISABLE_27?5:4); + break; + case MODULE_TXDISABLE_23 ... MODULE_TXDISABLE_24: + addr=0x61; + reg=0x19; + mask=0x1 << (attr->index==MODULE_TXDISABLE_23?7:6); + break; + /*cpld2:tx_disable_2, 0x21*/ + case MODULE_TXDISABLE_19 ... MODULE_TXDISABLE_20: + addr=0x61; + reg=0x21; + mask=0x1 << (attr->index==MODULE_TXDISABLE_19?1:0); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_34: + addr=0x61; + reg=0x21; + mask=0x1 << (attr->index==MODULE_TXDISABLE_33?2:3); + break; + case MODULE_TXDISABLE_37 ... MODULE_TXDISABLE_38: + addr=0x61; + reg=0x21; + mask=0x1 << (attr->index==MODULE_TXDISABLE_37?4:5); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_42: + addr=0x61; + reg=0x21; + mask=0x1 << (attr->index==MODULE_TXDISABLE_41?6:7); + break; + /*cpld2:tx_disable_3, 0x23*/ + case MODULE_TXDISABLE_45 ... MODULE_TXDISABLE_46: + addr=0x61; + reg=0x23; + mask=0x1 << (attr->index==MODULE_TXDISABLE_45?0:1); + break; + case MODULE_TXDISABLE_47 ... MODULE_TXDISABLE_48: + addr=0x61; + reg=0x23; + mask=0x1 << (attr->index==MODULE_TXDISABLE_47?3:2); + break; + case MODULE_TXDISABLE_44: + addr=0x61; + reg=0x23; + mask=0x1 << 4; + break; + + /*cpld3:present_1, 0x3*/ + case MODULE_PRESENT_43: + addr=0x62; + reg=0x3; + mask=0x1; + break; + case MODULE_PRESENT_39 ... MODULE_PRESENT_40: + addr=0x62; + reg=0x3; + mask=0x1 << (attr->index==MODULE_PRESENT_39?2:1); + break; + case MODULE_PRESENT_35 ... MODULE_PRESENT_36: + addr=0x62; + reg=0x3; + mask=0x1 << (attr->index==MODULE_PRESENT_35?4:3); + break; + case MODULE_PRESENT_49 ... MODULE_PRESENT_50: + addr=0x62; + reg=0x3; + mask=0x1 << (attr->index==MODULE_PRESENT_49?5:6); + break; + case MODULE_PRESENT_53: + addr=0x62; + reg=0x3; + mask=0x1 <<7; + break; + /*cpld3:present_2, 0x5*/ + case MODULE_PRESENT_54: + addr=0x62; + reg=0x5; + mask=0x1; + break; + case MODULE_PRESENT_57 ... MODULE_PRESENT_58: + addr=0x62; + reg=0x5; + mask=0x1 << (attr->index==MODULE_PRESENT_57?1:2); + break; + case MODULE_PRESENT_61 ... MODULE_PRESENT_62: + addr=0x62; + reg=0x5; + mask=0x1 << (attr->index==MODULE_PRESENT_61?3:4); + break; + case MODULE_PRESENT_63 ... MODULE_PRESENT_64: + addr=0x62; + reg=0x5; + mask=0x1 << (attr->index==MODULE_PRESENT_63?6:5); + break; + case MODULE_PRESENT_60: + addr=0x62; + reg=0x5; + mask=0x1 <<7; + break; + /*cpld3:present_3, 0x7*/ + case MODULE_PRESENT_59: + addr=0x62; + reg=0x7; + mask=0x1; + break; + case MODULE_PRESENT_55 ... MODULE_PRESENT_56: + addr=0x62; + reg=0x7; + mask=0x1 << (attr->index==MODULE_PRESENT_55?2:1); + break; + case MODULE_PRESENT_51 ... MODULE_PRESENT_52: + addr=0x62; + reg=0x7; + mask=0x1 << (attr->index==MODULE_PRESENT_51?4:3); + break; + + /*cpld3:tx_fault_1, 0x9*/ + case MODULE_TXFAULT_43: + addr=0x62; + reg=0x9; + mask=0x1; + break; + case MODULE_TXFAULT_39 ... MODULE_TXFAULT_40: + addr=0x62; + reg=0x9; + mask=0x1 << (attr->index==MODULE_TXFAULT_39?2:1); + break; + case MODULE_TXFAULT_35 ... MODULE_TXFAULT_36: + addr=0x62; + reg=0x9; + mask=0x1 << (attr->index==MODULE_TXFAULT_35?4:3); + break; + case MODULE_TXFAULT_49 ... MODULE_TXFAULT_50: + addr=0x62; + reg=0x9; + mask=0x1 << (attr->index==MODULE_TXFAULT_49?5:6); + break; + case MODULE_TXFAULT_53: + addr=0x62; + reg=0x9; + mask=0x1 <<7; + break; + /*cpld3:tx_fault_2, 0x11*/ + case MODULE_TXFAULT_54: + addr=0x62; + reg=0x11; + mask=0x1; + break; + case MODULE_TXFAULT_57 ... MODULE_TXFAULT_58: + addr=0x62; + reg=0x11; + mask=0x1 << (attr->index==MODULE_TXFAULT_57?1:2); + break; + case MODULE_TXFAULT_61 ... MODULE_TXFAULT_62: + addr=0x62; + reg=0x11; + mask=0x1 << (attr->index==MODULE_TXFAULT_61?3:4); + break; + case MODULE_TXFAULT_63 ... MODULE_TXFAULT_64: + addr=0x62; + reg=0x11; + mask=0x1 << (attr->index==MODULE_TXFAULT_63?6:5); + break; + case MODULE_TXFAULT_60: + addr=0x62; + reg=0x11; + mask=0x1 <<7; + break; + /*cpld3:tx_fault_3, 0x13*/ + case MODULE_TXFAULT_59: + addr=0x62; + reg=0x13; + mask=0x1; + break; + case MODULE_TXFAULT_55 ... MODULE_TXFAULT_56: + addr=0x62; + reg=0x13; + mask=0x1 << (attr->index==MODULE_TXFAULT_55?2:1); + break; + case MODULE_TXFAULT_51 ... MODULE_TXFAULT_52: + addr=0x62; + reg=0x13; + mask=0x1 << (attr->index==MODULE_TXFAULT_51?4:3); + break; + + /*cpld3:tx_disable_1, 0x15*/ + case MODULE_TXDISABLE_43: + addr=0x62; + reg=0x15; + mask=0x1; + break; + case MODULE_TXDISABLE_39 ... MODULE_TXDISABLE_40: + addr=0x62; + reg=0x15; + mask=0x1 << (attr->index==MODULE_TXDISABLE_39?2:1); + break; + case MODULE_TXDISABLE_35 ... MODULE_TXDISABLE_36: + addr=0x62; + reg=0x15; + mask=0x1 << (attr->index==MODULE_TXDISABLE_35?4:3); + break; + case MODULE_TXDISABLE_49 ... MODULE_TXDISABLE_50: + addr=0x62; + reg=0x15; + mask=0x1 << (attr->index==MODULE_TXDISABLE_49?5:6); + break; + case MODULE_TXDISABLE_53: + addr=0x62; + reg=0x15; + mask=0x1 <<7; + break; + /*cpld3:tx_disable_2, 0x17*/ + case MODULE_TXDISABLE_54: + addr=0x62; + reg=0x17; + mask=0x1; + break; + case MODULE_TXDISABLE_57 ... MODULE_TXDISABLE_58: + addr=0x62; + reg=0x17; + mask=0x1 << (attr->index==MODULE_TXDISABLE_57?1:2); + break; + case MODULE_TXDISABLE_61 ... MODULE_TXDISABLE_62: + addr=0x62; + reg=0x17; + mask=0x1 << (attr->index==MODULE_TXDISABLE_61?3:4); + break; + case MODULE_TXDISABLE_63 ... MODULE_TXDISABLE_64: + addr=0x62; + reg=0x17; + mask=0x1 << (attr->index==MODULE_TXDISABLE_63?6:5); + break; + case MODULE_TXDISABLE_60: + addr=0x62; + reg=0x17; + mask=0x1 <<7; + break; + /*cpld3:tx_disable_3, 0x19*/ + case MODULE_TXDISABLE_59: + addr=0x62; + reg=0x19; + mask=0x1; + break; + case MODULE_TXDISABLE_55 ... MODULE_TXDISABLE_56: + addr=0x62; + reg=0x19; + mask=0x1 << (attr->index==MODULE_TXDISABLE_55?2:1); + break; + case MODULE_TXDISABLE_51 ... MODULE_TXDISABLE_52: + addr=0x62; + reg=0x19; + mask=0x1 << (attr->index==MODULE_TXDISABLE_51?4:3); + break; + default: + return 0; + } + + if( attr->index >= MODULE_PRESENT_1 && attr->index <= MODULE_PRESENT_74 ) + { + revert = 1; + } + + mutex_lock(&data->update_lock); + status = asgvolt64_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", revert ? !(status & mask) : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_tx_disable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct asgvolt64_cpld_data *data = i2c_get_clientdata(client); + long disable; + int status; + u8 reg = 0, mask = 0, addr=0x60; + + status = kstrtol(buf, 10, &disable); + if (status) { + //return status; + status=1; + } + else + status=0; + + switch (attr->index) + { + /*25g sfp*/ + case MODULE_TXDISABLE_67 ... MODULE_TXDISABLE_74: + addr=0x61; + reg=0x25; + mask=0x1 << (attr->index - MODULE_TXDISABLE_67); + break; + + /*gpon*/ + /*cpld1:tx_disable_1,0x15*/ + case MODULE_TXDISABLE_1 ... MODULE_TXDISABLE_2: + addr=0x60; + reg=0x15; + mask=0x1 << (attr->index==MODULE_TXDISABLE_1?0:1); + break; + case MODULE_TXDISABLE_5 ... MODULE_TXDISABLE_6: + addr=0x60; + reg=0x15; + mask=0x1 << (attr->index==MODULE_TXDISABLE_5?2:3); + break; + case MODULE_TXDISABLE_9 ... MODULE_TXDISABLE_10: + addr=0x60; + reg=0x15; + mask=0x1 << (attr->index==MODULE_TXDISABLE_9?4:5); + break; + case MODULE_TXDISABLE_13 ... MODULE_TXDISABLE_14: + addr=0x60; + reg=0x15; + mask=0x1 << (attr->index==MODULE_TXDISABLE_13?6:7); + break; + /*cpld1:tx_disable_2, 0x17*/ + case MODULE_TXDISABLE_15 ... MODULE_TXDISABLE_16: + addr=0x60; + reg=0x17; + mask=0x1 << ((attr->index==MODULE_TXDISABLE_15)?1:0); + break; + case MODULE_TXDISABLE_11 ... MODULE_TXDISABLE_12: + addr=0x60; + reg=0x17; + mask=0x1 << ((attr->index==MODULE_TXDISABLE_11)?3:2); + break; + case MODULE_TXDISABLE_7 ... MODULE_TXDISABLE_8: + addr=0x60; + reg=0x17; + mask=0x1 << ((attr->index==MODULE_TXDISABLE_7)?5:4); + break; + case MODULE_TXDISABLE_3 ... MODULE_TXDISABLE_4: + addr=0x60; + reg=0x17; + mask=0x1 << ((attr->index==MODULE_TXDISABLE_3)?7:6); + break; + /*cpld1:tx_disable_3, 0x19*/ + case MODULE_TXDISABLE_17 ... MODULE_TXDISABLE_18: + addr=0x60; + reg=0x19; + mask=0x1 << ((attr->index==MODULE_TXDISABLE_17)?0:1); + break; + case MODULE_TXDISABLE_21 ... MODULE_TXDISABLE_22: + addr=0x60; + reg=0x19; + mask=0x1 << ((attr->index==MODULE_TXDISABLE_21)?2:3); + break; + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_26: + addr=0x60; + reg=0x19; + mask=0x1 << ((attr->index==MODULE_TXDISABLE_25)?4:5); + break; + + /*cpld2:tx_disable_1, 0x19*/ + case MODULE_TXDISABLE_29 ... MODULE_TXDISABLE_30: + addr=0x61; + reg=0x19; + mask=0x1 << (attr->index==MODULE_TXDISABLE_29?0:1); + break; + case MODULE_TXDISABLE_31 ... MODULE_TXDISABLE_32: + addr=0x61; + reg=0x19; + mask=0x1 << (attr->index==MODULE_TXDISABLE_31?3:2); + break; + case MODULE_TXDISABLE_27 ... MODULE_TXDISABLE_28: + addr=0x61; + reg=0x19; + mask=0x1 << (attr->index==MODULE_TXDISABLE_27?5:4); + break; + case MODULE_TXDISABLE_23 ... MODULE_TXDISABLE_24: + addr=0x61; + reg=0x19; + mask=0x1 << (attr->index==MODULE_TXDISABLE_23?7:6); + break; + /*cpld2:tx_disable_2, 0x21*/ + case MODULE_TXDISABLE_19 ... MODULE_TXDISABLE_20: + addr=0x61; + reg=0x21; + mask=0x1 << (attr->index==MODULE_TXDISABLE_19?1:0); + break; + case MODULE_TXDISABLE_33 ... MODULE_TXDISABLE_34: + addr=0x61; + reg=0x21; + mask=0x1 << (attr->index==MODULE_TXDISABLE_33?2:3); + break; + case MODULE_TXDISABLE_37 ... MODULE_TXDISABLE_38: + addr=0x61; + reg=0x21; + mask=0x1 << (attr->index==MODULE_TXDISABLE_37?4:5); + break; + case MODULE_TXDISABLE_41 ... MODULE_TXDISABLE_42: + addr=0x61; + reg=0x21; + mask=0x1 << (attr->index==MODULE_TXDISABLE_41?6:7); + break; + /*cpld2:tx_disable_3, 0x23*/ + case MODULE_TXDISABLE_45 ... MODULE_TXDISABLE_46: + addr=0x61; + reg=0x23; + mask=0x1 << (attr->index==MODULE_TXDISABLE_45?0:1); + break; + case MODULE_TXDISABLE_47 ... MODULE_TXDISABLE_48: + addr=0x61; + reg=0x23; + mask=0x1 << (attr->index==MODULE_TXDISABLE_47?3:2); + break; + case MODULE_TXDISABLE_44: + addr=0x61; + reg=0x23; + mask=0x1 << 4; + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = asgvolt64_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + /* Update tx_disable status */ + if (disable) { + status |= mask; + } + else { + + status &= ~mask; + } + status = asgvolt64_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) { + goto exit; + } + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct asgvolt64_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) { + return -EINVAL; + } + + if (addr > 0xFF || val > 0xFF) { + return -EINVAL; + } + + mutex_lock(&data->update_lock); + status = asgvolt64_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void asgvolt64_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void asgvolt64_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *attr, char *buf) +{ + int val = 0; + struct i2c_client *client = to_i2c_client(dev); + + val = i2c_smbus_read_byte_data(client, 0x1); + + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", client->addr, val); + } + + return sprintf(buf, "%d\n", val); +} + + +/* + * I2C init/probing/exit functions + */ +static int asgvolt64_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct asgvolt64_cpld_data *data; + int ret = -ENODEV; + + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct asgvolt64_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + /* Register sysfs hooks */ + switch (data->type) + { + case asgvolt64_cpld1: + group = &asgvolt64_cpld1_group; + break; + case asgvolt64_cpld2: + group = &asgvolt64_cpld2_group; + break; + case asgvolt64_cpld3: + group = &asgvolt64_cpld3_group; + break; + + default: + break; + } + + if (group) + { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + asgvolt64_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int asgvolt64_cpld_remove(struct i2c_client *client) +{ + struct asgvolt64_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + asgvolt64_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) + { + case asgvolt64_cpld1: + group = &asgvolt64_cpld1_group; + break; + case asgvolt64_cpld2: + group = &asgvolt64_cpld2_group; + break; + case asgvolt64_cpld3: + group = &asgvolt64_cpld3_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int asgvolt64_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int asgvolt64_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int asgvolt64_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 = asgvolt64_cpld_read_internal(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(asgvolt64_cpld_read); + +int asgvolt64_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 = asgvolt64_cpld_write_internal(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(asgvolt64_cpld_write); + +static struct i2c_driver asgvolt64_cpld_driver = { + .driver = { + .name = "asgvolt64_cpld", + .owner = THIS_MODULE, + }, + .probe = asgvolt64_cpld_probe, + .remove = asgvolt64_cpld_remove, + .id_table = asgvolt64_cpld_id, +}; + +static int __init asgvolt64_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&asgvolt64_cpld_driver); +} + +static void __exit asgvolt64_cpld_exit(void) +{ + i2c_del_driver(&asgvolt64_cpld_driver); +} + +MODULE_AUTHOR("Jostar Yang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(asgvolt64_cpld_init); +module_exit(asgvolt64_cpld_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-fan.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-fan.c new file mode 100755 index 00000000..af0b7b81 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-fan.c @@ -0,0 +1,459 @@ +/* + * Copyright (C) Brandon Chuang + * + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "asgvolt64_fan" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_FAN_READ_CMD 0x14 +#define IPMI_FAN_WRITE_CMD 0x15 +#define IPMI_TIMEOUT (20 * HZ) + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t set_fan(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_fan(struct device *dev, struct device_attribute *attr, char *buf); +static int asgvolt64_fan_probe(struct platform_device *pdev); +static int asgvolt64_fan_remove(struct platform_device *pdev); + +enum fan_id { + FAN_1, + FAN_2, + FAN_3, + FAN_4, + NUM_OF_FAN +}; + +enum fan_data_index { + FAN_PRESENT, + FAN_PWM, + FAN_SPEED0, + FAN_SPEED1, + FAN_DATA_COUNT +}; + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct asgvolt64_fan_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + unsigned char ipmi_resp[24]; + struct ipmi_data ipmi; + unsigned char ipmi_tx_data[3]; /* 0: FAN id, 1: 0x02, 2: PWM */ +}; + +struct asgvolt64_fan_data *data = NULL; + +static struct platform_driver asgvolt64_fan_driver = { + .probe = asgvolt64_fan_probe, + .remove = asgvolt64_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +#define FAN_PRESENT_ATTR_ID(index) FAN##index##_PRESENT +#define FAN_PWM_ATTR_ID(index) FAN##index##_PWM +#define FAN_RPM_ATTR_ID(index) FAN##index##_INPUT + +#define FAN_ATTR(fan_id) \ + FAN_PRESENT_ATTR_ID(fan_id), \ + FAN_PWM_ATTR_ID(fan_id), \ + FAN_RPM_ATTR_ID(fan_id) + +enum asgvolt64_fan_sysfs_attrs { + FAN_ATTR(1), + FAN_ATTR(2), + FAN_ATTR(3), + FAN_ATTR(4), + NUM_OF_FAN_ATTR, + NUM_OF_PER_FAN_ATTR = (NUM_OF_FAN_ATTR/NUM_OF_FAN) +}; + +/* fan attributes */ +#define DECLARE_FAN_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, show_fan, NULL, FAN##index##_PRESENT); \ + static SENSOR_DEVICE_ATTR(fan##index##_pwm, S_IWUSR | S_IRUGO, show_fan, set_fan, FAN##index##_PWM); \ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, show_fan, NULL, FAN##index##_INPUT) +#define DECLARE_FAN_ATTR(index) \ + &sensor_dev_attr_fan##index##_present.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_pwm.dev_attr.attr, \ + &sensor_dev_attr_fan##index##_input.dev_attr.attr + +DECLARE_FAN_SENSOR_DEVICE_ATTR(1); +DECLARE_FAN_SENSOR_DEVICE_ATTR(2); +DECLARE_FAN_SENSOR_DEVICE_ATTR(3); +DECLARE_FAN_SENSOR_DEVICE_ATTR(4); + + +static struct attribute *asgvolt64_fan_attributes[] = { + /* fan attributes */ + DECLARE_FAN_ATTR(1), + DECLARE_FAN_ATTR(2), + DECLARE_FAN_ATTR(3), + DECLARE_FAN_ATTR(4), + NULL +}; + +static const struct attribute_group asgvolt64_fan_group = { + .attrs = asgvolt64_fan_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static struct asgvolt64_fan_data *asgvolt64_fan_update_device(void) +{ + int status = 0; + + if (time_before(jiffies, data->last_updated + HZ * 5) && data->valid) { + return data; + } + + data->valid = 0; + status = ipmi_send_message(&data->ipmi, IPMI_FAN_READ_CMD, NULL, 0, + data->ipmi_resp, sizeof(data->ipmi_resp)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + +exit: + return data; +} + +static ssize_t show_fan(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char fid = attr->index / NUM_OF_PER_FAN_ATTR; + int value = 0; + int index = 0; + int present = 0; + int error = 0; + + mutex_lock(&data->update_lock); + + data = asgvolt64_fan_update_device(); + if (!data->valid) { + error = -EIO; + goto exit; + } + + index = fid * FAN_DATA_COUNT; /* base index */ + present = !data->ipmi_resp[index + FAN_PRESENT]; + + switch (attr->index) { + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + value = !data->ipmi_resp[index + FAN_PRESENT]; + break; + case FAN1_PWM: + case FAN2_PWM: + case FAN3_PWM: + case FAN4_PWM: + value = (data->ipmi_resp[index + FAN_PWM] + 1) * 625 / 100; + break; + case FAN1_INPUT: + case FAN2_INPUT: + case FAN3_INPUT: + case FAN4_INPUT: + value = (int)data->ipmi_resp[index + FAN_SPEED0] | + (int)data->ipmi_resp[index + FAN_SPEED1] << 8; + break; + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", present ? value : 0); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t set_fan(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long pwm; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char fid = attr->index / NUM_OF_PER_FAN_ATTR; + + status = kstrtol(buf, 10, &pwm); + if (status) { + return status; + } + + pwm = (pwm * 100) / 625 - 1; /* Convert pwm to register value */ + + mutex_lock(&data->update_lock); + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = 1; /* All FANs share the same PWM register, ALWAYS set 1 for each fan */ + data->ipmi_tx_data[1] = 0x02; + data->ipmi_tx_data[2] = pwm; + status = ipmi_send_message(&data->ipmi, IPMI_FAN_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Update pwm to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp[fid * FAN_DATA_COUNT + FAN_PWM] = pwm; + status = count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int asgvolt64_fan_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &asgvolt64_fan_group); + if (status) { + goto exit; + } + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int asgvolt64_fan_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &asgvolt64_fan_group); + + return 0; +} + +static int __init asgvolt64_fan_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct asgvolt64_fan_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + data->valid = 0; + + ret = platform_driver_register(&asgvolt64_fan_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&asgvolt64_fan_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit asgvolt64_fan_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&asgvolt64_fan_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("ASGVOLT64 fan driver"); +MODULE_LICENSE("GPL"); + +module_init(asgvolt64_fan_init); +module_exit(asgvolt64_fan_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-leds.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-leds.c new file mode 100755 index 00000000..d7b81032 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-leds.c @@ -0,0 +1,527 @@ +/* + * A LED driver for the accton_asgvolt64_led + * + * Copyright (C) 2014 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 asgvolt64_cpld_read (unsigned short cpld_addr, u8 reg); +extern int asgvolt64_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +#define DRVNAME "accton_asgvolt64_led" + +struct accton_asgvolt64_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[2]; /* only 1 register*/ +}; + +static struct accton_asgvolt64_led_data *ledctl = NULL; + +/* LED related data + */ + +#define LED_CNTRLER_I2C_ADDRESS (0x60) + +#define LED_TYPE_STATE_REG_MASK (0x8|0x10|0x20) +#define LED_MODE_STATE_RED_VALUE 0x18 +#define LED_MODE_STATE_BLUE_VALUE 0x28 +#define LED_MODE_STATE_GREEN_VALUE 0x30 +#define LED_MODE_STATE_OFF_VALUE 0 + +#define LED_TYPE_ALARM_REG_MASK (0x1|0x2|0x4) +#define LED_MODE_ALARM_RED_VALUE 0x3 +#define LED_MODE_ALARM_BLUE_VALUE 0x5 +#define LED_MODE_ALARM_GREEN_VALUE 0x6 +#define LED_MODE_ALARM_OFF_VALUE 0 + +#define LED_TYPE_LOC_REG_MASK 0x1 +#define LED_MODE_LOC_AMBER_BLINK_VALUE 0x0 +#define LED_MODE_LOC_OFF_VALUE 0x1 + +#define LED_TYPE_FAN_REG_MASK (0x20|0x10) +#define LED_MODE_FAN_GREEN_VALUE 0x10 +#define LED_MODE_FAN_OFF_VALUE (0x0) + +#define LED_TYPE_PSU2_REG_MASK (0x80|0x40) +#define LED_MODE_PSU2_RED_VALUE 0x40 +#define LED_MODE_PSU2_GREEN_VALUE 0x80 +#define LED_MODE_PSU2_OFF_VALUE (0x0) + +#define LED_TYPE_PSU1_REG_MASK (0x20|0x10) +#define LED_MODE_PSU1_RED_VALUE 0x10 +#define LED_MODE_PSU1_GREEN_VALUE 0x20 +#define LED_MODE_PSU1_OFF_VALUE (0x0) + +enum led_type { + LED_TYPE_LOC, + LED_TYPE_STATE, + LED_TYPE_ALARM, + LED_TYPE_FAN, + LED_TYPE_PSU1, + LED_TYPE_PSU2 +}; + +struct led_reg { + u32 types; + u8 reg_addr; +}; + +static const struct led_reg led_reg_map[] = { + { (1<update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting accton_asgvolt64_led update\n"); + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = accton_asgvolt64_led_read_value(led_reg_map[i].reg_addr); + + if (status < 0) { + ledctl->valid = 0; + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status); + goto exit; + } + else + { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void accton_asgvolt64_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + enum led_type type) +{ + int reg_val; + u8 reg ; + mutex_lock(&ledctl->update_lock); + + if( !accton_getLedReg(type, ®)) + { + dev_dbg(&ledctl->pdev->dev, "Not match item for %d.\n", type); + } + + + reg_val = accton_asgvolt64_led_read_value(reg); + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + + accton_asgvolt64_led_write_value(reg, reg_val); + + /* to prevent the slow-update issue */ + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + + +static void accton_asgvolt64_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_asgvolt64_led_set(led_cdev, led_light_mode, LED_TYPE_LOC); +} + +static enum led_brightness accton_asgvolt64_led_loc_get(struct led_classdev *cdev) +{ + accton_asgvolt64_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + + +static void accton_asgvolt64_led_state_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_asgvolt64_led_set(led_cdev, led_light_mode, LED_TYPE_STATE); +} + +static enum led_brightness accton_asgvolt64_led_state_get(struct led_classdev *cdev) +{ + accton_asgvolt64_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_STATE, ledctl->reg_val[1]); +} + +static void accton_asgvolt64_led_alarm_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_asgvolt64_led_set(led_cdev, led_light_mode, LED_TYPE_ALARM); +} + +static enum led_brightness accton_asgvolt64_led_alarm_get(struct led_classdev *cdev) +{ + accton_asgvolt64_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_ALARM, ledctl->reg_val[1]); +} + +static void accton_asgvolt64_led_fan_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_asgvolt64_led_set(led_cdev, led_light_mode, LED_TYPE_FAN); +} + +static enum led_brightness accton_asgvolt64_led_fan_get(struct led_classdev *cdev) +{ + accton_asgvolt64_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[0]); +} + +static void accton_asgvolt64_led_psu1_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_asgvolt64_led_set(led_cdev, led_light_mode, LED_TYPE_PSU1); +} + +static enum led_brightness accton_asgvolt64_led_psu1_get(struct led_classdev *cdev) +{ + accton_asgvolt64_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU1, ledctl->reg_val[0]); +} + +static void accton_asgvolt64_led_psu2_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + accton_asgvolt64_led_set(led_cdev, led_light_mode, LED_TYPE_PSU2); +} + +static enum led_brightness accton_asgvolt64_led_psu2_get(struct led_classdev *cdev) +{ + accton_asgvolt64_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_PSU2, ledctl->reg_val[0]); +} + +static struct led_classdev accton_asgvolt64_leds[] = { + [LED_TYPE_LOC] = { + .name = "loc", + .default_trigger = "unused", + .brightness_set = accton_asgvolt64_led_loc_set, + .brightness_get = accton_asgvolt64_led_loc_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_LOC_AMBER_BLINK_VALUE, + }, + [LED_TYPE_STATE] = { + .name = "state", + .default_trigger = "unused", + .brightness_set = accton_asgvolt64_led_state_set, + .brightness_get = accton_asgvolt64_led_state_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_RED, + }, + [LED_TYPE_ALARM] = { + .name = "alarm", + .default_trigger = "unused", + .brightness_set = accton_asgvolt64_led_alarm_set, + .brightness_get = accton_asgvolt64_led_alarm_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_RED, + }, + [LED_TYPE_FAN] = { + .name = "fan", + .default_trigger = "unused", + .brightness_set = accton_asgvolt64_led_fan_set, + .brightness_get = accton_asgvolt64_led_fan_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU1] = { + .name = "psu1", + .default_trigger = "unused", + .brightness_set = accton_asgvolt64_led_psu1_set, + .brightness_get = accton_asgvolt64_led_psu1_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "psu2", + .default_trigger = "unused", + .brightness_set = accton_asgvolt64_led_psu2_set, + .brightness_get = accton_asgvolt64_led_psu2_get, + .flags = LED_CORE_SUSPENDRESUME, + .max_brightness = LED_MODE_AUTO, + }, +}; + +static int accton_asgvolt64_led_suspend(struct platform_device *dev, + pm_message_t state) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_asgvolt64_leds); i++) { + led_classdev_suspend(&accton_asgvolt64_leds[i]); + } + + return 0; +} + +static int accton_asgvolt64_led_resume(struct platform_device *dev) +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(accton_asgvolt64_leds); i++) { + led_classdev_resume(&accton_asgvolt64_leds[i]); + } + + return 0; +} + +static int accton_asgvolt64_led_probe(struct platform_device *pdev) +{ + int ret, i; + + ret=0; + i=0; + + for (i = 0; i < ARRAY_SIZE(accton_asgvolt64_leds); i++) { + ret = led_classdev_register(&pdev->dev, &accton_asgvolt64_leds[i]); + if (ret < 0) + { + break; + } + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(accton_asgvolt64_leds)) { + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) { + led_classdev_unregister(&accton_asgvolt64_leds[i]); + } + } + + return ret; +} + +static int accton_asgvolt64_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(accton_asgvolt64_leds); i++) { + led_classdev_unregister(&accton_asgvolt64_leds[i]); + } + + return 0; +} + +static struct platform_driver accton_asgvolt64_led_driver = { + .probe = accton_asgvolt64_led_probe, + .remove = accton_asgvolt64_led_remove, + .suspend = accton_asgvolt64_led_suspend, + .resume = accton_asgvolt64_led_resume, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init accton_asgvolt64_led_init(void) +{ + int ret; + + + ret = platform_driver_register(&accton_asgvolt64_led_driver); + if (ret < 0) { + goto exit; + } + + ledctl = kzalloc(sizeof(struct accton_asgvolt64_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + platform_driver_unregister(&accton_asgvolt64_led_driver); + goto exit; + } + + 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(&accton_asgvolt64_led_driver); + kfree(ledctl); + goto exit; + } + +exit: + return ret; + ; +} + +static void __exit accton_asgvolt64_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&accton_asgvolt64_led_driver); + kfree(ledctl); +} + +module_init(accton_asgvolt64_led_init); +module_exit(accton_asgvolt64_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("accton_asgvolt64_led driver"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-psu.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-psu.c new file mode 100755 index 00000000..6414e9f4 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-psu.c @@ -0,0 +1,597 @@ +/* + * Copyright (C) Brandon Chuang + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "asgvolt64_psu" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_PSU_READ_CMD 0x16 +#define IPMI_PSU_MODEL_NAME_CMD 0x10 +#define IPMI_PSU_SERIAL_NUM_CMD 0x11 +#define IPMI_TIMEOUT (20 * HZ) + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t show_linear(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t show_psu(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *attr, char *buf); +static int asgvolt64_psu_probe(struct platform_device *pdev); +static int asgvolt64_psu_remove(struct platform_device *pdev); + +enum psu_id { + PSU_1, + PSU_2, + NUM_OF_PSU +}; + +enum psu_data_index { + PSU_PRESENT = 0, + PSU_TEMP_FAULT, + PSU_POWER_GOOD_CPLD, + PSU_POWER_GOOD_PMBUS, + PSU_OVER_VOLTAGE, + PSU_OVER_CURRENT, + PSU_POWER_ON, + PSU_VIN0, + PSU_VIN1, + PSU_VOUT0, + PSU_VOUT1, + PSU_IOUT0, + PSU_IOUT1, + PSU_TEMP0, + PSU_TEMP1, + PSU_FAN0, + PSU_FAN1, + PSU_POUT0, + PSU_POUT1, + PSU_STATUS_COUNT, + PSU_MODEL = 0, + PSU_SERIAL = 0 +}; + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct ipmi_psu_resp_data { + unsigned char status[19]; + char serial[19]; + char model[9]; +}; + +struct asgvolt64_psu_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid[2]; /* != 0 if registers are valid, 0: PSU1, 1: PSU2 */ + unsigned long last_updated[2]; /* In jiffies, 0: PSU1, 1: PSU2 */ + struct ipmi_data ipmi; + struct ipmi_psu_resp_data ipmi_resp[2]; /* 0: PSU1, 1: PSU2 */ + unsigned char ipmi_tx_data[2]; +}; + +struct asgvolt64_psu_data *data = NULL; + +static struct platform_driver asgvolt64_psu_driver = { + .probe = asgvolt64_psu_probe, + .remove = asgvolt64_psu_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +#define PSU_PRESENT_ATTR_ID(index) PSU##index##_PRESENT +#define PSU_POWERGOOD_ATTR_ID(index) PSU##index##_POWER_GOOD +#define PSU_VOUT_ATTR_ID(index) PSU##index##_VOUT +#define PSU_IOUT_ATTR_ID(index) PSU##index##_IOUT +#define PSU_POUT_ATTR_ID(index) PSU##index##_POUT +#define PSU_MODEL_ATTR_ID(index) PSU##index##_MODEL +#define PSU_SERIAL_ATTR_ID(index) PSU##index##_SERIAL +#define PSU_TEMP_INPUT_ATTR_ID(index) PSU##index##_TEMP_INPUT +#define PSU_FAN_INPUT_ATTR_ID(index) PSU##index##_FAN_INPUT + +#define PSU_ATTR(psu_id) \ + PSU_PRESENT_ATTR_ID(psu_id), \ + PSU_POWERGOOD_ATTR_ID(psu_id), \ + PSU_VOUT_ATTR_ID(psu_id), \ + PSU_IOUT_ATTR_ID(psu_id), \ + PSU_POUT_ATTR_ID(psu_id), \ + PSU_MODEL_ATTR_ID(psu_id), \ + PSU_SERIAL_ATTR_ID(psu_id), \ + PSU_TEMP_INPUT_ATTR_ID(psu_id), \ + PSU_FAN_INPUT_ATTR_ID(psu_id) + +enum asgvolt64_psu_sysfs_attrs { + /* psu attributes */ + PSU_ATTR(1), + PSU_ATTR(2), + NUM_OF_PSU_ATTR, + NUM_OF_PER_PSU_ATTR = (NUM_OF_PSU_ATTR/NUM_OF_PSU) +}; + +/* psu attributes */ +#define DECLARE_PSU_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(psu##index##_present, S_IRUGO, show_psu, NULL, PSU##index##_PRESENT); \ + static SENSOR_DEVICE_ATTR(psu##index##_power_good, S_IRUGO, show_psu, NULL, PSU##index##_POWER_GOOD); \ + static SENSOR_DEVICE_ATTR(psu##index##_vout, S_IRUGO, show_linear, NULL, PSU##index##_VOUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_iout, S_IRUGO, show_linear, NULL, PSU##index##_IOUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_pout, S_IRUGO, show_linear, NULL, PSU##index##_POUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_model, S_IRUGO, show_string, NULL, PSU##index##_MODEL); \ + static SENSOR_DEVICE_ATTR(psu##index##_serial, S_IRUGO, show_string, NULL, PSU##index##_SERIAL);\ + static SENSOR_DEVICE_ATTR(psu##index##_temp1_input, S_IRUGO, show_linear, NULL, PSU##index##_TEMP_INPUT); \ + static SENSOR_DEVICE_ATTR(psu##index##_fan1_input, S_IRUGO, show_psu, NULL, PSU##index##_FAN_INPUT) +#define DECLARE_PSU_ATTR(index) \ + &sensor_dev_attr_psu##index##_present.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_power_good.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_vout.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_iout.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_pout.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_model.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_serial.dev_attr.attr,\ + &sensor_dev_attr_psu##index##_temp1_input.dev_attr.attr, \ + &sensor_dev_attr_psu##index##_fan1_input.dev_attr.attr + +DECLARE_PSU_SENSOR_DEVICE_ATTR(1); +DECLARE_PSU_SENSOR_DEVICE_ATTR(2); + +static struct attribute *asgvolt64_psu_attributes[] = { + /* psu attributes */ + DECLARE_PSU_ATTR(1), + DECLARE_PSU_ATTR(2), + NULL +}; + +static const struct attribute_group asgvolt64_psu_group = { + .attrs = asgvolt64_psu_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static struct asgvolt64_psu_data *asgvolt64_psu_update_device(struct device_attribute *da) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + int status = 0; + + if (time_before(jiffies, data->last_updated[pid] + HZ * 5) && data->valid[pid]) { + return data; + } + + data->valid[pid] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = pid + 1; /* PSU ID base id for ipmi start from 1 */ + status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, data->ipmi_tx_data, 1, + data->ipmi_resp[pid].status, sizeof(data->ipmi_resp[pid].status)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Get model name from ipmi */ + data->ipmi_tx_data[1] = 0x10; + status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, data->ipmi_tx_data, 2, + data->ipmi_resp[pid].model, sizeof(data->ipmi_resp[pid].model) - 1); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Get serial number from ipmi */ + data->ipmi_tx_data[1] = 0x11; + status = ipmi_send_message(&data->ipmi, IPMI_PSU_READ_CMD, data->ipmi_tx_data, 2, + data->ipmi_resp[pid].serial, sizeof(data->ipmi_resp[pid].serial) - 1); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated[pid] = jiffies; + data->valid[pid] = 1; + +exit: + return data; +} + +#define VALIDATE_PRESENT_RETURN(id) \ +{ \ + if (data->ipmi_resp[id].status[PSU_PRESENT] != 0) { \ + mutex_unlock(&data->update_lock); \ + return -ENXIO; \ + } \ +} + +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 show_linear(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + u16 value = 0; + int error = 0; + int exponent = 0, mantissa = 0; + int multiplier = 1000; + + mutex_lock(&data->update_lock); + + data = asgvolt64_psu_update_device(da); + if (!data->valid[pid]) { + error = -EIO; + goto exit; + } + + switch (attr->index) { + case PSU1_VOUT: + case PSU2_VOUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((u16)data->ipmi_resp[pid].status[PSU_VOUT0] | + (u16)data->ipmi_resp[pid].status[PSU_VOUT1] << 8); + break; + case PSU1_IOUT: + case PSU2_IOUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((u16)data->ipmi_resp[pid].status[PSU_IOUT0] | + (u16)data->ipmi_resp[pid].status[PSU_IOUT1] << 8); + break; + case PSU1_POUT: + case PSU2_POUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((u16)data->ipmi_resp[pid].status[PSU_POUT0] | + (u16)data->ipmi_resp[pid].status[PSU_POUT1] << 8); + break; + case PSU1_TEMP_INPUT: + case PSU2_TEMP_INPUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].status[PSU_TEMP0] | + (u32)data->ipmi_resp[pid].status[PSU_TEMP1] << 8); + break; + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + + 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)); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t show_psu(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + int value = 0; + int error = 0; + + mutex_lock(&data->update_lock); + + data = asgvolt64_psu_update_device(da); + if (!data->valid[pid]) { + error = -EIO; + goto exit; + } + + switch (attr->index) { + case PSU1_PRESENT: + case PSU2_PRESENT: + value = !(data->ipmi_resp[pid].status[PSU_PRESENT]); + break; + case PSU1_POWER_GOOD: + case PSU2_POWER_GOOD: + VALIDATE_PRESENT_RETURN(pid); + value = data->ipmi_resp[pid].status[PSU_POWER_GOOD_CPLD]; + break; + case PSU1_FAN_INPUT: + case PSU2_FAN_INPUT: + VALIDATE_PRESENT_RETURN(pid); + value = ((u32)data->ipmi_resp[pid].status[PSU_FAN0] | + (u32)data->ipmi_resp[pid].status[PSU_FAN1] << 8); + break; + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", value); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +#define MODEL_NAME_LEN 8 +#define SERIAL_NUM_LEN 18 + +static ssize_t show_string(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_PSU_ATTR; + char *str = NULL; + int error = 0; + int len=0; + mutex_lock(&data->update_lock); + + data = asgvolt64_psu_update_device(da); + if (!data->valid[pid]) { + error = -EIO; + goto exit; + } + + switch (attr->index) { + case PSU1_MODEL: + case PSU2_MODEL: + VALIDATE_PRESENT_RETURN(pid); + str = data->ipmi_resp[pid].model; + len=MODEL_NAME_LEN; + break; + case PSU1_SERIAL: + case PSU2_SERIAL: + VALIDATE_PRESENT_RETURN(pid); + str = data->ipmi_resp[pid].serial; + len=SERIAL_NUM_LEN; + break; + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + return snprintf(buf,len, "%s\n", str); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static int asgvolt64_psu_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &asgvolt64_psu_group); + if (status) { + goto exit; + } + + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int asgvolt64_psu_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &asgvolt64_psu_group); + return 0; +} + +static int __init asgvolt64_psu_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct asgvolt64_psu_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + + ret = platform_driver_register(&asgvolt64_psu_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&asgvolt64_psu_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit asgvolt64_psu_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&asgvolt64_psu_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("ASGVOLT64 PSU driver"); +MODULE_LICENSE("GPL"); + +module_init(asgvolt64_psu_init); +module_exit(asgvolt64_psu_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-sfp.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-sfp.c new file mode 100755 index 00000000..bed89877 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-sfp.c @@ -0,0 +1,1438 @@ +/* + * Copyright (C) Brandon Chuang + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "asgvolt64_sfp" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_QSFP_READ_CMD 0x10 +#define IPMI_QSFP_WRITE_CMD 0x11 +#define IPMI_SFP_READ_CMD 0x1C +#define IPMI_SFP_WRITE_CMD 0x1D +#define IPMI_TIMEOUT (20 * HZ) +#define IPMI_DATA_MAX_LEN 128 + +#define SFP_EEPROM_SIZE 768 +#define QSFP_EEPROM_SIZE 640 + +#define NUM_OF_SFP 16 +#define NUM_OF_QSFP 4 +#define NUM_OF_PORT (NUM_OF_SFP + NUM_OF_QSFP) + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t set_sfp(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_sfp(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t set_qsfp_txdisable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_qsfp_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t set_qsfp_lpmode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_qsfp(struct device *dev, struct device_attribute *da, char *buf); +static int asgvolt64_sfp_probe(struct platform_device *pdev); +static int asgvolt64_sfp_remove(struct platform_device *pdev); +static ssize_t show_all(struct device *dev, struct device_attribute *da, char *buf); +static struct asgvolt64_sfp_data *asgvolt64_sfp_update_present(void); +static struct asgvolt64_sfp_data *asgvolt64_sfp_update_txdisable(void); +static struct asgvolt64_sfp_data *asgvolt64_sfp_update_txfault(void); +static struct asgvolt64_sfp_data *asgvolt64_sfp_update_rxlos(void); +static struct asgvolt64_sfp_data *asgvolt64_qsfp_update_present(void); +static struct asgvolt64_sfp_data *asgvolt64_qsfp_update_txdisable(void); +static struct asgvolt64_sfp_data *asgvolt64_qsfp_update_reset(void); + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +enum module_status { + SFP_PRESENT = 0, + SFP_TXDISABLE, + SFP_TXFAULT, + SFP_RXLOS, + NUM_OF_SFP_STATUS, + + QSFP_PRESENT = 0, + QSFP_TXDISABLE, + QSFP_RESET, + QSFP_LPMODE, + NUM_OF_QSFP_STATUS, + + PRESENT_ALL = 0, + RXLOS_ALL +}; + +struct ipmi_sfp_resp_data { + unsigned char eeprom[IPMI_DATA_MAX_LEN]; + char eeprom_valid; + + char sfp_valid[NUM_OF_SFP_STATUS]; /* != 0 if registers are valid */ + unsigned long sfp_last_updated[NUM_OF_SFP_STATUS]; /* In jiffies */ + unsigned char sfp_resp[NUM_OF_SFP_STATUS][NUM_OF_SFP]; /* 0: present, 1: tx-disable + 2: tx-fault, 3: rx-los */ + char qsfp_valid[NUM_OF_QSFP_STATUS]; /* != 0 if registers are valid */ + unsigned long qsfp_last_updated[NUM_OF_QSFP_STATUS]; /* In jiffies */ + unsigned char qsfp_resp[NUM_OF_QSFP_STATUS][NUM_OF_QSFP]; /* 0: present, 1: tx-disable, + 2: reset , 3: low power mode */ +}; + +struct asgvolt64_sfp_data { + struct platform_device *pdev; + struct mutex update_lock; + struct ipmi_data ipmi; + struct ipmi_sfp_resp_data ipmi_resp; + unsigned char ipmi_tx_data[3]; + struct bin_attribute eeprom[NUM_OF_PORT]; /* eeprom data */ +}; + +struct sfp_eeprom_write_data { + unsigned char ipmi_tx_data[4]; /* 0:port index 1:page number 2:offset 3:Data len */ + unsigned char write_buf[IPMI_DATA_MAX_LEN]; +}; + +struct asgvolt64_sfp_data *data = NULL; + +static struct platform_driver asgvolt64_sfp_driver = { + .probe = asgvolt64_sfp_probe, + .remove = asgvolt64_sfp_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +#define SFP_PRESENT_ATTR_ID(port) SFP##port##_PRESENT +#define SFP_TXDISABLE_ATTR_ID(port) SFP##port##_TXDISABLE +#define SFP_TXFAULT_ATTR_ID(port) SFP##port##_TXFAULT +#define SFP_RXLOS_ATTR_ID(port) SFP##port##_RXLOS + +#define SFP_ATTR(port) \ + SFP_PRESENT_ATTR_ID(port), \ + SFP_TXDISABLE_ATTR_ID(port), \ + SFP_TXFAULT_ATTR_ID(port), \ + SFP_RXLOS_ATTR_ID(port) + +#define QSFP_PRESENT_ATTR_ID(port) QSFP##port##_PRESENT +#define QSFP_TXDISABLE_ATTR_ID(port) QSFP##port##_TXDISABLE +#define QSFP_RESET_ATTR_ID(port) QSFP##port##_RESET +#define QSFP_LPMODE_ATTR_ID(port) QSFP##port##_LPMODE + +#define QSFP_ATTR(port) \ + QSFP_PRESENT_ATTR_ID(port), \ + QSFP_TXDISABLE_ATTR_ID(port), \ + QSFP_RESET_ATTR_ID(port), \ + QSFP_LPMODE_ATTR_ID(port) + +enum asgvolt64_sfp_sysfs_attrs { + SFP_ATTR(1), + SFP_ATTR(2), + SFP_ATTR(3), + SFP_ATTR(4), + SFP_ATTR(5), + SFP_ATTR(6), + SFP_ATTR(7), + SFP_ATTR(8), + SFP_ATTR(9), + SFP_ATTR(10), + SFP_ATTR(11), + SFP_ATTR(12), + SFP_ATTR(13), + SFP_ATTR(14), + SFP_ATTR(15), + SFP_ATTR(16), + NUM_OF_SFP_ATTR, + NUM_OF_PER_SFP_ATTR = (NUM_OF_SFP_ATTR/NUM_OF_SFP), +}; + +enum asgvolt64_qsfp_sysfs_attrs { + QSFP_ATTR(17), + QSFP_ATTR(18), + QSFP_ATTR(19), + QSFP_ATTR(20), + NUM_OF_QSFP_ATTR, + NUM_OF_PER_QSFP_ATTR = (NUM_OF_QSFP_ATTR/NUM_OF_QSFP), +}; + +/* sfp attributes */ +#define DECLARE_SFP_SENSOR_DEVICE_ATTR(port) \ + static SENSOR_DEVICE_ATTR(module_present_##port, S_IRUGO, show_sfp, NULL, SFP##port##_PRESENT); \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##port, S_IWUSR | S_IRUGO, show_sfp, set_sfp, SFP##port##_TXDISABLE); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##port, S_IRUGO, show_sfp, NULL, SFP##port##_TXFAULT); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##port, S_IRUGO, show_sfp, NULL, SFP##port##_RXLOS) +#define DECLARE_SFP_ATTR(port) \ + &sensor_dev_attr_module_present_##port.dev_attr.attr, \ + &sensor_dev_attr_module_tx_disable_##port.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##port.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##port.dev_attr.attr + + +/* qsfp attributes */ +#define DECLARE_QSFP_SENSOR_DEVICE_ATTR(port) \ + static SENSOR_DEVICE_ATTR(module_present_##port, S_IRUGO, show_qsfp, NULL, QSFP##port##_PRESENT); \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##port, S_IWUSR | S_IRUGO, show_qsfp, set_qsfp_txdisable, QSFP##port##_TXDISABLE); \ + static SENSOR_DEVICE_ATTR(module_reset_##port, S_IWUSR | S_IRUGO, show_qsfp, set_qsfp_reset, QSFP##port##_RESET); \ + static SENSOR_DEVICE_ATTR(module_lpmode_##port, S_IWUSR | S_IRUGO, show_qsfp, set_qsfp_lpmode, QSFP##port##_LPMODE) +#define DECLARE_QSFP_ATTR(port) \ + &sensor_dev_attr_module_present_##port.dev_attr.attr, \ + &sensor_dev_attr_module_tx_disable_##port.dev_attr.attr, \ + &sensor_dev_attr_module_reset_##port.dev_attr.attr, \ + &sensor_dev_attr_module_lpmode_##port.dev_attr.attr + +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_all, NULL, PRESENT_ALL); \ +static SENSOR_DEVICE_ATTR(module_rxlos_all, S_IRUGO, show_all, NULL, RXLOS_ALL); \ + +DECLARE_SFP_SENSOR_DEVICE_ATTR(1); +DECLARE_SFP_SENSOR_DEVICE_ATTR(2); +DECLARE_SFP_SENSOR_DEVICE_ATTR(3); +DECLARE_SFP_SENSOR_DEVICE_ATTR(4); +DECLARE_SFP_SENSOR_DEVICE_ATTR(5); +DECLARE_SFP_SENSOR_DEVICE_ATTR(6); +DECLARE_SFP_SENSOR_DEVICE_ATTR(7); +DECLARE_SFP_SENSOR_DEVICE_ATTR(8); +DECLARE_SFP_SENSOR_DEVICE_ATTR(9); +DECLARE_SFP_SENSOR_DEVICE_ATTR(10); +DECLARE_SFP_SENSOR_DEVICE_ATTR(11); +DECLARE_SFP_SENSOR_DEVICE_ATTR(12); +DECLARE_SFP_SENSOR_DEVICE_ATTR(13); +DECLARE_SFP_SENSOR_DEVICE_ATTR(14); +DECLARE_SFP_SENSOR_DEVICE_ATTR(15); +DECLARE_SFP_SENSOR_DEVICE_ATTR(16); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(17); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(18); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(19); +DECLARE_QSFP_SENSOR_DEVICE_ATTR(20); + +static struct attribute *asgvolt64_sfp_attributes[] = { + /* sfp attributes */ + DECLARE_SFP_ATTR(1), + DECLARE_SFP_ATTR(2), + DECLARE_SFP_ATTR(3), + DECLARE_SFP_ATTR(4), + DECLARE_SFP_ATTR(5), + DECLARE_SFP_ATTR(6), + DECLARE_SFP_ATTR(7), + DECLARE_SFP_ATTR(8), + DECLARE_SFP_ATTR(9), + DECLARE_SFP_ATTR(10), + DECLARE_SFP_ATTR(11), + DECLARE_SFP_ATTR(12), + DECLARE_SFP_ATTR(13), + DECLARE_SFP_ATTR(14), + DECLARE_SFP_ATTR(15), + DECLARE_SFP_ATTR(16), + DECLARE_QSFP_ATTR(17), + DECLARE_QSFP_ATTR(18), + DECLARE_QSFP_ATTR(19), + DECLARE_QSFP_ATTR(20), + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rxlos_all.dev_attr.attr, + NULL +}; + +static const struct attribute_group asgvolt64_sfp_group = { + .attrs = asgvolt64_sfp_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static struct asgvolt64_sfp_data *asgvolt64_sfp_update_present(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.sfp_last_updated[SFP_PRESENT] + HZ) && + data->ipmi_resp.sfp_valid[SFP_PRESENT]) { + return data; + } + + data->ipmi_resp.sfp_valid[SFP_PRESENT] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x10; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.sfp_resp[SFP_PRESENT], + sizeof(data->ipmi_resp.sfp_resp[SFP_PRESENT])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.sfp_last_updated[SFP_PRESENT] = jiffies; + data->ipmi_resp.sfp_valid[SFP_PRESENT] = 1; + +exit: + return data; +} + +static struct asgvolt64_sfp_data *asgvolt64_sfp_update_txdisable(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.sfp_last_updated[SFP_TXDISABLE] + HZ * 5) && + data->ipmi_resp.sfp_valid[SFP_TXDISABLE]) { + return data; + } + + data->ipmi_resp.sfp_valid[SFP_TXDISABLE] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x01; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.sfp_resp[SFP_TXDISABLE], + sizeof(data->ipmi_resp.sfp_resp[SFP_TXDISABLE])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.sfp_last_updated[SFP_TXDISABLE] = jiffies; + data->ipmi_resp.sfp_valid[SFP_TXDISABLE] = 1; + +exit: + return data; +} + +static struct asgvolt64_sfp_data *asgvolt64_sfp_update_txfault(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.sfp_last_updated[SFP_TXFAULT] + HZ * 5) && + data->ipmi_resp.sfp_valid[SFP_TXFAULT]) { + return data; + } + + data->ipmi_resp.sfp_valid[SFP_TXFAULT] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x12; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.sfp_resp[SFP_TXFAULT], + sizeof(data->ipmi_resp.sfp_resp[SFP_TXFAULT])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.sfp_last_updated[SFP_TXFAULT] = jiffies; + data->ipmi_resp.sfp_valid[SFP_TXFAULT] = 1; + +exit: + return data; +} + +static struct asgvolt64_sfp_data *asgvolt64_sfp_update_rxlos(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.sfp_last_updated[SFP_RXLOS] + HZ * 5) && + data->ipmi_resp.sfp_valid[SFP_RXLOS]) { + return data; + } + + data->ipmi_resp.sfp_valid[SFP_RXLOS] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x13; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.sfp_resp[SFP_RXLOS], + sizeof(data->ipmi_resp.sfp_resp[SFP_RXLOS])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.sfp_last_updated[SFP_RXLOS] = jiffies; + data->ipmi_resp.sfp_valid[SFP_RXLOS] = 1; + +exit: + return data; +} + +static struct asgvolt64_sfp_data *asgvolt64_qsfp_update_present(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.qsfp_last_updated[QSFP_PRESENT] + HZ) && + data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) { + return data; + } + + data->ipmi_resp.qsfp_valid[QSFP_PRESENT] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x10; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.qsfp_resp[QSFP_PRESENT], + sizeof(data->ipmi_resp.qsfp_resp[QSFP_PRESENT])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.qsfp_last_updated[QSFP_PRESENT] = jiffies; + data->ipmi_resp.qsfp_valid[QSFP_PRESENT] = 1; + +exit: + return data; +} + +static struct asgvolt64_sfp_data *asgvolt64_qsfp_update_txdisable(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.qsfp_last_updated[QSFP_TXDISABLE] + HZ * 5) && + data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE]) { + return data; + } + + data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x01; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE], + sizeof(data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.qsfp_last_updated[QSFP_TXDISABLE] = jiffies; + data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE] = 1; + +exit: + return data; +} + +static struct asgvolt64_sfp_data *asgvolt64_qsfp_update_reset(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.qsfp_last_updated[QSFP_RESET] + HZ * 5) && + data->ipmi_resp.qsfp_valid[QSFP_RESET]) { + return data; + } + + data->ipmi_resp.qsfp_valid[QSFP_RESET] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x11; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.qsfp_resp[QSFP_RESET], + sizeof(data->ipmi_resp.qsfp_resp[QSFP_RESET])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.qsfp_last_updated[QSFP_RESET] = jiffies; + data->ipmi_resp.qsfp_valid[QSFP_RESET] = 1; + +exit: + return data; +} + +static struct asgvolt64_sfp_data *asgvolt64_qsfp_update_lpmode(void) +{ + int status = 0; + + if (time_before(jiffies, data->ipmi_resp.qsfp_last_updated[QSFP_LPMODE] + HZ * 5) && + data->ipmi_resp.qsfp_valid[QSFP_LPMODE]) { + return data; + } + + data->ipmi_resp.qsfp_valid[QSFP_LPMODE] = 0; + + /* Get status from ipmi */ + data->ipmi_tx_data[0] = 0x12; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_READ_CMD, + data->ipmi_tx_data, 1, + data->ipmi_resp.qsfp_resp[QSFP_LPMODE], + sizeof(data->ipmi_resp.qsfp_resp[QSFP_LPMODE])); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->ipmi_resp.qsfp_last_updated[QSFP_LPMODE] = jiffies; + data->ipmi_resp.qsfp_valid[QSFP_LPMODE] = 1; + +exit: + return data; +} + +static ssize_t show_all(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u64 values = 0; + int i; + + switch (attr->index) { + case PRESENT_ALL: + { + mutex_lock(&data->update_lock); + + data = asgvolt64_sfp_update_present(); + if (!data->ipmi_resp.sfp_valid[SFP_PRESENT]) { + mutex_unlock(&data->update_lock); + return -EIO; + } + + data = asgvolt64_qsfp_update_present(); + if (!data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) { + mutex_unlock(&data->update_lock); + return -EIO; + } + + /* Update qsfp present status */ + for (i = (NUM_OF_QSFP-1); i >= 0; i--) { + values <<= 1; + values |= (data->ipmi_resp.qsfp_resp[QSFP_PRESENT][i] & 0x1); + } + + /* Update sfp present status */ + for (i = (NUM_OF_SFP-1); i >= 0; i--) { + values <<= 1; + values |= (data->ipmi_resp.sfp_resp[SFP_PRESENT][i] & 0x1); + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 54 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", + (unsigned int)(0xFF & values), + (unsigned int)(0xFF & (values >> 8)), + (unsigned int)(0xFF & (values >> 16)), + (unsigned int)(0xFF & (values >> 24)), + (unsigned int)(0xFF & (values >> 32)), + (unsigned int)(0xFF & (values >> 40)), + (unsigned int)(0x3F & (values >> 48))); + } + case RXLOS_ALL: + { + mutex_lock(&data->update_lock); + + data = asgvolt64_sfp_update_rxlos(); + if (!data->ipmi_resp.sfp_valid[SFP_RXLOS]) { + mutex_unlock(&data->update_lock); + return -EIO; + } + + /* Update sfp rxlos status */ + for (i = (NUM_OF_SFP-1); i >= 0; i--) { + values <<= 1; + values |= !(data->ipmi_resp.sfp_resp[SFP_RXLOS][i] & 0x1); + } + + mutex_unlock(&data->update_lock); + + /* Return values 1 -> 48 in order */ + return sprintf(buf, "%.2x %.2x %.2x %.2x %.2x %.2x\n", + (unsigned int)(0xFF & values), + (unsigned int)(0xFF & (values >> 8)), + (unsigned int)(0xFF & (values >> 16)), + (unsigned int)(0xFF & (values >> 24)), + (unsigned int)(0xFF & (values >> 32)), + (unsigned int)(0xFF & (values >> 40))); + } + default: + break; + } + + return 0; +} + +static ssize_t show_sfp(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_SFP_ATTR; /* port id, 0 based */ + int value = 0; + int error = 0; + + mutex_lock(&data->update_lock); + + switch (attr->index) { + case SFP1_PRESENT: + case SFP2_PRESENT: + case SFP3_PRESENT: + case SFP4_PRESENT: + case SFP5_PRESENT: + case SFP6_PRESENT: + case SFP7_PRESENT: + case SFP8_PRESENT: + case SFP9_PRESENT: + case SFP10_PRESENT: + case SFP11_PRESENT: + case SFP12_PRESENT: + case SFP13_PRESENT: + case SFP14_PRESENT: + case SFP15_PRESENT: + case SFP16_PRESENT: + { + data = asgvolt64_sfp_update_present(); + if (!data->ipmi_resp.sfp_valid[SFP_PRESENT]) { + error = -EIO; + goto exit; + } + + value = data->ipmi_resp.sfp_resp[SFP_PRESENT][pid]; + break; + } + case SFP1_TXDISABLE: + case SFP2_TXDISABLE: + case SFP3_TXDISABLE: + case SFP4_TXDISABLE: + case SFP5_TXDISABLE: + case SFP6_TXDISABLE: + case SFP7_TXDISABLE: + case SFP8_TXDISABLE: + case SFP9_TXDISABLE: + case SFP10_TXDISABLE: + case SFP11_TXDISABLE: + case SFP12_TXDISABLE: + case SFP13_TXDISABLE: + case SFP14_TXDISABLE: + case SFP15_TXDISABLE: + case SFP16_TXDISABLE: + { + data = asgvolt64_sfp_update_txdisable(); + if (!data->ipmi_resp.sfp_valid[SFP_TXDISABLE]) { + error = -EIO; + goto exit; + } + + value = !data->ipmi_resp.sfp_resp[SFP_TXDISABLE][pid]; + break; + } + case SFP1_TXFAULT: + case SFP2_TXFAULT: + case SFP3_TXFAULT: + case SFP4_TXFAULT: + case SFP5_TXFAULT: + case SFP6_TXFAULT: + case SFP7_TXFAULT: + case SFP8_TXFAULT: + case SFP9_TXFAULT: + case SFP10_TXFAULT: + case SFP11_TXFAULT: + case SFP12_TXFAULT: + case SFP13_TXFAULT: + case SFP14_TXFAULT: + case SFP15_TXFAULT: + case SFP16_TXFAULT: + { + data = asgvolt64_sfp_update_txfault(); + if (!data->ipmi_resp.sfp_valid[SFP_TXFAULT]) { + error = -EIO; + goto exit; + } + + value = data->ipmi_resp.sfp_resp[SFP_TXFAULT][pid]; + break; + } + case SFP1_RXLOS: + case SFP2_RXLOS: + case SFP3_RXLOS: + case SFP4_RXLOS: + case SFP5_RXLOS: + case SFP6_RXLOS: + case SFP7_RXLOS: + case SFP8_RXLOS: + case SFP9_RXLOS: + case SFP10_RXLOS: + case SFP11_RXLOS: + case SFP12_RXLOS: + case SFP13_RXLOS: + case SFP14_RXLOS: + case SFP15_RXLOS: + case SFP16_RXLOS: + { + data = asgvolt64_sfp_update_rxlos(); + if (!data->ipmi_resp.sfp_valid[SFP_RXLOS]) { + error = -EIO; + goto exit; + } + + value = !data->ipmi_resp.sfp_resp[SFP_RXLOS][pid]; + break; + } + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", value); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t set_sfp(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); + unsigned char pid = attr->index / NUM_OF_PER_SFP_ATTR; /* port id, 0 based */ + + status = kstrtol(buf, 10, &disable); + if (status) { + return status; + } + + disable = !disable; /* the IPMI cmd is 0 for tx-disable and 1 for tx-enable */ + + mutex_lock(&data->update_lock); + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = pid + 1; /* Port ID base id for ipmi start from 1 */ + data->ipmi_tx_data[1] = 0x01; + data->ipmi_tx_data[2] = disable; + status = ipmi_send_message(&data->ipmi, IPMI_SFP_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Update to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp.sfp_resp[SFP_TXDISABLE][pid] = disable; + status = count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_qsfp(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */ + int value = 0; + int error = 0; + + mutex_lock(&data->update_lock); + + switch (attr->index) { + case QSFP17_PRESENT: + case QSFP18_PRESENT: + case QSFP19_PRESENT: + case QSFP20_PRESENT: + { + data = asgvolt64_qsfp_update_present(); + if (!data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) { + error = -EIO; + goto exit; + } + + value = data->ipmi_resp.qsfp_resp[QSFP_PRESENT][pid]; + break; + } + case QSFP17_TXDISABLE: + case QSFP18_TXDISABLE: + case QSFP19_TXDISABLE: + case QSFP20_TXDISABLE: + { + data = asgvolt64_qsfp_update_txdisable(); + if (!data->ipmi_resp.qsfp_valid[QSFP_TXDISABLE]) { + error = -EIO; + goto exit; + } + + value = !!data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE][pid]; + break; + } + case QSFP17_RESET: + case QSFP18_RESET: + case QSFP19_RESET: + case QSFP20_RESET: + { + data = asgvolt64_qsfp_update_reset(); + if (!data->ipmi_resp.qsfp_valid[QSFP_RESET]) { + error = -EIO; + goto exit; + } + + value = !data->ipmi_resp.qsfp_resp[QSFP_RESET][pid]; + break; + } + case QSFP17_LPMODE: + case QSFP18_LPMODE: + case QSFP19_LPMODE: + case QSFP20_LPMODE: + { + data = asgvolt64_qsfp_update_lpmode(); + if (!data->ipmi_resp.qsfp_valid[QSFP_LPMODE]) { + error = -EIO; + goto exit; + } + + value = data->ipmi_resp.qsfp_resp[QSFP_LPMODE][pid]; + break; + } + default: + error = -EINVAL; + goto exit; + } + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", value); + +exit: + mutex_unlock(&data->update_lock); + return error; +} + +static ssize_t set_qsfp_txdisable(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); + unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */ + + mutex_lock(&data->update_lock); + + data = asgvolt64_qsfp_update_present(); + if (!data->ipmi_resp.qsfp_valid[QSFP_PRESENT]) { + status = -EIO; + goto exit; + } + + if (!data->ipmi_resp.qsfp_resp[QSFP_PRESENT][pid]) { + status = -ENXIO; + goto exit; + } + + status = kstrtol(buf, 10, &disable); + if (status) { + goto exit; + } + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = pid + 1; /* Port ID base id for ipmi start from 1 */ + data->ipmi_tx_data[1] = 0x01; + data->ipmi_tx_data[2] = disable ? 0xf : 0; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Update to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp.qsfp_resp[QSFP_TXDISABLE][pid] = disable; + status = count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_qsfp_reset(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long reset; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */ + + status = kstrtol(buf, 10, &reset); + if (status) { + return status; + } + + reset = !reset; /* the IPMI cmd is 0 for reset and 1 for out of reset */ + + mutex_lock(&data->update_lock); + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = pid + 1; /* Port ID base id for ipmi start from 1 */ + data->ipmi_tx_data[1] = 0x11; + data->ipmi_tx_data[2] = reset; + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Update to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp.qsfp_resp[QSFP_RESET][pid] = reset; + status = count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_qsfp_lpmode(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long lpmode; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char pid = attr->index / NUM_OF_PER_QSFP_ATTR; /* port id, 0 based */ + + status = kstrtol(buf, 10, &lpmode); + if (status) { + return status; + } + + mutex_lock(&data->update_lock); + + /* Send IPMI write command */ + data->ipmi_tx_data[0] = pid + 1; /* Port ID base id for ipmi start from 1 */ + data->ipmi_tx_data[1] = 0x12; + data->ipmi_tx_data[2] = lpmode; /* 0: High Power Mode, 1: Low Power Mode */ + status = ipmi_send_message(&data->ipmi, IPMI_QSFP_WRITE_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Update to ipmi_resp buffer to prevent from the impact of lazy update */ + data->ipmi_resp.qsfp_resp[QSFP_LPMODE][pid] = lpmode; + status = count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +/************************************************************************************* +SFP: PS: Index of SFP is 1~16 +Offset 0 ~ 127: Addr 0x50 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x1C 0" +Offset 128 ~ 255: Addr 0x50 Offset 128~255 IPMI CMD: "ipmitool raw 0x34 0x1C 1" +Offset 256 ~ 383: Addr 0x51 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x1C 2" +Offset 384 ~ 511: Addr 0x51 Offset 128~255(Page 0) IPMI CMD: "ipmitool raw 0x34 0x1C 3" +Offset 512 ~ 639: Addr 0x51 Offset 128~255(Page 1) IPMI CMD: "ipmitool raw 0x34 0x1C 4" +Offset 640 ~ 767: Addr 0x51 Offset 128~255(Page 2) IPMI CMD: "ipmitool raw 0x34 0x1C 5" + +QSFP: PS: index of QSFP is 1~4" +Offset 0 ~ 127: Addr 0x50 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x10 0" +Offset 128 ~ 255: Addr 0x50 Offset 128~255(Page 0) IPMI CMD: "ipmitool raw 0x34 0x10 1" +Offset 256 ~ 383: Addr 0x50 Offset 128~255(Page 1) IPMI CMD: "ipmitool raw 0x34 0x10 2" +Offset 384 ~ 511: Addr 0x50 Offset 128~255(Page 2) IPMI CMD: "ipmitool raw 0x34 0x10 3" +Offset 512 ~ 639: Addr 0x50 Offset 128~255(Page 3) IPMI CMD: "ipmitool raw 0x34 0x10 4" +**************************************************************************************/ +static ssize_t sfp_eeprom_read(loff_t off, char *buf, size_t count, int port) +{ + int status = 0; + unsigned char cmd = (port <= NUM_OF_SFP) ? IPMI_SFP_READ_CMD : IPMI_QSFP_READ_CMD; + unsigned char ipmi_port_id = (port <= NUM_OF_SFP) ? port : (port - NUM_OF_SFP); + unsigned char ipmi_page = off / IPMI_DATA_MAX_LEN; + unsigned char length = IPMI_DATA_MAX_LEN - (off % IPMI_DATA_MAX_LEN); + + data->ipmi_resp.eeprom_valid = 0; + data->ipmi_tx_data[0] = ipmi_port_id; + data->ipmi_tx_data[1] = ipmi_page; + status = ipmi_send_message(&data->ipmi, cmd, data->ipmi_tx_data, 2, + data->ipmi_resp.eeprom, IPMI_DATA_MAX_LEN); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + /* Calculate return length */ + if (count < length) { + length = count; + } + + memcpy(buf, data->ipmi_resp.eeprom + (off % IPMI_DATA_MAX_LEN), length); + data->ipmi_resp.eeprom_valid = 1; + return length; + +exit: + return status; +} + + +static ssize_t sfp_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + u64 port = 0; + + if (unlikely(!count)) { + return count; + } + + port = (u64)(attr->private); + + /* + * Read data from chip, protecting against concurrent updates + * from this host + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sfp_eeprom_read(off, buf, count, port); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; + +} + +/************************************************************************************* +SFP: PS: Index of SFP is 1~48 +ipmitool raw 0x34 0x1d +Offset 0 ~ 127: Addr 0x50 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x1d 0 offset " +Offset 128 ~ 255: Addr 0x50 Offset 128~255 IPMI CMD: "ipmitool raw 0x34 0x1d 1 offset " +Offset 256 ~ 383: Addr 0x51 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x1d 2 offset " +Offset 384 ~ 511: Addr 0x51 Offset 128~255(Page 0) IPMI CMD: "ipmitool raw 0x34 0x1d 3 offset " +Offset 512 ~ 639: Addr 0x51 Offset 128~255(Page 1) IPMI CMD: "ipmitool raw 0x34 0x1d 4 offset " +Offset 640 ~ 767: Addr 0x51 Offset 128~255(Page 2) IPMI CMD: "ipmitool raw 0x34 0x1d 5 offset " + +QSFP: PS: index of QSFP is 1~6" +ipmitool raw 0x34 0x11 +Offset 0 ~ 127: Addr 0x50 Offset 0~127 IPMI CMD: "ipmitool raw 0x34 0x11 0 offset " +Offset 128 ~ 255: Addr 0x50 Offset 128~255(Page 0) IPMI CMD: "ipmitool raw 0x34 0x11 1 offset " +Offset 256 ~ 383: Addr 0x50 Offset 128~255(Page 1) IPMI CMD: "ipmitool raw 0x34 0x11 2 offset " +Offset 384 ~ 511: Addr 0x50 Offset 128~255(Page 2) IPMI CMD: "ipmitool raw 0x34 0x11 3 offset " +Offset 512 ~ 639: Addr 0x50 Offset 128~255(Page 3) IPMI CMD: "ipmitool raw 0x34 0x11 4 offset " +**************************************************************************************/ +static ssize_t sfp_eeprom_write(loff_t off, char *buf, size_t count, int port) +{ + int status = 0; + unsigned char cmd = (port <= NUM_OF_SFP) ? IPMI_SFP_WRITE_CMD : IPMI_QSFP_WRITE_CMD; + unsigned char ipmi_port_id = (port <= NUM_OF_SFP) ? port : (port - NUM_OF_SFP); + unsigned char ipmi_page = off / IPMI_DATA_MAX_LEN; + unsigned char length = IPMI_DATA_MAX_LEN - (off % IPMI_DATA_MAX_LEN); + struct sfp_eeprom_write_data wdata; + + /* Calculate write length */ + if (count < length) { + length = count; + } + + wdata.ipmi_tx_data[0] = ipmi_port_id; + wdata.ipmi_tx_data[1] = ipmi_page; + wdata.ipmi_tx_data[2] = (off % IPMI_DATA_MAX_LEN); + wdata.ipmi_tx_data[3] = length; + memcpy(&wdata.write_buf, buf, length); + status = ipmi_send_message(&data->ipmi, cmd, &wdata.ipmi_tx_data[0], + length + sizeof(wdata.ipmi_tx_data), NULL, 0); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + return length; + +exit: + return status; +} + +static ssize_t sfp_bin_write(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + u64 port = 0; + + if (unlikely(!count)) { + return count; + } + + port = (u64)(attr->private); + + /* + * 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(off, buf, count, port); + if (status <= 0) { + if (retval == 0) { + retval = status; + } + break; + } + + buf += status; + off += status; + count -= status; + retval += status; + } + + mutex_unlock(&data->update_lock); + return retval; +} + +#define EEPROM_FORMAT "module_eeprom_%d" + +static int sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom, u64 port) +{ + int ret = 0; + char *eeprom_name = NULL; + + eeprom_name = kzalloc(32, GFP_KERNEL); + if (!eeprom_name) { + ret = -ENOMEM; + goto alloc_err; + } + + sprintf(eeprom_name, EEPROM_FORMAT, (int)port); + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = eeprom_name; + eeprom->attr.mode = S_IRUGO | S_IWUSR; + eeprom->read = sfp_bin_read; + eeprom->write = sfp_bin_write; + eeprom->size = (port <= NUM_OF_SFP) ? SFP_EEPROM_SIZE : QSFP_EEPROM_SIZE; + eeprom->private = (void*)port; + + /* Create eeprom file */ + ret = sysfs_create_bin_file(kobj, eeprom); + if (unlikely(ret != 0)) { + goto bin_err; + } + + return ret; + +bin_err: + kfree(eeprom_name); +alloc_err: + return ret; +} + +static int sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} + +static int asgvolt64_sfp_probe(struct platform_device *pdev) +{ + int status = -1; + int i = 0; + + for (i = 0; i < NUM_OF_PORT; i++) { + /* Register sysfs hooks */ + status = sysfs_eeprom_init(&pdev->dev.kobj, &data->eeprom[i], + i+1/* port name start from 1*/); + if (status) { + goto exit; + } + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &asgvolt64_sfp_group); + if (status) { + goto exit; + } + + + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + /* Remove the eeprom attributes which were created successfully */ + for (--i; i >= 0; i--) { + sysfs_eeprom_cleanup(&pdev->dev.kobj, &data->eeprom[i]); + } + + return status; +} + +static int asgvolt64_sfp_remove(struct platform_device *pdev) +{ + int i = 0; + + for (i = 0; i < NUM_OF_PORT; i++) { + sysfs_eeprom_cleanup(&pdev->dev.kobj, &data->eeprom[i]); + } + + sysfs_remove_group(&pdev->dev.kobj, &asgvolt64_sfp_group); + return 0; +} + +static int __init asgvolt64_sfp_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct asgvolt64_sfp_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + + ret = platform_driver_register(&asgvolt64_sfp_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&asgvolt64_sfp_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit asgvolt64_sfp_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&asgvolt64_sfp_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("ASGVOLT64 sfp driver"); +MODULE_LICENSE("GPL"); + +module_init(asgvolt64_sfp_init); +module_exit(asgvolt64_sfp_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-sys.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-sys.c new file mode 100755 index 00000000..809031ac --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-sys.c @@ -0,0 +1,488 @@ +/* + * Copyright (C) Brandon Chuang + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "asgvolt64_sys" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_TCAM_READ_CMD 0x1E +#define IPMI_TCAM_WRITE_CMD 0x1F +#define IPMI_TCAM_RESET_SUBCMD 1 +#define IPMI_TCAM_INT_SUMCMD 2 +#define IPMI_TCAM_INT_MASK_SUBCMD 3 + +#define IPMI_SYSEEPROM_READ_CMD 0x18 +#define IPMI_TIMEOUT (20 * HZ) +#define IPMI_READ_MAX_LEN 128 + +#define EEPROM_NAME "eeprom" +#define EEPROM_SIZE 512 /* 512 byte eeprom */ + +#define IPMI_GET_CPLD_VER_CMD 0x20 +#define FPGA_ADDR 0x60 +#define MAINBOARD_CPLD2_ADDR 0x62 +#define CPU_CPLD_ADDR 0x65 +#define FAN_CPLD_ADDR 0x66 + +#define IPMI_CPLD_READ_CMD 0x22 +#define IPMI_CPLD_WRITE_CMD 0x23 + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static int asgvolt64_sys_probe(struct platform_device *pdev); +static int asgvolt64_sys_remove(struct platform_device *pdev); +static ssize_t show_cpld_version(struct device *dev, struct device_attribute *da, char *buf); + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct asgvolt64_sys_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + struct ipmi_data ipmi; + unsigned char ipmi_resp_eeprom[EEPROM_SIZE]; + unsigned char ipmi_resp_tcam; /* tcam reset: (CPLD register 0x51) + Bit0/1: Reserved + Bit 2 : CPU_JTAG_RST + Bit 3 : RESET_SYS_CPLD + Bit 4 : RESET_MAC + Bit 5 : CPLD1_TCAM_SRST_L + Bit 6 : CPLD1_TCAM_PERST_L + Bit 7 : CPLD1_TCAM_CRST_L + tcam interrupt (CPLD register 0x62) + tcam interrupt mask (CPLD register 0x63) + Bit 0 : TCAM_CPLD1_GIO_L_1 + Bit 1 : TCAM_CPLD1_GIO_L_0 */ + unsigned char ipmi_resp_cpld; + unsigned char ipmi_tx_data[3]; + struct bin_attribute eeprom; /* eeprom data */ +}; + +struct asgvolt64_sys_data *data = NULL; + +static struct platform_driver asgvolt64_sys_driver = { + .probe = asgvolt64_sys_probe, + .remove = asgvolt64_sys_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; +#if 0 //BMC cmd that not support +enum asgvolt64_sys_sysfs_attrs { + FPGA_VER, /* mainboard fpga version */ + MB_CPLD2_VER, /* mainboard cpld2 version */ + FAN_CPLD_VER, /* FAN CPLD version */ + +}; + +static SENSOR_DEVICE_ATTR(fpga_ver, S_IRUGO, show_cpld_version, NULL, FPGA_VER); +static SENSOR_DEVICE_ATTR(mb_cpld2_ver, S_IRUGO, show_cpld_version, NULL, MB_CPLD2_VER); +static SENSOR_DEVICE_ATTR(fan_cpld_ver, S_IRUGO, show_cpld_version, NULL, FAN_CPLD_VER); + + +static struct attribute *asgvolt64_sys_attributes[] = { + &sensor_dev_attr_mb_cpld2_ver.dev_attr.attr, + &sensor_dev_attr_fpga_ver.dev_attr.attr, + &sensor_dev_attr_fan_cpld_ver.dev_attr.attr, + NULL +}; + + +static const struct attribute_group asgvolt64_sys_group = { + .attrs = asgvolt64_sys_attributes, +}; +#endif +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static ssize_t sys_eeprom_read(loff_t off, char *buf, size_t count) +{ + int status = 0; + unsigned char length = 0; + + if ((off + count) > EEPROM_SIZE) { + return -EINVAL; + } + + length = (count >= IPMI_READ_MAX_LEN) ? IPMI_READ_MAX_LEN : count; + data->ipmi_tx_data[0] = (off >> 8) & 0xff; + data->ipmi_tx_data[1] = (off & 0xff); + data->ipmi_tx_data[2] = length; + status = ipmi_send_message(&data->ipmi, IPMI_SYSEEPROM_READ_CMD, + data->ipmi_tx_data, sizeof(data->ipmi_tx_data), + data->ipmi_resp_eeprom + off, length); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + status = length; /* Read length */ + memcpy(buf, data->ipmi_resp_eeprom + off, length); + +exit: + return status; +} + +static ssize_t sysfs_bin_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + ssize_t retval = 0; + + if (unlikely(!count)) { + return count; + } + + /* + * Read data from chip, protecting against concurrent updates + * from this host + */ + mutex_lock(&data->update_lock); + + while (count) { + ssize_t status; + + status = sys_eeprom_read(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 int sysfs_eeprom_init(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_bin_attr_init(eeprom); + eeprom->attr.name = EEPROM_NAME; + eeprom->attr.mode = S_IRUGO; + eeprom->read = sysfs_bin_read; + eeprom->write = NULL; + eeprom->size = EEPROM_SIZE; + + /* Create eeprom file */ + return sysfs_create_bin_file(kobj, eeprom); +} + +static int sysfs_eeprom_cleanup(struct kobject *kobj, struct bin_attribute *eeprom) +{ + sysfs_remove_bin_file(kobj, eeprom); + return 0; +} +#if 0 +static struct asgvolt64_sys_data *asgvolt64_sys_update_cpld_ver(unsigned char cpld_addr) +{ + int status = 0; + + data->valid = 0; + data->ipmi_tx_data[0] = cpld_addr; + status = ipmi_send_message(&data->ipmi, IPMI_GET_CPLD_VER_CMD, data->ipmi_tx_data, 1, + &data->ipmi_resp_cpld, sizeof(data->ipmi_resp_cpld)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + +exit: + return data; +} +#endif + +#if 0 +static ssize_t show_cpld_version(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + unsigned char addr = 0, value = 0; + int error = 0; + + switch (attr->index) { + case FPGA_VER: + addr = FPGA_ADDR; + break; + case MB_CPLD2_VER: + addr = MAINBOARD_CPLD2_ADDR; + break; + case FAN_CPLD_VER: + addr = FAN_CPLD_ADDR; + break; + default: + return -EINVAL; + } + + mutex_lock(&data->update_lock); + + data = asgvolt64_sys_update_cpld_ver(addr); + if (!data->valid) { + error = -EIO; + goto exit; + } + + value = data->ipmi_resp_cpld; + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", value); + +exit: + mutex_unlock(&data->update_lock); + return error; +} +#endif +static int asgvolt64_sys_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_eeprom_init(&pdev->dev.kobj, &data->eeprom); + if (status) { + goto exit; + } + + /* Register sysfs hooks */ +#if 0 + status = sysfs_create_group(&pdev->dev.kobj, &asgvolt64_sys_group); + if (status) { + goto exit; + } +#endif + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int asgvolt64_sys_remove(struct platform_device *pdev) +{ + sysfs_eeprom_cleanup(&pdev->dev.kobj, &data->eeprom); + //sysfs_remove_group(&pdev->dev.kobj, &asgvolt64_sys_group); + + return 0; +} + +static int __init asgvolt64_sys_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct asgvolt64_sys_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + + ret = platform_driver_register(&asgvolt64_sys_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&asgvolt64_sys_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit asgvolt64_sys_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&asgvolt64_sys_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("ASGVOLT64 System driver"); +MODULE_LICENSE("GPL"); + +module_init(asgvolt64_sys_init); +module_exit(asgvolt64_sys_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-thermal.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-thermal.c new file mode 100755 index 00000000..f33826d2 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/modules/builds/x86-64-accton-asgvolt64-thermal.c @@ -0,0 +1,355 @@ +/* + * Copyright (C) Brandon Chuang + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "asgvolt64_thermal" +#define ACCTON_IPMI_NETFN 0x34 +#define IPMI_THERMAL_READ_CMD 0x12 +#define IPMI_TIMEOUT (20 * HZ) + +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); +static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf); +static int asgvolt64_thermal_probe(struct platform_device *pdev); +static int asgvolt64_thermal_remove(struct platform_device *pdev); + +enum temp_data_index { + TEMP_ADDR, + TEMP_FAULT, + TEMP_INPUT, + TEMP_DATA_COUNT +}; + +struct ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct ipmi_user_hndl ipmi_hndlrs; +}; + +struct asgvolt64_thermal_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + char ipmi_resp[22]; /* 3 bytes for each thermal. 7-thermal, so need 7*3=21 */ + struct ipmi_data ipmi; +}; + +struct asgvolt64_thermal_data *data = NULL; + +static struct platform_driver asgvolt64_thermal_driver = { + .probe = asgvolt64_thermal_probe, + .remove = asgvolt64_thermal_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +enum asgvolt64_thermal_sysfs_attrs { + TEMP1_INPUT, + TEMP2_INPUT, + TEMP3_INPUT, + TEMP4_INPUT, + TEMP5_INPUT, + TEMP6_INPUT, + TEMP7_INPUT, +}; + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, TEMP2_INPUT); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, TEMP3_INPUT); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, TEMP4_INPUT); +static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, TEMP5_INPUT); +static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp, NULL, TEMP6_INPUT); +static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp, NULL, TEMP7_INPUT); + +static struct attribute *asgvolt64_thermal_attributes[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, + &sensor_dev_attr_temp5_input.dev_attr.attr, + &sensor_dev_attr_temp6_input.dev_attr.attr, + &sensor_dev_attr_temp7_input.dev_attr.attr, + NULL +}; + +static const struct attribute_group asgvolt64_thermal_group = { + .attrs = asgvolt64_thermal_attributes, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int init_ipmi_data(struct ipmi_data *ipmi, int iface, + struct device *dev) +{ + int err; + + init_completion(&ipmi->read_complete); + + /* Initialize IPMI address */ + ipmi->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + ipmi->address.channel = IPMI_BMC_CHANNEL; + ipmi->address.data[0] = 0; + ipmi->interface = iface; + + /* Initialize message buffers */ + ipmi->tx_msgid = 0; + ipmi->tx_message.netfn = ACCTON_IPMI_NETFN; + + ipmi->ipmi_hndlrs.ipmi_recv_hndl = ipmi_msg_handler; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(ipmi->interface, &ipmi->ipmi_hndlrs, + ipmi, &ipmi->user); + if (err < 0) { + dev_err(dev, "Unable to register user with IPMI " + "interface %d\n", ipmi->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int ipmi_send_message(struct ipmi_data *ipmi, unsigned char cmd, + unsigned char *tx_data, unsigned short tx_len, + unsigned char *rx_data, unsigned short rx_len) +{ + int err; + + ipmi->tx_message.cmd = cmd; + ipmi->tx_message.data = tx_data; + ipmi->tx_message.data_len = tx_len; + ipmi->rx_msg_data = rx_data; + ipmi->rx_msg_len = rx_len; + + err = ipmi_validate_addr(&ipmi->address, sizeof(ipmi->address)); + if (err) + goto addr_err; + + ipmi->tx_msgid++; + err = ipmi_request_settime(ipmi->user, &ipmi->address, ipmi->tx_msgid, + &ipmi->tx_message, ipmi, 0, 0, 0); + if (err) + goto ipmi_req_err; + + err = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!err) + goto ipmi_timeout_err; + + return 0; + +ipmi_timeout_err: + err = -ETIMEDOUT; + dev_err(&data->pdev->dev, "request_timeout=%x\n", err); + return err; +ipmi_req_err: + dev_err(&data->pdev->dev, "request_settime=%x\n", err); + return err; +addr_err: + dev_err(&data->pdev->dev, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct ipmi_data *ipmi = user_msg_data; + + if (msg->msgid != ipmi->tx_msgid) { + dev_err(&data->pdev->dev, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)ipmi->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + ipmi->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + ipmi->rx_result = msg->msg.data[0]; + else + ipmi->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (ipmi->rx_msg_len < rx_len) + rx_len = ipmi->rx_msg_len; + ipmi->rx_msg_len = rx_len; + memcpy(ipmi->rx_msg_data, msg->msg.data + 1, ipmi->rx_msg_len); + } else + ipmi->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&ipmi->read_complete); +} + +static ssize_t show_temp(struct device *dev, struct device_attribute *da, char *buf) +{ + int status = 0; + int index = 0; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ * 5) || !data->valid) { + data->valid = 0; + + status = ipmi_send_message(&data->ipmi, IPMI_THERMAL_READ_CMD, NULL, 0, + data->ipmi_resp, sizeof(data->ipmi_resp)); + if (unlikely(status != 0)) { + goto exit; + } + + if (unlikely(data->ipmi.rx_result != 0)) { + status = -EIO; + goto exit; + } + + data->last_updated = jiffies; + data->valid = 1; + } + + /* Get temp fault status */ + index = attr->index * TEMP_DATA_COUNT + TEMP_FAULT; + if (unlikely(data->ipmi_resp[index] == 0)) { + status = -EIO; + goto exit; + } + + /* Get temperature in degree celsius */ + index = attr->index * TEMP_DATA_COUNT + TEMP_INPUT; + status = data->ipmi_resp[index] * 1000; + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", status); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int asgvolt64_thermal_probe(struct platform_device *pdev) +{ + int status = -1; + + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &asgvolt64_thermal_group); + if (status) { + goto exit; + } + + dev_info(&pdev->dev, "device created\n"); + + return 0; + +exit: + return status; +} + +static int asgvolt64_thermal_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&pdev->dev.kobj, &asgvolt64_thermal_group); + + return 0; +} + +static int __init asgvolt64_thermal_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct asgvolt64_thermal_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + data->valid = 0; + + ret = platform_driver_register(&asgvolt64_thermal_driver); + if (ret < 0) { + goto dri_reg_err; + } + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + /* Set up IPMI interface */ + ret = init_ipmi_data(&data->ipmi, 0, &data->pdev->dev); + if (ret) + goto ipmi_err; + + return 0; + +ipmi_err: + platform_device_unregister(data->pdev); +dev_reg_err: + platform_driver_unregister(&asgvolt64_thermal_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit asgvolt64_thermal_exit(void) +{ + ipmi_destroy_user(data->ipmi.user); + platform_device_unregister(data->pdev); + platform_driver_unregister(&asgvolt64_thermal_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("ASGVOLT64 Thermal driver"); +MODULE_LICENSE("GPL"); + +module_init(asgvolt64_thermal_init); +module_exit(asgvolt64_thermal_exit); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/PKG.yml new file mode 100755 index 00000000..24453d61 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-accton-asgvolt64 ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/Makefile new file mode 100755 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/lib/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/lib/Makefile new file mode 100755 index 00000000..8c1691c5 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/lib/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.eclipse.org/legal/epl-v10.html +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +# either express or implied. See the License for the specific +# language governing permissions and limitations under the +# License. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-accton-asgvolt64 +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_accton_asgvolt64 onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-accton-asgvolt64.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/x86-64/x86-64-accton-asgvolt64/onlp/builds/onlpdump/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/onlpdump/Makefile new file mode 100755 index 00000000..d5213b77 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/onlpdump/Makefile @@ -0,0 +1,46 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.eclipse.org/legal/epl-v10.html +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +# either express or implied. See the License for the specific +# language governing permissions and limitations under the +# License. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp x86_64_accton_asgvolt64 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/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/.module b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/.module new file mode 100755 index 00000000..5bb66e85 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/.module @@ -0,0 +1 @@ +name: x86_64_accton_asgvolt64 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/Makefile new file mode 100755 index 00000000..1091ecea --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include $(ONL)/make/config.mk +MODULE := x86_64_accton_asgvolt64 +AUTOMODULE := x86_64_accton_asgvolt64 +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/README b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/README new file mode 100755 index 00000000..f4b1aeaf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/README @@ -0,0 +1,6 @@ +############################################################################### +# +# x86_64_accton_asgvolt64 README +# +############################################################################### + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/auto/x86_64_accton_asgvolt64.yml b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/auto/x86_64_accton_asgvolt64.yml new file mode 100755 index 00000000..fd43e0c7 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/auto/x86_64_accton_asgvolt64.yml @@ -0,0 +1,50 @@ +############################################################################### +# +# x86_64_accton_asgvolt64 Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- X86_64_ACCTON_ASGVOLT64_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- X86_64_ACCTON_ASGVOLT64_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- X86_64_ACCTON_ASGVOLT64_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- X86_64_ACCTON_ASGVOLT64_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- X86_64_ACCTON_ASGVOLT64_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- X86_64_ACCTON_ASGVOLT64_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: x86_64_accton_asgvolt64_CONFIG_PORTING_STDLIB +- X86_64_ACCTON_ASGVOLT64_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- X86_64_ACCTON_ASGVOLT64_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION: + doc: "Assume chassis fan direction is the same as the PSU fan direction." + default: 0 + + +definitions: + cdefs: + X86_64_ACCTON_ASGVOLT64_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_accton_asgvolt64_config + + portingmacro: + x86_64_accton_asgvolt64: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/inc/x86_64_accton_asgvolt64/x86_64_accton_asgvolt64.x b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/inc/x86_64_accton_asgvolt64/x86_64_accton_asgvolt64.x new file mode 100755 index 00000000..05737a4e --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/inc/x86_64_accton_asgvolt64/x86_64_accton_asgvolt64.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/inc/x86_64_accton_asgvolt64/x86_64_accton_asgvolt64_config.h b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/inc/x86_64_accton_asgvolt64/x86_64_accton_asgvolt64_config.h new file mode 100755 index 00000000..dbc24520 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/inc/x86_64_accton_asgvolt64/x86_64_accton_asgvolt64_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_asgvolt64 Configuration Header + * + * @addtogroup x86_64_accton_asgvolt64-config + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_accton_asgvolt64_CONFIG_H__ +#define __x86_64_accton_asgvolt64_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef x86_64_accton_asgvolt64_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * x86_64_accton_asgvolt64_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef x86_64_accton_asgvolt64_CONFIG_INCLUDE_LOGGING +#define x86_64_accton_asgvolt64_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * x86_64_accton_asgvolt64_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef x86_64_accton_asgvolt64_CONFIG_LOG_OPTIONS_DEFAULT +#define x86_64_accton_asgvolt64_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * x86_64_accton_asgvolt64_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef x86_64_accton_asgvolt64_CONFIG_LOG_BITS_DEFAULT +#define x86_64_accton_asgvolt64_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * x86_64_accton_asgvolt64_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef x86_64_accton_asgvolt64_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define x86_64_accton_asgvolt64_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * x86_64_accton_asgvolt64_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef x86_64_accton_asgvolt64_CONFIG_PORTING_STDLIB +#define x86_64_accton_asgvolt64_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * x86_64_accton_asgvolt64_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef x86_64_accton_asgvolt64_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define x86_64_accton_asgvolt64_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS x86_64_accton_asgvolt64_CONFIG_PORTING_STDLIB +#endif + +/** + * x86_64_accton_asgvolt64_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef x86_64_accton_asgvolt64_CONFIG_INCLUDE_UCLI +#define x86_64_accton_asgvolt64_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * x86_64_accton_asgvolt64_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef x86_64_accton_asgvolt64_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define x86_64_accton_asgvolt64_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_accton_asgvolt64_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_accton_asgvolt64_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_accton_asgvolt64_config_settings table. */ +extern x86_64_accton_asgvolt64_config_settings_t x86_64_accton_asgvolt64_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_accton_asgvolt64_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_accton_asgvolt64_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_accton_asgvolt64_porting.h" + +#endif /* __x86_64_accton_asgvolt64_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/inc/x86_64_accton_asgvolt64/x86_64_accton_asgvolt64_dox.h b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/inc/x86_64_accton_asgvolt64/x86_64_accton_asgvolt64_dox.h new file mode 100755 index 00000000..0d13663e --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/inc/x86_64_accton_asgvolt64/x86_64_accton_asgvolt64_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_accton_asgvolt64 Doxygen Header + * + *****************************************************************************/ +#ifndef __x86_64_accton_asgvolt64_DOX_H__ +#define __x86_64_accton_asgvolt64_DOX_H__ + +/** + * @defgroup x86_64_accton_asgvolt64 x86_64_accton_asgvolt64 - x86_64_accton_asgvolt64 Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_accton_asgvolt64-x86_64_accton_asgvolt64 Public Interface + * @defgroup x86_64_accton_asgvolt64-config Compile Time Configuration + * @defgroup x86_64_accton_asgvolt64-porting Porting Macros + * + * @} + * + */ + +#endif /* __x86_64_accton_asgvolt64_DOX_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/inc/x86_64_accton_asgvolt64/x86_64_accton_asgvolt64_porting.h b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/inc/x86_64_accton_asgvolt64/x86_64_accton_asgvolt64_porting.h new file mode 100755 index 00000000..546faead --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/inc/x86_64_accton_asgvolt64/x86_64_accton_asgvolt64_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_asgvolt64 Porting Macros. + * + * @addtogroup x86_64_accton_asgvolt64-porting + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_accton_asgvolt64_PORTING_H__ +#define __x86_64_accton_asgvolt64_PORTING_H__ + + +/* */ +#if x86_64_accton_asgvolt64_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef x86_64_accton_asgvolt64_MALLOC + #if defined(GLOBAL_MALLOC) + #define x86_64_accton_asgvolt64_MALLOC GLOBAL_MALLOC + #elif x86_64_accton_asgvolt64_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_asgvolt64_MALLOC malloc + #else + #error The macro x86_64_accton_asgvolt64_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_asgvolt64_FREE + #if defined(GLOBAL_FREE) + #define x86_64_accton_asgvolt64_FREE GLOBAL_FREE + #elif x86_64_accton_asgvolt64_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_asgvolt64_FREE free + #else + #error The macro x86_64_accton_asgvolt64_FREE is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_asgvolt64_MEMSET + #if defined(GLOBAL_MEMSET) + #define x86_64_accton_asgvolt64_MEMSET GLOBAL_MEMSET + #elif x86_64_accton_asgvolt64_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_asgvolt64_MEMSET memset + #else + #error The macro x86_64_accton_asgvolt64_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_asgvolt64_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define x86_64_accton_asgvolt64_MEMCPY GLOBAL_MEMCPY + #elif x86_64_accton_asgvolt64_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_asgvolt64_MEMCPY memcpy + #else + #error The macro x86_64_accton_asgvolt64_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_asgvolt64_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define x86_64_accton_asgvolt64_STRNCPY GLOBAL_STRNCPY + #elif x86_64_accton_asgvolt64_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_asgvolt64_STRNCPY strncpy + #else + #error The macro x86_64_accton_asgvolt64_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_asgvolt64_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define x86_64_accton_asgvolt64_VSNPRINTF GLOBAL_VSNPRINTF + #elif x86_64_accton_asgvolt64_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_asgvolt64_VSNPRINTF vsnprintf + #else + #error The macro x86_64_accton_asgvolt64_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_asgvolt64_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define x86_64_accton_asgvolt64_SNPRINTF GLOBAL_SNPRINTF + #elif x86_64_accton_asgvolt64_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_asgvolt64_SNPRINTF snprintf + #else + #error The macro x86_64_accton_asgvolt64_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_accton_asgvolt64_STRLEN + #if defined(GLOBAL_STRLEN) + #define x86_64_accton_asgvolt64_STRLEN GLOBAL_STRLEN + #elif x86_64_accton_asgvolt64_CONFIG_PORTING_STDLIB == 1 + #define x86_64_accton_asgvolt64_STRLEN strlen + #else + #error The macro x86_64_accton_asgvolt64_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __x86_64_accton_asgvolt64_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/make.mk new file mode 100755 index 00000000..6aeec6e2 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_accton_asgvolt64_INCLUDES := -I $(THIS_DIR)inc +x86_64_accton_asgvolt64_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_accton_asgvolt64_DEPENDMODULE_ENTRIES := init:x86_64_accton_asgvolt64 ucli:x86_64_accton_asgvolt64 + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/Makefile new file mode 100755 index 00000000..d5fdf73c --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_accton_asgvolt64_ucli.c + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/debug.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/debug.c new file mode 100755 index 00000000..07564b2e --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/debug.c @@ -0,0 +1,45 @@ +#include "x86_64_accton_asgvolt64_int.h" + +#if x86_64_accton_asgvolt64_CONFIG_INCLUDE_DEBUG == 1 + +#include + +static char help__[] = + "Usage: debug [options]\n" + " -c CPLD Versions\n" + " -h Help\n" + ; + +int +x86_64_accton_asgvolt64_debug_main(int argc, char* argv[]) +{ + int c = 0; + int help = 0; + int rv = 0; + + while( (c = getopt(argc, argv, "ch")) != -1) { + switch(c) + { + case 'c': c = 1; break; + case 'h': help = 1; rv = 0; break; + default: help = 1; rv = 1; break; + } + + } + + if(help || argc == 1) { + printf("%s", help__); + return rv; + } + + if(c) { + printf("Not implemented.\n"); + } + + + return 0; +} + +#endif + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/fani.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/fani.c new file mode 100755 index 00000000..9383f15b --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/fani.c @@ -0,0 +1,229 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 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 "platform_lib.h" + +enum fan_id { + FAN_1_ON_FAN_BOARD = 1, + FAN_2_ON_FAN_BOARD, + FAN_3_ON_FAN_BOARD, + FAN_4_ON_FAN_BOARD, + FAN_1_ON_PSU_1, + FAN_1_ON_PSU_2, +}; + +#define MAX_FAN_SPEED 25500 +#define MAX_PSU_FAN_SPEED 25500 + +#define CHASSIS_FAN_INFO(fid) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fid##_ON_FAN_BOARD), "Chassis Fan - "#fid, 0 },\ + 0x0,\ + ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE,\ + 0,\ + 0,\ + ONLP_FAN_MODE_INVALID,\ + } + +#define PSU_FAN_INFO(pid, fid) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fid##_ON_PSU_##pid), "PSU "#pid" - Fan "#fid, 0 },\ + 0x0,\ + 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 finfo[] = { + { }, /* Not used */ + CHASSIS_FAN_INFO(1), + CHASSIS_FAN_INFO(2), + CHASSIS_FAN_INFO(3), + CHASSIS_FAN_INFO(4), + PSU_FAN_INFO(1, 1), + PSU_FAN_INFO(2, 1) +}; + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +_onlp_fani_info_get_fan(int fid, onlp_fan_info_t* info) +{ + int value, ret; + + /* get fan present status + */ + ret = onlp_file_read_int(&value, "%s""fan%d_present", FAN_BOARD_PATH, fid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH); + return ONLP_STATUS_E_INTERNAL; + } + + if (value == 0) { + return ONLP_STATUS_OK; /* fan is not present */ + } + info->status |= ONLP_FAN_STATUS_PRESENT; + + + /* get fan direction + */ + info->status |= ONLP_FAN_STATUS_F2B; + + + /* get fan speed + */ + ret = onlp_file_read_int(&value, "%s""fan%d_input", FAN_BOARD_PATH, fid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH); + return ONLP_STATUS_E_INTERNAL; + } + info->rpm = value; + info->percentage = (info->rpm * 100)/MAX_FAN_SPEED; + + + /* get fan fault status + */ + if (!info->rpm) { + info->status |= ONLP_FAN_STATUS_FAILED; + } + + return ONLP_STATUS_OK; +} + +static int +_onlp_fani_info_get_fan_on_psu(int pid, onlp_fan_info_t* info) +{ + int value, ret; + + info->status |= ONLP_FAN_STATUS_PRESENT; + + /* get fan direction + */ + info->status |= ONLP_FAN_STATUS_F2B; + + /* get fan speed + */ + ret = onlp_file_read_int(&value, "%s""psu%d_fan1_input", PSU_SYSFS_PATH, pid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s)\r\n", PSU_SYSFS_PATH); + return ONLP_STATUS_E_INTERNAL; + } + + info->rpm = value; + info->percentage = (info->rpm * 100)/MAX_PSU_FAN_SPEED; + + /* get fan fault status + */ + if (!info->rpm) { + info->status |= ONLP_FAN_STATUS_FAILED; + } + + 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 fid; + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + *info = finfo[fid]; + + switch (fid) + { + case FAN_1_ON_PSU_1: + rc = _onlp_fani_info_get_fan_on_psu(PSU1_ID, info); + break; + case FAN_1_ON_PSU_2: + rc = _onlp_fani_info_get_fan_on_psu(PSU2_ID, info); + break; + case FAN_1_ON_FAN_BOARD: + case FAN_2_ON_FAN_BOARD: + case FAN_3_ON_FAN_BOARD: + case FAN_4_ON_FAN_BOARD: + rc =_onlp_fani_info_get_fan(fid, info); + break; + default: + rc = ONLP_STATUS_E_INVALID; + break; + } + + return rc; +} + +/* + * 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 fid; + + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + + /* reject p=0 (p=0, stop fan) */ + if (p == 0){ + return ONLP_STATUS_E_INVALID; + } + + if (fid < FAN_1_ON_FAN_BOARD || fid > FAN_4_ON_FAN_BOARD) { + return ONLP_STATUS_E_INVALID; + } + + if (onlp_file_write_int(p, "%s""fan%d_pwm", FAN_BOARD_PATH, fid) < 0) { + AIM_LOG_ERROR("Unable to write data to file %s""fan%d_pwm", FAN_BOARD_PATH, fid); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/ledi.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/ledi.c new file mode 100755 index 00000000..4bd557dd --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/ledi.c @@ -0,0 +1,274 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2013 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +#define prefix_path "/sys/devices/platform/accton_asgvolt64_led/leds/" +#define filename "brightness" + +enum onlp_led_id +{ + LED_RESERVED = 0, + LED_LOC = 1, + LED_STATE, + LED_ALARM, + LED_PSU1, + LED_PSU2, + LED_FAN, +}; + +/* LED related data + */ + +enum led_light_mode { + LED_MODE_OFF, + LED_MODE_RED = 10, + LED_MODE_RED_BLINKING = 11, + LED_MODE_ORANGE = 12, + LED_MODE_ORANGE_BLINKING = 13, + LED_MODE_YELLOW = 14, + LED_MODE_YELLOW_BLINKING = 15, + LED_MODE_GREEN = 16, + LED_MODE_GREEN_BLINKING = 17, + LED_MODE_BLUE = 18, + LED_MODE_BLUE_BLINKING = 19, + LED_MODE_PURPLE = 20, + LED_MODE_PURPLE_BLINKING = 21, + LED_MODE_AUTO = 22, + LED_MODE_AUTO_BLINKING = 23, + LED_MODE_WHITE = 24, + LED_MODE_WHITE_BLINKING = 25, + LED_MODE_CYAN = 26, + LED_MODE_CYAN_BLINKING = 27, + LED_MODE_UNKNOWN = 99 +}; + +typedef struct led_light_mode_map { + enum onlp_led_id id; + enum led_light_mode driver_led_mode; + enum onlp_led_mode_e onlp_led_mode; +} led_light_mode_map_t; + +led_light_mode_map_t led_map[] = { +{LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF}, +{LED_LOC, LED_MODE_ORANGE_BLINKING,ONLP_LED_MODE_ORANGE_BLINKING}, +{LED_STATE, LED_MODE_RED, ONLP_LED_MODE_RED}, +{LED_STATE, LED_MODE_BLUE, ONLP_LED_MODE_BLUE}, +{LED_STATE, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, +{LED_ALARM, LED_MODE_RED, ONLP_LED_MODE_RED}, +{LED_ALARM, LED_MODE_BLUE, ONLP_LED_MODE_BLUE}, +{LED_ALARM, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, +{LED_FAN, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, +{LED_PSU1, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, +{LED_PSU2, LED_MODE_AUTO, ONLP_LED_MODE_AUTO} +}; + + +static char *leds[] = /* must map with onlp_led_id */ +{ + NULL, + "loc", + "state", + "alarm", + "psu1", + "psu2", + "fan" +}; + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t linfo[] = +{ + { }, /* Not used */ + { + { ONLP_LED_ID_CREATE(LED_LOC), "Chassis LED 1 (LOC LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE, + }, + { + { ONLP_LED_ID_CREATE(LED_STATE), "Chassis LED 2 (STATE LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_RED | ONLP_LED_CAPS_BLUE | ONLP_LED_CAPS_GREEN, + }, + { + { ONLP_LED_ID_CREATE(LED_ALARM), "Chassis LED 3 (ALARM LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_RED | ONLP_LED_CAPS_BLUE | ONLP_LED_CAPS_GREEN, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU1), "Chassis LED 4 (PSU1 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU2), "Chassis LED 5 (PSU2 LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_FAN), "Chassis LED 6 (FAN LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_AUTO, + }, +}; + +static int driver_to_onlp_led_mode(enum onlp_led_id id, enum led_light_mode driver_led_mode) +{ + int i, nsize = sizeof(led_map)/sizeof(led_map[0]); + + for (i = 0; i < nsize; i++) + { + if (id == led_map[i].id && driver_led_mode == led_map[i].driver_led_mode) + { + return led_map[i].onlp_led_mode; + } + } + + return 0; +} + +static int onlp_to_driver_led_mode(enum onlp_led_id id, onlp_led_mode_t onlp_led_mode) +{ + int i, nsize = sizeof(led_map)/sizeof(led_map[0]); + + for(i = 0; i < nsize; i++) + { + if (id == led_map[i].id && onlp_led_mode == led_map[i].onlp_led_mode) + { + return led_map[i].driver_led_mode; + } + } + + return 0; +} + +/* + * This function will be called prior to any other onlp_ledi_* functions. + */ +int +onlp_ledi_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int local_id; + char data[2] = {0}; + char fullpath[50] = {0}; + + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + + /* get fullpath */ + sprintf(fullpath, "%s%s/%s", prefix_path, leds[local_id], filename); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[ONLP_OID_ID_GET(id)]; + + /* Set LED mode */ + if (onlp_file_read_string(fullpath, data, sizeof(data), 0) != 0) { + DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__); + return ONLP_STATUS_E_INTERNAL; + } + + info->mode = driver_to_onlp_led_mode(local_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 local_id; + char fullpath[50] = {0}; + + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + sprintf(fullpath, "%s%s/%s", prefix_path, leds[local_id], filename); + + if (onlp_file_write_integer(fullpath, onlp_to_driver_led_mode(local_id, mode)) != 0) + { + return ONLP_STATUS_E_INTERNAL; + } + + 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/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/make.mk b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/make.mk new file mode 100755 index 00000000..75f6db73 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_accton_asgvolt64 +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/platform_lib.c new file mode 100755 index 00000000..1c520af2 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/platform_lib.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include "platform_lib.h" +#include +#include "x86_64_accton_asgvolt64_log.h" + + +static int _onlp_file_write(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 onlp_file_write_integer(char *filename, int value) +{ + char buf[8] = {0}; + sprintf(buf, "%d", value); + + return _onlp_file_write(filename, buf, (int)strlen(buf), 0); +} + +int onlp_file_read_binary(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 onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len) +{ + int ret; + + if (data_len >= buf_size) { + return -1; + } + + ret = onlp_file_read_binary(filename, buffer, buf_size-1, data_len); + + if (ret == 0) { + buffer[buf_size-1] = '\0'; + } + + return ret; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/platform_lib.h new file mode 100755 index 00000000..b9d60841 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/platform_lib.h @@ -0,0 +1,74 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 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 "x86_64_accton_asgvolt64_log.h" + +#define CHASSIS_FAN_COUNT 4 +#define CHASSIS_THERMAL_COUNT 8 +#define CHASSIS_PSU_COUNT 2 +#define CHASSIS_LED_COUNT 6 + +#define PSU1_ID 1 +#define PSU2_ID 2 + +#define PSU_SYSFS_PATH "/sys/devices/platform/asgvolt64_psu/" +#define FAN_BOARD_PATH "/sys/devices/platform/asgvolt64_fan/" +#define IDPROM_PATH "/sys/i2c/devices/0-0057/eeprom" + +int onlp_file_write_integer(char *filename, int value); +int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len); +int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len); + + +enum onlp_thermal_id +{ + THERMAL_RESERVED = 0, + THERMAL_CPU_CORE, + THERMAL_1_ON_MAIN_BROAD, + THERMAL_2_ON_MAIN_BROAD, + THERMAL_3_ON_MAIN_BROAD, + THERMAL_4_ON_MAIN_BROAD, + THERMAL_5_ON_MAIN_BROAD, + THERMAL_6_ON_MAIN_BROAD, + THERMAL_7_ON_MAIN_BROAD, + THERMAL_1_ON_PSU1, + THERMAL_1_ON_PSU2, +}; + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(fmt, args...) \ + printf("%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args) +#else + #define DEBUG_PRINT(fmt, args...) +#endif + +#endif /* __PLATFORM_LIB_H__ */ + + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/psui.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/psui.c new file mode 100755 index 00000000..b5adbe66 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/psui.c @@ -0,0 +1,153 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 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 "platform_lib.h" + +#define PSU_STATUS_PRESENT 1 +#define PSU_STATUS_POWER_GOOD 1 + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +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 pid = ONLP_OID_ID_GET(id); + // char test_str[32]; + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_psu_info_t)); + *info = pinfo[pid]; /* Set the onlp_oid_hdr_t */ + + /* Get the present state */ + ret = onlp_file_read_int(&val, "%s""psu%d_present", PSU_SYSFS_PATH, pid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s""psu%d_present)\r\n", PSU_SYSFS_PATH, pid); + return ONLP_STATUS_E_INTERNAL; + } + 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 */ + ret = onlp_file_read_int(&val, "%s""psu%d_power_good", PSU_SYSFS_PATH, pid); + if (ret < 0) { + AIM_LOG_ERROR("Unable to read status from (%s""psu%d_power_good)\r\n", PSU_SYSFS_PATH, pid); + return ONLP_STATUS_E_INTERNAL; + } + + if (val != PSU_STATUS_POWER_GOOD) { + info->status |= ONLP_PSU_STATUS_FAILED; + } + + if (info->status & ONLP_PSU_STATUS_FAILED) { + return ONLP_STATUS_OK; + } + /* Read voltage, current and power */ + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_vin", PSU_SYSFS_PATH, pid) == 0 && val) { + info->mvin = val; + info->caps |= ONLP_PSU_CAPS_VIN; + } + + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_vout", PSU_SYSFS_PATH, pid) == 0 && val) { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_iout", PSU_SYSFS_PATH, pid) == 0 && val) { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_pout", PSU_SYSFS_PATH, pid) == 0 && val) { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + /* Set the associated oid_table */ + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_fan1_input", PSU_SYSFS_PATH, pid) == 0 && val) { + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(pid + CHASSIS_FAN_COUNT); + } + + val = 0; + if (onlp_file_read_int(&val, "%s""psu%d_temp1_input", PSU_SYSFS_PATH, pid) == 0 && val) { + info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(pid + CHASSIS_THERMAL_COUNT); + } + + /* Read model */ + char *string = NULL; + int len = onlp_file_read_str(&string, "%s""psu%d_model", PSU_SYSFS_PATH, pid); + if (string && len) { + strncpy(info->model, string, len); + aim_free(string); + } + + /* Read serial */ + len = onlp_file_read_str(&string, "%s""psu%d_serial", PSU_SYSFS_PATH, pid); + if (string && len) { + strncpy(info->serial, string, len); + aim_free(string); + } + + return ret; +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/sfpi.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/sfpi.c new file mode 100755 index 00000000..501a59d1 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/sfpi.c @@ -0,0 +1,418 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2013 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include "x86_64_accton_asgvolt64_int.h" +#include "x86_64_accton_asgvolt64_log.h" + +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" +#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_present_%d" +#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_rx_los_%d" +#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_fault_%d" +#define MODULE_TXDISABLE_FORMAT "/sys/bus/i2c/devices/%d-00%d/module_tx_disable_%d" + +int sfp_map_bus[] ={ + 41,42,43,44,45,46,47,48, + 49,50,51,52,53,54,55,56, + 57,58,59,60,61,62,63,64, + 65,66,67,68,69,70,71,72, + 73,74,75,76,77,78,79,80, + 81,82,83,84,85,86,87,88, + 89,90,91,92,93,94,95,96, + 97,98,99,100,101,102,103,104, + 20, 21, + 25, 26, 27, 28, 29, 30, 31, 32,}; + +/************************************************************ + * + * SFPI Entry Points + * + ***********************************************************/ + +int +onlp_sfpi_init(void) +{ + /* Called at initialization time */ + return ONLP_STATUS_OK; +} +int +onlp_sfpi_map_bus_index(int port) +{ + if(port < 0 || port >=74) + return ONLP_STATUS_E_INTERNAL; + return sfp_map_bus[port]; +} + +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + /* + * Ports {0, 73} + */ + int p; + + for(p = 0; p < 74; p++) { + AIM_BITMAP_SET(bmap, p); + } + + return ONLP_STATUS_OK; +} +int onlp_sfpi_get_cpld_addr(int port, int * addr, int *bus) +{ + + if(port <0 || port >= 74) + return ONLP_STATUS_E_INTERNAL; + + /*gpon*/ + *addr=60; + *bus=9; + if(port >=0 && port <=25) + { + if(port ==22 || port ==23 || port==18 || port==19) + { + *addr = 61; + *bus = 10; + } + else + { + *addr = 60; + *bus = 9; + } + } + if(port >=26 && port <=47) + { + if(port ==34 || port==35 || port==38 || port==39 || port==42) + { + *addr = 62; + *bus = 11; + } + else + { + *addr = 61; + *bus = 10; + } + } + if(port >=48 && port <=63) + { + *addr = 62; + *bus = 11; + } + /*QSFP*/ + if(port >=64 && port <=65) + { + *addr = 60; + *bus = 9; + } + /*SFP*/ + if(port >=66 && port <=73) + { + *addr = 61; + *bus = 10; + } + + 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; + int bus=9, addr=0x60; + + if(port <0 || port >= 74) + return ONLP_STATUS_E_INTERNAL; + + if(onlp_sfpi_get_cpld_addr(port, &addr, &bus)!=ONLP_STATUS_OK) + return ONLP_STATUS_E_INTERNAL; + + + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + + return present; +} + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + int i=0, val=0; + + /* Populate bitmap */ + for(i = 0; i<74; i++) { + val=0; + if(i >=66 && i <=73) + { + if (onlp_file_read_int(&val, MODULE_RXLOS_FORMAT, 10, 61, i+1) < 0) + { + AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", i); + } + + if(val) + AIM_BITMAP_MOD(dst, i, 1); + else + AIM_BITMAP_MOD(dst, i, 0); + } + else + AIM_BITMAP_MOD(dst, i, 0); + + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + /* + * Read the SFP eeprom into data[] + * + * Return MISSING if SFP is missing. + * Return OK if eeprom is read + */ + int size = 0; + if(port <0 || port >= 74) + return ONLP_STATUS_E_INTERNAL; + + memset(data, 0, 256); + + if(onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, onlp_sfpi_map_bus_index(port)) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + FILE* fp; + char file[64] = {0}; + + if(port < 0 || port >=74) + return ONLP_STATUS_E_INTERNAL; + + sprintf(file, PORT_EEPROM_FORMAT, onlp_sfpi_map_bus_index(port)); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (fseek(fp, 256, SEEK_CUR) != 0) { + fclose(fp); + AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + int ret = fread(data, 1, 256, fp); + fclose(fp); + if (ret != 256) { + AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = onlp_sfpi_map_bus_index(port); + return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) +{ + int bus = onlp_sfpi_map_bus_index(port); + return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = onlp_sfpi_map_bus_index(port); + return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) +{ + int bus = onlp_sfpi_map_bus_index(port); + return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) +{ + int rv; + int addr=0x60; + int bus=9; + + if(port <0 || port >= 74) + return ONLP_STATUS_E_INTERNAL; + + if(onlp_sfpi_get_cpld_addr(port, &addr, &bus)!=ONLP_STATUS_OK) + return ONLP_STATUS_E_INTERNAL; + + switch(control) + { + case ONLP_SFP_CONTROL_TX_DISABLE: + { + if(port==64 || port == 65) + { + return ONLP_STATUS_OK; + } + + if (onlp_file_write_int(0, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + 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; + int addr=0x60; + int bus=9; + + if(port <0 || port >= 74) + return ONLP_STATUS_E_INTERNAL; + + if(onlp_sfpi_get_cpld_addr(port, &addr, &bus)!=ONLP_STATUS_OK) + return ONLP_STATUS_E_INTERNAL; + + switch(control) + { + case ONLP_SFP_CONTROL_RX_LOS: + { + if(port<=65) + { + rv = ONLP_STATUS_E_UNSUPPORTED; + } + else + { + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else + { + rv = ONLP_STATUS_OK; + } + } + break; + } + + case ONLP_SFP_CONTROL_TX_FAULT: + { + if(port==64 || port==65) + { + rv = ONLP_STATUS_E_UNSUPPORTED; + } + else + { + if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, bus, addr, (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + else + { + rv = ONLP_STATUS_OK; + } + } + break; + } + + case ONLP_SFP_CONTROL_TX_DISABLE: + { + if(port==64 || port==65) + { + rv = ONLP_STATUS_E_UNSUPPORTED; + } + else + { + if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, bus, addr, (port+1)) < 0) + { + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n", port); + rv = ONLP_STATUS_E_INTERNAL; + } + 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/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/sysi.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/sysi.c new file mode 100755 index 00000000..3fbe2459 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/sysi.c @@ -0,0 +1,136 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2017 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 "platform_lib.h" + +#include "x86_64_accton_asgvolt64_int.h" +#include "x86_64_accton_asgvolt64_log.h" + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-accton-asgvolt64-r0"; +} + +int +onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ + uint8_t* rdata = aim_zmalloc(512); + if(onlp_file_read(rdata, 512, size, IDPROM_PATH) == ONLP_STATUS_OK) { + if(*size == 512) { + *data = rdata; + return ONLP_STATUS_OK; + } + } + + aim_free(rdata); + *size = 0; + return ONLP_STATUS_E_INTERNAL; +} + +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)); + + /* 7 Thermal sensors on the chassis */ + for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* 5 LEDs on the chassis */ + for (i = 1; i <= CHASSIS_LED_COUNT; i++) { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* 2 PSUs on the chassis */ + for (i = 1; i <= CHASSIS_PSU_COUNT; i++) { + *e++ = ONLP_PSU_ID_CREATE(i); + } + + /* 4 Fans on the chassis */ + for (i = 1; i <= CHASSIS_FAN_COUNT; i++) { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + return 0; +} + + +#define CPLD_VERSION_SYSFS "/sys/bus/i2c/devices/%d-00%d/version" + + +typedef struct cpld_version { + int bus; + int addr; + int version; + char *description; +} cpld_version_t; + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + + int i, ret; + cpld_version_t cplds[] = { + { 9, 60, 0, "CPLD1"}, + { 10, 61, 0, "CPLD2"}, + { 11, 62, 0, "CPLD3"} }; + /* Read CPLD version + */ + for (i = 0; i < AIM_ARRAYSIZE(cplds); i++) { + ret = onlp_file_read_int(&cplds[i].version, CPLD_VERSION_SYSFS, cplds[i].bus, cplds[i].addr); + + if (ret < 0) { + AIM_LOG_ERROR("Unable to read version from CPLD(%s)\r\n", cplds[i].description); + return ONLP_STATUS_E_INTERNAL; + } + } + + pi->cpld_versions = aim_fstrdup("%s:%d, %s:%d, %s:%d, %s:%d", + cplds[0].description, cplds[0].version, + cplds[1].description, cplds[1].version, + cplds[2].description, cplds[2].version); + + return ONLP_STATUS_OK; +} + +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) +{ + aim_free(pi->cpld_versions); +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/thermali.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/thermali.c new file mode 100755 index 00000000..6e344155 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/thermali.c @@ -0,0 +1,143 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 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 "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static char* ipmi_devfiles__[] = /* must map with onlp_thermal_id */ +{ + NULL, + NULL, /* CPU_CORE files */ + "/sys/devices/platform/asgvolt64_thermal/temp1_input", + "/sys/devices/platform/asgvolt64_thermal/temp2_input", + "/sys/devices/platform/asgvolt64_thermal/temp3_input", + "/sys/devices/platform/asgvolt64_thermal/temp4_input", + "/sys/devices/platform/asgvolt64_thermal/temp5_input", + "/sys/devices/platform/asgvolt64_thermal/temp6_input", + "/sys/devices/platform/asgvolt64_thermal/temp7_input", + "/sys/devices/platform/asgvolt64_psu/psu1_temp1_input", + "/sys/devices/platform/asgvolt64_psu/psu2_temp1_input", +}; + +static char* cpu_coretemp_files[] = + { + "/sys/devices/platform/coretemp.0*temp2_input", + "/sys/devices/platform/coretemp.0*temp3_input", + "/sys/devices/platform/coretemp.0*temp4_input", + "/sys/devices/platform/coretemp.0*temp5_input", + NULL, + }; + +/* Static values */ +static onlp_thermal_info_t linfo[] = { + { }, /* Not used */ + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE), "CPU Core", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "LM75-1-4c", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_MAIN_BROAD), "LM75-2-4a", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "LM75-3-49", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_4_ON_MAIN_BROAD), "LM75-4-4e", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_5_ON_MAIN_BROAD), "LM75-5-48", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_6_ON_MAIN_BROAD), "LM75-6-4b", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_7_ON_MAIN_BROAD), "LM75-7-4d", 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(PSU1_ID)}, + 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(PSU2_ID)}, + 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 tid; + VALIDATE(id); + + tid = ONLP_OID_ID_GET(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[tid]; + + if(tid == THERMAL_CPU_CORE) { + int rv = onlp_file_read_int_max(&info->mcelsius, cpu_coretemp_files); + return rv; + } + + return onlp_file_read_int(&info->mcelsius, ipmi_devfiles__[tid]); +} + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_config.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_config.c new file mode 100755 index 00000000..1aaf0dec --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_config.c @@ -0,0 +1,81 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_accton_asgvolt64_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_accton_asgvolt64_config_STRINGIFY_VALUE(_x) __x86_64_accton_asgvolt64_config_STRINGIFY_NAME(_x) +x86_64_accton_asgvolt64_config_settings_t x86_64_accton_asgvolt64_config_settings[] = +{ +#ifdef x86_64_accton_asgvolt64_CONFIG_INCLUDE_LOGGING + { __x86_64_accton_asgvolt64_config_STRINGIFY_NAME(x86_64_accton_asgvolt64_CONFIG_INCLUDE_LOGGING), __x86_64_accton_asgvolt64_config_STRINGIFY_VALUE(x86_64_accton_asgvolt64_CONFIG_INCLUDE_LOGGING) }, +#else +{ x86_64_accton_asgvolt64_CONFIG_INCLUDE_LOGGING(__x86_64_accton_asgvolt64_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_asgvolt64_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_accton_asgvolt64_config_STRINGIFY_NAME(x86_64_accton_asgvolt64_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_accton_asgvolt64_config_STRINGIFY_VALUE(x86_64_accton_asgvolt64_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ x86_64_accton_asgvolt64_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_accton_asgvolt64_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_asgvolt64_CONFIG_LOG_BITS_DEFAULT + { __x86_64_accton_asgvolt64_config_STRINGIFY_NAME(x86_64_accton_asgvolt64_CONFIG_LOG_BITS_DEFAULT), __x86_64_accton_asgvolt64_config_STRINGIFY_VALUE(x86_64_accton_asgvolt64_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ x86_64_accton_asgvolt64_CONFIG_LOG_BITS_DEFAULT(__x86_64_accton_asgvolt64_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_asgvolt64_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_accton_asgvolt64_config_STRINGIFY_NAME(x86_64_accton_asgvolt64_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_accton_asgvolt64_config_STRINGIFY_VALUE(x86_64_accton_asgvolt64_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ x86_64_accton_asgvolt64_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_accton_asgvolt64_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_asgvolt64_CONFIG_PORTING_STDLIB + { __x86_64_accton_asgvolt64_config_STRINGIFY_NAME(x86_64_accton_asgvolt64_CONFIG_PORTING_STDLIB), __x86_64_accton_asgvolt64_config_STRINGIFY_VALUE(x86_64_accton_asgvolt64_CONFIG_PORTING_STDLIB) }, +#else +{ x86_64_accton_asgvolt64_CONFIG_PORTING_STDLIB(__x86_64_accton_asgvolt64_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_asgvolt64_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_accton_asgvolt64_config_STRINGIFY_NAME(x86_64_accton_asgvolt64_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_accton_asgvolt64_config_STRINGIFY_VALUE(x86_64_accton_asgvolt64_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ x86_64_accton_asgvolt64_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_accton_asgvolt64_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_asgvolt64_CONFIG_INCLUDE_UCLI + { __x86_64_accton_asgvolt64_config_STRINGIFY_NAME(x86_64_accton_asgvolt64_CONFIG_INCLUDE_UCLI), __x86_64_accton_asgvolt64_config_STRINGIFY_VALUE(x86_64_accton_asgvolt64_CONFIG_INCLUDE_UCLI) }, +#else +{ x86_64_accton_asgvolt64_CONFIG_INCLUDE_UCLI(__x86_64_accton_asgvolt64_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_accton_asgvolt64_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_accton_asgvolt64_config_STRINGIFY_NAME(x86_64_accton_asgvolt64_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_accton_asgvolt64_config_STRINGIFY_VALUE(x86_64_accton_asgvolt64_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ x86_64_accton_asgvolt64_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_accton_asgvolt64_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_accton_asgvolt64_config_STRINGIFY_VALUE +#undef __x86_64_accton_asgvolt64_config_STRINGIFY_NAME + +const char* +x86_64_accton_asgvolt64_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_accton_asgvolt64_config_settings[i].name; i++) { + if(strcmp(x86_64_accton_asgvolt64_config_settings[i].name, setting)) { + return x86_64_accton_asgvolt64_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_accton_asgvolt64_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_accton_asgvolt64_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_accton_asgvolt64_config_settings[i].name, x86_64_accton_asgvolt64_config_settings[i].value); + } + return i; +} + +/* */ + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_enums.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_enums.c new file mode 100755 index 00000000..1ebc7db1 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_int.h b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_int.h new file mode 100755 index 00000000..0e932435 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_accton_asgvolt64 Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_accton_asgvolt64_INT_H__ +#define __x86_64_accton_asgvolt64_INT_H__ + +#include + + +#endif /* __x86_64_accton_asgvolt64_INT_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_log.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_log.c new file mode 100755 index 00000000..bd326fa7 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_asgvolt64_log.h" +/* + * x86_64_accton_asgvolt64 log struct. + */ +AIM_LOG_STRUCT_DEFINE( + x86_64_accton_asgvolt64_CONFIG_LOG_OPTIONS_DEFAULT, + x86_64_accton_asgvolt64_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + x86_64_accton_asgvolt64_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_log.h b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_log.h new file mode 100755 index 00000000..f16c5809 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_accton_asgvolt64_LOG_H__ +#define __x86_64_accton_asgvolt64_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_accton_asgvolt64 +#include + +#endif /* __x86_64_accton_asgvolt64_LOG_H__ */ diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_module.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_module.c new file mode 100755 index 00000000..62e2f0d4 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_asgvolt64_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_accton_asgvolt64_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_accton_asgvolt64_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_ucli.c b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_ucli.c new file mode 100755 index 00000000..b0d28f6b --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/onlp/builds/src/module/src/x86_64_accton_asgvolt64_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if x86_64_accton_asgvolt64_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_accton_asgvolt64_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_accton_asgvolt64) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_accton_asgvolt64_ucli_module__ = + { + "x86_64_accton_asgvolt64_ucli", + NULL, + x86_64_accton_asgvolt64_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_accton_asgvolt64_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_accton_asgvolt64_ucli_module__); + n = ucli_node_create("x86_64_accton_asgvolt64", NULL, &x86_64_accton_asgvolt64_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_accton_asgvolt64")); + return n; +} + +#else +void* +x86_64_accton_asgvolt64_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/platform-config/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/platform-config/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/platform-config/r0/Makefile b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/platform-config/r0/Makefile new file mode 100755 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/platform-config/r0/PKG.yml b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/platform-config/r0/PKG.yml new file mode 100755 index 00000000..04550d41 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=accton BASENAME=x86-64-accton-asgvolt64 REVISION=r0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/platform-config/r0/src/lib/x86-64-accton-asgvolt64-r0.yml b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/platform-config/r0/src/lib/x86-64-accton-asgvolt64-r0.yml new file mode 100755 index 00000000..2cae57f6 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/platform-config/r0/src/lib/x86-64-accton-asgvolt64-r0.yml @@ -0,0 +1,33 @@ +--- + +###################################################################### +# +# platform-config for ASGVOLT64 +# +###################################################################### + +x86-64-accton-asgvolt64-r0: + + grub: + + serial: >- + --port=0x3f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-4-14 + + args: >- + nopat + console=ttyS0,115200n8 + tg3.short_preamble=1 + tg3.bcm5718s_reset=1 + + ##network: + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:1c.0/0000:0a:00.0 diff --git a/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/platform-config/r0/src/python/x86_64_accton_asgvolt64_r0/__init__.py b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/platform-config/r0/src/python/x86_64_accton_asgvolt64_r0/__init__.py new file mode 100755 index 00000000..85665ef4 --- /dev/null +++ b/packages/platforms/accton/x86-64/x86-64-accton-asgvolt64/platform-config/r0/src/python/x86_64_accton_asgvolt64_r0/__init__.py @@ -0,0 +1,65 @@ +from onl.platform.base import * +from onl.platform.accton import * + +class OnlPlatform_x86_64_accton_asgvolt64_r0(OnlPlatformAccton, + OnlPlatformPortConfig_20x100): + PLATFORM='x86-64-accton-asgvolt64-r0' + MODEL="ASGVOLT64" + SYS_OBJECT_ID=".volt.64" + + def baseconfig(self): + #self.insmod('ym2651y') + self.insmod('optoe') + for m in [ 'cpld', 'fan', 'psu', 'leds', 'thermal' ]: + self.insmod("x86-64-accton-asgvolt64-%s.ko" % m) + + ########### initialize I2C bus 0 ########### + self.new_i2c_devices([ + # initialize root(one-level) multiplexer (PCA9548) + ('pca9548', 0x77, 0), + # initiate (two-level) multiplexer (PCA9548) + ('pca9548', 0x70, 1), + # initiate (three-level) multiplexer (PCA9548) + ('pca9548', 0x72, 16), + + # initiate (four-level) multiplexer (PCA9548) (for 25g-sfp) + ('pca9548', 0x75, 19), + # initiate (four-level) multiplexer (PCA9548) (for 8 pca mux to xfp) + ('pca9548', 0x75, 22), + + # initiate (five-level) multiplexer (PCA9548) (for xfp) + ('pca9548', 0x76, 33), + ('pca9548', 0x76, 34), + ('pca9548', 0x76, 35), + ('pca9548', 0x76, 36), + ('pca9548', 0x76, 37), + ('pca9548', 0x76, 38), + ('pca9548', 0x76, 39), + ('pca9548', 0x76, 40), + + ('asgvlot64_cpld1', 0x60, 9), + ('asgvlot64_cpld2', 0x61, 10), + ('asgvlot64_cpld3', 0x62, 11) + ]) + + # initialize XFP port 1~64 + for port in range(41, 105): + self.new_i2c_device('optoe2', 0x50, port) + subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port-40, port), shell=True) + + # initialize QSFP port 1~2 (port_name=port65~66) + for port in range(20, 22): + self.new_i2c_device('optoe1', 0x50, port) + self.new_i2c_device('optoe1', 0x50, port) + subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port+45, port), shell=True) + + # initialize SFP port 1~8 (port_name=port67~74) + for port in range(25, 33): + self.new_i2c_device('optoe2', 0x50, port) + subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port+41, port), shell=True) + # initiate IDPROM + self.new_i2c_device('24c02', 0x57, 0) + + + return True +