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..0a88b5a5a2 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 @@ -644,9 +644,15 @@ class OnlPlatformPortConfig_2x400_8x100_64x25(object): class OnlPlatformPortConfig_48x1_8x10(object): PORT_COUNT=56 PORT_CONFIG="48x1 + 8x10" + class OnlPlatformPortConfig_40x100_13x400_2x10(object): PORT_COUNT=55 PORT_CONFIG="40x100 + 13x400 + 2x10" + class OnlPlatformPortConfig_64x800_2x25(object): PORT_COUNT=66 PORT_CONFIG="64x800 + 2x25" + +class OnlPlatformPortConfig_4x100_20x25(object): + PORT_COUNT=24 + PORT_CONFIG="4x100 + 20x25" diff --git a/packages/base/any/kernels/5.4-lts/configs/x86_64-all/x86_64-all.config b/packages/base/any/kernels/5.4-lts/configs/x86_64-all/x86_64-all.config index 08480880c6..076d2cf00a 100644 --- a/packages/base/any/kernels/5.4-lts/configs/x86_64-all/x86_64-all.config +++ b/packages/base/any/kernels/5.4-lts/configs/x86_64-all/x86_64-all.config @@ -2764,7 +2764,7 @@ CONFIG_SENSORS_UCD9000=y # CONFIG_SENSORS_TMP102 is not set # CONFIG_SENSORS_TMP103 is not set # CONFIG_SENSORS_TMP108 is not set -# CONFIG_SENSORS_TMP401 is not set +CONFIG_SENSORS_TMP401=y # CONFIG_SENSORS_TMP421 is not set # CONFIG_SENSORS_VIA_CPUTEMP is not set # CONFIG_SENSORS_VIA686A is not set diff --git a/packages/platforms/accton/x86-64/as7515-24x/.gitignore b/packages/platforms/accton/x86-64/as7515-24x/.gitignore new file mode 100644 index 0000000000..9a3f9e2082 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/.gitignore @@ -0,0 +1,2 @@ +*x86*64*accton*as7515*24x*.mk +onlpdump.mk diff --git a/packages/platforms/accton/x86-64/as7515-24x/Makefile b/packages/platforms/accton/x86-64/as7515-24x/Makefile new file mode 100644 index 0000000000..dc1e7b86f0 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/accton/x86-64/as7515-24x/modules/Makefile b/packages/platforms/accton/x86-64/as7515-24x/modules/Makefile new file mode 100644 index 0000000000..dc1e7b86f0 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/accton/x86-64/as7515-24x/modules/PKG.yml b/packages/platforms/accton/x86-64/as7515-24x/modules/PKG.yml new file mode 100644 index 0000000000..cfd6bc6042 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=accton BASENAME=x86-64-accton-as7515-24x ARCH=amd64 KERNELS="onl-kernel-5.4-lts-x86-64-all:amd64" diff --git a/packages/platforms/accton/x86-64/as7515-24x/modules/builds/.gitignore b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/.gitignore new file mode 100644 index 0000000000..a65b41774a --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/accton/x86-64/as7515-24x/modules/builds/Makefile b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/Makefile new file mode 100644 index 0000000000..7a1d8d762c --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-5.4-lts-x86-64-all:amd64 +KMODULES := src +VENDOR := accton +BASENAME := x86-64-accton-as7515-24x +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/Makefile b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/Makefile new file mode 100644 index 0000000000..12ae5de943 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/Makefile @@ -0,0 +1,7 @@ +obj-m += x86-64-accton-as7515-24x-fpga.o +obj-m += x86-64-accton-as7515-24x-cpld.o +obj-m += x86-64-accton-as7515-24x-fan.o +obj-m += x86-64-accton-as7515-24x-leds.o +obj-m += x86-64-accton-as7515-24x-mux.o +obj-m += x86-64-accton-as7515-24x-psu.o +obj-m += x86-64-accton-as7515-24x-sfp.o diff --git a/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-cpld.c b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-cpld.c new file mode 100644 index 0000000000..9886195058 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-cpld.c @@ -0,0 +1,540 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/* + * Copyright (C) 2024 Accton Technology Corporation. + * Brandon Chuang + * + * This module provides support for accessing the Accton CPLD and + * retrieving the status of QSFP-DD/SFP port. + * This includes the: + * Accton as7515_24x FPGA/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 +#include + +#define DRVNAME "as7515_24x_cpld" + +#define I2C_RW_RETRY_COUNT (10) +#define I2C_RW_RETRY_INTERVAL (60) /* ms */ + +/* FPGA */ +#define FPGA_BOARD_INFO_REG (0x00) +#define FPGA_MAJOR_VER_REG (0x01) +#define FPGA_MINOR_VER_REG (0x02) + +/* CPLD */ +#define CPLD_MAJOR_VER_REG (0x01) +#define CPLD_MINOR_VER_REG (0x02) + +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 { + as7515_24x_fpga, + as7515_24x_cpld +}; + +struct as7515_24x_cpld_data { + u8 reg; + enum cpld_type type; + struct mutex update_lock; + struct platform_device *led_pdev; + struct platform_device *sfp_pdev; +}; + +static const struct i2c_device_id as7515_24x_cpld_id[] = { + {"as7515_24x_fpga", as7515_24x_fpga}, + {"as7515_24x_cpld", as7515_24x_cpld}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, as7515_24x_cpld_id); + +enum as7515_24x_cpld_sysfs_attributes { + BOARD_INFO, + VERSION, + ACCESS +}; + +/* sysfs attributes for hwmon */ +static ssize_t show(struct device *dev, struct device_attribute *da, char *buf); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t reg_read(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t reg_write(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static int __as7515_24x_cpld_read(struct i2c_client *client, u8 reg); +static int __as7515_24x_cpld_write(struct i2c_client *client, u8 reg, + u8 value); + +/* declare transceiver attributes callback function */ +static SENSOR_DEVICE_ATTR(board_info, S_IRUGO, show, NULL, BOARD_INFO); +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, VERSION); +static SENSOR_DEVICE_ATTR(access, S_IRUGO | S_IWUSR, reg_read, reg_write, + ACCESS); + +static struct attribute *as7515_24x_fpga_attributes[] = { + &sensor_dev_attr_board_info.dev_attr.attr, + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static struct attribute *as7515_24x_cpld_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + NULL +}; + +static const struct attribute_group as7515_24x_fpga_group = { + .attrs = as7515_24x_fpga_attributes, +}; + +static const struct attribute_group as7515_24x_cpld_group = { + .attrs = as7515_24x_cpld_attributes, +}; + +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7515_24x_cpld_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int reg_major = 0, reg_minor = 0; + int major, minor; + + switch (attr->index) { + case VERSION: + switch (data->type) { + case as7515_24x_fpga: + reg_major = FPGA_MAJOR_VER_REG; + reg_minor = FPGA_MINOR_VER_REG; + break; + case as7515_24x_cpld: + reg_major = CPLD_MAJOR_VER_REG; + reg_minor = CPLD_MINOR_VER_REG; + break; + default: + break; + } + break; + default: + break; + } + + major = i2c_smbus_read_byte_data(client, reg_major); + if (major < 0) { + dev_dbg(&client->dev, "cpld(0x%02x) reg(0x%02x) err %d\n", + client->addr, reg_major, major); + return major; + } + + minor = i2c_smbus_read_byte_data(client, reg_minor); + if (minor < 0) { + dev_dbg(&client->dev, "cpld(0x%02x) reg(0x%02x) err %d\n", + client->addr, reg_minor, minor); + return minor; + } + + return sprintf(buf, "%d.%d\n", major, minor); +} + +static ssize_t show(struct device *dev, struct device_attribute *da, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int val = 0; + u8 reg = 0; + u8 mask = 0; + u8 invert = 0; + u8 bits_shift = 0; + + switch (attr->index) { + case BOARD_INFO: + reg = FPGA_BOARD_INFO_REG; + mask = 0x03; + break; + default: + break; + } + + val = i2c_smbus_read_byte_data(client, reg); + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%02x) reg(0x%02x) err %d\n", + client->addr, reg, val); + return -EIO; + } + + val = (val >> bits_shift) & mask; + return sprintf(buf, "%d\n", invert ? !(val) : (val)); +} + +static ssize_t reg_read(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7515_24x_cpld_data *data = i2c_get_clientdata(client); + int reg_val, status = 0; + + mutex_lock(&data->update_lock); + reg_val = __as7515_24x_cpld_read(client, data->reg); + if (unlikely(reg_val < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + status = sprintf(buf, "0x%02x\n", reg_val); + + exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t reg_write(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7515_24x_cpld_data *data = i2c_get_clientdata(client); + int args, status; + char *opt, tmp[32] = { 0 }; + char *tmp_p; + size_t copy_size; + u8 input[2] = { 0 }; + + copy_size = (count < sizeof(tmp)) ? count : sizeof(tmp) - 1; +#ifdef __STDC_LIB_EXT1__ + memcpy_s(tmp, copy_size, buf, copy_size); +#else + memcpy(tmp, buf, copy_size); +#endif + tmp[copy_size] = '\0'; + + args = 0; + tmp_p = tmp; + while (args < 2 && (opt = strsep(&tmp_p, " ")) != NULL) { + if (kstrtou8(opt, 16, &input[args]) == 0) { + args++; + } + } + + switch (args) { + case 2: + /* Write value to register */ + mutex_lock(&data->update_lock); + status = __as7515_24x_cpld_write(client, input[0], input[1]); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + break; + case 1: + /* Read value from register */ + data->reg = input[0]; + break; + default: + return -EINVAL; + } + + return count; + + exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as7515_24x_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 as7515_24x_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); +} + +/* + * I2C init/probing/exit functions + */ +static int as7515_24x_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as7515_24x_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 as7515_24x_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 as7515_24x_fpga: + group = &as7515_24x_fpga_group; + break; + case as7515_24x_cpld: + group = &as7515_24x_cpld_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) { + goto exit_free; + } + } + + as7515_24x_cpld_add_client(client); + + if (data->type == as7515_24x_fpga) { + data->led_pdev = platform_device_register_simple("as7515_24x_led", -1, NULL, 0); + if (IS_ERR(data->led_pdev)) { + ret = PTR_ERR(data->led_pdev); + goto exit_remove_client; + } + } + + if (data->type == as7515_24x_cpld) { + data->sfp_pdev = platform_device_register_simple("as7515_24x_sfp", -1, NULL, 0); + if (IS_ERR(data->sfp_pdev)) { + ret = PTR_ERR(data->sfp_pdev); + goto exit_remove_client; + } + } + + return 0; + +exit_remove_client: + as7515_24x_cpld_remove_client(client); + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + exit_free: + kfree(data); + exit: + return ret; +} + +static int as7515_24x_cpld_remove(struct i2c_client *client) +{ + struct as7515_24x_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + if (data->led_pdev) + platform_device_unregister(data->led_pdev); + + if (data->sfp_pdev) + platform_device_unregister(data->sfp_pdev); + + as7515_24x_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as7515_24x_fpga: + group = &as7515_24x_fpga_group; + break; + case as7515_24x_cpld: + group = &as7515_24x_cpld_group; + break; + default: + break; + } + + if (group) { + sysfs_remove_group(&client->dev.kobj, group); + } + + kfree(data); + + return 0; +} + +static int __as7515_24x_cpld_read(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 __as7515_24x_cpld_write(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 as7515_24x_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 = __as7515_24x_cpld_read(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} + +EXPORT_SYMBOL(as7515_24x_cpld_read); + +int as7515_24x_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 = __as7515_24x_cpld_write(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as7515_24x_cpld_write); + +static struct i2c_driver as7515_24x_cpld_driver = { + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, + .probe = as7515_24x_cpld_probe, + .remove = as7515_24x_cpld_remove, + .id_table = as7515_24x_cpld_id, +}; + +static int __init as7515_24x_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as7515_24x_cpld_driver); +} + +static void __exit as7515_24x_cpld_exit(void) +{ + i2c_del_driver(&as7515_24x_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("AS7515-24X CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as7515_24x_cpld_init); +module_exit(as7515_24x_cpld_exit); diff --git a/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-fan.c b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-fan.c new file mode 100644 index 0000000000..f5bc2181c3 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-fan.c @@ -0,0 +1,691 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/* + * A hwmon driver for the Accton as7515 24x fan + * + * Copyright (C) 2024 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7515_24x_fan" + +#define BOARD_INFO_REG_OFFSET 0x00 +#define FAN_STATUS_I2C_ADDR 0x40 +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 + +#define FAN_NUM 5 +#define MAX_FAN_INPUT 23000 +#define FAN_DUTY_CYCLE_REG_MASK 0x3F +#define FAN_MAX_PWM 100 + +static struct as7515_24x_fan_data *as7515_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t fan_set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t fan_set_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_wdt(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_wdt(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static int _reset_wdt(struct as7515_24x_fan_data *data); +static ssize_t reset_wdt(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x01, /* fan board version */ + 0x02, /* fan board sub version */ + 0x10, /* fan enable */ + 0x21, /* fan1 PWM */ + 0x31, /* fan2 PWM */ + 0x41, /* fan3 PWM */ + 0x51, /* fan4 PWM */ + 0x61, /* fan5 PWM */ + 0x20, /* fan 1 tach speed */ + 0x30, /* fan 2 tach speed */ + 0x40, /* fan 3 tach speed */ + 0x50, /* fan 4 tach speed */ + 0x60, /* fan 5 tach speed */ + 0x22, /* fan 1 present/fault */ + 0x32, /* fan 2 present/fault */ + 0x42, /* fan 3 present/fault */ + 0x52, /* fan 4 present/fault */ + 0x62, /* fan 5 present/fault */ + 0x0D, /* fan tech speed setting */ +}; + +/* fan data */ +struct as7515_24x_fan_data { + struct i2c_client *client; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ +}; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID, + FAN4_ID, + FAN5_ID +}; + +enum sysfs_fan_attributes { + FAN_MAJOR_VERSION_REG, + FAN_MINOR_VERSION_REG, + FAN_ENABLE_REG, + FAN1_PWM, + FAN2_PWM, + FAN3_PWM, + FAN4_PWM, + FAN5_PWM, + FAN1_INPUT, + FAN2_INPUT, + FAN3_INPUT, + FAN4_INPUT, + FAN5_INPUT, + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN_TECH_SETTING, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN1_ENABLE, + FAN2_ENABLE, + FAN3_ENABLE, + FAN4_ENABLE, + FAN5_ENABLE, + FAN1_TARGET, + FAN2_TARGET, + FAN3_TARGET, + FAN4_TARGET, + FAN5_TARGET, + FAN_MAX_RPM, + WDT_CLOCK, + WDT_COUNTER, + WDT_ENABLE, + WDT_RESET, + FAN_FW_VERSION +}; + +static const int fan_target_speed[64] = { + 0, 0, 0, 0, 0, 2324, 3218, 5007, /* 0x00 ~ 0x07 */ + 5364, 6080, 6795, 7331, 8226, 8762, 9298, 9477, /* 0x08 ~ 0x0F */ + 10014, 10371, 11087, 11444, 11623, 12160, 12339, 12875, /* 0x10 ~ 0x17 */ + 13054, 13412, 13769, 14127, 14484, 14842, 15200, 15379, /* 0x18 ~ 0x1F */ + 15915, 16273, 16630, 16988, 17346, 17525, 17882, 18061, /* 0x20 ~ 0x27 */ + 18240, 18776, 18955, 19313, 19670, 19670, 19849, 20028, /* 0x28 ~ 0x2F */ + 20386, 20565, 20743, 20922, 21101, 21280, 21638, 21816, /* 0x30 ~ 0x37 */ + 21995, 22174, 22353, 22532, 22711, 22889, 22889, 23000, /* 0x38 ~ 0x3F */ +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(version, S_IRUGO, fan_show_value, NULL, + FAN_FW_VERSION); +static SENSOR_DEVICE_ATTR(fan_input_max, S_IRUGO, fan_show_value, NULL, + FAN_MAX_RPM); + +/* Fan watchdog */ +static SENSOR_DEVICE_ATTR(wdt_clock, S_IRUGO | S_IWUSR, show_wdt, set_wdt, + WDT_CLOCK); +static SENSOR_DEVICE_ATTR(wdt_counter, S_IRUGO | S_IWUSR, show_wdt, set_wdt, + WDT_COUNTER); +static SENSOR_DEVICE_ATTR(wdt_enable, S_IRUGO | S_IWUSR, show_wdt, set_wdt, + WDT_ENABLE); +static SENSOR_DEVICE_ATTR(wdt_reset, S_IWUSR, NULL, reset_wdt, WDT_RESET); + +static struct attribute *fan_attributes_common[] = { + &sensor_dev_attr_version.dev_attr.attr, + &sensor_dev_attr_fan_input_max.dev_attr.attr, + &sensor_dev_attr_wdt_clock.dev_attr.attr, + &sensor_dev_attr_wdt_counter.dev_attr.attr, + &sensor_dev_attr_wdt_enable.dev_attr.attr, + &sensor_dev_attr_wdt_reset.dev_attr.attr, + NULL +}; + +#define FAN_ATTRS_COMMON() \ +static const struct attribute_group fan_attrgroup_common = { \ + .attrs = fan_attributes_common, \ +}; + +#define FAN_ATTRS(fid) \ + static SENSOR_DEVICE_ATTR(fan##fid##_present, S_IRUGO, fan_show_value, \ + NULL, FAN##fid##_PRESENT); \ + static SENSOR_DEVICE_ATTR(fan##fid##_pwm, S_IWUSR | S_IRUGO, \ + fan_show_value, fan_set_pwm, FAN##fid##_PWM); \ + static SENSOR_DEVICE_ATTR(fan##fid##_input, S_IRUGO, fan_show_value, \ + NULL, FAN##fid##_INPUT); \ + static SENSOR_DEVICE_ATTR(fan##fid##_target, S_IRUGO, fan_show_value, \ + NULL, FAN##fid##_TARGET); \ + static SENSOR_DEVICE_ATTR(fan##fid##_fault, S_IRUGO, fan_show_value, \ + NULL, FAN##fid##_FAULT); \ + static SENSOR_DEVICE_ATTR(fan##fid##_enable, S_IWUSR | S_IRUGO, \ + fan_show_value, fan_set_enable, FAN##fid##_ENABLE); \ + static struct attribute *fan_attributes##fid[] = { \ + &sensor_dev_attr_fan##fid##_present.dev_attr.attr, \ + &sensor_dev_attr_fan##fid##_pwm.dev_attr.attr, \ + &sensor_dev_attr_fan##fid##_input.dev_attr.attr, \ + &sensor_dev_attr_fan##fid##_target.dev_attr.attr, \ + &sensor_dev_attr_fan##fid##_fault.dev_attr.attr, \ + &sensor_dev_attr_fan##fid##_enable.dev_attr.attr, \ + NULL \ +} + +#define FAN_ATTR_GROUP(fid) \ + FAN_ATTRS(fid); \ +static const struct attribute_group fan_attrgroup_##fid = { \ + .attrs = fan_attributes##fid \ +} + +FAN_ATTRS_COMMON(); +FAN_ATTR_GROUP(1); +FAN_ATTR_GROUP(2); +FAN_ATTR_GROUP(3); +FAN_ATTR_GROUP(4); +FAN_ATTR_GROUP(5); + +static const struct attribute_group *fan_groups[] = { + &fan_attrgroup_common, + &fan_attrgroup_1, + &fan_attrgroup_2, + &fan_attrgroup_3, + &fan_attrgroup_4, + &fan_attrgroup_5, + NULL +}; + +//ATTRIBUTE_GROUPS(fan_group); + +static int as7515_fan_read_value(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 as7515_fan_write_value(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; +} + +/* fan utility functions + */ +static u8 reg_val_to_is_present(u8 reg_val) +{ + return !(reg_val & 0x1); +} + +static u32 reg_val_to_pwm(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return (((u32)reg_val) * 100 / 63); +} + +static u8 pwm_to_reg_val(u8 pwm) +{ + if (pwm == 0) + return 0; + else if (pwm > FAN_MAX_PWM) + pwm = FAN_MAX_PWM; + + return ((u32)pwm) * 63 / 100; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val, u8 tech_reg_val) +{ + u32 timer[] = { 1048, 2097, 4194, 8389 }; + u8 counter = (tech_reg_val & 0x3F); + u8 clock = (tech_reg_val >> 6) & 0x3; + + return (reg_val * 3000000) / (timer[clock] * counter); +} + +static u8 reg_val_to_fault(u8 reg_val) +{ + return !!(reg_val & 0x2); +} + +static u8 reg_val_to_enable(u8 reg_val, enum fan_id id) +{ + return !!(reg_val & BIT(id)); +} + +static ssize_t fan_set_pwm(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value; + struct as7515_24x_fan_data *data = dev_get_drvdata(dev); + 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_PWM) + return -EINVAL; + + error = as7515_fan_write_value(data->client, + fan_reg[attr->index], + pwm_to_reg_val(value)); + if (unlikely(error < 0)) { + dev_dbg(dev, "Unable to set fan pwm, error = (%d)\n", error); + return error; + } + + data->valid = 0; + return count; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7515_24x_fan_data *data = as7515_fan_update_device(dev); + ssize_t ret = 0; + + mutex_lock(&data->update_lock); + + if (data->valid) { + switch (attr->index) { + case FAN_FW_VERSION: + ret = sprintf(buf, "%d.%d\n", + data->reg_val[FAN_MAJOR_VERSION_REG], + data->reg_val[FAN_MINOR_VERSION_REG]); + break; + case FAN1_PRESENT ... FAN5_PRESENT: + ret = sprintf(buf, "%d\n", + reg_val_to_is_present(data->reg_val[attr->index])); + break; + case FAN1_PWM ... FAN5_PWM: + ret = sprintf(buf, "%u\n", + reg_val_to_pwm(data->reg_val[attr->index])); + break; + case FAN1_INPUT ... FAN5_INPUT: + ret = sprintf(buf, "%u\n", + reg_val_to_speed_rpm(data->reg_val[attr->index], + data->reg_val[FAN_TECH_SETTING])); + break; + case FAN1_TARGET ... FAN5_TARGET: + ret = sprintf(buf, "%u\n", + fan_target_speed[data->reg_val[FAN1_PWM + attr->index - FAN1_TARGET]]); + break; + case FAN1_FAULT ... FAN5_FAULT: + ret = sprintf(buf, "%d\n", + reg_val_to_fault(data->reg_val[FAN1_PRESENT + attr->index - FAN1_FAULT])); + break; + case FAN1_ENABLE ... FAN5_ENABLE: + ret = sprintf(buf, "%d\n", + reg_val_to_enable(data->reg_val[FAN_ENABLE_REG], + attr->index - FAN1_ENABLE)); + break; + case FAN_MAX_RPM: + ret = sprintf(buf, "%d\n", MAX_FAN_INPUT); + break; + default: + break; + } + } + + mutex_unlock(&data->update_lock); + return ret; +} + +static ssize_t fan_set_enable(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status, value; + struct as7515_24x_fan_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + status = kstrtoint(buf, 10, &value); + if (status) + return status; + + if (value < 0 || value > 1) + return -EINVAL; + + status = as7515_fan_read_value(data->client, fan_reg[FAN_ENABLE_REG]); + if (unlikely(status < 0)) { + dev_dbg(dev, "Unable to read the fan reg(0x%x), error = (%d)\n", + fan_reg[FAN_ENABLE_REG], status); + return status; + } + + if (value) + status |= BIT(attr->index - FAN1_ENABLE); + else + status &= ~BIT(attr->index - FAN1_ENABLE); + + as7515_fan_write_value(data->client, + fan_reg[FAN_ENABLE_REG], + status); + data->valid = 0; + return count; +} + +static ssize_t show_wdt(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7515_24x_fan_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int status = 0, invert = 0; + u8 reg = 0, mask = 0; + + switch (attr->index) { + case WDT_ENABLE: + invert = 1; + reg = 0x0A; + mask = 0x01; + break; + case WDT_CLOCK: + reg = 0x0B; + mask = 0xC0; + break; + case WDT_COUNTER: + reg = 0x0B; + mask = 0x3F; + break; + default: + return 0; + } + + mutex_lock(&data->update_lock); + status = as7515_fan_read_value(data->client, reg); + if (unlikely(status < 0)) + goto exit; + mutex_unlock(&data->update_lock); + + while (!(mask & 0x1)) { + status >>= 1; + mask >>= 1; + } + + return sprintf(buf, "%d\n", invert ? !(status & mask) : (status & mask)); +exit: + mutex_unlock(&data->update_lock); + return status; +} + +#define VALIDATE_WDT_VAL_RETURN(value, mask) \ + do { \ + if (value & ~mask) \ + return -EINVAL; \ + } while (0) + +static ssize_t set_wdt(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct as7515_24x_fan_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + long value; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &value); + if (status) + return status; + + switch (attr->index) { + case WDT_ENABLE: + value = !value; + reg = 0x0A; + mask = 0x01; + value &= mask; + VALIDATE_WDT_VAL_RETURN(value, mask); + break; + case WDT_CLOCK: + reg = 0x0B; + mask = 0xC0; + value <<= 6; + VALIDATE_WDT_VAL_RETURN(value, mask); + break; + case WDT_COUNTER: + reg = 0x0B; + mask = 0x3F; + value &= mask; + VALIDATE_WDT_VAL_RETURN(value, mask); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + + status = as7515_fan_read_value(data->client, reg); + if (unlikely(status < 0)) + goto exit; + + /* Update wdt status */ + status = (status & ~mask) | (value & mask); + status = as7515_fan_write_value(data->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 int _reset_wdt(struct as7515_24x_fan_data *data) +{ + int status; + + /* Set value as 1->0 to reset wdt */ + status = as7515_fan_write_value(data->client, 0x0A, 1); + if (unlikely(status < 0)) + return status; + + msleep(50); + status = as7515_fan_write_value(data->client, 0x0A, 0); + if (unlikely(status < 0)) + return status; + + return status; +} + +static ssize_t reset_wdt(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long value; + int status; + struct as7515_24x_fan_data *data = dev_get_drvdata(dev); + + status = kstrtol(buf, 10, &value); + if (status) + return status; + + if (!value) + return count; + + /* Read current status */ + mutex_lock(&data->update_lock); + + status = _reset_wdt(data); + if (unlikely(status < 0)) { + dev_dbg(dev, "Unable to reset the watchdog timer\n"); + return status; + } + + mutex_unlock(&data->update_lock); + return count; +} + +static struct as7515_24x_fan_data *as7515_fan_update_device(struct device *dev) +{ + struct as7515_24x_fan_data *data = dev_get_drvdata(dev); + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(dev, "Starting as7515_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as7515_fan_read_value(data->client, fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(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; + } + + mutex_unlock(&data->update_lock); + return data; +} + +static int as7515_24x_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7515_24x_fan_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7515_24x_fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + data->client = client; + mutex_init(&data->update_lock); + dev_info(&client->dev, "chip found\n"); + + data->hwmon_dev = + hwmon_device_register_with_groups(&client->dev, client->name, data, + fan_groups); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_free; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + + exit_free: + kfree(data); + exit: + return status; +} + +static int as7515_24x_fan_remove(struct i2c_client *client) +{ + struct as7515_24x_fan_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + kfree(data); + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static const struct i2c_device_id as7515_24x_fan_id[] = { + {"as7515_24x_fan", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, as7515_24x_fan_id); + +static struct i2c_driver as7515_24x_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7515_24x_fan_probe, + .remove = as7515_24x_fan_remove, + .id_table = as7515_24x_fan_id, + .address_list = normal_i2c, +}; + +module_i2c_driver(as7515_24x_fan_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7515_fan driver"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-fpga.c b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-fpga.c new file mode 100644 index 0000000000..fd7a3e2f5c --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-fpga.c @@ -0,0 +1,318 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/* + * Copyright (C) 2024 Accton Technology Corporation. + * Brandon Chuang + * + * This module supports the accton fpga via pcie that read/write reg + * mechanism to get OSFP/SFP status ...etc. + * This includes the: + * Accton as7515_24x FPGA + * + * Copyright (C) 2017 Finisar Corp. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*********************************************** + * variable define + * *********************************************/ +#define DRVNAME "as7515_24x_fpga" + +/* + * PCIE BAR0 address + */ +#define BAR0_NUM 0 +#define REGION_LEN 0xFF +#define FPGA_PCI_VENDOR_ID 0x1172 +#define FPGA_PCI_DEVICE_ID 0xE001 + +#define FPGA_PCIE_START_OFFSET 0x0000 +#define FPGA_BOARD_INFO_REG (FPGA_PCIE_START_OFFSET + 0x00) +#define FPGA_MAJOR_VER_REG (FPGA_PCIE_START_OFFSET + 0x01) +#define FPGA_MINOR_VER_REG (FPGA_PCIE_START_OFFSET + 0x02) + +/*********************************************** + * macro define + * *********************************************/ +#define pcie_err(fmt, args...) \ + printk(KERN_ERR "["DRVNAME"]: " fmt " ", ##args) + +#define pcie_info(fmt, args...) \ + printk(KERN_ERR "["DRVNAME"]: " fmt " ", ##args) + +/*********************************************** + * structure & variable declare + * *********************************************/ +typedef struct pci_fpga_device_s { + void __iomem *data_base_addr0; + resource_size_t data_region0; + struct pci_dev *pci_dev; +} pci_fpga_device_t; + +/*fpga port status*/ +struct as7515_24x_fpga_data { + pci_fpga_device_t pci_fpga_dev; + struct platform_device *led_pdev; + struct mutex update_lock; +}; + +static struct platform_device *pdev = NULL; + +/*********************************************** + * enum define + * *********************************************/ +enum fpga_sysfs_attributes { + FPGA_VERSION +}; + +/*********************************************** + * function declare + * *********************************************/ + +static ssize_t status_read(struct device *dev, struct device_attribute *da, + char *buf); + +static SENSOR_DEVICE_ATTR(version, S_IRUGO, status_read, NULL, FPGA_VERSION); + +static struct attribute *fpga_attributes[] = { + &sensor_dev_attr_version.dev_attr.attr, + NULL +}; + +static const struct attribute_group fpga_group = { + .attrs = fpga_attributes, +}; + +static inline unsigned int fpga_read(void __iomem *addr) +{ + return ioread8(addr); +} + +static inline void fpga_write(void __iomem *addr, u8 val) +{ + iowrite8(val, addr); +} + +int as7515_24x_fpga_read(u8 reg) +{ + int ret = -EPERM; + struct as7515_24x_fpga_data *fpga_ctl; + + if (!pdev) + return -EPERM; + + fpga_ctl = dev_get_drvdata(&pdev->dev); + if (!fpga_ctl) + return -EPERM; + + mutex_lock(&fpga_ctl->update_lock); + ret = fpga_read(fpga_ctl->pci_fpga_dev.data_base_addr0 + reg); + mutex_unlock(&fpga_ctl->update_lock); + + return ret; +} +EXPORT_SYMBOL(as7515_24x_fpga_read); + +int as7515_24x_fpga_write(u8 reg, u8 value) +{ + struct as7515_24x_fpga_data *fpga_ctl; + + if (!pdev) + return -EPERM; + + fpga_ctl = dev_get_drvdata(&pdev->dev); + if (!fpga_ctl) + return -EPERM; + + mutex_lock(&fpga_ctl->update_lock); + fpga_write(fpga_ctl->pci_fpga_dev.data_base_addr0 + reg, value); + mutex_unlock(&fpga_ctl->update_lock); + + return 0; +} +EXPORT_SYMBOL(as7515_24x_fpga_write); + +static ssize_t status_read(struct device *dev, struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7515_24x_fpga_data *fpga_ctl = dev_get_drvdata(dev); + ssize_t ret = -EINVAL; + u16 reg; + u8 major, minor; + + switch(attr->index) + { + case FPGA_VERSION: + reg = FPGA_MAJOR_VER_REG; + major = fpga_read(fpga_ctl->pci_fpga_dev.data_base_addr0 + reg); + reg = FPGA_MINOR_VER_REG; + minor = fpga_read(fpga_ctl->pci_fpga_dev.data_base_addr0 + reg); + + ret = sprintf(buf, "%d.%d\n", major, minor); + break; + default: + break; + } + + return ret; +} + +static int as7515_24x_pcie_fpga_stat_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct as7515_24x_fpga_data *fpga_ctl; + struct pci_dev *pcidev; + struct resource *ret; + int status = 0, err = 0; + + fpga_ctl = devm_kzalloc(dev, sizeof(struct as7515_24x_fpga_data), GFP_KERNEL); + if (!fpga_ctl) { + return -ENOMEM; + } + mutex_init(&fpga_ctl->update_lock); + platform_set_drvdata(pdev, fpga_ctl); + + pcidev = pci_get_device(FPGA_PCI_VENDOR_ID, FPGA_PCI_DEVICE_ID, NULL); + if (!pcidev) { + dev_err(dev, "Cannot found PCI device(%x:%x)\n", + FPGA_PCI_VENDOR_ID, FPGA_PCI_DEVICE_ID); + return -ENODEV; + } + fpga_ctl->pci_fpga_dev.pci_dev = pcidev; + + err = pci_enable_device(pcidev); + if (err != 0) { + dev_err(dev, "Cannot enable PCI device(%x:%x)\n", + FPGA_PCI_VENDOR_ID, FPGA_PCI_DEVICE_ID); + status = -ENODEV; + goto exit_pci_disable; + } + /* enable PCI bus-mastering */ + pci_set_master(pcidev); + + /* + * Detect platform for changing the setting behavior of LP mode. + */ + fpga_ctl->pci_fpga_dev.data_base_addr0 = pci_iomap(pcidev, BAR0_NUM, 0); + if (fpga_ctl->pci_fpga_dev.data_base_addr0 == NULL) { + dev_err(dev, "Failed to map BAR0\n"); + status = -EIO; + goto exit_pci_disable; + } + + fpga_ctl->pci_fpga_dev.data_region0 = pci_resource_start(pcidev, BAR0_NUM); + ret = request_mem_region(fpga_ctl->pci_fpga_dev.data_region0, REGION_LEN, DRVNAME); + if (ret == NULL) { + dev_err(dev, "[%s] cannot request region\n", DRVNAME); + status = -EIO; + goto exit_pci_iounmap0; + } + dev_info(dev, "(BAR%d resource: Start=0x%lx, Length=0x%x)", BAR0_NUM, + (unsigned long)fpga_ctl->pci_fpga_dev.data_region0, REGION_LEN); + + status = sysfs_create_group(&pdev->dev.kobj, &fpga_group); + if (status) + goto exit_pci_release0; + + fpga_ctl->led_pdev = platform_device_register_simple("as7515_24x_led", -1, NULL, 0); + if (IS_ERR(fpga_ctl->led_pdev)) { + status = PTR_ERR(fpga_ctl->led_pdev); + goto exit_sysfs_group; + } + + return 0; + +exit_sysfs_group: + sysfs_remove_group(&pdev->dev.kobj, &fpga_group); +exit_pci_release0: + release_mem_region(fpga_ctl->pci_fpga_dev.data_region0, REGION_LEN); +exit_pci_iounmap0: + pci_iounmap(fpga_ctl->pci_fpga_dev.pci_dev, fpga_ctl->pci_fpga_dev.data_base_addr0); +exit_pci_disable: + pci_disable_device(fpga_ctl->pci_fpga_dev.pci_dev); + + return status; +} + +static int as7515_24x_pcie_fpga_stat_remove(struct platform_device *pdev) +{ + struct as7515_24x_fpga_data *fpga_ctl = platform_get_drvdata(pdev); + + if (fpga_ctl->led_pdev) + platform_device_unregister(fpga_ctl->led_pdev); + + if (pci_is_enabled(fpga_ctl->pci_fpga_dev.pci_dev)) { + sysfs_remove_group(&pdev->dev.kobj, &fpga_group); + pci_iounmap(fpga_ctl->pci_fpga_dev.pci_dev, fpga_ctl->pci_fpga_dev.data_base_addr0); + release_mem_region(fpga_ctl->pci_fpga_dev.data_region0, REGION_LEN); + pci_disable_device(fpga_ctl->pci_fpga_dev.pci_dev); + } + + return 0; +} + +static struct platform_driver pcie_fpga_port_stat_driver = { + .probe = as7515_24x_pcie_fpga_stat_probe, + .remove = as7515_24x_pcie_fpga_stat_remove, + .driver = { + .owner = THIS_MODULE, + .name = DRVNAME, + }, +}; + +static int __init as7515_24x_pcie_fpga_init(void) +{ + int status = 0; + + /* + * Create FPGA platform driver and device + */ + status = platform_driver_register(&pcie_fpga_port_stat_driver); + if (status < 0) + return status; + + pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(pdev)) { + status = PTR_ERR(pdev); + goto exit_pci; + } + + return status; + +exit_pci: + platform_driver_unregister(&pcie_fpga_port_stat_driver); + + return status; +} + +static void __exit as7515_24x_pcie_fpga_exit(void) +{ + platform_device_unregister(pdev); + platform_driver_unregister(&pcie_fpga_port_stat_driver); +} + +module_init(as7515_24x_pcie_fpga_init); +module_exit(as7515_24x_pcie_fpga_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("AS7515-24X FPGA via PCIE"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-leds.c b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-leds.c new file mode 100644 index 0000000000..580fbf9407 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-leds.c @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/* + * Copyright (C) 2024 Accton Technology Corporation. + * Brandon Chuang + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7515_24x_led" + +#define FPGA_BLINKING_REG (0x8F) + +static ssize_t set_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_led(struct device *dev, struct device_attribute *attr, + char *buf); + +extern int as7515_24x_fpga_read(u8 reg); +extern int as7515_24x_fpga_write(u8 reg, u8 value); +static int as7515_24x_led_probe(struct platform_device *pdev); +static int as7515_24x_led_remove(struct platform_device *pdev); + +enum led_type { + LED_TYPE_FAN, + LED_TYPE_LOC, + LED_TYPE_PSU1, + LED_TYPE_PSU2, + LED_TYPE_DIAG, + LED_COUNT +}; + +enum led_light_mode { + LED_MODE_OFF, + LED_MODE_RED = 10, + LED_MODE_RED_BLINKING = 11, + LED_MODE_ORANGE = 12, + LED_MODE_ORANGE_BLINKING = 13, + LED_MODE_YELLOW = 14, + LED_MODE_YELLOW_BLINKING = 15, + LED_MODE_GREEN = 16, + LED_MODE_GREEN_BLINKING = 17, + LED_MODE_BLUE = 18, + LED_MODE_BLUE_BLINKING = 19, + LED_MODE_PURPLE = 20, + LED_MODE_PURPLE_BLINKING = 21, + LED_MODE_AUTO = 22, + LED_MODE_AUTO_BLINKING = 23, + LED_MODE_WHITE = 24, + LED_MODE_WHITE_BLINKING = 25, + LED_MODE_CYAN = 26, + LED_MODE_CYAN_BLINKING = 27, + LED_MODE_UNKNOWN = 99 +}; + +struct as7515_24x_led_data { + struct mutex update_lock; +}; + +struct as7515_24x_led_data *data = NULL; + +enum RGB_COLOR { + RGB_RED = 0, + RGB_GREEN, + RGB_BLUE, + RGB_COUNT +}; + +struct color_reg { + u8 reg_addr; + u8 reg_val; +}; + +struct led_config { + enum led_type type; + enum led_light_mode mode; + struct color_reg rgb[RGB_COUNT]; +}; + +static struct led_config led_config_data[] = { + /* Type Mode */ + {LED_TYPE_DIAG, LED_MODE_ORANGE, + {{0x8B, 0xFF}, {0x8A, 0x3F}, {0x89, 0x00}}}, /* R G B */ + {LED_TYPE_DIAG, LED_MODE_GREEN, + {{0x8B, 0x00}, {0x8A, 0xFF}, {0x89, 0x00}}}, + {LED_TYPE_DIAG, LED_MODE_GREEN_BLINKING, + {{0x8B, 0x00}, {0x8A, 0xFF}, {0x89, 0x00}}}, + + {LED_TYPE_LOC, LED_MODE_BLUE_BLINKING, + {{0x85, 0x00}, {0x84, 0x00}, {0x83, 0xFF}}}, + {LED_TYPE_LOC, LED_MODE_OFF, + {{0x85, 0x00}, {0x84, 0x00}, {0x83, 0x00}}}, + + {LED_TYPE_FAN, LED_MODE_ORANGE, + {{0x88, 0xFF}, {0x87, 0x3F}, {0x86, 0x00}}}, + {LED_TYPE_FAN, LED_MODE_GREEN, + {{0x88, 0x00}, {0x87, 0xFF}, {0x86, 0x00}}}, + {LED_TYPE_FAN, LED_MODE_OFF, + {{0x88, 0x00}, {0x87, 0x00}, {0x86, 0x00}}}, + + {LED_TYPE_PSU1, LED_MODE_ORANGE, + {{0x8E, 0xFF}, {0x8D, 0x20}, {0x8C, 0x00}}}, + {LED_TYPE_PSU1, LED_MODE_GREEN, + {{0x8E, 0x00}, {0x8D, 0xFF}, {0x8C, 0x00}}}, + {LED_TYPE_PSU1, LED_MODE_OFF, + {{0x8E, 0x00}, {0x8D, 0x00}, {0x8C, 0x00}}}, + + {LED_TYPE_PSU2, LED_MODE_ORANGE, + {{0x82, 0xFF}, {0x81, 0x20}, {0x80, 0x00}}}, + {LED_TYPE_PSU2, LED_MODE_GREEN, + {{0x82, 0x00}, {0x81, 0xFF}, {0x80, 0x00}}}, + {LED_TYPE_PSU2, LED_MODE_OFF, + {{0x82, 0x00}, {0x81, 0x00}, {0x80, 0x00}}} +}; + +static SENSOR_DEVICE_ATTR(led_psu1, S_IWUSR | S_IRUGO, show_led, set_led, + LED_TYPE_PSU1); +static SENSOR_DEVICE_ATTR(led_psu2, S_IWUSR | S_IRUGO, show_led, set_led, + LED_TYPE_PSU2); +static SENSOR_DEVICE_ATTR(led_loc, S_IWUSR | S_IRUGO, show_led, set_led, + LED_TYPE_LOC); +static SENSOR_DEVICE_ATTR(led_diag, S_IWUSR | S_IRUGO, show_led, set_led, + LED_TYPE_DIAG); +static SENSOR_DEVICE_ATTR(led_fan, S_IWUSR | S_IRUGO, show_led, set_led, + LED_TYPE_FAN); + +static struct attribute *as7515_24x_led_attributes[] = { + &sensor_dev_attr_led_psu1.dev_attr.attr, + &sensor_dev_attr_led_psu2.dev_attr.attr, + &sensor_dev_attr_led_loc.dev_attr.attr, + &sensor_dev_attr_led_fan.dev_attr.attr, + &sensor_dev_attr_led_diag.dev_attr.attr, + NULL +}; + +static const struct attribute_group led_group[] = { + { .attrs = as7515_24x_led_attributes } +}; + +static int led_read_value(u8 reg) +{ + return as7515_24x_fpga_read(reg); +} + +static int led_write_value(u8 reg, u8 value) +{ + return as7515_24x_fpga_write(reg, value); +} + +static int _led_validate_mode(enum led_type type, enum led_light_mode mode) +{ + int i, status = -EINVAL; + + for (i = 0; i < ARRAY_SIZE(led_config_data); i++) { + if (type != led_config_data[i].type) + continue; + + if (mode != led_config_data[i].mode) + continue; + + /* led mode is found */ + status = 0; + break; + } + + return status; +} + +static enum led_light_mode _led_get_mode_from_rgb(enum led_type type) +{ + u8 match = 0; + int i, j, status; + u8 rgb_val[RGB_COUNT]; + + for (i = 0; i < ARRAY_SIZE(led_config_data); i++) { + if (type != led_config_data[i].type) + continue; + + for (j = 0; j < ARRAY_SIZE(led_config_data[i].rgb); j++) { + status = led_read_value(led_config_data[i].rgb[j].reg_addr); + if (status < 0) + return LED_MODE_UNKNOWN; + + rgb_val[j] = status; + } + + match = 1; + break; + } + + if (!match) + return LED_MODE_UNKNOWN; + + for (i = 0; i < ARRAY_SIZE(led_config_data); i++) { + if (type != led_config_data[i].type) + continue; + + if ((led_config_data[i].rgb[RGB_RED].reg_val == rgb_val[RGB_RED]) && + (led_config_data[i].rgb[RGB_GREEN].reg_val == rgb_val[RGB_GREEN]) && + (led_config_data[i].rgb[RGB_BLUE].reg_val == rgb_val[RGB_BLUE])) { + return led_config_data[i].mode; + } + } + + return LED_MODE_UNKNOWN; +} + +static int led_get_blinking(enum led_type type) +{ + int status; + + status = led_read_value(FPGA_BLINKING_REG); + if (status < 0) + return 0; + + return !!(BIT(type) & status); +} + +static int led_set_blinking(enum led_type type, int blinking) +{ + int status; + + status = led_read_value(FPGA_BLINKING_REG); + if (status < 0) + return status; + + if (blinking) + status |= BIT(type); + else + status &= ~BIT(type); + + return led_write_value(FPGA_BLINKING_REG, status); +} + +static int led_is_blinking_mode(enum led_light_mode mode) +{ + if (mode == LED_MODE_OFF || mode == LED_MODE_UNKNOWN) + return 0; + + return (mode % 2); +} + +static enum led_light_mode led_get_mode(enum led_type type) +{ + int status, blinking = 0; + enum led_light_mode mode = LED_MODE_UNKNOWN; + + mode = _led_get_mode_from_rgb(type); + if (mode == LED_MODE_OFF || mode == LED_MODE_UNKNOWN) + return mode; + + /* transit to blinking mode if blinking is enabled */ + blinking = led_get_blinking(type); + if (blinking) { + if (!led_is_blinking_mode(mode)) + mode += 1; /* normal mode to blinking mode */ + } + else { + if (led_is_blinking_mode(mode)) + mode -= 1; /* blinking mode to normal mode */ + } + + /* Validate led mode */ + status = _led_validate_mode(type, mode); + if (status) + return LED_MODE_UNKNOWN; + + return mode; +} + +static int _led_set_mode_rgb(enum led_type type, enum led_light_mode mode) +{ + int i, j, status; + + for (i = 0; i < ARRAY_SIZE(led_config_data); i++) { + if (type != led_config_data[i].type) + continue; + + if (mode != led_config_data[i].mode) + continue; + + for (j = 0; j < ARRAY_SIZE(led_config_data[i].rgb); j++) { + status = led_write_value(led_config_data[i].rgb[j].reg_addr, + led_config_data[i].rgb[j].reg_val); + if (status < 0) + return status; + } + } + + return 0; +} + +static int led_set_mode(enum led_type type, enum led_light_mode mode) +{ + int status = 0; + + /* Validate led mode */ + status = _led_validate_mode(type, mode); + if (status) + return status; + + status = _led_set_mode_rgb(type, mode); + if (status < 0) + return status; + + return led_set_blinking(type, led_is_blinking_mode(mode)); +} + +static ssize_t show_led(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7515_24x_led_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + enum led_light_mode mode = LED_MODE_UNKNOWN; + + mutex_lock(&data->update_lock); + mode = led_get_mode(attr->index); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", mode); +} + +static ssize_t set_led(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + long mode; + int status; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct as7515_24x_led_data *data = dev_get_drvdata(dev); + + status = kstrtol(buf, 10, &mode); + if (status) + return status; + + mutex_lock(&data->update_lock); + + status = led_set_mode(attr->index, mode); + if (status < 0) + goto exit; + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int as7515_24x_led_probe(struct platform_device *pdev) +{ + int status = -1; + int i = 0; + struct as7515_24x_led_data *data; + + data = kzalloc(sizeof(struct as7515_24x_led_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + mutex_init(&data->update_lock); + platform_set_drvdata(pdev, data); + + /* Register sysfs hooks */ + for (i = 0; i < ARRAY_SIZE(led_group); i++) { + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &led_group[i]); + if (status) + goto exit_sysfs_group; + } + + dev_info(&pdev->dev, "device created\n"); + return 0; + +exit_sysfs_group: + for (--i; i >= 0; i--) { + sysfs_remove_group(&pdev->dev.kobj, &led_group[i]); + } + + kfree(data); + return status; +} + +static int as7515_24x_led_remove(struct platform_device *pdev) +{ + struct as7515_24x_led_data *data = platform_get_drvdata(pdev); + int i = 0; + + for (i = 0; i < ARRAY_SIZE(led_group); i++) { + sysfs_remove_group(&pdev->dev.kobj, &led_group[i]); + } + + kfree(data); + return 0; +} + +static struct platform_device_id as7515_24x_led_id[] = { + { DRVNAME, 0 }, + {} +}; +MODULE_DEVICE_TABLE(platform, as7515_24x_led_id); + +static struct platform_driver as7515_24x_led_driver = { + .probe = as7515_24x_led_probe, + .remove = as7515_24x_led_remove, + .id_table = as7515_24x_led_id, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(as7515_24x_led_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7515_24x_led driver"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-mux.c b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-mux.c new file mode 100644 index 0000000000..333e92b1bd --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-mux.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/* + * Copyright (C) 2024 Accton Technology Corporation. + * 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 as7515-24x CPLD/FPGA + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7515_24x_mux" + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +#define AS7515_FPGA_MUX_NCHANS 13 +#define AS7515_FPGA_MUX_SELECT_REG 0x0 +#define AS7515_FPGA_MUX_DESELECT_VAL 0xFF + +#define AS7515_CPLD_MUX_NCHANS 24 +#define AS7515_CPLD_MUX_SELECT_REG 0x0 +#define AS7515_CPLD_MUX_DESELECT_VAL 0xFF + +enum mux_type { + as7515_fpga_mux, + as7515_cpld_mux +}; + +struct chip_desc { + u8 nchans; + u8 select_reg; + u8 deselect_val; +}; + +struct as7515_24x_mux_data { + enum mux_type type; + struct mutex update_lock; + struct i2c_client *client; +}; + +/* Provide specs for the as456x CPLD types we know about */ +static const struct chip_desc chips[] = { + [as7515_fpga_mux] = { + .nchans = AS7515_FPGA_MUX_NCHANS, + .select_reg = AS7515_FPGA_MUX_SELECT_REG, + .deselect_val = AS7515_FPGA_MUX_DESELECT_VAL}, + [as7515_cpld_mux] = { + .nchans = AS7515_CPLD_MUX_NCHANS, + .select_reg = AS7515_CPLD_MUX_SELECT_REG, + .deselect_val = AS7515_CPLD_MUX_DESELECT_VAL} +}; + +static const struct i2c_device_id as7515_24x_mux_id[] = { + {"as7515_fpga_mux", as7515_fpga_mux}, + {"as7515_cpld_mux", as7515_cpld_mux}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, as7515_24x_mux_id); + +static const struct of_device_id as7515_24x_mux_of_match[] = { + {.compatible = "accton,as7515_fpga_mux",.data = &chips[as7515_fpga_mux]}, + {.compatible = "accton,as7515_cpld_mux",.data = &chips[as7515_cpld_mux]}, + {} +}; + +MODULE_DEVICE_TABLE(of, as7515_24x_mux_of_match); + +/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() + for this as they will try to lock adapter a second time */ +static int as7515_24x_mux_write(struct i2c_adapter *adap, + struct i2c_client *client, u8 reg, u8 val) +{ + union i2c_smbus_data data; + + data.byte = val; + return __i2c_smbus_xfer(adap, client->addr, client->flags, + I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE_DATA, + &data); +} + +static int as7515_24x_mux_select_chan(struct i2c_mux_core *muxc, u32 chan) +{ + struct as7515_24x_mux_data *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int ret = 0; + u8 reg_val = 0; + + mutex_lock(&data->update_lock); + switch (data->type) { + case as7515_fpga_mux: + reg_val = (chan <= 8) ? chan : (1 << (chan-5)); + ret = as7515_24x_mux_write(muxc->parent, client, + chips[data->type].select_reg, + reg_val); + break; + case as7515_cpld_mux: + ret = as7515_24x_mux_write(muxc->parent, client, + chips[data->type].select_reg, chan); + break; + default: + break; + } + + mutex_unlock(&data->update_lock); + return ret; +} + +static int as7515_24x_mux_deselect_mux(struct i2c_mux_core *muxc, u32 chan) +{ + struct as7515_24x_mux_data *data = i2c_mux_priv(muxc); + struct i2c_client *client = data->client; + int ret = 0; + + mutex_lock(&data->update_lock); + ret = as7515_24x_mux_write(muxc->parent, client, + chips[data->type].select_reg, + chips[data->type].deselect_val); + mutex_unlock(&data->update_lock); + return ret; +} + +static void as7515_24x_mux_cleanup(struct i2c_mux_core *muxc) +{ + i2c_mux_del_adapters(muxc); +} + +/* + * I2C init/probing/exit functions + */ +static int as7515_24x_mux_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct device *dev = &client->dev; + struct as7515_24x_mux_data *data; + struct i2c_mux_core *muxc; + int ret = -ENODEV; + int i = 0; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + return -ENODEV; + + muxc = i2c_mux_alloc(adap, dev, AS7515_CPLD_MUX_NCHANS, sizeof(*data), 0, + as7515_24x_mux_select_chan, + as7515_24x_mux_deselect_mux); + if (!muxc) + return -ENOMEM; + + data = i2c_mux_priv(muxc); + mutex_init(&data->update_lock); + data->type = id->driver_data; + data->client = client; + i2c_set_clientdata(client, muxc); + + /* Now create an adapter for each channel */ + for (i = 0; i < chips[data->type].nchans; i++) { + ret = i2c_mux_add_adapter(muxc, 0, i, 0); + if (ret) + goto exit_mux; + } + + return 0; + + exit_mux: + as7515_24x_mux_cleanup(muxc); + return ret; +} + +static int as7515_24x_mux_remove(struct i2c_client *client) +{ + struct i2c_mux_core *muxc = i2c_get_clientdata(client); + as7515_24x_mux_cleanup(muxc); + return 0; +} + +static struct i2c_driver as7515_24x_mux_driver = { + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, + .probe = as7515_24x_mux_probe, + .remove = as7515_24x_mux_remove, + .id_table = as7515_24x_mux_id, +}; + +module_i2c_driver(as7515_24x_mux_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7515_24x_mux driver"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-psu.c b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-psu.c new file mode 100644 index 0000000000..3ff40e27d2 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-psu.c @@ -0,0 +1,363 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/* + * An hwmon driver for accton as7515_24x Power Module + * + * Copyright (C) 2024 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as7515_24x_psu" + +#define PSU_REG_PRESENT 0x51 +#define PSU_REG_POWERGOOD 0x52 + +#define MODEL_NAME_LEN 12 +#define MODEL_NAME_REG_OFFSET 0x0A + +#define SERIAL_NUM_LEN 8 +#define SERIAL_NUM_REG_OFFSET 0x18 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(id))) +#define IS_PRESENT(id, value) (!(value & BIT(id))) + +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 as7515_24x_fpga_read(u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as7515_24x_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[2]; /* Status(present/power_good) register read from CPLD */ + char model_name[MODEL_NAME_LEN+1]; /* Model name, read from eeprom */ + char serial[SERIAL_NUM_LEN+1]; /* Serial number, read from eeprom*/ +}; + +static struct as7515_24x_psu_data *as7515_24x_psu_update_device(struct device *dev); + +enum as7515_24x_psu_sysfs_attributes { + PSU_PRESENT, + PSU_POWER_GOOD, + PSU_MODEL_NAME, + PSU_SERIAL_NUMBER +}; + +/* 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_numer, S_IRUGO, show_string, NULL, PSU_SERIAL_NUMBER); + +static struct attribute *as7515_24x_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_numer.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 as7515_24x_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 = as7515_24x_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[PSU_PRESENT]); + } + else { /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status[PSU_POWER_GOOD]); + } + + 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 as7515_24x_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 = as7515_24x_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; + default: + ret = -EINVAL; + goto exit; + } + + ret = sprintf(buf, "%s\n", ptr); + +exit: + mutex_unlock(&data->update_lock); + return ret; +} + +static const struct attribute_group as7515_24x_psu_group = { + .attrs = as7515_24x_psu_attributes, +}; + +static int as7515_24x_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as7515_24x_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as7515_24x_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); + + dev_info(&client->dev, "chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &as7515_24x_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, &as7515_24x_psu_group); +exit_free: + kfree(data); +exit: + return status; +} + +static int as7515_24x_psu_remove(struct i2c_client *client) +{ + struct as7515_24x_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as7515_24x_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as7515_24x_psu1, + as7515_24x_psu2 +}; + +static const struct i2c_device_id as7515_24x_psu_id[] = { + { "as7515_24x_psu1", as7515_24x_psu1 }, + { "as7515_24x_psu2", as7515_24x_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as7515_24x_psu_id); + +static struct i2c_driver as7515_24x_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as7515_24x_psu_probe, + .remove = as7515_24x_psu_remove, + .id_table = as7515_24x_psu_id, + .address_list = normal_i2c, +}; + +static int as7515_24x_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 as7515_24x_psu_read_bytes(struct i2c_client *client, u8 command, u8 *data, + int data_len) +{ + int ret = 0; + + while (data_len) { + ssize_t status; + + status = as7515_24x_psu_read_byte(client, command, data); + if (status <= 0) { + ret = status; + break; + } + + data += 1; + command += 1; + data_len -= 1; + } + + return ret; +} + +static struct as7515_24x_psu_data *as7515_24x_psu_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as7515_24x_psu_data *data = i2c_get_clientdata(client); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + u8 status_regs[] = { PSU_REG_PRESENT, PSU_REG_POWERGOOD }; + + dev_dbg(&client->dev, "Starting as7515_24x update\n"); + data->valid = 0; + + /* Read psu status */ + for (i = 0; i < ARRAY_SIZE(status_regs); i++) { + status = as7515_24x_fpga_read(status_regs[i]); + + if (status < 0) { + dev_dbg(&client->dev, "fpga reg err %d\n", status); + goto exit; + } + else { + data->status[i] = status; + } + } + + memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->serial, 0, sizeof(data->serial)); + + if (IS_POWER_GOOD(data->index, data->status[PSU_POWER_GOOD])) { + /* Read model name */ + status = as7515_24x_psu_read_bytes(client, MODEL_NAME_REG_OFFSET, data->model_name, + ARRAY_SIZE(data->model_name)-1); + if (status < 0) { + data->model_name[0] = '\0'; + dev_dbg(&client->dev, "unable to read model name from (0x%x)\n", client->addr); + goto exit; + } + + /* Read serial number */ + status = as7515_24x_psu_read_bytes(client, SERIAL_NUM_REG_OFFSET, data->serial, + ARRAY_SIZE(data->serial)-1); + if (status < 0) { + data->serial[0] = '\0'; + dev_dbg(&client->dev, "unable to read serial number from (0x%x)\n", client->addr); + goto exit; + } + else { + data->serial[ARRAY_SIZE(data->serial)-1] = '\0'; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + return data; +} + +module_i2c_driver(as7515_24x_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7515_24x_psu driver"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-sfp.c b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-sfp.c new file mode 100644 index 0000000000..7315798061 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/modules/builds/src/x86-64-accton-as7515-24x-sfp.c @@ -0,0 +1,500 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 +/* + * An hwmon driver for accton as7515 Power Module + * + * Copyright (C) 2024 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 "as7515_24x_sfp" + +#define SFP_STATUS_I2C_ADDR 0x61 +#define PORT_NUM (4 + 20) /* 4 OSFP + 20 SFP */ + +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 show_module(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 set_module_reset_all(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); + +extern int as7515_24x_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as7515_24x_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* Platform specific data + */ +struct as7515_sfp_data { + struct mutex update_lock; +}; + +#define TRANSCEIVER_ATTR_ID_QSFP(index) \ + MODULE_PRESENT_##index = (index-1), \ + MODULE_LPMODE_##index = (index-1) + (PORT_NUM * 1), \ + MODULE_RESET_##index = (index-1) + (PORT_NUM * 2) + +#define TRANSCEIVER_ATTR_ID_SFP(index) \ + MODULE_PRESENT_##index = (index-1), \ + MODULE_TX_DISABLE_##index = (index-1) + (PORT_NUM * 3), \ + MODULE_TX_FAULT_##index = (index-1) + (PORT_NUM * 4), \ + MODULE_RX_LOS_##index = (index-1) + (PORT_NUM * 5) + +/* + * MODULE_PRESENT_1 ... MODULE_PRESENT_24 => 0 ... 23 + * MODULE_LPMODE_1 ... MODULE_LPMODE_4 => 24 ... 27 + * MODULE_RESET_1 ... MODULE_RESET_4 => 48 ... 51 + * MODULE_TX_DISABLE_5 ... MODULE_TX_DISABLE_24 => 76 ... 95 + * MODULE_TX_FAULT_5 ... MODULE_TX_FAULT_24 => 100 ... 119 + * MODULE_RX_LOS_5 ... MODULE_RX_LOS_24 => 124 ... 143 + */ + +enum as7515_sfp_sysfs_attributes { + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + MODULE_RESET_ALL, + /* transceiver attributes */ + TRANSCEIVER_ATTR_ID_QSFP(1), + TRANSCEIVER_ATTR_ID_QSFP(2), + TRANSCEIVER_ATTR_ID_QSFP(3), + TRANSCEIVER_ATTR_ID_QSFP(4), + TRANSCEIVER_ATTR_ID_SFP(5), + TRANSCEIVER_ATTR_ID_SFP(6), + TRANSCEIVER_ATTR_ID_SFP(7), + TRANSCEIVER_ATTR_ID_SFP(8), + TRANSCEIVER_ATTR_ID_SFP(9), + TRANSCEIVER_ATTR_ID_SFP(10), + TRANSCEIVER_ATTR_ID_SFP(11), + TRANSCEIVER_ATTR_ID_SFP(12), + TRANSCEIVER_ATTR_ID_SFP(13), + TRANSCEIVER_ATTR_ID_SFP(14), + TRANSCEIVER_ATTR_ID_SFP(15), + TRANSCEIVER_ATTR_ID_SFP(16), + TRANSCEIVER_ATTR_ID_SFP(17), + TRANSCEIVER_ATTR_ID_SFP(18), + TRANSCEIVER_ATTR_ID_SFP(19), + TRANSCEIVER_ATTR_ID_SFP(20), + TRANSCEIVER_ATTR_ID_SFP(21), + TRANSCEIVER_ATTR_ID_SFP(22), + TRANSCEIVER_ATTR_ID_SFP(23), + TRANSCEIVER_ATTR_ID_SFP(24) +}; + +/* sysfs attributes for hwmon + */ +#define MODULE_ATTRS_COMMON() \ + 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); \ + static SENSOR_DEVICE_ATTR(module_reset_all, S_IWUSR, \ + NULL, set_module_reset_all, MODULE_RESET_ALL); \ + static struct attribute *module_attributes_common[] = { \ + &sensor_dev_attr_module_present_all.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, \ + &sensor_dev_attr_module_reset_all.dev_attr.attr, \ + NULL \ + } + +#define MODULE_ATTRS_QSFP(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, \ + show_module, NULL, MODULE_PRESENT_##index); \ + static SENSOR_DEVICE_ATTR(module_reset_##index, S_IRUGO | S_IWUSR,\ + show_module, set_control, MODULE_RESET_##index); \ + static SENSOR_DEVICE_ATTR(module_lpmode_##index, S_IRUGO | S_IWUSR, \ + show_module, set_control, MODULE_LPMODE_##index); \ + static struct attribute *module_attributes##index[] = { \ + &sensor_dev_attr_module_present_##index.dev_attr.attr, \ + &sensor_dev_attr_module_reset_##index.dev_attr.attr, \ + &sensor_dev_attr_module_lpmode_##index.dev_attr.attr, \ + NULL \ + } + +#define MODULE_ATTRS_SFP(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, \ + show_module, NULL, MODULE_PRESENT_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR,\ + show_module, set_control, MODULE_TX_DISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, \ + show_module, NULL, MODULE_RX_LOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, \ + show_module, NULL, MODULE_TX_FAULT_##index); \ + static struct attribute *module_attributes##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, \ + NULL \ + } + +MODULE_ATTRS_COMMON(); +MODULE_ATTRS_QSFP(1); +MODULE_ATTRS_QSFP(2); +MODULE_ATTRS_QSFP(3); +MODULE_ATTRS_QSFP(4); +MODULE_ATTRS_SFP(5); +MODULE_ATTRS_SFP(6); +MODULE_ATTRS_SFP(7); +MODULE_ATTRS_SFP(8); +MODULE_ATTRS_SFP(9); +MODULE_ATTRS_SFP(10); +MODULE_ATTRS_SFP(11); +MODULE_ATTRS_SFP(12); +MODULE_ATTRS_SFP(13); +MODULE_ATTRS_SFP(14); +MODULE_ATTRS_SFP(15); +MODULE_ATTRS_SFP(16); +MODULE_ATTRS_SFP(17); +MODULE_ATTRS_SFP(18); +MODULE_ATTRS_SFP(19); +MODULE_ATTRS_SFP(20); +MODULE_ATTRS_SFP(21); +MODULE_ATTRS_SFP(22); +MODULE_ATTRS_SFP(23); +MODULE_ATTRS_SFP(24); + +#define MODULE_ATTR_GROUP_COMMON() { .attrs = module_attributes_common } +#define MODULE_ATTR_GROUP_QSFP(index) { .attrs = module_attributes##index } +#define MODULE_ATTR_GROUP_SFP(index) { .attrs = module_attributes##index } + +static struct attribute_group sfp_group[] = { + MODULE_ATTR_GROUP_COMMON(), + MODULE_ATTR_GROUP_QSFP(1), + MODULE_ATTR_GROUP_QSFP(2), + MODULE_ATTR_GROUP_QSFP(3), + MODULE_ATTR_GROUP_QSFP(4), + MODULE_ATTR_GROUP_SFP(5), + MODULE_ATTR_GROUP_SFP(6), + MODULE_ATTR_GROUP_SFP(7), + MODULE_ATTR_GROUP_SFP(8), + MODULE_ATTR_GROUP_SFP(9), + MODULE_ATTR_GROUP_SFP(10), + MODULE_ATTR_GROUP_SFP(11), + MODULE_ATTR_GROUP_SFP(12), + MODULE_ATTR_GROUP_SFP(13), + MODULE_ATTR_GROUP_SFP(14), + MODULE_ATTR_GROUP_SFP(15), + MODULE_ATTR_GROUP_SFP(16), + MODULE_ATTR_GROUP_SFP(17), + MODULE_ATTR_GROUP_SFP(18), + MODULE_ATTR_GROUP_SFP(19), + MODULE_ATTR_GROUP_SFP(20), + MODULE_ATTR_GROUP_SFP(21), + MODULE_ATTR_GROUP_SFP(22), + MODULE_ATTR_GROUP_SFP(23), + MODULE_ATTR_GROUP_SFP(24) +}; + +struct attribute_mapping { + u16 attr_base; + u16 reg; + u8 invert; +}; + +// Define an array of attribute mappings +static const struct attribute_mapping attribute_mappings[] = { + [ MODULE_PRESENT_1 ... MODULE_PRESENT_4 ] = { MODULE_PRESENT_1, 0x10, 1 }, + [ MODULE_PRESENT_5 ... MODULE_PRESENT_12 ] = { MODULE_PRESENT_5, 0x11, 1 }, + [ MODULE_PRESENT_13 ... MODULE_PRESENT_20 ] = { MODULE_PRESENT_13, 0x12, 1 }, + [ MODULE_PRESENT_21 ... MODULE_PRESENT_24 ] = { MODULE_PRESENT_21, 0x13, 1 }, + [ MODULE_LPMODE_1 ... MODULE_LPMODE_4 ] = { MODULE_LPMODE_1, 0x09, 0 }, + [ MODULE_RESET_1 ... MODULE_RESET_4 ] = { MODULE_RESET_1, 0x08, 1 }, + [ MODULE_TX_DISABLE_5 ... MODULE_TX_DISABLE_12 ] = { MODULE_TX_DISABLE_5, 0x0A, 0 }, + [ MODULE_TX_DISABLE_13 ... MODULE_TX_DISABLE_20 ] = { MODULE_TX_DISABLE_13, 0x0B, 0 }, + [ MODULE_TX_DISABLE_21 ... MODULE_TX_DISABLE_24 ] = { MODULE_TX_DISABLE_21, 0x0C, 0 }, + [ MODULE_TX_FAULT_5 ... MODULE_TX_FAULT_12 ] = { MODULE_TX_FAULT_5, 0x15, 0 }, + [ MODULE_TX_FAULT_13 ... MODULE_TX_FAULT_20 ] = { MODULE_TX_FAULT_13, 0x16, 0 }, + [ MODULE_TX_FAULT_21 ... MODULE_TX_FAULT_24 ] = { MODULE_TX_FAULT_21, 0x17, 0 }, + [ MODULE_RX_LOS_5 ... MODULE_RX_LOS_12 ] = { MODULE_RX_LOS_5, 0x21, 0 }, + [ MODULE_RX_LOS_13 ... MODULE_RX_LOS_20 ] = { MODULE_RX_LOS_13, 0x22, 0 }, + [ MODULE_RX_LOS_21 ... MODULE_RX_LOS_24 ] = { MODULE_RX_LOS_21, 0x23, 0 } +}; + +static int as7515_sfp_read_value(u8 reg) +{ + return as7515_24x_cpld_read(SFP_STATUS_I2C_ADDR, reg); +} + +static int as7515_sfp_write_value(u8 reg, u8 value) +{ + return as7515_24x_cpld_write(SFP_STATUS_I2C_ADDR, reg, value); +} + +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 regs[] = { 0x10, 0x11, 0x12, 0x13 }; + u8 values[ARRAY_SIZE(regs)] = { 0 }; + struct as7515_sfp_data *data = dev_get_drvdata(dev); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7515_sfp_read_value(regs[i]); + if (status < 0) + goto exit; + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values in order */ + return sprintf(buf, "%.2x %.2x %.2x\n", + (unsigned int)((values[0] & 0x0F) | ((values[1] & 0xF) << 4)), + (unsigned int)(((values[1] & 0xF0) >> 4) | ((values[2] & 0xF) << 4)), + (unsigned int)(((values[2] & 0xF0) >> 4) | ((values[3] & 0xF) << 4))); + +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 regs[] = { 0x21, 0x22, 0x23 }; + u8 values[ARRAY_SIZE(regs)] = { 0 }; + struct as7515_sfp_data *data = dev_get_drvdata(dev); + + mutex_lock(&data->update_lock); + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + status = as7515_sfp_read_value(regs[i]); + if (status < 0) + goto exit; + + values[i] = (u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values in order */ + return sprintf(buf, "%.2x %.2x %.2x\n", + (unsigned int)((values[0] & 0x0F) << 4), + (unsigned int)(((values[0] & 0xF0) >> 4) | ((values[1] & 0xF) << 4)), + (unsigned int)(((values[1] & 0xF0) >> 4) | ((values[2] & 0xF) << 4))); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_module_reset_all(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct as7515_sfp_data *data = dev_get_drvdata(dev); + long value; + int status; + u8 reg = 0x08; + + status = kstrtol(buf, 10, &value); + if (status) + return status; + + /* Read current status */ + mutex_lock(&data->update_lock); + + /* Update status */ + if (value) + value = 0; + else + value = 0x0F; + + /* Set value to CPLD */ + status = as7515_sfp_write_value(reg, value); + if (unlikely(status < 0)) + goto exit; + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_module(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct as7515_sfp_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int status = 0; + u8 reg = 0, mask = 0, invert = 0; + + switch (attr->index) { + case MODULE_PRESENT_1 ... MODULE_RX_LOS_24: + invert = attribute_mappings[attr->index].invert; + reg = attribute_mappings[attr->index].reg; + mask = BIT(attr->index - attribute_mappings[attr->index].attr_base); + break; + default: + return 0; + } + + mutex_lock(&data->update_lock); + status = as7515_sfp_read_value(reg); + if (unlikely(status < 0)) + goto exit; + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", invert ? !(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 as7515_sfp_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + long value; + int status; + u8 reg = 0, mask = 0, invert = 0; + + status = kstrtol(buf, 10, &value); + if (status) + return status; + + switch (attr->index) { + case MODULE_LPMODE_1 ... MODULE_LPMODE_4: + case MODULE_RESET_1 ... MODULE_RESET_4: + case MODULE_TX_DISABLE_5 ... MODULE_TX_DISABLE_24: + invert = attribute_mappings[attr->index].invert; + reg = attribute_mappings[attr->index].reg; + mask = BIT(attr->index - attribute_mappings[attr->index].attr_base); + break; + default: + return 0; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as7515_sfp_read_value(reg); + if (unlikely(status < 0)) + goto exit; + + /* Update status */ + value = invert ? !value : !!value; + + if (value) + value = (status | mask); + else + value = (status & ~mask); + + /* Set value to CPLD */ + status = as7515_sfp_write_value(reg, value); + if (unlikely(status < 0)) + goto exit; + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static int as7515_sfp_probe(struct platform_device *pdev) +{ + int status = -1; + int i = 0; + struct as7515_sfp_data *data; + + data = kzalloc(sizeof(struct as7515_sfp_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + mutex_init(&data->update_lock); + platform_set_drvdata(pdev, data); + + /* Register sysfs hooks */ + for (i = 0; i < ARRAY_SIZE(sfp_group); i++) { + /* Register sysfs hooks */ + status = sysfs_create_group(&pdev->dev.kobj, &sfp_group[i]); + if (status) + goto exit_sysfs_group; + } + + dev_info(&pdev->dev, "device created\n"); + return 0; + +exit_sysfs_group: + for (--i; i >= 0; i--) { + sysfs_remove_group(&pdev->dev.kobj, &sfp_group[i]); + } + + kfree(data); + return status; +} + + +static int as7515_sfp_remove(struct platform_device *pdev) +{ + struct as7515_sfp_data *data = platform_get_drvdata(pdev); + int i = 0; + + for (i = 0; i < ARRAY_SIZE(sfp_group); i++) { + sysfs_remove_group(&pdev->dev.kobj, &sfp_group[i]); + } + + kfree(data); + return 0; +} + +static const struct platform_device_id as7515_sfp_id[] = { + { DRVNAME, 0 }, + {} +}; +MODULE_DEVICE_TABLE(platform, as7515_sfp_id); + +static struct platform_driver as7515_sfp_driver = { + .probe = as7515_sfp_probe, + .remove = as7515_sfp_remove, + .id_table = as7515_sfp_id, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(as7515_sfp_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as7515_sfp driver"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/Makefile b/packages/platforms/accton/x86-64/as7515-24x/onlp/Makefile new file mode 100644 index 0000000000..502e772a7b --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/PKG.yml b/packages/platforms/accton/x86-64/as7515-24x/onlp/PKG.yml new file mode 100644 index 0000000000..9b251eca72 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-accton-as7515-24x ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/Makefile b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/Makefile new file mode 100644 index 0000000000..e7437cb23a --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/lib/Makefile b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/lib/Makefile new file mode 100644 index 0000000000..0c95ed138b --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/lib/Makefile @@ -0,0 +1,3 @@ +PLATFORM := x86-64-accton-as7515-24x +include $(ONL)/packages/base/any/onlp/builds/platform/libonlp-platform.mk + diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/onlpdump/Makefile b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/onlpdump/Makefile new file mode 100644 index 0000000000..8127081a47 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/onlpdump/Makefile @@ -0,0 +1,3 @@ +PLATFORM := x86-64-accton-as7515-24x +include $(ONL)/packages/base/any/onlp/builds/platform/onlps.mk + diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/.module b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/.module new file mode 100644 index 0000000000..ae32691d30 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/.module @@ -0,0 +1 @@ +name: x86_64_accton_as7515_24x diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/Makefile b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/Makefile new file mode 100644 index 0000000000..2a2ea0690b --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include $(ONL)/make/config.mk +MODULE := x86_64_accton_as7515_24x +AUTOMODULE := x86_64_accton_as7515_24x +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/auto/make.mk b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/auto/make.mk new file mode 100644 index 0000000000..46fe550bf8 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/auto/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# x86_64_accton_as7515_24x Autogeneration +# +############################################################################### +x86_64_accton_as7515_24x_AUTO_DEFS := module/auto/x86_64_accton_as7515_24x.yml +x86_64_accton_as7515_24x_AUTO_DIRS := module/inc/x86_64_accton_as7515_24x module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/auto/x86_64_accton_as7515_24x.yml b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/auto/x86_64_accton_as7515_24x.yml new file mode 100644 index 0000000000..88cc4132a5 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/auto/x86_64_accton_as7515_24x.yml @@ -0,0 +1,50 @@ +############################################################################### +# +# x86_64_accton_as7515_24x Autogeneration Definitions +# +############################################################################### + +cdefs: &cdefs +- X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- X86_64_ACCTON_AS7515_24X_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- X86_64_ACCTON_AS7515_24X_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- X86_64_ACCTON_AS7515_24X_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: x86_64_accton_as7515_24x_CONFIG_PORTING_STDLIB +- X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- X86_64_ACCTON_AS7515_24X_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_as7515_24x_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_accton_as7515_24x_config + + portingmacro: + x86_64_accton_as7515_24x: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/inc/x86_64_accton_as7515_24x/x86_64_accton_as7515_24x.x b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/inc/x86_64_accton_as7515_24x/x86_64_accton_as7515_24x.x new file mode 100644 index 0000000000..9cd6cee5e7 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/inc/x86_64_accton_as7515_24x/x86_64_accton_as7515_24x.x @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/inc/x86_64_accton_as7515_24x/x86_64_accton_as7515_24x_config.h b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/inc/x86_64_accton_as7515_24x/x86_64_accton_as7515_24x_config.h new file mode 100644 index 0000000000..602864801e --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/inc/x86_64_accton_as7515_24x/x86_64_accton_as7515_24x_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_as7515_24x Configuration Header + * + * @addtogroup x86_64_accton_as7515_24x-config + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_accton_as7515_24x_CONFIG_H__ +#define __x86_64_accton_as7515_24x_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef x86_64_accton_as7515_24x_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_LOGGING +#define X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * X86_64_ACCTON_AS7515_24X_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef X86_64_ACCTON_AS7515_24X_CONFIG_LOG_OPTIONS_DEFAULT +#define X86_64_ACCTON_AS7515_24X_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * X86_64_ACCTON_AS7515_24X_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef X86_64_ACCTON_AS7515_24X_CONFIG_LOG_BITS_DEFAULT +#define X86_64_ACCTON_AS7515_24X_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * X86_64_ACCTON_AS7515_24X_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef X86_64_ACCTON_AS7515_24X_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define X86_64_ACCTON_AS7515_24X_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_STDLIB +#define X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS x86_64_accton_as7515_24x_CONFIG_PORTING_STDLIB +#endif + +/** + * X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_UCLI +#define X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_accton_as7515_24x_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_accton_as7515_24x_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_accton_as7515_24x_config_settings table. */ +extern x86_64_accton_as7515_24x_config_settings_t x86_64_accton_as7515_24x_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_accton_as7515_24x_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_accton_as7515_24x_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_accton_as7515_24x_porting.h" + +#endif /* __x86_64_accton_as7515_24x_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/inc/x86_64_accton_as7515_24x/x86_64_accton_as7515_24x_dox.h b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/inc/x86_64_accton_as7515_24x/x86_64_accton_as7515_24x_dox.h new file mode 100644 index 0000000000..4650dfd76c --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/inc/x86_64_accton_as7515_24x/x86_64_accton_as7515_24x_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_accton_as7515_24x Doxygen Header + * + *****************************************************************************/ +#ifndef __x86_64_accton_as7515_24x_DOX_H__ +#define __x86_64_accton_as7515_24x_DOX_H__ + +/** + * @defgroup x86_64_accton_as7515_24x x86_64_accton_as7515_24x - x86_64_accton_as7515_24x Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_accton_as7515_24x-x86_64_accton_as7515_24x Public Interface + * @defgroup x86_64_accton_as7515_24x-config Compile Time Configuration + * @defgroup x86_64_accton_as7515_24x-porting Porting Macros + * + * @} + * + */ + +#endif /* __x86_64_accton_as7515_24x_DOX_H__ */ diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/inc/x86_64_accton_as7515_24x/x86_64_accton_as7515_24x_porting.h b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/inc/x86_64_accton_as7515_24x/x86_64_accton_as7515_24x_porting.h new file mode 100644 index 0000000000..0a7f4f1f0f --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/inc/x86_64_accton_as7515_24x/x86_64_accton_as7515_24x_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_as7515_24x Porting Macros. + * + * @addtogroup x86_64_accton_as7515_24x-porting + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_accton_as7515_24x_PORTING_H__ +#define __x86_64_accton_as7515_24x_PORTING_H__ + + +/* */ +#if X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef X86_64_ACCTON_AS7515_24X_MALLOC + #if defined(GLOBAL_MALLOC) + #define X86_64_ACCTON_AS7515_24X_MALLOC GLOBAL_MALLOC + #elif X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7515_24X_MALLOC malloc + #else + #error The macro X86_64_ACCTON_AS7515_24X_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7515_24X_FREE + #if defined(GLOBAL_FREE) + #define X86_64_ACCTON_AS7515_24X_FREE GLOBAL_FREE + #elif X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7515_24X_FREE free + #else + #error The macro X86_64_ACCTON_AS7515_24X_FREE is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7515_24X_MEMSET + #if defined(GLOBAL_MEMSET) + #define X86_64_ACCTON_AS7515_24X_MEMSET GLOBAL_MEMSET + #elif X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7515_24X_MEMSET memset + #else + #error The macro X86_64_ACCTON_AS7515_24X_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7515_24X_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define X86_64_ACCTON_AS7515_24X_MEMCPY GLOBAL_MEMCPY + #elif X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7515_24X_MEMCPY memcpy + #else + #error The macro X86_64_ACCTON_AS7515_24X_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7515_24X_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define X86_64_ACCTON_AS7515_24X_STRNCPY GLOBAL_STRNCPY + #elif X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7515_24X_STRNCPY strncpy + #else + #error The macro X86_64_ACCTON_AS7515_24X_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7515_24X_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define X86_64_ACCTON_AS7515_24X_VSNPRINTF GLOBAL_VSNPRINTF + #elif X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7515_24X_VSNPRINTF vsnprintf + #else + #error The macro X86_64_ACCTON_AS7515_24X_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7515_24X_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define X86_64_ACCTON_AS7515_24X_SNPRINTF GLOBAL_SNPRINTF + #elif X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7515_24X_SNPRINTF snprintf + #else + #error The macro X86_64_ACCTON_AS7515_24X_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS7515_24X_STRLEN + #if defined(GLOBAL_STRLEN) + #define X86_64_ACCTON_AS7515_24X_STRLEN GLOBAL_STRLEN + #elif X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS7515_24X_STRLEN strlen + #else + #error The macro X86_64_ACCTON_AS7515_24X_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __x86_64_accton_as7515_24x_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/make.mk b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/make.mk new file mode 100644 index 0000000000..5f1f189bed --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_accton_as7515_24x_INCLUDES := -I $(THIS_DIR)inc +x86_64_accton_as7515_24x_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_accton_as7515_24x_DEPENDMODULE_ENTRIES := init:x86_64_accton_as7515_24x ucli:x86_64_accton_as7515_24x + diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/Makefile b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/Makefile new file mode 100644 index 0000000000..ccb98326a5 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_accton_as7515_24x_ucli.c + diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/debug.c b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/debug.c new file mode 100644 index 0000000000..f4ec955d37 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/debug.c @@ -0,0 +1,68 @@ +/************************************************************ + * + * + * 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 "x86_64_accton_as7515_24x_int.h" + +#if x86_64_accton_as7515_24x_CONFIG_INCLUDE_DEBUG == 1 + +#include + +static char help__[] = + "Usage: debug [options]\n" + " -c CPLD Versions\n" + " -h Help\n" + ; + +int +x86_64_accton_as7515_24x_debug_main(int argc, char* argv[]) +{ + int c = 0; + int help = 0; + int rv = 0; + + while( (c = getopt(argc, argv, "ch")) != -1) { + switch(c) + { + case 'c': c = 1; break; + case 'h': help = 1; rv = 0; break; + default: help = 1; rv = 1; break; + } + + } + + if(help || argc == 1) { + printf("%s", help__); + return rv; + } + + if(c) { + printf("Not implemented.\n"); + } + + + return 0; +} + +#endif diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/fani.c b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/fani.c new file mode 100644 index 0000000000..db8d271bd7 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/fani.c @@ -0,0 +1,185 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +enum fan_id { + FAN_1_ON_FAN_BOARD = 1, + FAN_2_ON_FAN_BOARD, + FAN_3_ON_FAN_BOARD, + FAN_4_ON_FAN_BOARD, + FAN_5_ON_FAN_BOARD +}; + +#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,\ + } + +/* Static fan information */ +onlp_fan_info_t finfo[] = { + { }, /* Not used */ + CHASSIS_FAN_INFO(1), + CHASSIS_FAN_INFO(2), + CHASSIS_FAN_INFO(3), + CHASSIS_FAN_INFO(4), + CHASSIS_FAN_INFO(5) +}; + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +_onlp_fani_info_get(int fid, onlp_fan_info_t* info) +{ + int value, ret, pwm; + + /* get fan present status + */ + ret = fan_info_get(fid, "present", &value); + if (ret < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + if (value == 0) { + return ONLP_STATUS_OK; + } + info->status |= ONLP_FAN_STATUS_PRESENT; + + /* get fan fault status (turn on when any one fails) + */ + ret = fan_info_get(fid, "fault", &value); + if (ret < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + if (value > 0) { + info->status |= ONLP_FAN_STATUS_FAILED; + return ONLP_STATUS_OK; + } + + /* get fan speed + */ + ret = fan_info_get(fid, "input", &value); + if (ret < 0) { + return ONLP_STATUS_E_INTERNAL; + } + info->rpm = value; + + /* get speed percentage from rpm + */ + pwm = 0; + ret = fan_info_get(fid, "pwm", &pwm); + if (ret < 0) { + return ONLP_STATUS_E_INTERNAL; + } + + value = 0; + ret = fan_info_get(fid, "target", &value); + if (ret < 0 || value == 0) { + return ONLP_STATUS_E_INTERNAL; + } + + info->percentage = (info->rpm*pwm)/value; + if (info->percentage > 100) + info->percentage = 100; + + 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_FAN_BOARD: + case FAN_2_ON_FAN_BOARD: + case FAN_3_ON_FAN_BOARD: + case FAN_4_ON_FAN_BOARD: + case FAN_5_ON_FAN_BOARD: + rc = _onlp_fani_info_get(fid, info); + break; + default: + rc = ONLP_STATUS_E_INVALID; + break; + } + + return rc; +} + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_percentage_set(onlp_oid_t id, int p) +{ + int fid; + + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + + if (fid < FAN_1_ON_FAN_BOARD || fid > FAN_5_ON_FAN_BOARD) { + return ONLP_STATUS_E_UNSUPPORTED; + } + + if (onlp_file_write_int(p, FAN_SYSFS_FORMAT, fid, "pwm") != 0) { + AIM_LOG_ERROR("Unable to change duty cycle of fan (%d)\r\n", fid); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/ledi.c b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/ledi.c new file mode 100644 index 0000000000..bc3a127477 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/ledi.c @@ -0,0 +1,226 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2013 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +enum led_light_mode { /*must be the same with the definition @ kernel driver */ + LED_MODE_OFF, + LED_MODE_RED = 10, + LED_MODE_RED_BLINKING = 11, + LED_MODE_ORANGE = 12, + LED_MODE_ORANGE_BLINKING = 13, + LED_MODE_YELLOW = 14, + LED_MODE_YELLOW_BLINKING = 15, + LED_MODE_GREEN = 16, + LED_MODE_GREEN_BLINKING = 17, + LED_MODE_BLUE = 18, + LED_MODE_BLUE_BLINKING = 19, + LED_MODE_PURPLE = 20, + LED_MODE_PURPLE_BLINKING = 21, + LED_MODE_AUTO = 22, + LED_MODE_AUTO_BLINKING = 23, + LED_MODE_WHITE = 24, + LED_MODE_WHITE_BLINKING = 25, + LED_MODE_CYAN = 26, + LED_MODE_CYAN_BLINKING = 27, + LED_MODE_UNKNOWN = 99 +}; + +typedef struct led_light_mode_map { + enum onlp_led_id id; + enum led_light_mode driver_led_mode; + enum onlp_led_mode_e onlp_led_mode; +} led_light_mode_map_t; + +led_light_mode_map_t led_map[] = { + { LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF }, + { LED_LOC, LED_MODE_BLUE_BLINKING, ONLP_LED_MODE_BLUE_BLINKING }, + { LED_DIAG, LED_MODE_ORANGE, ONLP_LED_MODE_ORANGE }, + { LED_DIAG, LED_MODE_GREEN, ONLP_LED_MODE_GREEN }, + { LED_DIAG, LED_MODE_GREEN_BLINKING,ONLP_LED_MODE_GREEN_BLINKING }, + { LED_PSU1, LED_MODE_OFF, ONLP_LED_MODE_OFF }, + { LED_PSU1, LED_MODE_GREEN, ONLP_LED_MODE_GREEN }, + { LED_PSU1, LED_MODE_ORANGE, ONLP_LED_MODE_ORANGE }, + { LED_PSU2, LED_MODE_OFF, ONLP_LED_MODE_OFF }, + { LED_PSU2, LED_MODE_GREEN, ONLP_LED_MODE_GREEN }, + { LED_PSU2, LED_MODE_ORANGE, ONLP_LED_MODE_ORANGE }, + { LED_FAN, LED_MODE_OFF, ONLP_LED_MODE_OFF }, + { LED_FAN, LED_MODE_GREEN, ONLP_LED_MODE_GREEN }, + { LED_FAN, LED_MODE_ORANGE, ONLP_LED_MODE_ORANGE } +}; + +static char *leds[] = { /* must map with onlp_led_id */ + NULL, + "loc", + "diag", + "psu1", + "psu2", + "fan" +}; + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t linfo[] = +{ + { }, /* Not used */ + { + { ONLP_LED_ID_CREATE(LED_LOC), "Chassis LED 1 (LOC LED)", 0, {0} }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_BLUE_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_DIAG), "Chassis LED 2 (DIAG LED)", 0, {0} }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_GREEN_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU1), "Chassis LED 3 (PSU1 LED)", 0, {0} }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU2), "Chassis LED 4 (PSU2 LED)", 0, {0} }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN, + }, + { + { ONLP_LED_ID_CREATE(LED_FAN), "Chassis LED 5 (FAN LED)", 0, {0} }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN, + } +}; + +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, SYS_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); + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function puts the LED into the given mode. It is a more functional + * interface for multimode LEDs. + * + * Only modes reported in the LED's capabilities will be attempted. + */ +int +onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) +{ + int lid; + VALIDATE(id); + + lid = ONLP_OID_ID_GET(id); + + if (onlp_file_write_int(onlp_to_driver_led_mode(lid , mode), SYS_LED_FORMAT, leds[lid]) != 0) { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/make.mk b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/make.mk new file mode 100644 index 0000000000..1a1833b3eb --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_accton_as7515_24x +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/platform_lib.c b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/platform_lib.c new file mode 100644 index 0000000000..33e56252eb --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/platform_lib.c @@ -0,0 +1,142 @@ +/************************************************************ + * + * + * 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" + +char* psu_get_eeprom_dir(int pid) +{ + char *path[] = { PSU1_EEPROM_SYSFS_FORMAT, PSU2_EEPROM_SYSFS_FORMAT }; + return path[pid-1]; +} + +char* psu_get_pmbus_dir(int pid) +{ + char *path[] = { PSU1_PMBUS_SYSFS_FORMAT, PSU2_PMBUS_SYSFS_FORMAT }; + return path[pid-1]; +} + +int onlp_get_psu_hwmon_idx(int pid) +{ + /* find hwmon index */ + char* file = NULL; + char* dir = NULL; + char path[64]; + int ret, hwmon_idx, max_hwmon_idx = 20; + + dir = psu_get_pmbus_dir(pid); + if (dir == NULL) + return ONLP_STATUS_E_INTERNAL; + + for (hwmon_idx = 0; hwmon_idx <= max_hwmon_idx; hwmon_idx++) { + snprintf(path, sizeof(path), "%s/hwmon/hwmon%d/", dir, hwmon_idx); + + ret = onlp_file_find(path, "name", &file); + AIM_FREE_IF_PTR(file); + + if (ONLP_STATUS_OK == ret) + return hwmon_idx; + } + + return -1; +} + +int onlp_get_fan_hwmon_idx(void) +{ + /* find hwmon index */ + char* file = NULL; + char path[64]; + int ret, hwmon_idx, max_hwmon_idx = 20; + + for (hwmon_idx = 0; hwmon_idx <= max_hwmon_idx; hwmon_idx++) { + snprintf(path, sizeof(path), "/sys/bus/i2c/devices/8-0066/hwmon/hwmon%d/", hwmon_idx); + + ret = onlp_file_find(path, "name", &file); + AIM_FREE_IF_PTR(file); + + if (ONLP_STATUS_OK == ret) + return hwmon_idx; + } + + return -1; +} + +int psu_cpld_status_get(int pid, char *node, int *value) +{ + char *path; + *value = 0; + + path = psu_get_eeprom_dir(pid); + if (path == NULL) + return ONLP_STATUS_E_INTERNAL; + + return onlp_file_read_int(value, "%s*%s", path, node); +} + +int psu_eeprom_str_get(int pid, char *data_buf, int data_len, char *data_name) +{ + char *path; + int len = 0; + char *str = NULL; + + path = psu_get_eeprom_dir(pid); + if (path == NULL) + return ONLP_STATUS_E_INTERNAL; + + /* Read attribute */ + len = onlp_file_read_str(&str, "%s/%s", path, 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; +} + +int psu_pmbus_info_get(int pid, char *node, int *value) +{ + char *path; + *value = 0; + + path = psu_get_pmbus_dir(pid); + if (path == NULL) + return ONLP_STATUS_E_INTERNAL; + + return onlp_file_read_int(value, "%s*%s", path, node); +} + +int fan_info_get(int fid, char *node, int *value) +{ + *value = 0; + return onlp_file_read_int(value, FAN_SYSFS_FORMAT, fid, node); +} diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/platform_lib.h b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/platform_lib.h new file mode 100644 index 0000000000..870d5ab1f8 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/platform_lib.h @@ -0,0 +1,90 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#ifndef __PLATFORM_LIB_H__ +#define __PLATFORM_LIB_H__ + +#include "x86_64_accton_as7515_24x_log.h" + +#define CHASSIS_FAN_COUNT 5 +#define CHASSIS_THERMAL_COUNT 7 +#define CHASSIS_LED_COUNT 5 +#define CHASSIS_PSU_COUNT 2 +#define NUM_OF_THERMAL_PER_PSU 2 + +#define PSU1_ID 1 +#define PSU2_ID 2 + +#define PSU1_EEPROM_SYSFS_FORMAT "/sys/bus/i2c/devices/6-0052" +#define PSU2_EEPROM_SYSFS_FORMAT "/sys/bus/i2c/devices/7-0050" +#define PSU1_PMBUS_SYSFS_FORMAT "/sys/bus/i2c/devices/6-005a" +#define PSU2_PMBUS_SYSFS_FORMAT "/sys/bus/i2c/devices/7-0058" + +#define FAN_SYSFS_FORMAT "/sys/bus/i2c/devices/8-0066*fan%d_%s" +#define FAN_SYSFS_FORMAT_1 "/sys/bus/i2c/devices/8-0066/hwmon/hwmon%d/%s" +#define SYS_LED_FORMAT "/sys/devices/platform/as7515_24x_led/led_%s" +#define IDPROM_PATH "/sys/bus/i2c/devices/4-0056/eeprom" + +enum onlp_thermal_id { + THERMAL_RESERVED = 0, + THERMAL_CPU_CORE, + THERMAL_1_ON_MAIN_BROAD, + THERMAL_2_ON_MAIN_BROAD, + THERMAL_3_ON_MAIN_BROAD, + THERMAL_4_ON_MAIN_BROAD, + THERMAL_5_ON_MAIN_BROAD, + THERMAL_6_ON_MAIN_BROAD, + THERMAL_1_ON_PSU1, + THERMAL_2_ON_PSU1, + THERMAL_1_ON_PSU2, + THERMAL_2_ON_PSU2, + THERMAL_COUNT +}; + +enum onlp_led_id { + LED_LOC = 1, + LED_DIAG, + LED_PSU1, + LED_PSU2, + LED_FAN +}; + +int psu_cpld_status_get(int pid, char *node, int *value); +int psu_pmbus_info_get(int id, char *node, int *value); +int psu_eeprom_str_get(int pid, char *data_buf, int data_len, char *data_name); +int onlp_get_psu_hwmon_idx(int pid); +int onlp_get_fan_hwmon_idx(void); +int fan_info_get(int fid, char *node, int *value); + +#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/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/psui.c b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/psui.c new file mode 100644 index 0000000000..79282b3eb2 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/psui.c @@ -0,0 +1,153 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#define PSU_STATUS_PRESENT 1 +#define PSU_STATUS_POWER_GOOD 1 + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +int +onlp_psui_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * Get all information about the given PSU oid. + */ +static onlp_psu_info_t pinfo[] = { + { }, /* Not used */ + { + { ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0, {0} }, + }, + { + { ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0, {0} }, + } +}; + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int val = 0; + int ret = ONLP_STATUS_OK; + int pid = ONLP_OID_ID_GET(id); + int thermal_count = 0; + VALIDATE(id); + + memset(info, 0, sizeof(onlp_psu_info_t)); + *info = pinfo[pid]; /* Set the onlp_oid_hdr_t */ + + /* Get the present state */ + val = 0; + ret = psu_cpld_status_get(pid, "psu_present", &val); + if (ret < 0) { + info->status &= ~ONLP_PSU_STATUS_PRESENT; + 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 */ + val = 0; + ret = psu_cpld_status_get(pid, "psu_power_good", &val); + if (ret < 0) { + info->status |= ONLP_PSU_STATUS_FAILED; + return ONLP_STATUS_E_INTERNAL; + } + + if (val != PSU_STATUS_POWER_GOOD) { + info->status |= ONLP_PSU_STATUS_FAILED; + return ONLP_STATUS_OK; + } + + /* Set capability + */ + info->caps = ONLP_PSU_CAPS_AC; + + /* Set the associated oid_table */ + thermal_count = CHASSIS_THERMAL_COUNT; + info->hdr.coids[0] = ONLP_THERMAL_ID_CREATE(thermal_count + (pid-1)*NUM_OF_THERMAL_PER_PSU + 1); + info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(thermal_count + (pid-1)*NUM_OF_THERMAL_PER_PSU + 2); + + /* Read voltage, current and power */ + val = 0; + ret = psu_pmbus_info_get(pid, "psu_v_in", &val); + if (ret == ONLP_STATUS_OK && val) { + info->mvin = val; + info->caps |= ONLP_PSU_CAPS_VIN; + } + + val = 0; + ret = psu_pmbus_info_get(pid, "psu_i_in", &val); + if (ret == ONLP_STATUS_OK && val) { + info->miin = val; + info->caps |= ONLP_PSU_CAPS_IIN; + } + + val = 0; + ret = psu_pmbus_info_get(pid, "psu_p_in", &val); + if (ret == ONLP_STATUS_OK && val) { + info->mpin = val; + info->caps |= ONLP_PSU_CAPS_PIN; + } + + val = 0; + ret = psu_pmbus_info_get(pid, "psu_v_out", &val); + if (ret == ONLP_STATUS_OK && val) { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + val = 0; + ret = psu_pmbus_info_get(pid, "psu_i_out", &val); + if (ret == ONLP_STATUS_OK && val) { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + val = 0; + ret = psu_pmbus_info_get(pid, "psu_p_out", &val); + if (ret == ONLP_STATUS_OK && val) { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + psu_eeprom_str_get(pid, info->model, sizeof(info->model), "psu_model_name"); + psu_eeprom_str_get(pid, info->serial, sizeof(info->serial), "psu_serial_numer"); + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/sfpi.c b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/sfpi.c new file mode 100644 index 0000000000..f7d7c8b922 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/sfpi.c @@ -0,0 +1,380 @@ +/************************************************************ + * + * + * 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_as7515_24x_int.h" +#include "x86_64_accton_as7515_24x_log.h" + +#define VALIDATE_SFP(_port) \ + do { \ + if (_port < 4 || _port > 23) \ + return ONLP_STATUS_E_UNSUPPORTED; \ + } while(0) + +#define VALIDATE_QSFP(_port) \ + do { \ + if (_port < 0 || _port > 3 ) \ + return ONLP_STATUS_E_UNSUPPORTED; \ + } while(0) + +#define MODULE_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" +#define MODULE_PRESENT_FORMAT "/sys/devices/platform/as7515_24x_sfp/module_present_%d" +#define MODULE_RXLOS_FORMAT "/sys/devices/platform/as7515_24x_sfp/module_rx_los_%d" +#define MODULE_TXFAULT_FORMAT "/sys/devices/platform/as7515_24x_sfp/module_tx_fault_%d" +#define MODULE_TXDISABLE_FORMAT "/sys/devices/platform/as7515_24x_sfp/module_tx_disable_%d" +#define MODULE_RESET_FORMAT "/sys/devices/platform/as7515_24x_sfp/module_reset_%d" +#define MODULE_LPMODE_FORMAT "/sys/devices/platform/as7515_24x_sfp/module_lpmode_%d" +#define MODULE_PRESENT_ALL_ATTR "/sys/devices/platform/as7515_24x_sfp/module_present_all" +#define MODULE_RXLOS_ALL_ATTR "/sys/devices/platform/as7515_24x_sfp/module_rx_los_all" + +#define NUM_OF_SFP_PORT 24 +static const int port_bus_index[NUM_OF_SFP_PORT] = { + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37 +}; + +#define PORT_BUS_INDEX(port) (port_bus_index[port]) + +/************************************************************ + * + * 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 {0, 23} + */ + int p; + + for(p = 0; p < NUM_OF_SFP_PORT; p++) { + AIM_BITMAP_SET(bmap, p); + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_present(int port) +{ + /* + * Return 1 if present. + * Return 0 if not present. + * Return < 0 if error. + */ + int present; + + 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+1); + return ONLP_STATUS_E_INTERNAL; + } + + return present; +} + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + int i = 0; + uint32_t bytes[3] = {0}; + FILE* fp = NULL; + int count = 0; + + /* Read present status of each port */ + fp = fopen(MODULE_PRESENT_ALL_ATTR, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD."); + return ONLP_STATUS_E_INTERNAL; + } + + count = fscanf(fp, "%x %x %x", bytes+0, bytes+1, bytes+2); + fclose(fp); + + if(count != 3) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD."); + return ONLP_STATUS_E_INTERNAL; + } + + /* Convert to 64 bit integer in port order */ + AIM_BITMAP_CLR_ALL(dst); + uint32_t presence_all = 0 ; + for (i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) { + presence_all <<= 8; + presence_all |= bytes[i]; + } + + /* Populate bitmap */ + for (i = 0; presence_all; i++) { + AIM_BITMAP_MOD(dst, i, (presence_all & 1)); + presence_all >>= 1; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + int i = 0; + uint32_t bytes[3] = {0}; + FILE* fp = NULL; + int count = 0; + + /* Read present status of each port */ + fp = fopen(MODULE_RXLOS_ALL_ATTR, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_present_all device file of CPLD."); + return ONLP_STATUS_E_INTERNAL; + } + + count = fscanf(fp, "%x %x %x", bytes+0, bytes+1, bytes+2); + fclose(fp); + + if(count != 3) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields the module_present_all device file of CPLD."); + return ONLP_STATUS_E_INTERNAL; + } + + /* Convert to 64 bit integer in port order */ + AIM_BITMAP_CLR_ALL(dst); + uint32_t rx_los_all = 0 ; + for (i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) { + rx_los_all <<= 8; + rx_los_all |= bytes[i]; + } + /* Populate bitmap */ + for(i = 0; rx_los_all; i++) { + AIM_BITMAP_MOD(dst, i, (rx_los_all & 1)); + rx_los_all >>= 1; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + /* + * Read the SFP eeprom into data[] + * + * Return MISSING if SFP is missing. + * Return OK if eeprom is read + */ + int size = 0; + memset(data, 0, 256); + + if(onlp_file_read(data, 256, &size, MODULE_EEPROM_FORMAT, PORT_BUS_INDEX(port)) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + FILE* fp; + char file[64] = {0}; + + sprintf(file, MODULE_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_dev_readb(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = PORT_BUS_INDEX(port); + return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) +{ + int bus = PORT_BUS_INDEX(port); + return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) +{ + int bus = PORT_BUS_INDEX(port); + return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) +{ + int bus = PORT_BUS_INDEX(port); + return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE); +} + +int +onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) +{ + switch(control) { + case ONLP_SFP_CONTROL_TX_DISABLE: { + VALIDATE_SFP(port); + + 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; + } + case ONLP_SFP_CONTROL_RESET_STATE: { + VALIDATE_QSFP(port); + + if (onlp_file_write_int(value, MODULE_RESET_FORMAT, port+1) < 0) { + AIM_LOG_ERROR("Unable to write reset status to port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; + } + case ONLP_SFP_CONTROL_LP_MODE: { + VALIDATE_QSFP(port); + + if (onlp_file_write_int(value, MODULE_LPMODE_FORMAT, port+1) < 0) { + AIM_LOG_ERROR("Unable to write reset status to port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; + } + default: + break; + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) +{ + *value = 0; + + 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: { + VALIDATE_SFP(port); + + 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; + } + case ONLP_SFP_CONTROL_RESET_STATE: { + VALIDATE_QSFP(port); + + if (onlp_file_read_int(value, MODULE_RESET_FORMAT, port+1) < 0) { + AIM_LOG_ERROR("Unable to read reset status from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; + } + case ONLP_SFP_CONTROL_LP_MODE: { + VALIDATE_QSFP(port); + + if (onlp_file_read_int(value, MODULE_LPMODE_FORMAT, port+1) < 0) { + AIM_LOG_ERROR("Unable to read lpmode status from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; + } + default: + break; + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/sysi.c b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/sysi.c new file mode 100644 index 0000000000..be28df4b06 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/sysi.c @@ -0,0 +1,385 @@ +/************************************************************ + * + * + * 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 +#include "platform_lib.h" + +#include "x86_64_accton_as7515_24x_int.h" +#include "x86_64_accton_as7515_24x_log.h" + +#define NUM_OF_CPLD_VER 3 +#define THERMAL_POLICY_SENSOR_COUNT 5 + +int onlp_sysi_set_fan_duty_all(int duty); +int onlp_sysi_get_fan_status(void); +int onlp_sysi_get_thermal_temp(int tid, int *temp); + +enum fan_duty_level { + FAN_DUTY_MIN = 40, + FAN_DUTY_MID = 70, + FAN_DUTY_MAX = 100 +}; + +typedef int (*temp_getter_t)(int tid, int *temp); +typedef int (*fan_pwm_setter_t)(int pwm); +typedef int (*fan_status_getter_t)(void); + +typedef struct { + int id; + int tlow_1; /* In mini-Celsius */ + int tup_1; /* In mini-Celsius */ + int tlow_2; /* In mini-Celsius */ + int tup_2; /* In mini-Celsius */ +} thermal_policy_t; + +typedef struct temp_handler { + temp_getter_t temp_reader; +} temp_handler_t; + +typedef struct fan_handler { + fan_pwm_setter_t pwm_writer; + fan_status_getter_t status_reader; +} fan_handler_t; + +struct thermal_policy_manager { + temp_getter_t temp_reader; + fan_handler_t fan_hdlr; + thermal_policy_t policy[THERMAL_POLICY_SENSOR_COUNT]; + const int duty_default; + const int duty_on_fail; +}; + +static struct thermal_policy_manager tp_mgr = { + .temp_reader = onlp_sysi_get_thermal_temp, + .fan_hdlr = { + .pwm_writer = onlp_sysi_set_fan_duty_all, + .status_reader = onlp_sysi_get_fan_status + }, + .duty_on_fail = FAN_DUTY_MAX, + .duty_default = FAN_DUTY_MIN, + .policy = { + [0] = { THERMAL_1_ON_MAIN_BROAD, 47000, 52000, 56000, 61000 }, /* MB_FrontCenter_temp(0x49) */ + [1] = { THERMAL_2_ON_MAIN_BROAD, 45000, 50000, 54000, 59000 }, /* MB_FrontLeft_temp(0x4A) */ + [2] = { THERMAL_3_ON_MAIN_BROAD, 53000, 58000, 61000, 66000 }, /* MB_FrontCenter_temp(0x4C) */ + [3] = { THERMAL_4_ON_MAIN_BROAD, 43000, 48000, 53000, 58000 }, /* MB_FrontRight_temp(0x4D) */ + [4] = { THERMAL_6_ON_MAIN_BROAD, 70000, 75000, 80000, 85000 } /* MB_RearLeft_temp(0x4C) */ + } +}; + +static char* cpld_ver_path[NUM_OF_CPLD_VER] = { + "/sys/devices/platform/as7515_24x_fpga/version", /* FPGA */ + "/sys/bus/i2c/devices/2-0061/version", /* CPLD */ + "/sys/bus/i2c/devices/8-0066/hwmon/hwmon*version" /* Fan CPLD */ +}; + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-accton-as7515-24x-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(rdata); + *size = 0; + return ONLP_STATUS_E_INTERNAL; +} + +int +onlp_sysi_oids_get(onlp_oid_t* table, int max) +{ + int i; + onlp_oid_t* e = table; + memset(table, 0, max*sizeof(onlp_oid_t)); + + /* 7 Thermal sensors on the chassis */ + for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* 5 LEDs on the chassis */ + for (i = 1; i <= CHASSIS_LED_COUNT; i++) { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* 2 PSUs on the chassis */ + for (i = 1; i <= CHASSIS_PSU_COUNT; i++) { + *e++ = ONLP_PSU_ID_CREATE(i); + } + + /* 5 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) +{ + int i, len, ret = ONLP_STATUS_OK; + char *v[NUM_OF_CPLD_VER] = { NULL }; + + for (i = 0; i < AIM_ARRAYSIZE(cpld_ver_path); i++) { + if (i == 2) { + int hwmon_idx = onlp_get_fan_hwmon_idx(); + + if (hwmon_idx < 0) { + ret = ONLP_STATUS_E_INTERNAL; + break; + } + + len = onlp_file_read_str(&v[i], FAN_SYSFS_FORMAT_1, hwmon_idx, "version"); + } + else { + len = onlp_file_read_str(&v[i], cpld_ver_path[i]); + } + + if (v[i] == NULL || len <= 0) { + ret = ONLP_STATUS_E_INTERNAL; + break; + } + } + + if (ret == ONLP_STATUS_OK) { + pi->cpld_versions = aim_fstrdup("\r\nFPGA:%s\r\nCPLD:%s" + "\r\nFan CPLD:%s", v[0], v[1], v[2]); + } + + for (i = 0; i < AIM_ARRAYSIZE(v); i++) { + AIM_FREE_IF_PTR(v[i]); + } + + return ret; +} + +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) +{ + aim_free(pi->cpld_versions); +} + +void +onlp_sysi_onie_data_free(uint8_t* data) +{ + aim_free(data); +} + +int +onlp_sysi_platform_manage_leds(void) +{ + int i, ret = ONLP_STATUS_OK; + int fan_led = ONLP_LED_MODE_GREEN; + int psu_led[CHASSIS_PSU_COUNT] = { ONLP_LED_MODE_GREEN, ONLP_LED_MODE_GREEN }; + + /* Get each fan status + */ + for (i = 1; i <= CHASSIS_FAN_COUNT; i++) + { + onlp_fan_info_t fan_info; + + ret = onlp_fani_info_get(ONLP_FAN_ID_CREATE(i), &fan_info); + if (ret != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to get fan(%d) status\r\n", i); + fan_led = ONLP_LED_MODE_ORANGE; + break; + } + + if (!(fan_info.status & ONLP_FAN_STATUS_PRESENT)) { + fan_led = ONLP_LED_MODE_ORANGE; + break; + } + + if (fan_info.status & ONLP_FAN_STATUS_FAILED) { + fan_led = ONLP_LED_MODE_ORANGE; + break; + } + } + + onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FAN), fan_led); + + /* Get each psu status + */ + for (i = 0; i < CHASSIS_PSU_COUNT; i++) { + onlp_psu_info_t psu_info; + + if (onlp_psui_info_get(ONLP_PSU_ID_CREATE(PSU1_ID + i), &psu_info) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to get psu(%d) status\r\n", i); + psu_led[i] = ONLP_LED_MODE_ORANGE; + continue; + } + + if (!(psu_info.status & ONLP_PSU_STATUS_PRESENT)) { + psu_led[i] = ONLP_LED_MODE_OFF; + continue; + } + + if (psu_info.status & ONLP_PSU_STATUS_FAILED) { + psu_led[i] = ONLP_LED_MODE_ORANGE; + continue; + } + } + + for (i = 0; i < CHASSIS_PSU_COUNT; i++) { + onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_PSU1 + i), psu_led[i]); + } + + return ONLP_STATUS_OK; +} + +int onlp_sysi_get_thermal_temp(int tid, int *temp) +{ + int ret; + onlp_thermal_info_t ti; + + ret = onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(tid), &ti); + if (ret != ONLP_STATUS_OK) + return ret; + + *temp = ti.mcelsius; + return ONLP_STATUS_OK; +} + +int onlp_sysi_set_fan_duty_all(int duty) +{ + int fid, ret = ONLP_STATUS_OK; + + for (fid = 1; fid <= CHASSIS_FAN_COUNT; fid++) { + if (ONLP_STATUS_OK != onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(fid), duty)) { + ret = ONLP_STATUS_E_INTERNAL; + } + } + + return ret; +} + +int onlp_sysi_get_fan_status(void) +{ + int i, ret; + onlp_fan_info_t fi[CHASSIS_FAN_COUNT]; + memset(fi, 0, sizeof(fi)); + + for (i = 0; i < CHASSIS_FAN_COUNT; i++) { + ret = onlp_fani_info_get(ONLP_FAN_ID_CREATE(i+1), &fi[i]); + if (ret != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to get fan(%d) status\r\n", i+1); + return ONLP_STATUS_E_INTERNAL; + } + + if (!(fi[i].status & ONLP_FAN_STATUS_PRESENT)) { + AIM_LOG_ERROR("Fan(%d) is NOT present\r\n", i+1); + return ONLP_STATUS_E_INTERNAL; + } + + if (fi[i].status & ONLP_FAN_STATUS_FAILED) { + AIM_LOG_ERROR("Fan(%d) is NOT operational\r\n", i+1); + return ONLP_STATUS_E_INTERNAL; + } + } + + return ONLP_STATUS_OK; +} + +int onlp_sysi_platform_manage_fans(void) +{ + int i, ret, duty_found = 0; + int all_below_tlow_1 = 1; + int all_below_tlow_2 = 1; + int any_above_tup_1 = 0; + int any_above_tup_2 = 0; + static int fan_duty = FAN_DUTY_MIN; + int temperature[THERMAL_POLICY_SENSOR_COUNT] = { 0 }; + + /* Get fan status + * Bring fan speed to FAN_DUTY_MAX if any fan is not present or operational + */ + if (tp_mgr.fan_hdlr.status_reader() != ONLP_STATUS_OK) { + fan_duty = tp_mgr.duty_on_fail; + tp_mgr.fan_hdlr.pwm_writer(fan_duty); + return ONLP_STATUS_E_INTERNAL; + } + + /* Get thermal status + * Bring fan speed to FAN_DUTY_MAX if read any thermal failed + */ + for (i = 0; i < AIM_ARRAYSIZE(tp_mgr.policy); i++) { + ret = tp_mgr.temp_reader(tp_mgr.policy[i].id, &temperature[i]); + if (ret != ONLP_STATUS_OK) { + fan_duty = tp_mgr.duty_on_fail; + tp_mgr.fan_hdlr.pwm_writer(fan_duty); + return ret; + } + } + + /* Apply thermal policy */ + for (i = 0; i < AIM_ARRAYSIZE(tp_mgr.policy); i++) { + any_above_tup_1 = (temperature[i] > tp_mgr.policy[i].tup_1) ? 1 : any_above_tup_1; + any_above_tup_2 = (temperature[i] > tp_mgr.policy[i].tup_2) ? 1 : any_above_tup_2; + all_below_tlow_1 = (temperature[i] >= tp_mgr.policy[i].tlow_1) ? 0 : all_below_tlow_1; + all_below_tlow_2 = (temperature[i] >= tp_mgr.policy[i].tlow_2) ? 0 : all_below_tlow_2; + } + + switch (fan_duty) { + case FAN_DUTY_MIN: + duty_found = 1; + fan_duty = any_above_tup_1 ? FAN_DUTY_MID : FAN_DUTY_MIN; + break; + case FAN_DUTY_MID: + duty_found = 1; + fan_duty = any_above_tup_2 ? FAN_DUTY_MAX : + (all_below_tlow_1 ? FAN_DUTY_MIN : FAN_DUTY_MID); + break; + case FAN_DUTY_MAX: + duty_found = 1; + fan_duty = all_below_tlow_2 ? FAN_DUTY_MID : FAN_DUTY_MAX; + break; + default: + duty_found = 0; + break; + } + + if (!duty_found) { + fan_duty = tp_mgr.duty_default; + } + + tp_mgr.fan_hdlr.pwm_writer(fan_duty); + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/thermali.c b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/thermali.c new file mode 100644 index 0000000000..00c07d7f36 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/thermali.c @@ -0,0 +1,143 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * Thermal Sensor Platform Implementation. + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static char* devfiles__[] = { /* must map with onlp_thermal_id */ + NULL, + NULL, /* CPU_CORE files */ + "/sys/bus/i2c/devices/13-0049*temp1_input", + "/sys/bus/i2c/devices/13-004a*temp1_input", + "/sys/bus/i2c/devices/13-004c*temp1_input", + "/sys/bus/i2c/devices/13-004d*temp1_input", + "/sys/bus/i2c/devices/1-004c*temp1_input", + "/sys/bus/i2c/devices/1-004c*temp2_input", + "/sys/bus/i2c/devices/6-005a*psu_temp2_input", + "/sys/bus/i2c/devices/6-005a*psu_temp3_input", + "/sys/bus/i2c/devices/7-0058*psu_temp2_input", + "/sys/bus/i2c/devices/7-0058*psu_temp3_input" +}; + +static char* cpu_coretemp_files[] = { + "/sys/devices/platform/coretemp.0*temp1_input", + "/sys/devices/platform/coretemp.0*temp4_input", + "/sys/devices/platform/coretemp.0*temp8_input", + "/sys/devices/platform/coretemp.0*temp10_input", + "/sys/devices/platform/coretemp.0*temp14_input", + NULL, +}; + +/* Static values */ +static onlp_thermal_info_t tinfo[] = { + { }, /* Not used */ + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE), "CPU Core", 0, {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, {79000, 87000, 95000} + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "MB_FrontCenter_temp(0x49)", 0, {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, {71000, 76000, 81000} + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_MAIN_BROAD), "MB_FrontLeft_temp(0x4A)", 0, {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, {69000, 74000, 79000} + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "MB_FrontCenter_temp(0x4C)", 0, {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, {76000, 81000, 86000} + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_4_ON_MAIN_BROAD), "MB_FrontRight_temp(0x4D)", 0, {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, {68000, 73000, 78000} + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_5_ON_MAIN_BROAD), "MB_RearCenter_temp(0x4C)", 0, {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_6_ON_MAIN_BROAD), "MB_RearLeft_temp(0x4C)", 0, {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, {95000, 100000, 105000} + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU1_ID), {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU1), "PSU-1 Thermal Sensor 2", ONLP_PSU_ID_CREATE(PSU1_ID), {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), "PSU-2 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU2_ID), {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU2), "PSU-2 Thermal Sensor 2", ONLP_PSU_ID_CREATE(PSU2_ID), {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + } +}; + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * Retrieve the information structure for the given thermal OID. + * + * If the OID is invalid, return ONLP_E_STATUS_INVALID. + * If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL. + * Otherwise, return ONLP_STATUS_OK with the OID's information. + * + * Note -- it is expected that you fill out the information + * structure even if the sensor described by the OID is not present. + */ +int +onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) +{ + int tid; + VALIDATE(id); + + tid = ONLP_OID_ID_GET(id); + *info = tinfo[tid]; + + if (tid == THERMAL_CPU_CORE) { + return onlp_file_read_int_max(&info->mcelsius, cpu_coretemp_files); + } + + return onlp_file_read_int(&info->mcelsius, devfiles__[tid]); +} diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_config.c b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_config.c new file mode 100644 index 0000000000..3bba21fc29 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_config.c @@ -0,0 +1,81 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_accton_as7515_24x_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_accton_as7515_24x_config_STRINGIFY_VALUE(_x) __x86_64_accton_as7515_24x_config_STRINGIFY_NAME(_x) +x86_64_accton_as7515_24x_config_settings_t x86_64_accton_as7515_24x_config_settings[] = +{ +#ifdef X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_LOGGING + { __x86_64_accton_as7515_24x_config_STRINGIFY_NAME(X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_LOGGING), __x86_64_accton_as7515_24x_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_LOGGING) }, +#else +{ X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_LOGGING(__x86_64_accton_as7515_24x_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7515_24X_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_accton_as7515_24x_config_STRINGIFY_NAME(X86_64_ACCTON_AS7515_24X_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_accton_as7515_24x_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7515_24X_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS7515_24X_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_accton_as7515_24x_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7515_24X_CONFIG_LOG_BITS_DEFAULT + { __x86_64_accton_as7515_24x_config_STRINGIFY_NAME(X86_64_ACCTON_AS7515_24X_CONFIG_LOG_BITS_DEFAULT), __x86_64_accton_as7515_24x_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7515_24X_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS7515_24X_CONFIG_LOG_BITS_DEFAULT(__x86_64_accton_as7515_24x_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7515_24X_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_accton_as7515_24x_config_STRINGIFY_NAME(X86_64_ACCTON_AS7515_24X_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_accton_as7515_24x_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7515_24X_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS7515_24X_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_accton_as7515_24x_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_STDLIB + { __x86_64_accton_as7515_24x_config_STRINGIFY_NAME(X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_STDLIB), __x86_64_accton_as7515_24x_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_STDLIB) }, +#else +{ X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_STDLIB(__x86_64_accton_as7515_24x_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_accton_as7515_24x_config_STRINGIFY_NAME(X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_accton_as7515_24x_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ X86_64_ACCTON_AS7515_24X_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_accton_as7515_24x_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_UCLI + { __x86_64_accton_as7515_24x_config_STRINGIFY_NAME(X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_UCLI), __x86_64_accton_as7515_24x_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_UCLI) }, +#else +{ X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_UCLI(__x86_64_accton_as7515_24x_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_accton_as7515_24x_config_STRINGIFY_NAME(X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_accton_as7515_24x_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ X86_64_ACCTON_AS7515_24X_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_accton_as7515_24x_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_accton_as7515_24x_config_STRINGIFY_VALUE +#undef __x86_64_accton_as7515_24x_config_STRINGIFY_NAME + +const char* +x86_64_accton_as7515_24x_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_accton_as7515_24x_config_settings[i].name; i++) { + if(!strcmp(x86_64_accton_as7515_24x_config_settings[i].name, setting)) { + return x86_64_accton_as7515_24x_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_accton_as7515_24x_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_accton_as7515_24x_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_accton_as7515_24x_config_settings[i].name, x86_64_accton_as7515_24x_config_settings[i].value); + } + return i; +} + +/* */ + diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_enums.c b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_enums.c new file mode 100644 index 0000000000..303f5fb496 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_int.h b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_int.h new file mode 100644 index 0000000000..ca473a3ea2 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_int.h @@ -0,0 +1,11 @@ +/**************************************************************************//** + * + * x86_64_accton_as7515_24x Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_accton_as7515_24x_INT_H__ +#define __x86_64_accton_as7515_24x_INT_H__ + +#include + +#endif /* __x86_64_accton_as7515_24x_INT_H__ */ diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_log.c b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_log.c new file mode 100644 index 0000000000..6cbf97873e --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_log.c @@ -0,0 +1,17 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_as7515_24x_log.h" +/* + * x86_64_accton_as7515_24x log struct. + */ +AIM_LOG_STRUCT_DEFINE( + X86_64_ACCTON_AS7515_24X_CONFIG_LOG_OPTIONS_DEFAULT, + X86_64_ACCTON_AS7515_24X_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + X86_64_ACCTON_AS7515_24X_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_log.h b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_log.h new file mode 100644 index 0000000000..31414914b3 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_accton_as7515_24x_LOG_H__ +#define __x86_64_accton_as7515_24x_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_accton_as7515_24x +#include + +#endif /* __x86_64_accton_as7515_24x_LOG_H__ */ diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_module.c b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_module.c new file mode 100644 index 0000000000..fbb7c5522a --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_as7515_24x_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_accton_as7515_24x_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_as7515_24x_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_ucli.c b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_ucli.c new file mode 100644 index 0000000000..9550046c12 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/onlp/builds/x86_64_accton_as7515_24x/module/src/x86_64_accton_as7515_24x_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if x86_64_accton_as7515_24x_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_accton_as7515_24x_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_accton_as7515_24x) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_accton_as7515_24x_ucli_module__ = + { + "x86_64_accton_as7515_24x_ucli", + NULL, + x86_64_accton_as7515_24x_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_accton_as7515_24x_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_accton_as7515_24x_ucli_module__); + n = ucli_node_create("x86_64_accton_as7515_24x", NULL, &x86_64_accton_as7515_24x_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_accton_as7515_24x")); + return n; +} + +#else +void* +x86_64_accton_as7515_24x_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/accton/x86-64/as7515-24x/platform-config/Makefile b/packages/platforms/accton/x86-64/as7515-24x/platform-config/Makefile new file mode 100644 index 0000000000..003238cf6d --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/as7515-24x/platform-config/r0/Makefile b/packages/platforms/accton/x86-64/as7515-24x/platform-config/r0/Makefile new file mode 100644 index 0000000000..003238cf6d --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/as7515-24x/platform-config/r0/PKG.yml b/packages/platforms/accton/x86-64/as7515-24x/platform-config/r0/PKG.yml new file mode 100644 index 0000000000..5080a1dca4 --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=accton BASENAME=x86-64-accton-as7515-24x REVISION=r0 diff --git a/packages/platforms/accton/x86-64/as7515-24x/platform-config/r0/src/lib/x86-64-accton-as7515-24x-r0.yml b/packages/platforms/accton/x86-64/as7515-24x/platform-config/r0/src/lib/x86-64-accton-as7515-24x-r0.yml new file mode 100644 index 0000000000..45de03967d --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/platform-config/r0/src/lib/x86-64-accton-as7515-24x-r0.yml @@ -0,0 +1,31 @@ +--- + +###################################################################### +# +# platform-config for AS7515-24X +# +###################################################################### + +x86-64-accton-as7515-24x-r0: + + grub: + + serial: >- + --port=0x3f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-5-4 + + args: >- + console=ttyS0,115200n8 + intel_iommu=pt + + ##network + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:14.0 diff --git a/packages/platforms/accton/x86-64/as7515-24x/platform-config/r0/src/python/x86_64_accton_as7515_24x_r0/__init__.py b/packages/platforms/accton/x86-64/as7515-24x/platform-config/r0/src/python/x86_64_accton_as7515_24x_r0/__init__.py new file mode 100644 index 0000000000..1348202b2b --- /dev/null +++ b/packages/platforms/accton/x86-64/as7515-24x/platform-config/r0/src/python/x86_64_accton_as7515_24x_r0/__init__.py @@ -0,0 +1,68 @@ +import commands +from itertools import chain +from onl.platform.base import * +from onl.platform.accton import * + +class OnlPlatform_x86_64_accton_as7515_24x_r0(OnlPlatformAccton, + OnlPlatformPortConfig_4x100_20x25): + PLATFORM='x86-64-accton-as7515-24x-r0' + MODEL="AS7515-24X" + SYS_OBJECT_ID=".7515.24" + + def modprobe(self, module, required=True, params={}): + cmd = "modprobe %s" % module + subprocess.check_call(cmd, shell=True) + + def baseconfig(self): + self.modprobe('optoe') + self.modprobe('at24') + self.modprobe('ym2651y') + + for m in [ 'fpga', 'cpld', 'fan', 'leds', 'mux', 'psu', 'sfp' ]: + self.insmod("x86-64-accton-as7515-24x-%s.ko" % m) + + ########### initialize I2C bus 0 ########### + self.new_i2c_devices([ + # initialize FPGA + ('as7515_fpga_mux', 0x77, 0), # i2c 1-13 + + # initialize CPLD + ('as7515_24x_cpld', 0x61, 2), + ('as7515_cpld_mux', 0x74, 2), # i2c 14-37 + + # initialize Thermal Sensor + ('tmp431', 0x4C, 1), + ('lm75', 0x49, 13), + ('lm75', 0x4A, 13), + ('lm75', 0x4C, 13), + ('lm75', 0x4D, 13), + + # initiate PSU + ('as7515_24x_psu1', 0x52, 6), + ('ym2401', 0x5A, 6), + ('as7515_24x_psu2', 0x50, 7), + ('ym2401', 0x58, 7), + + # initiate FAN + ('as7515_24x_fan', 0x66, 8), + + # initiate sys-eeprom + ('24c64', 0x56, 4), + ]) + + subprocess.call('echo 0 > /sys/devices/platform/as7515_24x_sfp/module_reset_all', shell=True) + + # initialize SFP/QSFP + sfp_bus = [ + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37 + ] + for port in range(0, len(sfp_bus)): + self.new_i2c_device('optoe1' if (port < 4) else 'optoe2', 0x50, sfp_bus[port]) + subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, sfp_bus[port]), shell=True) + + # initialize LED + subprocess.call('echo 0 > /sys/devices/platform/as7515_24x_led/led_loc', shell=True) + subprocess.call('echo 16 > /sys/devices/platform/as7515_24x_led/led_diag', shell=True) + + return True