From a5a8ecf0706bb0ee767fa3f1d09330a7fab70597 Mon Sep 17 00:00:00 2001 From: Roger Ho Date: Mon, 24 Feb 2025 15:26:44 +0800 Subject: [PATCH] [Accton][as4625-30p] Add new platform CPU: Intel Atom Processor C3508 1.6GHZ DDR4 SDRAM: 16GB 2400MHz with ECC(SO-DIMM) DDR4*1 SPI Flash(boot): 16Mb * 2 M.2 SSD: SATA 32GB MLC EC: IT8528E/VG-I TPM: SLB 9670XQ2.0 FW7.63 INFINEON Management: WGI210AT, INTEL, Out-band Mangement Ethernet port[RJ45], UART RS232 console port(RJ45) MAC: Broadcom Trident3 X2 BCM562771 PoE: STM32F100C8T6BTR1, PoE MCU, BCM59131 *4, PSE Controller Ethernet Ports: 24 x 1G Base-T + 6 x 10G SFP+ (Port1 ~ Port16 support PoE 30W; Port17 ~ Port24 support PoE 90W) Power Supply: AC 600W PSU, UMEC, 1+1 redundant load-sharing, hot-swappable Cooling: F2B fixed fan with 3 pcs of 40mmx40mmx28mm 12V Dimention:350.35mm(L: Depth) x 440mm(W: Width) x 44mm(H: Height) Note: 1. The latest kernel version supported by the Open Network Linux (ONL) upstream is 5.4, and there is no newer kernel version available or maintained at this time. Therefore, this platform is based on kernel 5.4. 2. Some advanced features, such as SDK-based management or advanced switching, require proprietary Broadcom binaries. These binaries are not included in ONL due to licensing restrictions. This commit only ports the platform code and does not include any Broadcom SDK or proprietary binaries. Signed-off-by: Roger Ho --- .../src/python/onl/platform/base.py | 4 + .../accton/x86-64/as4625-30p/.gitignore | 3 + .../accton/x86-64/as4625-30p/Makefile | 1 + .../accton/x86-64/as4625-30p/modules/Makefile | 1 + .../accton/x86-64/as4625-30p/modules/PKG.yml | 1 + .../as4625-30p/modules/builds/.gitignore | 1 + .../x86-64/as4625-30p/modules/builds/Makefile | 8 + .../as4625-30p/modules/builds/src/Makefile | 4 + .../src/x86-64-accton-as4625-30p-cpld.c | 664 ++++++++++++++++++ .../builds/src/x86-64-accton-as4625-30p-fan.c | 424 +++++++++++ .../src/x86-64-accton-as4625-30p-leds.c | 398 +++++++++++ .../builds/src/x86-64-accton-as4625-30p-psu.c | 464 ++++++++++++ .../accton/x86-64/as4625-30p/onlp/Makefile | 1 + .../accton/x86-64/as4625-30p/onlp/PKG.yml | 1 + .../x86-64/as4625-30p/onlp/builds/Makefile | 2 + .../as4625-30p/onlp/builds/lib/Makefile | 2 + .../as4625-30p/onlp/builds/onlpdump/Makefile | 2 + .../x86_64_accton_as4625_30p/.gitignore | 0 .../builds/x86_64_accton_as4625_30p/.module | 1 + .../builds/x86_64_accton_as4625_30p/Makefile | 9 + .../builds/x86_64_accton_as4625_30p/README | 6 + .../module/auto/make.mk | 8 + .../module/auto/x86_64_accton_as4625_30p.yml | 49 ++ .../x86_64_accton_as4625_30p.x | 14 + .../x86_64_accton_as4625_30p_config.h | 137 ++++ .../x86_64_accton_as4625_30p_dox.h | 26 + .../x86_64_accton_as4625_30p_porting.h | 97 +++ .../x86_64_accton_as4625_30p/module/make.mk | 10 + .../module/src/Makefile | 9 + .../module/src/fani.c | 279 ++++++++ .../module/src/ledi.c | 239 +++++++ .../module/src/make.mk | 9 + .../module/src/platform_lib.c | 68 ++ .../module/src/platform_lib.h | 82 +++ .../module/src/psui.c | 181 +++++ .../module/src/sfpi.c | 358 ++++++++++ .../module/src/sysi.c | 310 ++++++++ .../module/src/thermali.c | 259 +++++++ .../src/x86_64_accton_as4625_30p_config.c | 80 +++ .../src/x86_64_accton_as4625_30p_enums.c | 10 + .../module/src/x86_64_accton_as4625_30p_int.h | 12 + .../module/src/x86_64_accton_as4625_30p_log.c | 18 + .../module/src/x86_64_accton_as4625_30p_log.h | 12 + .../src/x86_64_accton_as4625_30p_module.c | 24 + .../src/x86_64_accton_as4625_30p_ucli.c | 50 ++ .../as4625-30p/platform-config/Makefile | 1 + .../as4625-30p/platform-config/r0/Makefile | 1 + .../as4625-30p/platform-config/r0/PKG.yml | 1 + .../src/lib/x86-64-accton-as4625-30p-r0.yml | 30 + .../x86_64_accton_as4625_30p_r0/__init__.py | 59 ++ 50 files changed, 4430 insertions(+) create mode 100644 packages/platforms/accton/x86-64/as4625-30p/.gitignore create mode 100644 packages/platforms/accton/x86-64/as4625-30p/Makefile create mode 100644 packages/platforms/accton/x86-64/as4625-30p/modules/Makefile create mode 100644 packages/platforms/accton/x86-64/as4625-30p/modules/PKG.yml create mode 100644 packages/platforms/accton/x86-64/as4625-30p/modules/builds/.gitignore create mode 100644 packages/platforms/accton/x86-64/as4625-30p/modules/builds/Makefile create mode 100644 packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/Makefile create mode 100644 packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/x86-64-accton-as4625-30p-cpld.c create mode 100644 packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/x86-64-accton-as4625-30p-fan.c create mode 100644 packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/x86-64-accton-as4625-30p-leds.c create mode 100644 packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/x86-64-accton-as4625-30p-psu.c create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/Makefile create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/PKG.yml create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/Makefile create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/lib/Makefile create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/onlpdump/Makefile create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/.gitignore create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/.module create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/Makefile create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/README create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/auto/make.mk create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/auto/x86_64_accton_as4625_30p.yml create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/inc/x86_64_accton_as4625_30p/x86_64_accton_as4625_30p.x create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/inc/x86_64_accton_as4625_30p/x86_64_accton_as4625_30p_config.h create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/inc/x86_64_accton_as4625_30p/x86_64_accton_as4625_30p_dox.h create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/inc/x86_64_accton_as4625_30p/x86_64_accton_as4625_30p_porting.h create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/make.mk create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/Makefile create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/fani.c create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/ledi.c create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/make.mk create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/platform_lib.c create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/platform_lib.h create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/psui.c create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/sfpi.c create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/sysi.c create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/thermali.c create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_config.c create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_enums.c create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_int.h create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_log.c create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_log.h create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_module.c create mode 100644 packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_ucli.c create mode 100644 packages/platforms/accton/x86-64/as4625-30p/platform-config/Makefile create mode 100644 packages/platforms/accton/x86-64/as4625-30p/platform-config/r0/Makefile create mode 100644 packages/platforms/accton/x86-64/as4625-30p/platform-config/r0/PKG.yml create mode 100644 packages/platforms/accton/x86-64/as4625-30p/platform-config/r0/src/lib/x86-64-accton-as4625-30p-r0.yml create mode 100644 packages/platforms/accton/x86-64/as4625-30p/platform-config/r0/src/python/x86_64_accton_as4625_30p_r0/__init__.py diff --git a/packages/base/all/vendor-config-onl/src/python/onl/platform/base.py b/packages/base/all/vendor-config-onl/src/python/onl/platform/base.py index 08bdb9839b..0e48481162 100644 --- a/packages/base/all/vendor-config-onl/src/python/onl/platform/base.py +++ b/packages/base/all/vendor-config-onl/src/python/onl/platform/base.py @@ -650,3 +650,7 @@ class OnlPlatformPortConfig_40x100_13x400_2x10(object): class OnlPlatformPortConfig_64x800_2x25(object): PORT_COUNT=66 PORT_CONFIG="64x800 + 2x25" + +class OnlPlatformPortConfig_24x1_6x10(object): + PORT_COUNT=30 + PORT_CONFIG="24x1 + 6x10" diff --git a/packages/platforms/accton/x86-64/as4625-30p/.gitignore b/packages/platforms/accton/x86-64/as4625-30p/.gitignore new file mode 100644 index 0000000000..5b92eddd55 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/.gitignore @@ -0,0 +1,3 @@ +*x86*64*accton*as4625*30p*.mk +onlpdump.mk + diff --git a/packages/platforms/accton/x86-64/as4625-30p/Makefile b/packages/platforms/accton/x86-64/as4625-30p/Makefile new file mode 100644 index 0000000000..dc1e7b86f0 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/accton/x86-64/as4625-30p/modules/Makefile b/packages/platforms/accton/x86-64/as4625-30p/modules/Makefile new file mode 100644 index 0000000000..dc1e7b86f0 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/accton/x86-64/as4625-30p/modules/PKG.yml b/packages/platforms/accton/x86-64/as4625-30p/modules/PKG.yml new file mode 100644 index 0000000000..c730edf93b --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=accton BASENAME=x86-64-accton-as4625-30p ARCH=amd64 KERNELS="onl-kernel-5.4-lts-x86-64-all:amd64" diff --git a/packages/platforms/accton/x86-64/as4625-30p/modules/builds/.gitignore b/packages/platforms/accton/x86-64/as4625-30p/modules/builds/.gitignore new file mode 100644 index 0000000000..a65b41774a --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/accton/x86-64/as4625-30p/modules/builds/Makefile b/packages/platforms/accton/x86-64/as4625-30p/modules/builds/Makefile new file mode 100644 index 0000000000..b44a215db3 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/modules/builds/Makefile @@ -0,0 +1,8 @@ +KERNELS := onl-kernel-5.4-lts-x86-64-all:amd64 +#KMODULES := $(wildcard *.c) +KMODULES := src +#KMODULES := x86-64-accton-as4625-30p-cpld.c x86-64-accton-as4625-30p-fan.c x86-64-accton-as4625-30p-leds.c x86-64-accton-as4625-30p-psu.c +VENDOR := accton +BASENAME := x86-64-accton-as4625-30p +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/Makefile b/packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/Makefile new file mode 100644 index 0000000000..67f3a015ca --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/Makefile @@ -0,0 +1,4 @@ +obj-m += x86-64-accton-as4625-30p-cpld.o +obj-m += x86-64-accton-as4625-30p-fan.o +obj-m += x86-64-accton-as4625-30p-leds.o +obj-m += x86-64-accton-as4625-30p-psu.o diff --git a/packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/x86-64-accton-as4625-30p-cpld.c b/packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/x86-64-accton-as4625-30p-cpld.c new file mode 100644 index 0000000000..978a366498 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/x86-64-accton-as4625-30p-cpld.c @@ -0,0 +1,664 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as4625 CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as4625_cpld1 +}; + +struct as4625_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as4625_cpld_id[] = { + { "as4625_cpld1", as4625_cpld1 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as4625_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 as4625_cpld_sysfs_attributes { + VERSION_MAJOR, + VERSION_MINOR, + PCB_ID, + PCB_VERSION, + POWER_ENABLE_MAINBOARD, + POWER_ENABLE_POE, + SYSTEM_THERMAL_SHUTDOWN, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + 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_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_RXLOS_ATTR_ID(25), + TRANSCEIVER_RXLOS_ATTR_ID(26), + TRANSCEIVER_RXLOS_ATTR_ID(27), + TRANSCEIVER_RXLOS_ATTR_ID(28), + TRANSCEIVER_RXLOS_ATTR_ID(29), + TRANSCEIVER_RXLOS_ATTR_ID(30), + TRANSCEIVER_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) +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_control(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 as4625_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as4625_cpld_write_internal(struct i2c_client *client, u8 reg, + u8 value); + +/* 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_control, 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 + +static SENSOR_DEVICE_ATTR(version_major, S_IRUGO, show_version, NULL, VERSION_MAJOR); +static SENSOR_DEVICE_ATTR(version_minor, S_IRUGO, show_version, NULL, VERSION_MINOR); +static SENSOR_DEVICE_ATTR(pcb_id, S_IRUGO, show_version, NULL, PCB_ID); +static SENSOR_DEVICE_ATTR(pcb_version, S_IRUGO, show_version, NULL, PCB_VERSION); +static SENSOR_DEVICE_ATTR(pwr_enable_mb, S_IRUGO | S_IWUSR, show_status, set_control, POWER_ENABLE_MAINBOARD); +static SENSOR_DEVICE_ATTR(pwr_enable_poe, S_IRUGO | S_IWUSR, show_status, set_control, POWER_ENABLE_POE); +static SENSOR_DEVICE_ATTR(thermal_shutdown, S_IRUGO | S_IWUSR, show_status, set_control, SYSTEM_THERMAL_SHUTDOWN); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); + +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, \ + NULL, MODULE_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, \ + MODULE_RXLOS_ALL); + +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(25); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(26); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(27); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(28); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(29); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(30); + +static struct attribute *as4625_cpld1_attributes[] = { + &sensor_dev_attr_version_major.dev_attr.attr, + &sensor_dev_attr_version_minor.dev_attr.attr, + &sensor_dev_attr_pcb_id.dev_attr.attr, + &sensor_dev_attr_pcb_version.dev_attr.attr, + &sensor_dev_attr_pwr_enable_mb.dev_attr.attr, + &sensor_dev_attr_pwr_enable_poe.dev_attr.attr, + &sensor_dev_attr_thermal_shutdown.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_SFP_TRANSCEIVER_ATTR(25), + DECLARE_SFP_TRANSCEIVER_ATTR(26), + DECLARE_SFP_TRANSCEIVER_ATTR(27), + DECLARE_SFP_TRANSCEIVER_ATTR(28), + DECLARE_SFP_TRANSCEIVER_ATTR(29), + DECLARE_SFP_TRANSCEIVER_ATTR(30), + NULL +}; + +static const struct attribute_group as4625_cpld1_group = { + .attrs = as4625_cpld1_attributes, +}; + +static ssize_t show_present_all(struct device *dev, + struct device_attribute *da, char *buf) +{ + int i, status; + u8 values[1] = {0}; + u8 regs_cpld[] = {0x6}; + u8 *regs[] = { regs_cpld }; + u8 size[] = { ARRAY_SIZE(regs_cpld) }; + struct i2c_client *client = to_i2c_client(dev); + struct as4625_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < size[data->type]; i++) { + status = as4625_cpld_read_internal(client, regs[data->type][i]); + + if (status < 0) + goto exit; + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values in order */ + return sprintf(buf, "%.2x\n", values[0] & 0x3F); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[2] = {0}; + u8 regs_cpld[] = {0x7}; + u8 *regs[] = { regs_cpld }; + u8 size[] = { ARRAY_SIZE(regs_cpld) }; + struct i2c_client *client = to_i2c_client(dev); + struct as4625_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < size[data->type]; i++) { + status = as4625_cpld_read_internal(client, regs[data->type][i]); + + if (status < 0) + goto exit; + + values[i] = (u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values in order */ + return sprintf(buf, "%.2x\n", values[0] & 0x3F); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as4625_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, reverse = 0; + + switch (attr->index) { + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_30: + reg = 0x5; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case MODULE_PRESENT_25 ... MODULE_PRESENT_30: + reg = 0x6; + mask = 0x1 << (attr->index - MODULE_PRESENT_25); + reverse = 1; + break; + case MODULE_RXLOS_25 ... MODULE_RXLOS_30: + reg = 0x7; + mask = 0x1 << (attr->index - MODULE_RXLOS_25); + break; + case MODULE_TXFAULT_25 ... MODULE_TXFAULT_30: + reg = 0x8; + mask = 0x1 << (attr->index - MODULE_TXFAULT_25); + break; + case POWER_ENABLE_MAINBOARD: + reg = 0x3; + mask = 0x1; + reverse = 1; + break; + case POWER_ENABLE_POE: + reg = 0x21; + mask = 0x1; + break; + case SYSTEM_THERMAL_SHUTDOWN: + reg = 0x27; + mask = 0x1; + break; + default: + return 0; + } + + mutex_lock(&data->update_lock); + status = as4625_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", reverse ? !(status & mask) + : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_control(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 as4625_cpld_data *data = i2c_get_clientdata(client); + long value; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &value); + + if (status) + return status; + + switch (attr->index) { + case MODULE_TXDISABLE_25 ... MODULE_TXDISABLE_30: + reg = 0x5; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_25); + break; + case POWER_ENABLE_MAINBOARD: + reg = 0x3; + mask = 0x1; + value = !value; + break; + case POWER_ENABLE_POE: + reg = 0x21; + mask = 0x1; + break; + case SYSTEM_THERMAL_SHUTDOWN: + reg = 0x27; + mask = 0x1; + break; + default: + return -EINVAL; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as4625_cpld_read_internal(client, reg); + if (unlikely(status < 0)) + goto exit; + + /* Update tx_disable status */ + if (value) + status |= mask; + else + status &= ~mask; + + status = as4625_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 as4625_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 = as4625_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 as4625_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 as4625_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 *da, + char *buf) +{ + int val = 0, reg = 0; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + switch (attr->index) { + case PCB_ID: + case PCB_VERSION: + reg = 0x0; + break; + case VERSION_MAJOR: + reg = 0x1; + break; + case VERSION_MINOR: + reg = 0x2; + break; + default: + break; + } + + val = i2c_smbus_read_byte_data(client, reg); + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", + client->addr, val); + return val; + } + + if (attr->index == PCB_ID) + val = (val >> 3) & 0x7; /* bit 3-5 */ + else if (attr->index == PCB_VERSION) + val &= 0x7; /* bit 0-2 */ + + return sprintf(buf, "%d\n", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as4625_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as4625_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 as4625_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 as4625_cpld1: + group = &as4625_cpld1_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) + goto exit_free; + } + + as4625_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as4625_cpld_remove(struct i2c_client *client) +{ + struct as4625_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as4625_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as4625_cpld1: + group = &as4625_cpld1_group; + break; + default: + break; + } + + if (group) + sysfs_remove_group(&client->dev.kobj, group); + + kfree(data); + return 0; +} + +static int as4625_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 as4625_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 as4625_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 = as4625_cpld_read_internal(cpld_node->client, + reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as4625_cpld_read); + +int as4625_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 = as4625_cpld_write_internal(cpld_node->client, + reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as4625_cpld_write); + +static struct i2c_driver as4625_cpld_driver = { + .driver = { + .name = "as4625_cpld", + .owner = THIS_MODULE, + }, + .probe = as4625_cpld_probe, + .remove = as4625_cpld_remove, + .id_table = as4625_cpld_id, +}; + +static int __init as4625_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as4625_cpld_driver); +} + +static void __exit as4625_cpld_exit(void) +{ + i2c_del_driver(&as4625_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as4625_cpld_init); +module_exit(as4625_cpld_exit); diff --git a/packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/x86-64-accton-as4625-30p-fan.c b/packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/x86-64-accton-as4625-30p-fan.c new file mode 100644 index 0000000000..2648349246 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/x86-64-accton-as4625-30p-fan.c @@ -0,0 +1,424 @@ +/* + * A hwmon driver for the Accton as4625 fan + * + * Copyright (C) 2016 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as4625_fan" + +#define FAN_STATUS_I2C_ADDR 0x64 + +static struct as4625_fan_data *as4625_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +extern int as4625_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as4625_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x40, /* fan-1 PWM */ + 0x41, /* fan-2 PWM */ + 0x42, /* fan-3 PWM */ + 0x46, /* fan-1 speed(rpm) */ + 0x47, /* fan-2 speed(rpm) */ + 0x48, /* fan-3 speed(rpm) */ + 0x00 /* fan direction, 001: AS4625-30P (F2B), 010: AS4625-30P (B2F) */ +}; + +static const int fan_target_speed_f2b[] = { + 0, 1350, 2550, 3900, 6450, 7800, 9150, 10500, + 11850, 13050, 14400, 15600, 16950, 18150, 19650, 23000 +}; + +static const int fan_target_speed_b2f[] = { + 0, 3150, 5850, 8100, 12150, 13650, 15000, 16350, + 17850, 19050, 19950, 20700, 21450, 22200, 22800, 23400 +}; + +/* fan data */ +struct as4625_fan_data { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ +}; + +struct as4625_fan_data *data = NULL; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID +}; + +enum sysfs_fan_attributes { + FAN1_PWM, + FAN2_PWM, + FAN3_PWM, + FAN1_INPUT, + FAN2_INPUT, + FAN3_INPUT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN1_DIR, + FAN2_DIR, + FAN3_DIR, + FAN1_TARGET_RPM, + FAN2_TARGET_RPM, + FAN3_TARGET_RPM +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_pwm, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_PWM) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_pwm.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_INPUT) +#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_input.dev_attr.attr + +#define DECLARE_FAN_DIR_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_dir, S_IRUGO, fan_show_value, NULL, FAN##index##_DIR) +#define DECLARE_FAN_DIR_ATTR(index) &sensor_dev_attr_fan##index##_dir.dev_attr.attr + +#define DECLARE_FAN_TARGET_RPM_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_target_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_TARGET_RPM) +#define DECLARE_FAN_TARGET_RPM_ATTR(index) &sensor_dev_attr_fan##index##_target_rpm.dev_attr.attr + +/* 3 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3); + +/* 3 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3); + +/* 3 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(3); + +/* 3 fan direction attribute in this platform */ +DECLARE_FAN_DIR_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIR_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIR_SENSOR_DEV_ATTR(3); + +/* 3 fan target speed attribute in this platform */ +DECLARE_FAN_TARGET_RPM_SENSOR_DEV_ATTR(1); +DECLARE_FAN_TARGET_RPM_SENSOR_DEV_ATTR(2); +DECLARE_FAN_TARGET_RPM_SENSOR_DEV_ATTR(3); + +static struct attribute *as4625_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1), + DECLARE_FAN_FAULT_ATTR(2), + DECLARE_FAN_FAULT_ATTR(3), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + DECLARE_FAN_DUTY_CYCLE_ATTR(2), + DECLARE_FAN_DUTY_CYCLE_ATTR(3), + DECLARE_FAN_SPEED_RPM_ATTR(1), + DECLARE_FAN_SPEED_RPM_ATTR(2), + DECLARE_FAN_SPEED_RPM_ATTR(3), + DECLARE_FAN_DIR_ATTR(1), + DECLARE_FAN_DIR_ATTR(2), + DECLARE_FAN_DIR_ATTR(3), + DECLARE_FAN_TARGET_RPM_ATTR(1), + DECLARE_FAN_TARGET_RPM_ATTR(2), + DECLARE_FAN_TARGET_RPM_ATTR(3), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0x0F +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 150 + +static int as4625_fan_read_value(u8 reg) +{ + return as4625_cpld_read(FAN_STATUS_I2C_ADDR, reg); +} + +static int as4625_fan_write_value(u8 reg, u8 value) +{ + return as4625_cpld_write(FAN_STATUS_I2C_ADDR, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return (u32)(reg_val+1) * 625 / 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + if (duty_cycle == 0) + return 0; + else if (duty_cycle > FAN_MAX_DUTY_CYCLE) + duty_cycle = FAN_MAX_DUTY_CYCLE; + + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 is_fan_fault(struct as4625_fan_data *data, enum fan_id id) +{ + return !reg_val_to_speed_rpm(data->reg_val[FAN1_INPUT + id]); +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value, reg; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + + reg = fan_reg[attr->index - FAN1_PWM]; + as4625_fan_write_value(reg, duty_cycle_to_reg_val(value)); + data->valid = 0; + + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + ssize_t ret = 0; + + mutex_lock(&data->update_lock); + + data = as4625_fan_update_device(dev); + if (data->valid) { + switch (attr->index) { + case FAN1_PWM: + case FAN2_PWM: + case FAN3_PWM: + { + u32 duty_cycle; + duty_cycle = reg_val_to_duty_cycle( + data->reg_val[attr->index]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_INPUT: + case FAN2_INPUT: + case FAN3_INPUT: + ret = sprintf(buf, "%u\n", + reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + ret = sprintf(buf, "%d\n", + is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + + case FAN1_DIR: + case FAN2_DIR: + case FAN3_DIR: + { + u8 board_id = (data->reg_val[6] >> 3) & 0x7; + ret = sprintf(buf, "%s\n", (board_id == 2) + ? "B2F" : "F2B"); + break; + } + + case FAN1_TARGET_RPM: + case FAN2_TARGET_RPM: + case FAN3_TARGET_RPM: + { + u8 board_id = (data->reg_val[6] >> 3) & 0x7; + const int *target = NULL; + int pwm_index = FAN1_PWM + (attr->index - FAN1_TARGET_RPM); + target = (board_id == 2) + ? fan_target_speed_b2f : fan_target_speed_f2b; + ret = sprintf(buf, "%d\n", + target[data->reg_val[pwm_index] & 0xF]); + break; + } + default: + break; + } + } + + mutex_unlock(&data->update_lock); + + return ret; +} + +static const struct attribute_group as4625_fan_group = { + .attrs = as4625_fan_attributes, +}; + +static struct as4625_fan_data *as4625_fan_update_device(struct device *dev) +{ + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&data->pdev->dev, "Starting as4625_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as4625_fan_read_value(fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&data->pdev->dev, "reg %d, err %d\n", + fan_reg[i], status); + return data; + } else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + return data; +} + +static int as4625_fan_probe(struct platform_device *pdev) +{ + int status; + + data->hwmon_dev = hwmon_device_register_with_info(&pdev->dev, + DRVNAME, NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + return status; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&data->hwmon_dev->kobj, &as4625_fan_group); + if (status) + goto exit_remove; + + dev_info(&pdev->dev, "device created\n"); + return 0; + +exit_remove: + hwmon_device_unregister(data->hwmon_dev); + return status; +} + +static int as4625_fan_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&data->hwmon_dev->kobj, &as4625_fan_group); + hwmon_device_unregister(data->hwmon_dev); + return 0; +} + +static struct platform_driver as4625_fan_driver = { + .probe = as4625_fan_probe, + .remove = as4625_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init as4625_fan_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as4625_fan_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + data->valid = 0; + + ret = platform_driver_register(&as4625_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; + } + + return 0; + +dev_reg_err: + platform_driver_unregister(&as4625_fan_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as4625_fan_exit(void) +{ + platform_device_unregister(data->pdev); + platform_driver_unregister(&as4625_fan_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as4625_fan driver"); +MODULE_LICENSE("GPL"); + +module_init(as4625_fan_init); +module_exit(as4625_fan_exit); diff --git a/packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/x86-64-accton-as4625-30p-leds.c b/packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/x86-64-accton-as4625-30p-leds.c new file mode 100644 index 0000000000..8919117518 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/x86-64-accton-as4625-30p-leds.c @@ -0,0 +1,398 @@ +/* + * A LED driver for the as4625_led + * + * Copyright (C) 2016 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as4625_led" + +extern int as4625_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as4625_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +struct as4625_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]; /* Register value, 0 = System/LOC/PSU0 LED + 1 = PSU1/FAN/POE LED */ +}; + +static struct as4625_led_data *ledctl = NULL; + +#define LED_CNTRLER_I2C_ADDRESS (0x64) + +#define LED_TYPE_SYS_REG_MASK (0xF0) +#define LED_MODE_SYS_GREEN_BLINK_VALUE (0x60) +#define LED_MODE_SYS_GREEN_VALUE (0x20) +#define LED_MODE_SYS_AMBER_VALUE (0x80) +#define LED_MODE_SYS_AMBER_BLINK_VALUE (0x90) +#define LED_MODE_SYS_OFF_VALUE (0x00) + +#define LED_TYPE_LOC_REG_MASK (0x0C) +#define LED_MODE_LOC_GREEN_VALUE (0x04) +#define LED_MODE_LOC_AMBER_VALUE (0x08) +#define LED_MODE_LOC_OFF_VALUE (0x00) +#define LED_MODE_LOC_OFF_VALUE_1 (0x0C) + +#define LED_TYPE_POE_REG_MASK (0x03) +#define LED_MODE_POE_OFF_VALUE (0x00) +#define LED_MODE_POE_OFF_VALUE_1 (0x03) +#define LED_MODE_POE_GREEN_VALUE (0x01) +#define LED_MODE_POE_AMBER_VALUE (0x02) + +static const u8 led_reg[] = { + 0x30, /* System/LOC/PSU0 LED */ + 0x31 /* PSU1/FAN/POE LED */ +}; + +enum led_type { + LED_TYPE_SYS, + LED_TYPE_LOC, + LED_TYPE_PSU1, + LED_TYPE_PSU2, + LED_TYPE_FAN, + LED_TYPE_POE +}; + +/* FAN/PSU/DIAG/RELEASE led mode */ +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER, + LED_MODE_AMBER_BLINK, + LED_MODE_RED, + LED_MODE_RED_BLINK, + LED_MODE_BLUE, + LED_MODE_BLUE_BLINK, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +struct led_type_mode { + enum led_type type; + enum led_light_mode mode; + int type_mask; + int mode_value; +}; + +static struct led_type_mode led_type_mode_data[] = { + {LED_TYPE_SYS, LED_MODE_GREEN_BLINK, LED_TYPE_SYS_REG_MASK, LED_MODE_SYS_GREEN_BLINK_VALUE}, + {LED_TYPE_SYS, LED_MODE_GREEN, LED_TYPE_SYS_REG_MASK, LED_MODE_SYS_GREEN_VALUE}, + {LED_TYPE_SYS, LED_MODE_AMBER_BLINK, LED_TYPE_SYS_REG_MASK, LED_MODE_SYS_AMBER_BLINK_VALUE}, + {LED_TYPE_SYS, LED_MODE_AMBER, LED_TYPE_SYS_REG_MASK, LED_MODE_SYS_AMBER_VALUE}, + {LED_TYPE_SYS, LED_MODE_OFF, LED_TYPE_SYS_REG_MASK, LED_MODE_SYS_OFF_VALUE}, + {LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE}, + {LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE_1}, + {LED_TYPE_LOC, LED_MODE_GREEN, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_GREEN_VALUE}, + {LED_TYPE_LOC, LED_MODE_AMBER, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_VALUE}, + {LED_TYPE_POE, LED_MODE_OFF, LED_TYPE_POE_REG_MASK, LED_MODE_POE_OFF_VALUE}, + {LED_TYPE_POE, LED_MODE_OFF, LED_TYPE_POE_REG_MASK, LED_MODE_POE_OFF_VALUE_1}, + {LED_TYPE_POE, LED_MODE_GREEN, LED_TYPE_POE_REG_MASK, LED_MODE_POE_GREEN_VALUE}, + {LED_TYPE_POE, LED_MODE_AMBER, LED_TYPE_POE_REG_MASK, LED_MODE_POE_AMBER_VALUE} +}; + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) + continue; + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_value) { + return led_type_mode_data[i].mode; + } + } + + return LED_MODE_UNKNOWN; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + int type_mask, mode_value; + + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + type_mask = led_type_mode_data[i].type_mask; + mode_value = led_type_mode_data[i].mode_value; + reg_val = (reg_val & ~type_mask) | mode_value; + } + + return reg_val; +} + +static int as4625_led_read_value(u8 reg) +{ + return as4625_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg); +} + +static int as4625_led_write_value(u8 reg, u8 value) +{ + return as4625_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value); +} + +static void as4625_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting as4625_led update\n"); + ledctl->valid = 0; + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = as4625_led_read_value(led_reg[i]); + + if (status < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", + led_reg[i], status); + goto exit; + } else { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void as4625_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + u8 reg, enum led_type type) +{ + int reg_val; + + mutex_lock(&ledctl->update_lock); + reg_val = as4625_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); + as4625_led_write_value(reg, reg_val); + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void as4625_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness as4625_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static void as4625_led_sys_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as4625_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_SYS); +} + +static enum led_brightness as4625_led_sys_get(struct led_classdev *cdev) +{ + as4625_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_SYS, ledctl->reg_val[0]); +} + +static enum led_brightness as4625_led_loc_get(struct led_classdev *cdev) +{ + as4625_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void as4625_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as4625_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC); +} + +static enum led_brightness as4625_led_poe_get(struct led_classdev *cdev) +{ + as4625_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_POE, ledctl->reg_val[1]); +} + +static void as4625_led_poe_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as4625_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_POE); +} + +static struct led_classdev as4625_leds[] = { + [LED_TYPE_SYS] = { + .name = "as4625_led::sys", + .default_trigger = "unused", + .brightness_set = as4625_led_sys_set, + .brightness_get = as4625_led_sys_get, + .max_brightness = LED_MODE_AMBER_BLINK, + }, + [LED_TYPE_LOC] = { + .name = "as4625_led::loc", + .default_trigger = "unused", + .brightness_set = as4625_led_loc_set, + .brightness_get = as4625_led_loc_get, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_PSU1] = { + .name = "as4625_led::psu1", + .default_trigger = "unused", + .brightness_set = as4625_led_auto_set, + .brightness_get = as4625_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "as4625_led::psu2", + .default_trigger = "unused", + .brightness_set = as4625_led_auto_set, + .brightness_get = as4625_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN] = { + .name = "as4625_led::fan", + .default_trigger = "unused", + .brightness_set = as4625_led_auto_set, + .brightness_get = as4625_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_POE] = { + .name = "as4625_led::poe", + .default_trigger = "unused", + .brightness_set = as4625_led_poe_set, + .brightness_get = as4625_led_poe_get, + .max_brightness = LED_MODE_AMBER, + } +}; + +static int as4625_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(as4625_leds); i++) { + ret = led_classdev_register(&pdev->dev, &as4625_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(as4625_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) + led_classdev_unregister(&as4625_leds[i]); + } + + return ret; +} + +static int as4625_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(as4625_leds); i++) + led_classdev_unregister(&as4625_leds[i]); + + return 0; +} + +static struct platform_driver as4625_led_driver = { + .probe = as4625_led_probe, + .remove = as4625_led_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init as4625_led_init(void) +{ + int ret; + + ret = platform_driver_register(&as4625_led_driver); + if (ret < 0) + goto exit; + + ledctl = kzalloc(sizeof(struct as4625_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + goto exit_driver; + } + + 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); + goto exit_free; + } + + return 0; + +exit_free: + kfree(ledctl); +exit_driver: + platform_driver_unregister(&as4625_led_driver); +exit: + return ret; +} + +static void __exit as4625_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&as4625_led_driver); + kfree(ledctl); +} + +late_initcall(as4625_led_init); +module_exit(as4625_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as4625_led driver"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/x86-64-accton-as4625-30p-psu.c b/packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/x86-64-accton-as4625-30p-psu.c new file mode 100644 index 0000000000..23f63f7c81 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/modules/builds/src/x86-64-accton-as4625-30p-psu.c @@ -0,0 +1,464 @@ +/* + * An hwmon driver for accton as4625_30p Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as4625_30p_psu" + +#define PSU_STATUS_I2C_ADDR 0x64 +#define PSU_STATUS_I2C_REG_OFFSET 0x4 + +#define MAX_MODEL_NAME 14 +#define MAX_SERIAL_NUMBER 10 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4+2))) +#define IS_PRESENT(id, value) (!(value & BIT(id*4))) + +#define FAN_DIR_LEN 4 +const char FAN_DIR_F2B[] = "F2B"; +const char FAN_DIR_B2F[] = "B2F"; + +static int models_min_offset = 0; +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf); +extern int as4625_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as4625_30p_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[MAX_MODEL_NAME]; /* Model name, read from eeprom */ + char serial[MAX_SERIAL_NUMBER]; /* Serial number, read from eeprom*/ + char fan_dir[FAN_DIR_LEN]; +}; + +static struct as4625_30p_psu_data + *as4625_30p_psu_update_device(struct device *dev); + +enum as4625_30p_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_SERIAL_NUMBER, + PSU_FAN_DIR +}; + +enum psu_type { + PSU_UP6001R_1079G, /* F2B */ + UNKNOWN_PSU +}; +struct model_name_info { + enum psu_type type; + u8 offset; + u8 length; + char* model_name; +}; +struct model_name_info models[] = { + { PSU_UP6001R_1079G, 0x20, 13, "UP6001R-1079G" }, +}; +struct serial_number_info { + u8 offset; + u8 length; +}; +struct serial_number_info serials[] = { + [PSU_UP6001R_1079G] = { 0x3B, 9 }, +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, \ + PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, \ + PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, \ + PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_serial_number, S_IRUGO, show_string, NULL, \ + PSU_SERIAL_NUMBER); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_string, NULL, \ + PSU_FAN_DIR); + +static struct attribute *as4625_30p_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_serial_number.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as4625_30p_psu_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 status = 0; + + mutex_lock(&data->update_lock); + + data = as4625_30p_psu_update_device(dev); + if (!data->valid) { + mutex_unlock(&data->update_lock); + return sprintf(buf, "0\n"); + } + + if (attr->index == PSU_PRESENT) + status = IS_PRESENT(data->index, data->status); + else /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as4625_30p_psu_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + char *ptr = NULL; + int ret = 0; + + mutex_lock(&data->update_lock); + + data = as4625_30p_psu_update_device(dev); + if (!data->valid) { + ret = -EIO; + goto exit; + } + + switch (attr->index) { + case PSU_MODEL_NAME: + ptr = data->model_name; + break; + case PSU_SERIAL_NUMBER: + ptr = data->serial; + break; + case PSU_FAN_DIR: + ptr = data->fan_dir; + break; + default: + ret = -EINVAL; + goto exit; + } + + ret = sprintf(buf, "%s\n", ptr); + +exit: + mutex_unlock(&data->update_lock); + return ret; +} + +static const struct attribute_group as4625_30p_psu_group = { + .attrs = as4625_30p_psu_attributes, +}; + +static int find_models_min_offset(void) { + int i, min_offset = models[0].offset; + + for(i = 1; i < ARRAY_SIZE(models); i++) { + if(models[i].offset < min_offset) { + min_offset = models[i].offset; + } + } + + return min_offset; +} + +static int as4625_30p_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as4625_30p_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as4625_30p_psu_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + data->valid = 0; + data->index = dev_id->driver_data; + mutex_init(&data->update_lock); + i2c_set_clientdata(client, data); + models_min_offset = find_models_min_offset(); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as4625_30p_psu_group); + if (status) + goto exit_free; + + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, + DRVNAME, NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as4625_30p_psu_group); +exit_free: + kfree(data); +exit: + return status; +} + +static int as4625_30p_psu_remove(struct i2c_client *client) +{ + struct as4625_30p_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as4625_30p_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as4625_30p_psu1, + as4625_30p_psu2 +}; + +static const struct i2c_device_id as4625_30p_psu_id[] = { + { "as4625_30p_psu1", as4625_30p_psu1 }, + { "as4625_30p_psu2", as4625_30p_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as4625_30p_psu_id); + +static struct i2c_driver as4625_30p_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as4625_30p_psu_probe, + .remove = as4625_30p_psu_remove, + .id_table = as4625_30p_psu_id, + .address_list = normal_i2c, +}; + +static int as4625_30p_psu_read_byte(struct i2c_client *client, u8 command, + u8 *data) +{ + int status = 0; + int retry_count = 5; + + while (retry_count) { + status = i2c_smbus_read_byte_data(client, command); + if (unlikely(status < 0)) { + msleep(10); + retry_count--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, + "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", + command, status); + goto abort; + } + + *data = (u8)status; + +abort: + return status; +} + +static int as4625_30p_psu_read_bytes(struct i2c_client *client, u8 command, + u8 *data, int data_len) +{ + int ret = 0; + + while (data_len) { + ssize_t status; + + status = as4625_30p_psu_read_byte(client, command, data); + if (status <= 0) { + ret = status; + break; + } + + data += 1; + command += 1; + data_len -= 1; + } + + return ret; +} + +static struct as4625_30p_psu_data *as4625_30p_psu_update_device( + struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as4625_30p_psu_data *data = i2c_get_clientdata(client); + char temp_model_name[MAX_MODEL_NAME] = {0}; + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + int i; + + dev_dbg(&client->dev, "Starting as4625_30p update\n"); + data->valid = 0; + + /* Read psu status */ + status = as4625_cpld_read(PSU_STATUS_I2C_ADDR, + PSU_STATUS_I2C_REG_OFFSET); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", + PSU_STATUS_I2C_ADDR, status); + goto exit; + } else { + data->status = status; + } + + memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->serial, 0, sizeof(data->serial)); + memset(data->fan_dir, 0, sizeof(data->fan_dir)); + + if (IS_POWER_GOOD(data->index, data->status)) { + enum psu_type type = UNKNOWN_PSU; + + /* Read model name */ + status = as4625_30p_psu_read_bytes(client, + models_min_offset, + temp_model_name, + ARRAY_SIZE(temp_model_name)); + if (status < 0) { + dev_dbg(&client->dev, + "unable to read model name from (0x%x)\n", + client->addr); + goto exit; + } + + for (i = 0; i < ARRAY_SIZE(models); i++) { + if ((models[i].length+1) > ARRAY_SIZE(data->model_name)) { + dev_dbg(&client->dev, + "invalid models[%d].length(%d), should not exceed the size of data->model_name(%ld)\n", + i, models[i].length, ARRAY_SIZE(data->model_name)); + continue; + } + + snprintf(data->model_name, models[i].length + 1, "%s", + temp_model_name + (models[i].offset - models_min_offset)); + + /* Determine if the model name is known, if not, read next index */ + if (strcmp(data->model_name, models[i].model_name) == 0) { + type = models[i].type; + break; + } + + data->model_name[0] = '\0'; + } + + switch (type) { + case PSU_UP6001R_1079G: + memcpy(data->fan_dir, FAN_DIR_F2B, sizeof(FAN_DIR_F2B)); + break; + default: + dev_dbg(&client->dev, "Unknown PSU type for fan direction\n"); + break; + } + + /* Read serial number */ + if (type < ARRAY_SIZE(serials)) { + if ((serials[type].length+1) > ARRAY_SIZE(data->serial)) { + dev_dbg(&client->dev, + "invalid serials[%d].length(%d), should not exceed the size of data->serial(%ld)\n", + type, serials[type].length, ARRAY_SIZE(data->serial)); + goto exit; + } + + memset(data->serial, 0, sizeof(data->serial)); + status = as4625_30p_psu_read_bytes(client, serials[type].offset, + data->serial, + serials[type].length); + if (status < 0) { + dev_dbg(&client->dev, + "unable to read serial from (0x%x) offset(0x%02x)\n", + client->addr, serials[type].length); + goto exit; + } + else { + data->serial[serials[type].length]= '\0'; + } + } + else { + dev_dbg(&client->dev, "invalid PSU type(%d)\n", type); + return data; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + return data; +} + +module_i2c_driver(as4625_30p_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as4625_30p_psu driver"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/Makefile b/packages/platforms/accton/x86-64/as4625-30p/onlp/Makefile new file mode 100644 index 0000000000..502e772a7b --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/PKG.yml b/packages/platforms/accton/x86-64/as4625-30p/onlp/PKG.yml new file mode 100644 index 0000000000..51d5b39832 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-accton-as4625-30p ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/Makefile b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/Makefile new file mode 100644 index 0000000000..e7437cb23a --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/lib/Makefile b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/lib/Makefile new file mode 100644 index 0000000000..724163acb5 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/lib/Makefile @@ -0,0 +1,2 @@ +PLATFORM := x86-64-accton-as4625-30p +include $(ONL)/packages/base/any/onlp/builds/platform/libonlp-platform.mk diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/onlpdump/Makefile b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/onlpdump/Makefile new file mode 100644 index 0000000000..c568bebe42 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/onlpdump/Makefile @@ -0,0 +1,2 @@ +PLATFORM := x86-64-accton-as4625-30p +include $(ONL)/packages/base/any/onlp/builds/platform/onlps.mk diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/.gitignore b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/.module b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/.module new file mode 100644 index 0000000000..da2e0b075d --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/.module @@ -0,0 +1 @@ +name: x86_64_accton_as4625_30p diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/Makefile b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/Makefile new file mode 100644 index 0000000000..ea19645832 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include $(ONL)/make/config.mk +MODULE := x86_64_accton_as4625_30p +AUTOMODULE := x86_64_accton_as4625_30p +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/README b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/README new file mode 100644 index 0000000000..314a74b9e1 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/README @@ -0,0 +1,6 @@ +############################################################################### +# +# x86_64_accton_as4625_30p README +# +############################################################################### + diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/auto/make.mk b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/auto/make.mk new file mode 100644 index 0000000000..af2429dd0e --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/auto/make.mk @@ -0,0 +1,8 @@ +############################################################################### +# +# x86_64_accton_as4625_30p Autogeneration +# +############################################################################### +x86_64_accton_as4625_30p_AUTO_DEFS := module/auto/x86_64_accton_as4625_30p.yml +x86_64_accton_as4625_30p_AUTO_DIRS := module/inc/x86_64_accton_as4625_30p module/src +include $(BUILDER)/auto.mk diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/auto/x86_64_accton_as4625_30p.yml b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/auto/x86_64_accton_as4625_30p.yml new file mode 100644 index 0000000000..82f228a2db --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/auto/x86_64_accton_as4625_30p.yml @@ -0,0 +1,49 @@ +############################################################################### +# +# x86_64_accton_as4625_30p Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- X86_64_ACCTON_AS4625_30P_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- X86_64_ACCTON_AS4625_30P_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- X86_64_ACCTON_AS4625_30P_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_STDLIB +- X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- X86_64_ACCTON_AS4625_30P_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_AS4625_30P_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_accton_as4625_30p_config + + portingmacro: + x86_64_accton_as4625_30p: + macros: + - malloc + - free + - memset + - memcpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/inc/x86_64_accton_as4625_30p/x86_64_accton_as4625_30p.x b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/inc/x86_64_accton_as4625_30p/x86_64_accton_as4625_30p.x new file mode 100644 index 0000000000..76fab7fa64 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/inc/x86_64_accton_as4625_30p/x86_64_accton_as4625_30p.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/inc/x86_64_accton_as4625_30p/x86_64_accton_as4625_30p_config.h b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/inc/x86_64_accton_as4625_30p/x86_64_accton_as4625_30p_config.h new file mode 100644 index 0000000000..c8cb0e4197 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/inc/x86_64_accton_as4625_30p/x86_64_accton_as4625_30p_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_as4625_30p Configuration Header + * + * @addtogroup x86_64_accton_as4625_30p-config + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS4625_30P_CONFIG_H__ +#define __X86_64_ACCTON_AS4625_30P_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef X86_64_ACCTON_AS4625_30P_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_LOGGING +#define X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * X86_64_ACCTON_AS4625_30P_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef X86_64_ACCTON_AS4625_30P_CONFIG_LOG_OPTIONS_DEFAULT +#define X86_64_ACCTON_AS4625_30P_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * X86_64_ACCTON_AS4625_30P_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef X86_64_ACCTON_AS4625_30P_CONFIG_LOG_BITS_DEFAULT +#define X86_64_ACCTON_AS4625_30P_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * X86_64_ACCTON_AS4625_30P_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef X86_64_ACCTON_AS4625_30P_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define X86_64_ACCTON_AS4625_30P_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_STDLIB +#define X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_STDLIB +#endif + +/** + * X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_UCLI +#define X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_accton_as4625_30p_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_accton_as4625_30p_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_accton_as4625_30p_config_settings table. */ +extern x86_64_accton_as4625_30p_config_settings_t x86_64_accton_as4625_30p_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_accton_as4625_30p_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_accton_as4625_30p_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_accton_as4625_30p_porting.h" + +#endif /* __X86_64_ACCTON_AS4625_30P_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/inc/x86_64_accton_as4625_30p/x86_64_accton_as4625_30p_dox.h b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/inc/x86_64_accton_as4625_30p/x86_64_accton_as4625_30p_dox.h new file mode 100644 index 0000000000..c4b17eba58 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/inc/x86_64_accton_as4625_30p/x86_64_accton_as4625_30p_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_accton_as4625_30p Doxygen Header + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS4625_30P_DOX_H__ +#define __X86_64_ACCTON_AS4625_30P_DOX_H__ + +/** + * @defgroup x86_64_accton_as4625_30p x86_64_accton_as4625_30p - x86_64_accton_as4625_30p Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_accton_as4625_30p-x86_64_accton_as4625_30p Public Interface + * @defgroup x86_64_accton_as4625_30p-config Compile Time Configuration + * @defgroup x86_64_accton_as4625_30p-porting Porting Macros + * + * @} + * + */ + +#endif /* __X86_64_ACCTON_AS4625_30P_DOX_H__ */ diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/inc/x86_64_accton_as4625_30p/x86_64_accton_as4625_30p_porting.h b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/inc/x86_64_accton_as4625_30p/x86_64_accton_as4625_30p_porting.h new file mode 100644 index 0000000000..abd30d24c9 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/inc/x86_64_accton_as4625_30p/x86_64_accton_as4625_30p_porting.h @@ -0,0 +1,97 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_as4625_30p Porting Macros. + * + * @addtogroup x86_64_accton_as4625_30p-porting + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS4625_30P_PORTING_H__ +#define __X86_64_ACCTON_AS4625_30P_PORTING_H__ + + +/* */ +#if X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef X86_64_ACCTON_AS4625_30P_MALLOC + #if defined(GLOBAL_MALLOC) + #define X86_64_ACCTON_AS4625_30P_MALLOC GLOBAL_MALLOC + #elif X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS4625_30P_MALLOC malloc + #else + #error The macro X86_64_ACCTON_AS4625_30P_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS4625_30P_FREE + #if defined(GLOBAL_FREE) + #define X86_64_ACCTON_AS4625_30P_FREE GLOBAL_FREE + #elif X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS4625_30P_FREE free + #else + #error The macro X86_64_ACCTON_AS4625_30P_FREE is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS4625_30P_MEMSET + #if defined(GLOBAL_MEMSET) + #define X86_64_ACCTON_AS4625_30P_MEMSET GLOBAL_MEMSET + #elif X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS4625_30P_MEMSET memset + #else + #error The macro X86_64_ACCTON_AS4625_30P_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS4625_30P_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define X86_64_ACCTON_AS4625_30P_MEMCPY GLOBAL_MEMCPY + #elif X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS4625_30P_MEMCPY memcpy + #else + #error The macro X86_64_ACCTON_AS4625_30P_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS4625_30P_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define X86_64_ACCTON_AS4625_30P_VSNPRINTF GLOBAL_VSNPRINTF + #elif X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS4625_30P_VSNPRINTF vsnprintf + #else + #error The macro X86_64_ACCTON_AS4625_30P_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS4625_30P_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define X86_64_ACCTON_AS4625_30P_SNPRINTF GLOBAL_SNPRINTF + #elif X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS4625_30P_SNPRINTF snprintf + #else + #error The macro X86_64_ACCTON_AS4625_30P_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS4625_30P_STRLEN + #if defined(GLOBAL_STRLEN) + #define X86_64_ACCTON_AS4625_30P_STRLEN GLOBAL_STRLEN + #elif X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS4625_30P_STRLEN strlen + #else + #error The macro X86_64_ACCTON_AS4625_30P_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __X86_64_ACCTON_AS4625_30P_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/make.mk b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/make.mk new file mode 100644 index 0000000000..6641757deb --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_accton_as4625_30p_INCLUDES := -I $(THIS_DIR)inc +x86_64_accton_as4625_30p_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_accton_as4625_30p_DEPENDMODULE_ENTRIES := init:x86_64_accton_as4625_30p ucli:x86_64_accton_as4625_30p + diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/Makefile b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/Makefile new file mode 100644 index 0000000000..36a7a578d7 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_accton_as4625_30p_ucli.c + diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/fani.c b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/fani.c new file mode 100644 index 0000000000..fd3fb57f54 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/fani.c @@ -0,0 +1,279 @@ +/************************************************************ + * + * + * 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 "platform_lib.h" + +#define PSU_PREFIX_PATH "/sys/bus/i2c/devices/" + +#define MAX_FAN_SPEED 23000 +#define MAX_PSU_FAN_SPEED 25500 + +enum fan_id { + FAN_1_ON_FAN_BOARD = 1, + FAN_2_ON_FAN_BOARD, + FAN_3_ON_FAN_BOARD, + FAN_1_ON_PSU_1, + FAN_1_ON_PSU_2, +}; + +#define CHASSIS_FAN_INFO(fid) { \ + { ONLP_FAN_ID_CREATE(FAN_##fid##_ON_FAN_BOARD), "Chassis Fan - "#fid, 0, {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, {0} },\ + 0x0,\ + 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), + 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; + + /* get fan present status + */ + info->status |= ONLP_FAN_STATUS_PRESENT; + + /* get fan fault status (turn on when any one fails) + */ + if (onlp_file_read_int(&value, "%s""fan%d_fault", + FAN_NODE_PATH, fid) < 0) { + AIM_LOG_ERROR("Unable to read fan fault status from (%s)\r\n", + FAN_NODE_PATH); + return ONLP_STATUS_E_INTERNAL; + } + if (value > 0) + info->status |= ONLP_FAN_STATUS_FAILED; + + + /* get fan direction (both : the same) + */ + info->status |= ONLP_FAN_STATUS_F2B; + + + /* get fan speed + */ + if (onlp_file_read_int(&value, "%s""fan%d_input", + FAN_NODE_PATH, fid) < 0) { + AIM_LOG_ERROR("Unable to read fan speed from (%s)\r\n", + FAN_NODE_PATH); + + return ONLP_STATUS_E_INTERNAL; + } + info->rpm = value; + + /* get pwm percentage + */ + if (onlp_file_read_int(&value, "%s""fan%d_pwm", + FAN_NODE_PATH, fid) < 0) { + AIM_LOG_ERROR("Unable to read fan duty from (%s)\r\n", + FAN_NODE_PATH); + return ONLP_STATUS_E_INTERNAL; + } + info->percentage = value; + + return ONLP_STATUS_OK; +} + +static uint32_t +_onlp_get_fan_direction_on_psu(int pid) +{ + psu_type_t psu_type; + + psu_type = get_psu_type(pid, NULL, 0); + switch (psu_type) { + case PSU_TYPE_UP6001R_1079G_F2B: + return ONLP_FAN_STATUS_F2B; + case PSU_TYPE_UNKNOWN: + return 0; + default: + return ONLP_FAN_STATUS_B2F; + } +} + +static int +_onlp_fani_info_get_fan_on_psu(int pid, onlp_fan_info_t* info) +{ + int val = 0; + int psu_type; + + info->status |= ONLP_FAN_STATUS_PRESENT; + + /* get fan direction + */ + info->status |= _onlp_get_fan_direction_on_psu(pid); + + /* get fan fault status + */ + if (psu_pmbus_info_get(pid, "psu_fan1_fault", &val) + == ONLP_STATUS_OK) + info->status |= (val > 0) ? ONLP_FAN_STATUS_FAILED : 0; + + /* get fan speed + */ + if (psu_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) + == ONLP_STATUS_OK) { + info->rpm = val; + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + } + + /* Get PSU type */ + psu_type = get_psu_type(pid, NULL, 0); + if (psu_type == PSU_TYPE_UNKNOWN) { + /* + * For display all PSU information that includes the + * fan and temperature, even access hardware fail. + */ + 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: + rc =_onlp_fani_info_get_fan(fid, info); + break; + default: + rc = ONLP_STATUS_E_INVALID; + break; + } + + return rc; +} + +/* + * This function sets the speed of the given fan in RPM. + * + * This function will only be called if the fan supprots the RPM_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_rpm_set(onlp_oid_t id, int rpm) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_percentage_set(onlp_oid_t id, int p) +{ + int fid; + char *path = NULL; + + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + + /* reject p=0 (p=0, stop fan) */ + if (p == 0) + return ONLP_STATUS_E_INVALID; + + switch (fid) { + case FAN_1_ON_FAN_BOARD: + path = FAN_NODE(fan1_pwm); + break; + case FAN_2_ON_FAN_BOARD: + path = FAN_NODE(fan2_pwm); + break; + case FAN_3_ON_FAN_BOARD: + path = FAN_NODE(fan3_pwm); + break; + default: + return ONLP_STATUS_E_INVALID; + } + + if (onlp_file_write_int(p, path) < 0) { + AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/ledi.c b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/ledi.c new file mode 100644 index 0000000000..aec5d7337a --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/ledi.c @@ -0,0 +1,239 @@ +/************************************************************ + * + * + * 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 VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +#define LED_FORMAT "/sys/class/leds/as4625_led::%s/brightness" + +/* LED related data + */ +enum onlp_led_id { + LED_RESERVED = 0, + LED_SYS, + LED_LOC, + LED_PSU1, + LED_PSU2, + LED_FAN, + LED_POE +}; + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_AMBER, + LED_MODE_RED, + LED_MODE_BLUE, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER_BLINK, + LED_MODE_RED_BLINK, + LED_MODE_BLUE_BLINK, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +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_SYS, LED_MODE_GREEN_BLINK, ONLP_LED_MODE_GREEN_BLINKING}, + {LED_SYS, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, + {LED_SYS, LED_MODE_AMBER_BLINK, ONLP_LED_MODE_ORANGE_BLINKING}, + {LED_SYS, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, + + {LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF}, + {LED_LOC, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, + {LED_LOC, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, + + {LED_PSU1, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + {LED_PSU2, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + {LED_FAN, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + + {LED_POE, LED_MODE_OFF, ONLP_LED_MODE_OFF}, + {LED_POE, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, + {LED_POE, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, +}; + +static char *leds[] = { /* must map with onlp_led_id */ + NULL, + "sys", + "loc", + "psu1", + "psu2", + "fan", + "poe" +}; + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t linfo[] = +{ + { }, /* Not used */ + { + { ONLP_LED_ID_CREATE(LED_SYS), "LED 1 (SYS LED)", 0, {0} }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN_BLINKING | + ONLP_LED_CAPS_ORANGE_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_LOC), "LED 2 (LOC LED)", 0, {0} }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU1), "LED 3 (PSU1 LED)", 0, {0} }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU2), "LED 4 (PSU2 LED)", 0, {0} }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_FAN), "LED 5 (FAN LED)", 0, {0} }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_POE), "LED 6 (POE LED)", 0, {0} }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE, + }, +}; + +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 lid, value; + VALIDATE(id); + + lid = ONLP_OID_ID_GET(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[ONLP_OID_ID_GET(id)]; + + /* Get LED mode */ + if (onlp_file_read_int(&value, LED_FORMAT, leds[lid]) < 0) + return ONLP_STATUS_E_INTERNAL; + + info->mode = driver_to_onlp_led_mode(lid, value); + + /* 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); + else + return onlp_ledi_mode_set(id, ONLP_LED_MODE_GREEN); +} + +/* + * 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 lid; + VALIDATE(id); + + lid = ONLP_OID_ID_GET(id); + + if (onlp_file_write_int(onlp_to_driver_led_mode(lid , mode), + LED_FORMAT, leds[lid]) != 0) + return ONLP_STATUS_E_INTERNAL; + + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/make.mk b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/make.mk new file mode 100644 index 0000000000..8d8461797a --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_accton_as4625_30p +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/platform_lib.c b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/platform_lib.c new file mode 100644 index 0000000000..8314b2e9b1 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/platform_lib.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include "platform_lib.h" +#include +#include "x86_64_accton_as4625_30p_log.h" + +#define PSU_MODEL_NAME_LEN 13 +#define I2C_PSU_FAN_DIR_LEN 3 + +psu_type_t get_psu_type(int id, char *data_buf, int data_len) +{ + int len = 0; + char *path[] = { PSU1_AC_EEPROM_PREFIX, PSU2_AC_EEPROM_PREFIX }; + char *str = NULL; + psu_type_t ptype = PSU_TYPE_UNKNOWN; + + /* Read attribute */ + len = onlp_file_read_str(&str, "%s%s", path[id-1], "psu_model_name"); + if (!str || len <= 0 || len < PSU_MODEL_NAME_LEN) { + AIM_FREE_IF_PTR(str); + return PSU_TYPE_UNKNOWN; + } + + /* Check AC model name */ + if (strncmp(str, "UP6001R-1079G", strlen("UP6001R-1079G")) == 0) + ptype = PSU_TYPE_UP6001R_1079G_F2B; + else + ptype = PSU_TYPE_UNKNOWN; + + if (len < data_len) + aim_strlcpy(data_buf, str, len+1); + + AIM_FREE_IF_PTR(str); + return ptype; +} + +int psu_pmbus_info_get(int id, char *node, int *value) +{ + char *path[] = { PSU1_AC_PMBUS_PREFIX, PSU2_AC_PMBUS_PREFIX }; + *value = 0; + + return onlp_file_read_int(value, "%s%s", path[id-1], node); +} + +int get_psu_eeprom_str(int id, char *data_buf, int data_len, char *data_name) +{ + int len = 0; + char *path[] = { PSU1_AC_EEPROM_PREFIX, PSU2_AC_EEPROM_PREFIX }; + char *str = NULL; + + /* Read attribute */ + len = onlp_file_read_str(&str, "%s%s", path[id-1], data_name); + if (!str || len <= 0) { + AIM_FREE_IF_PTR(str); + return ONLP_STATUS_E_INTERNAL; + } + + if (len > data_len) { + AIM_FREE_IF_PTR(str); + return ONLP_STATUS_E_INVALID; + } + + aim_strlcpy(data_buf, str, len+1); + AIM_FREE_IF_PTR(str); + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/platform_lib.h b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/platform_lib.h new file mode 100644 index 0000000000..2e24f22628 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/platform_lib.h @@ -0,0 +1,82 @@ +/************************************************************ + * + * + * 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 +#include "x86_64_accton_as4625_30p_log.h" + +#define CHASSIS_FAN_COUNT 3 +#define CHASSIS_THERMAL_COUNT 4 +#define CHASSIS_PSU_COUNT 2 +#define CHASSIS_LED_COUNT 6 + +#define NUM_OF_THERMAL_PER_PSU 3 + +#define NUM_OF_CPU_CORES 4 + +#define PSU1_ID 1 +#define PSU2_ID 2 + +#define PSU_NODE_MAX_INT_LEN 8 +#define PSU_NODE_MAX_PATH_LEN 64 + +#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/8-0058/" +#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/9-0059/" + +#define PSU1_AC_PMBUS_NODE(node) PSU1_AC_PMBUS_PREFIX#node +#define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node + +#define PSU1_AC_EEPROM_PREFIX "/sys/bus/i2c/devices/8-0050/" +#define PSU2_AC_EEPROM_PREFIX "/sys/bus/i2c/devices/9-0051/" + +#define CPLD_NODE_PATH "/sys/bus/i2c/devices/i2c-0/0-0064/" + +#define FAN_NODE_PATH "/sys/devices/platform/as4625_fan/hwmon*" +#define FAN_NODE(node) FAN_NODE_PATH#node + +#define IDPROM_PATH "/sys/bus/i2c/devices/7-0051/eeprom" + +int psu_pmbus_info_get(int id, char *node, int *value); + +typedef enum psu_type { + PSU_TYPE_UNKNOWN, + PSU_TYPE_UP6001R_1079G_F2B, +} psu_type_t; + +psu_type_t get_psu_type(int id, char* modelname, int modelname_len); +int get_psu_eeprom_str(int id, char *data_buf, int data_len, char *data_name); + +#define AIM_FREE_IF_PTR(p) \ + do \ + { \ + if (p) { \ + aim_free(p); \ + p = NULL; \ + } \ + } while (0) + +#endif /* __PLATFORM_LIB_H__ */ diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/psui.c b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/psui.c new file mode 100644 index 0000000000..5a8760401c --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/psui.c @@ -0,0 +1,181 @@ +/************************************************************ + * + * + * 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) + +static int +psu_status_info_get(int id, char *node, int *value) +{ + char *path[] = { PSU1_AC_EEPROM_PREFIX, PSU2_AC_EEPROM_PREFIX }; + *value = 0; + + return onlp_file_read_int(value, "%s%s", path[id-1], node); +} + +int +onlp_psui_init(void) +{ + return ONLP_STATUS_OK; +} + +static int +psu_ym2651y_info_get(onlp_psu_info_t* info) +{ + int val = 0; + int index = ONLP_OID_ID_GET(info->hdr.id); + + /* Set capability + */ + info->caps = ONLP_PSU_CAPS_AC; + + if (info->status & ONLP_PSU_STATUS_FAILED) + return ONLP_STATUS_OK; + + /* Set the associated oid_table */ + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT); + + info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE((index-1) * + NUM_OF_THERMAL_PER_PSU + + CHASSIS_THERMAL_COUNT + + 1); + + info->hdr.coids[2] = ONLP_THERMAL_ID_CREATE((index-1) * + NUM_OF_THERMAL_PER_PSU + + CHASSIS_THERMAL_COUNT + + 2); + + info->hdr.coids[3] = ONLP_THERMAL_ID_CREATE((index-1) * + NUM_OF_THERMAL_PER_PSU + + CHASSIS_THERMAL_COUNT + + 3); + /* Read voltage, current and power */ + if (psu_pmbus_info_get(index, "psu_v_out", &val) == 0) { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + if (psu_pmbus_info_get(index, "psu_i_out", &val) == 0) { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + if (psu_pmbus_info_get(index, "psu_p_out", &val) == 0) { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + get_psu_eeprom_str(index, info->serial, sizeof(info->serial), + "psu_serial_number"); + + return ONLP_STATUS_OK; +} + +/* + * Get all information about the given PSU oid. + */ +static onlp_psu_info_t pinfo[] = +{ + { }, /* Not used */ + { + { ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0 }, + }, + { + { ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0 }, + } +}; + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int val = 0; + int ret = ONLP_STATUS_OK; + int index = ONLP_OID_ID_GET(id); + psu_type_t psu_type; + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_psu_info_t)); + *info = pinfo[index]; /* Set the onlp_oid_hdr_t */ + + /* Get the present state */ + if (psu_status_info_get(index, "psu_present", &val) != 0) { + AIM_LOG_ERROR("Unable to read PSU(%d) node(psu_present)\r\n", + index); + 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 */ + if (psu_status_info_get(index, "psu_power_good", &val) != 0) { + AIM_LOG_ERROR("Unable to read PSU(%d) node(psu_power_good)\r\n", + index); + return ONLP_STATUS_E_INTERNAL; + } + if (val != PSU_STATUS_POWER_GOOD) { + info->status |= ONLP_PSU_STATUS_UNPLUGGED; + } + + /* Get PSU type */ + psu_type = get_psu_type(index, info->model, sizeof(info->model)); + switch (psu_type) { + case PSU_TYPE_UP6001R_1079G_F2B: + ret = psu_ym2651y_info_get(info); + break; + case PSU_TYPE_UNKNOWN: /* User insert a unknown PSU or unplugged.*/ + /* Set the associated oid_table */ + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT); + info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(CHASSIS_THERMAL_COUNT + (index-1)*NUM_OF_THERMAL_PER_PSU + 1); + info->hdr.coids[2] = ONLP_THERMAL_ID_CREATE(CHASSIS_THERMAL_COUNT + (index-1)*NUM_OF_THERMAL_PER_PSU + 2); + info->hdr.coids[3] = ONLP_THERMAL_ID_CREATE(CHASSIS_THERMAL_COUNT + (index-1)*NUM_OF_THERMAL_PER_PSU + 3); + if (val == PSU_STATUS_POWER_GOOD) { + info->status |= ONLP_PSU_STATUS_FAILED; + } + ret = ONLP_STATUS_OK; + break; + default: + ret = ONLP_STATUS_E_UNSUPPORTED; + break; + } + + return ret; +} diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/sfpi.c b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/sfpi.c new file mode 100644 index 0000000000..e603bda09c --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/sfpi.c @@ -0,0 +1,358 @@ +/************************************************************ + * + * + * 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_as4625_30p_int.h" +#include "x86_64_accton_as4625_30p_log.h" + +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" +#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/0-0064/module_present_%d" +#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/0-0064/module_rx_los_%d" +#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/0-0064/module_tx_fault_%d" +#define MODULE_TXDISABLE_FORMAT "/sys/bus/i2c/devices/0-0064/module_tx_disable_%d" +#define MODULE_RESET_FORMAT "/sys/bus/i2c/devices/0-0064/module_reset_%d" +#define MODULE_LPMODE_FORMAT "/sys/bus/i2c/devices/0-0064/module_lpmode_%d" +#define MODULE_PRESENT_ALL_ATTR "/sys/bus/i2c/devices/0-0064/module_present_all" +#define MODULE_RXLOS_ALL_ATTR "/sys/bus/i2c/devices/0-0064/module_rx_los_all" +/* QSFP device address of eeprom */ +#define PORT_EEPROM_DEVADDR 0x50 +/* QSFP tx disable offset */ +#define QSFP_EEPROM_OFFSET_TXDIS 0x56 + +int port_bus_index[] = { 10, 11, 12, 13, 14, 15 }; +#define PORT_BUS_INDEX(port) (port_bus_index[port-24]) + +#define VALIDATE_SFP(_port) \ + do { \ + if (_port < 24 || _port > 30) \ + return ONLP_STATUS_E_UNSUPPORTED; \ + } while(0) + + +/************************************************************ + * + * SFPI Entry Points + * + ***********************************************************/ +int +onlp_sfpi_init(void) +{ + /* Called at initialization time */ + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + /* + * Ports {24, 29} + */ + int p; + + for (p = 24; p < 30; p++) { + AIM_BITMAP_SET(bmap, p); + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_present(int port) +{ + /* + * Return 1 if present. + * Return 0 if not present. + * Return < 0 if error. + */ + int present; + VALIDATE_SFP(port); + + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, 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) +{ + uint32_t byte; + FILE* fp; + + /* Read present status of port 24 ~ 29 */ + int count = 0; + + fp = fopen(MODULE_PRESENT_ALL_ATTR, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_present_all device file"); + return ONLP_STATUS_E_INTERNAL; + } + + count = fscanf(fp, "%x", &byte); + fclose(fp); + + if(count != 1) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read the module_present_all device file"); + return ONLP_STATUS_E_INTERNAL; + } + + /* Mask out non-existant SFP ports */ + byte &= 0x3F; + + /* Convert to 64 bit integer in port order */ + int i = 0; + uint64_t presence_all = byte; + + /* Populate bitmap */ + presence_all <<= 24; + + for(i = 0; presence_all; i++) { + AIM_BITMAP_MOD(dst, i, (presence_all & 1)); + presence_all >>= 1; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + uint32_t byte; + FILE* fp; + + uint32_t byte1; + FILE* fp1; + + /* Read rxlos status of port 24 ~ 29 */ + int count = 0; + + /* Read present status of port 24 ~ 29 */ + int count1 = 0; + + fp = fopen(MODULE_RXLOS_ALL_ATTR, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_rx_los_all device file"); + return ONLP_STATUS_E_INTERNAL; + } + + count = fscanf(fp, "%x", &byte); + fclose(fp); + + if(count != 1) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read the module_rx_los_all device file"); + return ONLP_STATUS_E_INTERNAL; + } + + fp1 = fopen(MODULE_PRESENT_ALL_ATTR, "r"); + if(fp1 == NULL) { + AIM_LOG_ERROR("Unable to open the module_present_all device file"); + return ONLP_STATUS_E_INTERNAL; + } + + count1 = fscanf(fp1, "%x", &byte1); + fclose(fp1); + + if(count1 != 1) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read the module_present_all device file"); + return ONLP_STATUS_E_INTERNAL; + } + + /* Mask out non-existant SFP ports */ + byte &= 0x3F; + byte &= byte1; + + /* Convert to 64 bit integer in port order */ + AIM_BITMAP_CLR_ALL(dst); + int i = 0; + uint64_t rx_los_all = byte; + + /* Populate bitmap */ + rx_los_all <<= 24; + for(i = 0; rx_los_all; i++) { + AIM_BITMAP_MOD(dst, i, (rx_los_all & 1)); + rx_los_all >>= 1; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + /* + * Read the SFP eeprom into data[] + * + * Return MISSING if SFP is missing. + * Return OK if eeprom is read + */ + int size = 0; + VALIDATE_SFP(port); + + memset(data, 0, 256); + + if (onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, + PORT_BUS_INDEX(port)) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n" + , port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + FILE* fp; + char file[64] = {0}; + + if(port < 24) + return ONLP_STATUS_E_UNSUPPORTED; + sprintf(file, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port)); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)" + , port); + return ONLP_STATUS_E_INTERNAL; + } + + if (fseek(fp, 256, SEEK_CUR) != 0) { + fclose(fp); + AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)" + , port); + return ONLP_STATUS_E_INTERNAL; + } + + int ret = fread(data, 1, 256, fp); + fclose(fp); + if (ret != 256) { + AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)" + , port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) +{ + switch(control) { + case ONLP_SFP_CONTROL_TX_DISABLE:{ + if (port >= 24 && port <= 29) { + if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT + , (port+1)) < 0) { + AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n" + , port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; + } else { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_E_INTERNAL; + } + + default: + break; + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) +{ + + switch(control) { + case ONLP_SFP_CONTROL_RX_LOS: { + VALIDATE_SFP(port); + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, (port+1)) + < 0) { + AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n" + , port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; + } + + case ONLP_SFP_CONTROL_TX_FAULT: { + VALIDATE_SFP(port); + if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, (port+1)) + < 0) { + AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n" + , port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; + } + + case ONLP_SFP_CONTROL_TX_DISABLE: { + if (port >= 24 && port <= 29) + { + if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, + (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n" + , port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; + } else { + return ONLP_STATUS_E_INTERNAL; + } + + + return ONLP_STATUS_E_INTERNAL; + } + default: + break; + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/sysi.c b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/sysi.c new file mode 100644 index 0000000000..bbe92dd067 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/sysi.c @@ -0,0 +1,310 @@ +/************************************************************ + * + * + * 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 +#include +#include +#include +#include "platform_lib.h" +#include "x86_64_accton_as4625_30p_int.h" +#include "x86_64_accton_as4625_30p_log.h" + +#define BIOS_VER_PATH "/sys/devices/virtual/dmi/id/bios_version" +#define PREFIX_PATH_ON_CPLD_DEV "/sys/bus/i2c/devices/0-0064/" +#define REFERENCE_THERMAL_ID (ONLP_THERMAL_ID_CREATE(1 + 2)) /* MB_LeftFront_temp(0x4D) */ + +/* Fan speed levels corresponding to thermal conditions */ +enum { + LEVEL_FAN_0 = 0, + LEVEL_FAN_1, + LEVEL_FAN_2, + LEVEL_FAN_3, + LEVEL_FAN_4, + LEVEL_FAN_5, + LEVEL_FAN_6, + LEVEL_FAN_7, + LEVEL_FAN_8, + LEVEL_FAN_9, + LEVEL_FAN_MAX, + LEVEL_FAN_TOTAL +}; +#define LEVEL_FAN_DEF LEVEL_FAN_4 +#define LEVEL_FAN_SHUTDOWN LEVEL_FAN_MAX + +/* Fan control policy: maps temperature thresholds to fan duty and states */ +typedef struct fan_ctrl_policy { + int duty_cycle; + int temp_threshold_high; + int temp_threshold_low; +} fan_ctrl_policy_t; + +/* Fan control policy table */ +fan_ctrl_policy_t thermal_policy[] = { + [LEVEL_FAN_0] = {19, 23000, 20000}, + [LEVEL_FAN_1] = {32, 34000, 31000}, + [LEVEL_FAN_2] = {38, 40000, 37000}, + [LEVEL_FAN_3] = {44, 42000, 39000}, + [LEVEL_FAN_4] = {50, 44000, 41000}, + [LEVEL_FAN_5] = {57, 46000, 43000}, + [LEVEL_FAN_6] = {63, 50000, 47000}, + [LEVEL_FAN_7] = {69, 53000, 50000}, + [LEVEL_FAN_8] = {82, 55000, 52000}, + [LEVEL_FAN_9] = {94, 56000, 53000}, + [LEVEL_FAN_MAX] = {100, 57000, 54000}, +}; + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-accton-as4625-30p-r0"; +} + +int +onlp_sysi_onie_data_get(uint8_t** data, int* size) +{ + uint8_t* rdata = aim_zmalloc(256); + + if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) { + if(*size == 256) { + *data = rdata; + return ONLP_STATUS_OK; + } + } + + AIM_FREE_IF_PTR(rdata); + *size = 0; + return ONLP_STATUS_E_INTERNAL; +} + +void +onlp_sysi_onie_data_free(uint8_t* data) +{ + AIM_FREE_IF_PTR(data); +} + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + int i; + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + + /* 4 Thermal sensors on the chassis */ + for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* 6 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); + } + + /* 3 Fans on the chassis */ + for (i = 1; i <= CHASSIS_FAN_COUNT; i++) { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + return 0; +} + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + onlp_onie_info_t onie; + int ver_major = 0, ver_minor = 0; + char *bios_ver = NULL; + + if(onlp_file_read_str(&bios_ver, BIOS_VER_PATH) < 0) + return ONLP_STATUS_E_INTERNAL; + + if (onlp_onie_decode_file(&onie, IDPROM_PATH) < 0) + return ONLP_STATUS_E_INTERNAL; + + if(onlp_file_read_int(&ver_major, "%s/version_major", PREFIX_PATH_ON_CPLD_DEV) < 0) + return ONLP_STATUS_E_INTERNAL; + + if(onlp_file_read_int(&ver_minor, "%s/version_minor", PREFIX_PATH_ON_CPLD_DEV) < 0) + return ONLP_STATUS_E_INTERNAL; + + pi->cpld_versions = aim_fstrdup("\r\n\t CPU CPLD(0x64): %02X.%02X", + ver_major, ver_minor); + + pi->other_versions = aim_fstrdup("\r\n\t BIOS: %s\r\n\t ONIE: %s", + bios_ver, onie.onie_version); + + onlp_onie_info_free(&onie); + AIM_FREE_IF_PTR(bios_ver); + + return 0; +} + +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) +{ + AIM_FREE_IF_PTR(pi->cpld_versions); + AIM_FREE_IF_PTR(pi->other_versions); +} + +int onlp_sysi_platform_manage_fans(void) +{ + static int prev_warning = 0; + static int prev_sys_temp = 0; + static int prev_duty_cycle = 50; + int warning = 0; + int shutdown = 0; + int sys_temp = ONLP_STATUS_E_INVALID; + int fan_status_error = 0, temp_status_error = 0; + int fan_fail = 0; + onlp_thermal_info_t thermali[CHASSIS_THERMAL_COUNT-1]; + int i = 0; + int duty_cycle = 0; + + /* 1. refresh fan status */ + fan_fail = 0; + fan_status_error = 0; + for(i = 1; i <= CHASSIS_FAN_COUNT; i++){ + onlp_fan_info_t fan_info; + if (onlp_fani_info_get(ONLP_FAN_ID_CREATE(i), &fan_info) + != ONLP_STATUS_OK) { + AIM_LOG_WARN("Unable to get fan(%s) status.\r\n", fan_info.hdr.description); + fan_status_error = 1; + break; + } + + if (fan_info.status & ONLP_FAN_STATUS_FAILED || + !(fan_info.status & ONLP_FAN_STATUS_PRESENT)) { + AIM_LOG_WARN("Fan(%s) is not working\r\n", fan_info.hdr.description); + fan_fail = 1; + break; + } + } + + /* 2. refresh temperature status */ + temp_status_error = 0; + for(i = 0; i < CHASSIS_THERMAL_COUNT-1; i++){ + if (onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(i+2), &thermali[i]) + != ONLP_STATUS_OK) { + thermali[i].status = ONLP_STATUS_E_MISSING; + AIM_LOG_WARN("Unable to read thermal(%s) status.\n\r", thermali[i].hdr.description); + temp_status_error = 1; + } else { + /* MB_LeftFront_temp(0x4D) */ + if (REFERENCE_THERMAL_ID == thermali[i].hdr.id) { + sys_temp = thermali[i].mcelsius; + } + } + } + + if(fan_fail || fan_status_error || temp_status_error || sys_temp == ONLP_STATUS_E_INVALID){ + AIM_LOG_WARN("Error occurred while updating fan and thermal status\n\r"); + } else { + if(prev_sys_temp != sys_temp){ + if (prev_sys_temp < sys_temp) { /* Handle temperature rising scenario */ + AIM_LOG_INFO("Temperature RISING: prev_temp=%d, curr_temp=%d", prev_sys_temp, sys_temp); + for (i = 0; i < AIM_ARRAYSIZE(thermal_policy); i++) { + duty_cycle = thermal_policy[i].duty_cycle; + if (sys_temp <= thermal_policy[i].temp_threshold_high) { + break; + } + } + AIM_LOG_INFO("Temperature RISING: Final duty_cycle selected: %d", duty_cycle); + } else if (prev_sys_temp > sys_temp) { /* Handle temperature falling scenario */ + AIM_LOG_INFO("Temperature FALLING: prev_temp=%d, curr_temp=%d", prev_sys_temp, sys_temp); + for (i = AIM_ARRAYSIZE(thermal_policy) - 1; i >= 0; i--) { + duty_cycle = thermal_policy[i].duty_cycle; + if (sys_temp >= thermal_policy[i].temp_threshold_low) { + break; + } + } + AIM_LOG_INFO("Temperature FALLING: Final duty_cycle selected: %d", duty_cycle); + } + prev_sys_temp = sys_temp; + } else { + duty_cycle = prev_duty_cycle; + } + } + + /* 3. check temperature of each thermal sensor */ + for(i = 0; i < CHASSIS_THERMAL_COUNT-1; i++){ + if(thermali[i].status == ONLP_STATUS_E_MISSING) { + continue; + } + if(thermali[i].mcelsius >= thermali[i].thresholds.shutdown){ + warning = 1; + shutdown = 1; + AIM_LOG_WARN("thermal(%s) temperature(%d) reach shutdown threshold(%d)\n\r", + thermali[i].hdr.description, thermali[i].mcelsius, thermali[i].thresholds.shutdown); + } else if(thermali[i].mcelsius >= thermali[i].thresholds.error){ + warning = 1; + AIM_LOG_WARN("thermal(%s) temperature(%d) reach high threshold(%d)\n\r", + thermali[i].hdr.description, thermali[i].mcelsius, thermali[i].thresholds.error); + } + } + + /* 4. action */ + if(warning || shutdown || fan_fail || fan_status_error || temp_status_error || sys_temp == ONLP_STATUS_E_INVALID) { + duty_cycle = thermal_policy[LEVEL_FAN_MAX].duty_cycle; + } + if(prev_duty_cycle != duty_cycle) { + AIM_LOG_INFO("Fan duty cycle changed: %d -> %d", prev_duty_cycle, duty_cycle); + for(i = 1; i <= CHASSIS_FAN_COUNT; i++){ + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(i), duty_cycle); + } + prev_duty_cycle = duty_cycle; + } + + if(prev_warning != warning){ + if(warning) { + AIM_LOG_WARN("Alarm for temperature high is detected\n\r"); + } else { + AIM_LOG_INFO("Alarm for temperature high is cleared\n\r"); + } + prev_warning = warning; + } + + if(shutdown){ + AIM_LOG_WARN("Alarm-Critical for temperature critical is detected, disable PoE\n\r"); + AIM_SYSLOG_CRIT("Temperature critical", "Temperature critical", + "Alarm-Critical for temperature critical is detected, disable PoE\n\r"); + onlp_file_write_int(0, PREFIX_PATH_ON_CPLD_DEV"pwr_enable_poe"); + + AIM_LOG_WARN("Alarm-Critical for temperature critical is detected, trigger thermal shutdown\n\r"); + AIM_SYSLOG_CRIT("Temperature critical", "Temperature critical", + "Alarm-Critical for temperature critical is detected, trigger thermal shutdown\n\r"); + /* Sync log buffer to disk */ + system("sync;sync;sync"); + system("/sbin/fstrim -av"); + sleep(5); + onlp_file_write_int(1, PREFIX_PATH_ON_CPLD_DEV"thermal_shutdown"); + } + return 0; +} diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/thermali.c b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/thermali.c new file mode 100644 index 0000000000..ab8cbc37c6 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/thermali.c @@ -0,0 +1,259 @@ +/************************************************************ + * + * + * 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 +#include "platform_lib.h" +#include +#include + +#define CPU_CORETEMP_PATH "/sys/devices/platform/coretemp.0/hwmon/hwmon*/temp*_input" +#define CPU_TEMP_SCAN_MAX_FILES 64 /* Maximum number of temperature input files to scan */ +#define CPU_TEMP_PATH_MAX_LEN 256 /* Maximum temperature file path length */ + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +/* + * Structure to store temperature sensor file information + */ +typedef struct { + char path[CPU_TEMP_PATH_MAX_LEN]; /* Full path of the temperature file */ + int index; /* Index number extracted from the filename */ +} temp_entry; + +size_t get_temp_from_glob_pattern(const char *pattern, temp_entry *result, size_t max_results); + +enum onlp_thermal_id { + THERMAL_RESERVED = 0, + THERMAL_CPU_CORE, + THERMAL_1_ON_MAIN_BROAD, + THERMAL_3_ON_MAIN_BROAD, + THERMAL_5_ON_MAIN_BROAD, + THERMAL_1_ON_PSU1, + THERMAL_2_ON_PSU1, + THERMAL_3_ON_PSU1, + THERMAL_1_ON_PSU2, + THERMAL_2_ON_PSU2, + THERMAL_3_ON_PSU2, +}; + +static char* devfiles__[] = { /* must map with onlp_thermal_id */ + NULL, + NULL, /* CPU_CORE files */ + "/sys/bus/i2c/devices/3-004a*temp1_input", + "/sys/bus/i2c/devices/3-004d*temp1_input", + "/sys/bus/i2c/devices/3-004f*temp1_input", + "/sys/bus/i2c/devices/8-0058*psu_temp1_input", + "/sys/bus/i2c/devices/8-0058*psu_temp2_input", + "/sys/bus/i2c/devices/8-0058*psu_temp3_input", + "/sys/bus/i2c/devices/9-0059*psu_temp1_input", + "/sys/bus/i2c/devices/9-0059*psu_temp2_input", + "/sys/bus/i2c/devices/9-0059*psu_temp3_input" +}; + +/* Static values */ +static onlp_thermal_info_t linfo[] = { + { }, /* Not used */ + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE), "CPU Core", 0, {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 66000, 69000, 71000 } + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "MB_RightRear_temp(0x4A)", 0, {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 62000, 64000, 65000 } + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "MB_LeftFront_temp(0x4D)", 0, {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 59000, 61000, 62000 } + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_5_ON_MAIN_BROAD), "MB_RightFront_temp(0x4F)", 0, {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 62000, 64000, 65000 } + }, + { { 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, { 61000, 61000, 72000 } + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU1), "PSU-1 Thermal Sensor 2", ONLP_PSU_ID_CREATE(PSU1_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 65000, 65000, 79000 } + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_PSU1), "PSU-1 Thermal Sensor 3", ONLP_PSU_ID_CREATE(PSU1_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 65000, 65000, 99000 } + }, + { { 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, { 61000, 61000, 72000 } + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU2), "PSU-2 Thermal Sensor 2", ONLP_PSU_ID_CREATE(PSU2_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 65000, 65000, 79000 } + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_PSU2), "PSU-2 Thermal Sensor 3", ONLP_PSU_ID_CREATE(PSU2_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 65000, 65000, 99000 } + } +}; + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + return ONLP_STATUS_OK; +} + +int get_max_cpu_coretemp(int *max_cpu_coretemp) +{ + int cpu_coretemp = 0; + int i = 0; + size_t count; + temp_entry temp_entries[CPU_TEMP_SCAN_MAX_FILES] = {0}; + + *max_cpu_coretemp = 0; + count = get_temp_from_glob_pattern(CPU_CORETEMP_PATH, temp_entries, AIM_ARRAYSIZE(temp_entries)); + if (count == 0) { + AIM_LOG_ERROR("No CPU core temperature sensors found\n"); + return ONLP_STATUS_E_INTERNAL; + } + + for(i = 0; i < count; i++){ + if(onlp_file_read_int(&cpu_coretemp, temp_entries[i].path) < 0) { + AIM_LOG_ERROR("Unable to read cpu coretemp from %s\r\n", temp_entries[i].path); + return ONLP_STATUS_E_INTERNAL; + } + + if(cpu_coretemp > *max_cpu_coretemp) { + *max_cpu_coretemp = cpu_coretemp; + } + } + + 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; + int psu_id; + psu_type_t psu_type; + VALIDATE(id); + + tid = ONLP_OID_ID_GET(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[tid]; + + if ((tid >= THERMAL_1_ON_PSU1) && (tid <= THERMAL_3_ON_PSU2)) { + psu_id = ((tid - THERMAL_1_ON_PSU1) / NUM_OF_THERMAL_PER_PSU) + 1; + + /* Get PSU type */ + psu_type = get_psu_type(psu_id, NULL, 0); + if (psu_type == PSU_TYPE_UNKNOWN) { + /* For display all PSU information that includes the fan and + * temperature, even access hardware fail. + */ + info->status |= ONLP_THERMAL_STATUS_FAILED; + return ONLP_STATUS_OK; + } + } + + if (tid == THERMAL_CPU_CORE) { + return get_max_cpu_coretemp(&info->mcelsius); + } + + return onlp_file_read_int(&info->mcelsius, devfiles__[tid]); +} + +/** + * Finds temperature sensor files matching a glob pattern and sorts them by index + * + * This function uses glob pattern matching to find temperature sensor files in the + * file system, extracts the index number from each filename, and sorts the results + * by this index for consistent processing order. + * + * @param pattern The glob pattern to match sensor files (e.g. "/sys/class/hwmon/hwmon[*]/temp[*]_input") + * @param result Pre-allocated array to store the matched file entries + * @param max_results Maximum number of results to store in the result array + * @return Number of temperature files found and stored in the result array, 0 on error + */ +size_t get_temp_from_glob_pattern(const char *pattern, temp_entry *result, size_t max_results) { + glob_t glob_result; + size_t i, count = 0; + int index; + + if (!pattern || !result || max_results == 0) { + return 0; + } + + /* Perform glob pattern matching with GLOB_NOSORT for better performance */ + if (glob(pattern, GLOB_NOSORT, NULL, &glob_result) != 0) { + AIM_LOG_ERROR("Failed to find files matching pattern: %s\n", pattern); + return 0; + } + + /* Process each matched file and extract temperature indices */ + for (i = 0; i < glob_result.gl_pathc && count < max_results; i++) { + char path_buf[CPU_TEMP_PATH_MAX_LEN], *filename; + const char *full_path = glob_result.gl_pathv[i]; + + if (strlen(glob_result.gl_pathv[i]) >= CPU_TEMP_PATH_MAX_LEN) { + AIM_LOG_ERROR("Path too long (max %d chars): %s\n", + CPU_TEMP_PATH_MAX_LEN - 1, full_path); + continue; + } + + snprintf(path_buf, sizeof(path_buf), "%s", full_path); + filename = basename(path_buf); + if (filename && sscanf(filename, "temp%d_input", &index) == 1) { + snprintf(result[count].path, sizeof(result[count].path), "%s", full_path); + result[count].index = index; + count++; + } + } + + /* Free glob resources */ + globfree(&glob_result); + + return count; +} diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_config.c b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_config.c new file mode 100644 index 0000000000..030df40191 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_config.c @@ -0,0 +1,80 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_accton_as4625_30p_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_accton_as4625_30p_config_STRINGIFY_VALUE(_x) __x86_64_accton_as4625_30p_config_STRINGIFY_NAME(_x) +x86_64_accton_as4625_30p_config_settings_t x86_64_accton_as4625_30p_config_settings[] = +{ +#ifdef X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_LOGGING + { __x86_64_accton_as4625_30p_config_STRINGIFY_NAME(X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_LOGGING), __x86_64_accton_as4625_30p_config_STRINGIFY_VALUE(X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_LOGGING) }, +#else +{ X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_LOGGING(__x86_64_accton_as4625_30p_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS4625_30P_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_accton_as4625_30p_config_STRINGIFY_NAME(X86_64_ACCTON_AS4625_30P_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_accton_as4625_30p_config_STRINGIFY_VALUE(X86_64_ACCTON_AS4625_30P_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS4625_30P_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_accton_as4625_30p_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS4625_30P_CONFIG_LOG_BITS_DEFAULT + { __x86_64_accton_as4625_30p_config_STRINGIFY_NAME(X86_64_ACCTON_AS4625_30P_CONFIG_LOG_BITS_DEFAULT), __x86_64_accton_as4625_30p_config_STRINGIFY_VALUE(X86_64_ACCTON_AS4625_30P_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS4625_30P_CONFIG_LOG_BITS_DEFAULT(__x86_64_accton_as4625_30p_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS4625_30P_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_accton_as4625_30p_config_STRINGIFY_NAME(X86_64_ACCTON_AS4625_30P_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_accton_as4625_30p_config_STRINGIFY_VALUE(X86_64_ACCTON_AS4625_30P_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS4625_30P_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_accton_as4625_30p_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_STDLIB + { __x86_64_accton_as4625_30p_config_STRINGIFY_NAME(X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_STDLIB), __x86_64_accton_as4625_30p_config_STRINGIFY_VALUE(X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_STDLIB) }, +#else +{ X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_STDLIB(__x86_64_accton_as4625_30p_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_accton_as4625_30p_config_STRINGIFY_NAME(X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_accton_as4625_30p_config_STRINGIFY_VALUE(X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ X86_64_ACCTON_AS4625_30P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_accton_as4625_30p_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_UCLI + { __x86_64_accton_as4625_30p_config_STRINGIFY_NAME(X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_UCLI), __x86_64_accton_as4625_30p_config_STRINGIFY_VALUE(X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_UCLI) }, +#else +{ X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_UCLI(__x86_64_accton_as4625_30p_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_accton_as4625_30p_config_STRINGIFY_NAME(X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_accton_as4625_30p_config_STRINGIFY_VALUE(X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ X86_64_ACCTON_AS4625_30P_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_accton_as4625_30p_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_accton_as4625_30p_config_STRINGIFY_VALUE +#undef __x86_64_accton_as4625_30p_config_STRINGIFY_NAME + +const char* +x86_64_accton_as4625_30p_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_accton_as4625_30p_config_settings[i].name; i++) { + if(!strcmp(x86_64_accton_as4625_30p_config_settings[i].name, setting)) { + return x86_64_accton_as4625_30p_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_accton_as4625_30p_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_accton_as4625_30p_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_accton_as4625_30p_config_settings[i].name, x86_64_accton_as4625_30p_config_settings[i].value); + } + return i; +} + +/* */ diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_enums.c b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_enums.c new file mode 100644 index 0000000000..d7426dd4ae --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_int.h b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_int.h new file mode 100644 index 0000000000..ec0bd715a5 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_accton_as4625_30p Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_accton_as4625_30p_INT_H__ +#define __x86_64_accton_as4625_30p_INT_H__ + +#include + + +#endif /* __x86_64_accton_as4625_30p_INT_H__ */ diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_log.c b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_log.c new file mode 100644 index 0000000000..cb4dbd4b6b --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_as4625_30p_log.h" +/* + * x86_64_accton_as4625_30p log struct. + */ +AIM_LOG_STRUCT_DEFINE( + X86_64_ACCTON_AS4625_30P_CONFIG_LOG_OPTIONS_DEFAULT, + X86_64_ACCTON_AS4625_30P_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + X86_64_ACCTON_AS4625_30P_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_log.h b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_log.h new file mode 100644 index 0000000000..acd11f4f88 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_accton_as4625_30p_LOG_H__ +#define __x86_64_accton_as4625_30p_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_accton_as4625_30p +#include + +#endif /* __x86_64_accton_as4625_30p_LOG_H__ */ diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_module.c b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_module.c new file mode 100644 index 0000000000..12b4c58aed --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_as4625_30p_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_accton_as4625_30p_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_as4625_30p_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_ucli.c b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_ucli.c new file mode 100644 index 0000000000..d1ec4401cd --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/onlp/builds/x86_64_accton_as4625_30p/module/src/x86_64_accton_as4625_30p_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if x86_64_accton_as4625_30p_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_accton_as4625_30p_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_accton_as4625_30p) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_accton_as4625_30p_ucli_module__ = + { + "x86_64_accton_as4625_30p_ucli", + NULL, + x86_64_accton_as4625_30p_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_accton_as4625_30p_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_accton_as4625_30p_ucli_module__); + n = ucli_node_create("x86_64_accton_as4625_30p", NULL, &x86_64_accton_as4625_30p_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_accton_as4625_30p")); + return n; +} + +#else +void* +x86_64_accton_as4625_30p_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/accton/x86-64/as4625-30p/platform-config/Makefile b/packages/platforms/accton/x86-64/as4625-30p/platform-config/Makefile new file mode 100644 index 0000000000..502e772a7b --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/accton/x86-64/as4625-30p/platform-config/r0/Makefile b/packages/platforms/accton/x86-64/as4625-30p/platform-config/r0/Makefile new file mode 100644 index 0000000000..502e772a7b --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/accton/x86-64/as4625-30p/platform-config/r0/PKG.yml b/packages/platforms/accton/x86-64/as4625-30p/platform-config/r0/PKG.yml new file mode 100644 index 0000000000..be2a4f7e69 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=accton BASENAME=x86-64-accton-as4625-30p REVISION=r0 diff --git a/packages/platforms/accton/x86-64/as4625-30p/platform-config/r0/src/lib/x86-64-accton-as4625-30p-r0.yml b/packages/platforms/accton/x86-64/as4625-30p/platform-config/r0/src/lib/x86-64-accton-as4625-30p-r0.yml new file mode 100644 index 0000000000..5f7b10c38a --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/platform-config/r0/src/lib/x86-64-accton-as4625-30p-r0.yml @@ -0,0 +1,30 @@ +--- + +###################################################################### +# +# platform-config for AS4625 +# +###################################################################### + +x86-64-accton-as4625-30p-r0: + + grub: + + serial: >- + --port=0x3f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-5-4 + + args: >- + console=ttyS0,115200n8 + intel_iommu=off + + network: + interfaces: + ma1: + name: eth0 diff --git a/packages/platforms/accton/x86-64/as4625-30p/platform-config/r0/src/python/x86_64_accton_as4625_30p_r0/__init__.py b/packages/platforms/accton/x86-64/as4625-30p/platform-config/r0/src/python/x86_64_accton_as4625_30p_r0/__init__.py new file mode 100644 index 0000000000..0292ecdeb0 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-30p/platform-config/r0/src/python/x86_64_accton_as4625_30p_r0/__init__.py @@ -0,0 +1,59 @@ +from onl.platform.base import * +from onl.platform.accton import * + +class OnlPlatform_x86_64_accton_as4625_30p_r0(OnlPlatformAccton, + OnlPlatformPortConfig_24x1_6x10): + + PLATFORM='x86-64-accton-as4625-30p-r0' + MODEL="AS4625-30P" + SYS_OBJECT_ID=".4625.30.1" + + def baseconfig(self): + os.system("modprobe i2c-ismt") + os.system("modprobe at24") + self.insmod('optoe') + self.insmod('ym2651y') + + for m in [ 'cpld', 'fan', 'leds', 'psu' ]: + self.insmod("x86-64-accton-as4625-30p-%s.ko" % m) + + ########### initialize I2C bus 0, bus 1 ########### + self.new_i2c_devices([ + + #initiate CPLD + ('as4625_cpld1', 0x64, 0), + + # initialize multiplexer (PCA9548) + ('pca9548', 0x70, 1), + ('pca9548', 0x71, 1) + ]) + + self.new_i2c_devices([ + # inititate LM75 + ('lm75', 0x4a, 3), + ('lm75', 0x4d, 3), + ('lm75', 0x4f, 3) + ]) + + self.new_i2c_devices([ + # initiate PSU-1 + ('as4625_30p_psu1', 0x50, 8), + ('ym2651', 0x58, 8), + # initiate PSU-2 + ('as4625_30p_psu2', 0x51, 9), + ('ym2651', 0x59, 9), + ]) + + # initialize pca9548 idle_state in kernel 5.4.40 version + subprocess.call('echo -2 | tee /sys/bus/i2c/drivers/pca954x/*-00*/idle_state > /dev/null', shell=True) + + # initialize SFP port 25~30 + for port in range(25, 31): + self.new_i2c_device('optoe2', 0x50, port-15) + subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port-15), shell=True) + + # initialize the LOC led to off + subprocess.call('echo 0 > /sys/class/leds/as4625_led::loc/brightness', shell=True) + + self.new_i2c_device('24c02', 0x51, 7) + return True