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 08bdb9839..85064693c 100644 --- a/packages/base/all/vendor-config-onl/src/python/onl/platform/base.py +++ b/packages/base/all/vendor-config-onl/src/python/onl/platform/base.py @@ -650,3 +650,7 @@ class OnlPlatformPortConfig_40x100_13x400_2x10(object): class OnlPlatformPortConfig_64x800_2x25(object): PORT_COUNT=66 PORT_CONFIG="64x800 + 2x25" + +class OnlPlatformPortConfig_48x1_6x10(object): + PORT_COUNT=54 + PORT_CONFIG="48x1 + 6x10" diff --git a/packages/platforms/accton/x86-64/as4625-54p/.gitignore b/packages/platforms/accton/x86-64/as4625-54p/.gitignore new file mode 100644 index 000000000..d7acb5a8c --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/.gitignore @@ -0,0 +1,3 @@ +*x86*64*accton*as4625*54p*.mk +onlpdump.mk + diff --git a/packages/platforms/accton/x86-64/as4625-54p/Makefile b/packages/platforms/accton/x86-64/as4625-54p/Makefile new file mode 100644 index 000000000..502e772a7 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/accton/x86-64/as4625-54p/modules/Makefile b/packages/platforms/accton/x86-64/as4625-54p/modules/Makefile new file mode 100644 index 000000000..502e772a7 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/accton/x86-64/as4625-54p/modules/PKG.yml b/packages/platforms/accton/x86-64/as4625-54p/modules/PKG.yml new file mode 100644 index 000000000..693c54ff5 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=accton BASENAME=x86-64-accton-as4625-54p ARCH=amd64 KERNELS="onl-kernel-4.19-lts-x86-64-all:amd64" diff --git a/packages/platforms/accton/x86-64/as4625-54p/modules/builds/.gitignore b/packages/platforms/accton/x86-64/as4625-54p/modules/builds/.gitignore new file mode 100644 index 000000000..a65b41774 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/accton/x86-64/as4625-54p/modules/builds/Makefile b/packages/platforms/accton/x86-64/as4625-54p/modules/builds/Makefile new file mode 100644 index 000000000..51cd3e04e --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-4.19-lts-x86-64-all:amd64 +KMODULES := $(wildcard *.c) +VENDOR := accton +BASENAME := x86-64-accton-as4625-54p +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/accton/x86-64/as4625-54p/modules/builds/x86-64-accton-as4625-54p-cpld.c b/packages/platforms/accton/x86-64/as4625-54p/modules/builds/x86-64-accton-as4625-54p-cpld.c new file mode 100644 index 000000000..62e40f078 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/modules/builds/x86-64-accton-as4625-54p-cpld.c @@ -0,0 +1,664 @@ +/* + * Copyright (C) Brandon Chuang + * + * This module supports the accton cpld that hold the channel select + * mechanism for other i2c slave devices, such as SFP. + * This includes the: + * Accton as4625 CPLD1/CPLD2/CPLD3 + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_RW_RETRY_COUNT 10 +#define I2C_RW_RETRY_INTERVAL 60 /* ms */ + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; + +struct cpld_client_node { + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_type { + as4625_cpld1 +}; + +struct as4625_cpld_data { + enum cpld_type type; + struct device *hwmon_dev; + struct mutex update_lock; +}; + +static const struct i2c_device_id as4625_cpld_id[] = { + { "as4625_cpld1", as4625_cpld1 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, as4625_cpld_id); + +#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index +#define TRANSCEIVER_TXDISABLE_ATTR_ID(index) MODULE_TXDISABLE_##index +#define TRANSCEIVER_RXLOS_ATTR_ID(index) MODULE_RXLOS_##index +#define TRANSCEIVER_TXFAULT_ATTR_ID(index) MODULE_TXFAULT_##index + +enum as4625_cpld_sysfs_attributes { + VERSION_MAJOR, + VERSION_MINOR, + PCB_ID, + PCB_VERSION, + POWER_ENABLE_MAINBOARD, + POWER_ENABLE_POE, + SYSTEM_THERMAL_SHUTDOWN, + ACCESS, + MODULE_PRESENT_ALL, + MODULE_RXLOS_ALL, + /* transceiver attributes */ + TRANSCEIVER_PRESENT_ATTR_ID(49), + TRANSCEIVER_PRESENT_ATTR_ID(50), + TRANSCEIVER_PRESENT_ATTR_ID(51), + TRANSCEIVER_PRESENT_ATTR_ID(52), + TRANSCEIVER_PRESENT_ATTR_ID(53), + TRANSCEIVER_PRESENT_ATTR_ID(54), + TRANSCEIVER_TXDISABLE_ATTR_ID(49), + TRANSCEIVER_TXDISABLE_ATTR_ID(50), + TRANSCEIVER_TXDISABLE_ATTR_ID(51), + TRANSCEIVER_TXDISABLE_ATTR_ID(52), + TRANSCEIVER_TXDISABLE_ATTR_ID(53), + TRANSCEIVER_TXDISABLE_ATTR_ID(54), + TRANSCEIVER_RXLOS_ATTR_ID(49), + TRANSCEIVER_RXLOS_ATTR_ID(50), + TRANSCEIVER_RXLOS_ATTR_ID(51), + TRANSCEIVER_RXLOS_ATTR_ID(52), + TRANSCEIVER_RXLOS_ATTR_ID(53), + TRANSCEIVER_RXLOS_ATTR_ID(54), + TRANSCEIVER_TXFAULT_ATTR_ID(49), + TRANSCEIVER_TXFAULT_ATTR_ID(50), + TRANSCEIVER_TXFAULT_ATTR_ID(51), + TRANSCEIVER_TXFAULT_ATTR_ID(52), + TRANSCEIVER_TXFAULT_ATTR_ID(53), + TRANSCEIVER_TXFAULT_ATTR_ID(54) +}; + +/* sysfs attributes for hwmon + */ +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_present_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_control(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf); +static int as4625_cpld_read_internal(struct i2c_client *client, u8 reg); +static int as4625_cpld_write_internal(struct i2c_client *client, u8 reg, + u8 value); + +/* transceiver attributes */ +#define DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \ + static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_status, NULL, MODULE_PRESENT_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_disable_##index, S_IRUGO | S_IWUSR, show_status, set_control, MODULE_TXDISABLE_##index); \ + static SENSOR_DEVICE_ATTR(module_rx_los_##index, S_IRUGO, show_status, NULL, MODULE_RXLOS_##index); \ + static SENSOR_DEVICE_ATTR(module_tx_fault_##index, S_IRUGO, show_status, NULL, MODULE_TXFAULT_##index) +#define DECLARE_SFP_TRANSCEIVER_ATTR(index) \ + &sensor_dev_attr_module_present_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_disable_##index.dev_attr.attr, \ + &sensor_dev_attr_module_rx_los_##index.dev_attr.attr, \ + &sensor_dev_attr_module_tx_fault_##index.dev_attr.attr + +static SENSOR_DEVICE_ATTR(version_major, S_IRUGO, show_version, NULL, VERSION_MAJOR); +static SENSOR_DEVICE_ATTR(version_minor, S_IRUGO, show_version, NULL, VERSION_MINOR); +static SENSOR_DEVICE_ATTR(pcb_id, S_IRUGO, show_version, NULL, PCB_ID); +static SENSOR_DEVICE_ATTR(pcb_version, S_IRUGO, show_version, NULL, PCB_VERSION); +static SENSOR_DEVICE_ATTR(pwr_enable_mb, S_IRUGO | S_IWUSR, show_status, set_control, POWER_ENABLE_MAINBOARD); +static SENSOR_DEVICE_ATTR(pwr_enable_poe, S_IRUGO | S_IWUSR, show_status, set_control, POWER_ENABLE_POE); +static SENSOR_DEVICE_ATTR(thermal_shutdown, S_IRUGO | S_IWUSR, show_status, set_control, SYSTEM_THERMAL_SHUTDOWN); +static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS); + +/* transceiver attributes */ +static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, \ + NULL, MODULE_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(module_rx_los_all, S_IRUGO, show_rxlos_all, NULL, \ + MODULE_RXLOS_ALL); + +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(49); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(50); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(51); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(52); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(53); +DECLARE_SFP_TRANSCEIVER_SENSOR_DEVICE_ATTR(54); + +static struct attribute *as4625_cpld1_attributes[] = { + &sensor_dev_attr_version_major.dev_attr.attr, + &sensor_dev_attr_version_minor.dev_attr.attr, + &sensor_dev_attr_pcb_id.dev_attr.attr, + &sensor_dev_attr_pcb_version.dev_attr.attr, + &sensor_dev_attr_pwr_enable_mb.dev_attr.attr, + &sensor_dev_attr_pwr_enable_poe.dev_attr.attr, + &sensor_dev_attr_thermal_shutdown.dev_attr.attr, + &sensor_dev_attr_access.dev_attr.attr, + /* transceiver attributes */ + &sensor_dev_attr_module_present_all.dev_attr.attr, + &sensor_dev_attr_module_rx_los_all.dev_attr.attr, + DECLARE_SFP_TRANSCEIVER_ATTR(49), + DECLARE_SFP_TRANSCEIVER_ATTR(50), + DECLARE_SFP_TRANSCEIVER_ATTR(51), + DECLARE_SFP_TRANSCEIVER_ATTR(52), + DECLARE_SFP_TRANSCEIVER_ATTR(53), + DECLARE_SFP_TRANSCEIVER_ATTR(54), + NULL +}; + +static const struct attribute_group as4625_cpld1_group = { + .attrs = as4625_cpld1_attributes, +}; + +static ssize_t show_present_all(struct device *dev, + struct device_attribute *da, char *buf) +{ + int i, status; + u8 values[1] = {0}; + u8 regs_cpld[] = {0x6}; + u8 *regs[] = { regs_cpld }; + u8 size[] = { ARRAY_SIZE(regs_cpld) }; + struct i2c_client *client = to_i2c_client(dev); + struct as4625_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < size[data->type]; i++) { + status = as4625_cpld_read_internal(client, regs[data->type][i]); + + if (status < 0) + goto exit; + + values[i] = ~(u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values in order */ + return sprintf(buf, "%.2x\n", values[0] & 0x3F); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_rxlos_all(struct device *dev, struct device_attribute *da, + char *buf) +{ + int i, status; + u8 values[2] = {0}; + u8 regs_cpld[] = {0x7}; + u8 *regs[] = { regs_cpld }; + u8 size[] = { ARRAY_SIZE(regs_cpld) }; + struct i2c_client *client = to_i2c_client(dev); + struct as4625_cpld_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + for (i = 0; i < size[data->type]; i++) { + status = as4625_cpld_read_internal(client, regs[data->type][i]); + + if (status < 0) + goto exit; + + values[i] = (u8)status; + } + + mutex_unlock(&data->update_lock); + + /* Return values in order */ + return sprintf(buf, "%.2x\n", values[0] & 0x3F); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as4625_cpld_data *data = i2c_get_clientdata(client); + int status = 0; + u8 reg = 0, mask = 0, reverse = 0; + + switch (attr->index) { + case MODULE_TXDISABLE_49 ... MODULE_TXDISABLE_54: + reg = 0x5; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_49); + break; + case MODULE_PRESENT_49 ... MODULE_PRESENT_54: + reg = 0x6; + mask = 0x1 << (attr->index - MODULE_PRESENT_49); + reverse = 1; + break; + case MODULE_RXLOS_49 ... MODULE_RXLOS_54: + reg = 0x7; + mask = 0x1 << (attr->index - MODULE_RXLOS_49); + break; + case MODULE_TXFAULT_49 ... MODULE_TXFAULT_54: + reg = 0x8; + mask = 0x1 << (attr->index - MODULE_TXFAULT_49); + break; + case POWER_ENABLE_MAINBOARD: + reg = 0x3; + mask = 0x1; + reverse = 1; + break; + case POWER_ENABLE_POE: + reg = 0x21; + mask = 0x1; + break; + case SYSTEM_THERMAL_SHUTDOWN: + reg = 0x27; + mask = 0x1; + break; + default: + return 0; + } + + mutex_lock(&data->update_lock); + status = as4625_cpld_read_internal(client, reg); + if (unlikely(status < 0)) { + goto exit; + } + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", reverse ? !(status & mask) + : !!(status & mask)); + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t set_control(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct as4625_cpld_data *data = i2c_get_clientdata(client); + long value; + int status; + u8 reg = 0, mask = 0; + + status = kstrtol(buf, 10, &value); + + if (status) + return status; + + switch (attr->index) { + case MODULE_TXDISABLE_49 ... MODULE_TXDISABLE_54: + reg = 0x5; + mask = 0x1 << (attr->index - MODULE_TXDISABLE_49); + break; + case POWER_ENABLE_MAINBOARD: + reg = 0x3; + mask = 0x1; + value = !value; + break; + case POWER_ENABLE_POE: + reg = 0x21; + mask = 0x1; + break; + case SYSTEM_THERMAL_SHUTDOWN: + reg = 0x27; + mask = 0x1; + break; + default: + return -EINVAL; + } + + /* Read current status */ + mutex_lock(&data->update_lock); + status = as4625_cpld_read_internal(client, reg); + if (unlikely(status < 0)) + goto exit; + + /* Update tx_disable status */ + if (value) + status |= mask; + else + status &= ~mask; + + status = as4625_cpld_write_internal(client, reg, status); + if (unlikely(status < 0)) + goto exit; + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static ssize_t access(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int status; + u32 addr, val; + struct i2c_client *client = to_i2c_client(dev); + struct as4625_cpld_data *data = i2c_get_clientdata(client); + + if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) + return -EINVAL; + + if (addr > 0xFF || val > 0xFF) + return -EINVAL; + + mutex_lock(&data->update_lock); + status = as4625_cpld_write_internal(client, addr, val); + if (unlikely(status < 0)) + goto exit; + + mutex_unlock(&data->update_lock); + return count; + +exit: + mutex_unlock(&data->update_lock); + return status; +} + +static void as4625_cpld_add_client(struct i2c_client *client) +{ + struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node) + , GFP_KERNEL); + + if (!node) { + dev_dbg(&client->dev, + "Can't allocate cpld_client_node (0x%x)\n", + client->addr); + return; + } + + node->client = client; + + mutex_lock(&list_lock); + list_add(&node->list, &cpld_client_list); + mutex_unlock(&list_lock); +} + +static void as4625_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, + list); + + if (cpld_node->client == client) { + found = 1; + break; + } + } + + if (found) { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t show_version(struct device *dev, struct device_attribute *da, + char *buf) +{ + int val = 0, reg = 0; + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + switch (attr->index) { + case PCB_ID: + case PCB_VERSION: + reg = 0x0; + break; + case VERSION_MAJOR: + reg = 0x1; + break; + case VERSION_MINOR: + reg = 0x2; + break; + default: + break; + } + + val = i2c_smbus_read_byte_data(client, reg); + if (val < 0) { + dev_dbg(&client->dev, "cpld(0x%x) reg(0x1) err %d\n", + client->addr, val); + return val; + } + + if (attr->index == PCB_ID) + val = (val >> 3) & 0x7; /* bit 3-5 */ + else if (attr->index == PCB_VERSION) + val &= 0x7; /* bit 0-2 */ + + return sprintf(buf, "%d\n", val); +} + +/* + * I2C init/probing/exit functions + */ +static int as4625_cpld_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct as4625_cpld_data *data; + int ret = -ENODEV; + const struct attribute_group *group = NULL; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto exit; + + data = kzalloc(sizeof(struct as4625_cpld_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->type = id->driver_data; + + /* Register sysfs hooks */ + switch (data->type) { + case as4625_cpld1: + group = &as4625_cpld1_group; + break; + default: + break; + } + + if (group) { + ret = sysfs_create_group(&client->dev.kobj, group); + if (ret) + goto exit_free; + } + + as4625_cpld_add_client(client); + return 0; + +exit_free: + kfree(data); +exit: + return ret; +} + +static int as4625_cpld_remove(struct i2c_client *client) +{ + struct as4625_cpld_data *data = i2c_get_clientdata(client); + const struct attribute_group *group = NULL; + + as4625_cpld_remove_client(client); + + /* Remove sysfs hooks */ + switch (data->type) { + case as4625_cpld1: + group = &as4625_cpld1_group; + break; + default: + break; + } + + if (group) + sysfs_remove_group(&client->dev.kobj, group); + + kfree(data); + return 0; +} + +static int as4625_cpld_read_internal(struct i2c_client *client, u8 reg) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_read_byte_data(client, reg); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +static int as4625_cpld_write_internal(struct i2c_client *client, u8 reg, + u8 value) +{ + int status = 0, retry = I2C_RW_RETRY_COUNT; + + while (retry) { + status = i2c_smbus_write_byte_data(client, reg, value); + if (unlikely(status < 0)) { + msleep(I2C_RW_RETRY_INTERVAL); + retry--; + continue; + } + + break; + } + + return status; +} + +int as4625_cpld_read(unsigned short cpld_addr, u8 reg) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EPERM; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, + list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as4625_cpld_read_internal(cpld_node->client, + reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as4625_cpld_read); + +int as4625_cpld_write(unsigned short cpld_addr, u8 reg, u8 value) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int ret = -EIO; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, + list); + + if (cpld_node->client->addr == cpld_addr) { + ret = as4625_cpld_write_internal(cpld_node->client, + reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(as4625_cpld_write); + +static struct i2c_driver as4625_cpld_driver = { + .driver = { + .name = "as4625_cpld", + .owner = THIS_MODULE, + }, + .probe = as4625_cpld_probe, + .remove = as4625_cpld_remove, + .id_table = as4625_cpld_id, +}; + +static int __init as4625_cpld_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&as4625_cpld_driver); +} + +static void __exit as4625_cpld_exit(void) +{ + i2c_del_driver(&as4625_cpld_driver); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("Accton I2C CPLD driver"); +MODULE_LICENSE("GPL"); + +module_init(as4625_cpld_init); +module_exit(as4625_cpld_exit); diff --git a/packages/platforms/accton/x86-64/as4625-54p/modules/builds/x86-64-accton-as4625-54p-fan.c b/packages/platforms/accton/x86-64/as4625-54p/modules/builds/x86-64-accton-as4625-54p-fan.c new file mode 100644 index 000000000..75ea3b449 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/modules/builds/x86-64-accton-as4625-54p-fan.c @@ -0,0 +1,424 @@ +/* + * A hwmon driver for the Accton as4625 fan + * + * Copyright (C) 2016 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as4625_fan" + +#define FAN_STATUS_I2C_ADDR 0x64 + +static struct as4625_fan_data *as4625_fan_update_device(struct device *dev); +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count); +extern int as4625_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as4625_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +/* fan related data, the index should match sysfs_fan_attributes + */ +static const u8 fan_reg[] = { + 0x40, /* fan-1 PWM */ + 0x41, /* fan-2 PWM */ + 0x42, /* fan-3 PWM */ + 0x46, /* fan-1 speed(rpm) */ + 0x47, /* fan-2 speed(rpm) */ + 0x48, /* fan-3 speed(rpm) */ + 0x00 /* fan direction, 001: AS4625-54T (F2B), 010: AS4625-54T (B2F) */ +}; + +static const int fan_target_speed_f2b[] = { + 0, 1350, 2550, 3900, 6450, 7800, 9150, 10500, + 11850, 13050, 14400, 15600, 16950, 18150, 19650, 23000 +}; + +static const int fan_target_speed_b2f[] = { + 0, 3150, 5850, 8100, 12150, 13650, 15000, 16350, + 17850, 19050, 19950, 20700, 21450, 22200, 22800, 23400 +}; + +/* fan data */ +struct as4625_fan_data { + struct platform_device *pdev; + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */ +}; + +struct as4625_fan_data *data = NULL; + +enum fan_id { + FAN1_ID, + FAN2_ID, + FAN3_ID +}; + +enum sysfs_fan_attributes { + FAN1_PWM, + FAN2_PWM, + FAN3_PWM, + FAN1_INPUT, + FAN2_INPUT, + FAN3_INPUT, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN1_DIR, + FAN2_DIR, + FAN3_DIR, + FAN1_TARGET_RPM, + FAN2_TARGET_RPM, + FAN3_TARGET_RPM +}; + +/* Define attributes + */ +#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT) +#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.dev_attr.attr + +#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_pwm, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_PWM) +#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_pwm.dev_attr.attr + +#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_input, S_IRUGO, fan_show_value, NULL, FAN##index##_INPUT) +#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_input.dev_attr.attr + +#define DECLARE_FAN_DIR_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_dir, S_IRUGO, fan_show_value, NULL, FAN##index##_DIR) +#define DECLARE_FAN_DIR_ATTR(index) &sensor_dev_attr_fan##index##_dir.dev_attr.attr + +#define DECLARE_FAN_TARGET_RPM_SENSOR_DEV_ATTR(index) \ + static SENSOR_DEVICE_ATTR(fan##index##_target_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_TARGET_RPM) +#define DECLARE_FAN_TARGET_RPM_ATTR(index) &sensor_dev_attr_fan##index##_target_rpm.dev_attr.attr + +/* 3 fan fault attributes in this platform */ +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2); +DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3); + +/* 3 fan speed(rpm) attributes in this platform */ +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2); +DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3); + +/* 3 fan duty cycle attribute in this platform */ +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(3); + +/* 3 fan direction attribute in this platform */ +DECLARE_FAN_DIR_SENSOR_DEV_ATTR(1); +DECLARE_FAN_DIR_SENSOR_DEV_ATTR(2); +DECLARE_FAN_DIR_SENSOR_DEV_ATTR(3); + +/* 3 fan target speed attribute in this platform */ +DECLARE_FAN_TARGET_RPM_SENSOR_DEV_ATTR(1); +DECLARE_FAN_TARGET_RPM_SENSOR_DEV_ATTR(2); +DECLARE_FAN_TARGET_RPM_SENSOR_DEV_ATTR(3); + +static struct attribute *as4625_fan_attributes[] = { + /* fan related attributes */ + DECLARE_FAN_FAULT_ATTR(1), + DECLARE_FAN_FAULT_ATTR(2), + DECLARE_FAN_FAULT_ATTR(3), + DECLARE_FAN_DUTY_CYCLE_ATTR(1), + DECLARE_FAN_DUTY_CYCLE_ATTR(2), + DECLARE_FAN_DUTY_CYCLE_ATTR(3), + DECLARE_FAN_SPEED_RPM_ATTR(1), + DECLARE_FAN_SPEED_RPM_ATTR(2), + DECLARE_FAN_SPEED_RPM_ATTR(3), + DECLARE_FAN_DIR_ATTR(1), + DECLARE_FAN_DIR_ATTR(2), + DECLARE_FAN_DIR_ATTR(3), + DECLARE_FAN_TARGET_RPM_ATTR(1), + DECLARE_FAN_TARGET_RPM_ATTR(2), + DECLARE_FAN_TARGET_RPM_ATTR(3), + NULL +}; + +#define FAN_DUTY_CYCLE_REG_MASK 0x0F +#define FAN_MAX_DUTY_CYCLE 100 +#define FAN_REG_VAL_TO_SPEED_RPM_STEP 150 + +static int as4625_fan_read_value(u8 reg) +{ + return as4625_cpld_read(FAN_STATUS_I2C_ADDR, reg); +} + +static int as4625_fan_write_value(u8 reg, u8 value) +{ + return as4625_cpld_write(FAN_STATUS_I2C_ADDR, reg, value); +} + +/* fan utility functions + */ +static u32 reg_val_to_duty_cycle(u8 reg_val) +{ + reg_val &= FAN_DUTY_CYCLE_REG_MASK; + return (u32)(reg_val+1) * 625 / 100; +} + +static u8 duty_cycle_to_reg_val(u8 duty_cycle) +{ + if (duty_cycle == 0) + return 0; + else if (duty_cycle > FAN_MAX_DUTY_CYCLE) + duty_cycle = FAN_MAX_DUTY_CYCLE; + + return ((u32)duty_cycle * 100 / 625) - 1; +} + +static u32 reg_val_to_speed_rpm(u8 reg_val) +{ + return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP; +} + +static u8 is_fan_fault(struct as4625_fan_data *data, enum fan_id id) +{ + return !reg_val_to_speed_rpm(data->reg_val[FAN1_INPUT + id]); +} + +static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da, + const char *buf, size_t count) +{ + int error, value, reg; + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + + error = kstrtoint(buf, 10, &value); + if (error) + return error; + + if (value < 0 || value > FAN_MAX_DUTY_CYCLE) + return -EINVAL; + + mutex_lock(&data->update_lock); + + reg = fan_reg[attr->index - FAN1_PWM]; + as4625_fan_write_value(reg, duty_cycle_to_reg_val(value)); + data->valid = 0; + + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + ssize_t ret = 0; + + mutex_lock(&data->update_lock); + + data = as4625_fan_update_device(dev); + if (data->valid) { + switch (attr->index) { + case FAN1_PWM: + case FAN2_PWM: + case FAN3_PWM: + { + u32 duty_cycle; + duty_cycle = reg_val_to_duty_cycle( + data->reg_val[attr->index]); + ret = sprintf(buf, "%u\n", duty_cycle); + break; + } + case FAN1_INPUT: + case FAN2_INPUT: + case FAN3_INPUT: + ret = sprintf(buf, "%u\n", + reg_val_to_speed_rpm(data->reg_val[attr->index])); + break; + + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + ret = sprintf(buf, "%d\n", + is_fan_fault(data, attr->index - FAN1_FAULT)); + break; + + case FAN1_DIR: + case FAN2_DIR: + case FAN3_DIR: + { + u8 board_id = (data->reg_val[6] >> 3) & 0x7; + ret = sprintf(buf, "%s\n", (board_id == 2) + ? "B2F" : "F2B"); + break; + } + + case FAN1_TARGET_RPM: + case FAN2_TARGET_RPM: + case FAN3_TARGET_RPM: + { + u8 board_id = (data->reg_val[6] >> 3) & 0x7; + const int *target = NULL; + int pwm_index = FAN1_PWM + (attr->index - FAN1_TARGET_RPM); + target = (board_id == 2) + ? fan_target_speed_b2f : fan_target_speed_f2b; + ret = sprintf(buf, "%d\n", + target[data->reg_val[pwm_index] & 0xF]); + break; + } + default: + break; + } + } + + mutex_unlock(&data->update_lock); + + return ret; +} + +static const struct attribute_group as4625_fan_group = { + .attrs = as4625_fan_attributes, +}; + +static struct as4625_fan_data *as4625_fan_update_device(struct device *dev) +{ + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || + !data->valid) { + int i; + + dev_dbg(&data->pdev->dev, "Starting as4625_fan update\n"); + data->valid = 0; + + /* Update fan data + */ + for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) { + int status = as4625_fan_read_value(fan_reg[i]); + + if (status < 0) { + data->valid = 0; + mutex_unlock(&data->update_lock); + dev_dbg(&data->pdev->dev, "reg %d, err %d\n", + fan_reg[i], status); + return data; + } else { + data->reg_val[i] = status; + } + } + + data->last_updated = jiffies; + data->valid = 1; + } + + return data; +} + +static int as4625_fan_probe(struct platform_device *pdev) +{ + int status; + + data->hwmon_dev = hwmon_device_register_with_info(&pdev->dev, + DRVNAME, NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + return status; + } + + /* Register sysfs hooks */ + status = sysfs_create_group(&data->hwmon_dev->kobj, &as4625_fan_group); + if (status) + goto exit_remove; + + dev_info(&pdev->dev, "device created\n"); + return 0; + +exit_remove: + hwmon_device_unregister(data->hwmon_dev); + return status; +} + +static int as4625_fan_remove(struct platform_device *pdev) +{ + sysfs_remove_group(&data->hwmon_dev->kobj, &as4625_fan_group); + hwmon_device_unregister(data->hwmon_dev); + return 0; +} + +static struct platform_driver as4625_fan_driver = { + .probe = as4625_fan_probe, + .remove = as4625_fan_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init as4625_fan_init(void) +{ + int ret; + + data = kzalloc(sizeof(struct as4625_fan_data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto alloc_err; + } + + mutex_init(&data->update_lock); + data->valid = 0; + + ret = platform_driver_register(&as4625_fan_driver); + if (ret < 0) + goto dri_reg_err; + + data->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(data->pdev)) { + ret = PTR_ERR(data->pdev); + goto dev_reg_err; + } + + return 0; + +dev_reg_err: + platform_driver_unregister(&as4625_fan_driver); +dri_reg_err: + kfree(data); +alloc_err: + return ret; +} + +static void __exit as4625_fan_exit(void) +{ + platform_device_unregister(data->pdev); + platform_driver_unregister(&as4625_fan_driver); + kfree(data); +} + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as4625_fan driver"); +MODULE_LICENSE("GPL"); + +module_init(as4625_fan_init); +module_exit(as4625_fan_exit); diff --git a/packages/platforms/accton/x86-64/as4625-54p/modules/builds/x86-64-accton-as4625-54p-leds.c b/packages/platforms/accton/x86-64/as4625-54p/modules/builds/x86-64-accton-as4625-54p-leds.c new file mode 100644 index 000000000..891911751 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/modules/builds/x86-64-accton-as4625-54p-leds.c @@ -0,0 +1,398 @@ +/* + * A LED driver for the as4625_led + * + * Copyright (C) 2016 Accton Technology Corporation. + * Brandon Chuang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as4625_led" + +extern int as4625_cpld_read(unsigned short cpld_addr, u8 reg); +extern int as4625_cpld_write(unsigned short cpld_addr, u8 reg, u8 value); + +struct as4625_led_data { + struct platform_device *pdev; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 reg_val[2]; /* Register value, 0 = System/LOC/PSU0 LED + 1 = PSU1/FAN/POE LED */ +}; + +static struct as4625_led_data *ledctl = NULL; + +#define LED_CNTRLER_I2C_ADDRESS (0x64) + +#define LED_TYPE_SYS_REG_MASK (0xF0) +#define LED_MODE_SYS_GREEN_BLINK_VALUE (0x60) +#define LED_MODE_SYS_GREEN_VALUE (0x20) +#define LED_MODE_SYS_AMBER_VALUE (0x80) +#define LED_MODE_SYS_AMBER_BLINK_VALUE (0x90) +#define LED_MODE_SYS_OFF_VALUE (0x00) + +#define LED_TYPE_LOC_REG_MASK (0x0C) +#define LED_MODE_LOC_GREEN_VALUE (0x04) +#define LED_MODE_LOC_AMBER_VALUE (0x08) +#define LED_MODE_LOC_OFF_VALUE (0x00) +#define LED_MODE_LOC_OFF_VALUE_1 (0x0C) + +#define LED_TYPE_POE_REG_MASK (0x03) +#define LED_MODE_POE_OFF_VALUE (0x00) +#define LED_MODE_POE_OFF_VALUE_1 (0x03) +#define LED_MODE_POE_GREEN_VALUE (0x01) +#define LED_MODE_POE_AMBER_VALUE (0x02) + +static const u8 led_reg[] = { + 0x30, /* System/LOC/PSU0 LED */ + 0x31 /* PSU1/FAN/POE LED */ +}; + +enum led_type { + LED_TYPE_SYS, + LED_TYPE_LOC, + LED_TYPE_PSU1, + LED_TYPE_PSU2, + LED_TYPE_FAN, + LED_TYPE_POE +}; + +/* FAN/PSU/DIAG/RELEASE led mode */ +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER, + LED_MODE_AMBER_BLINK, + LED_MODE_RED, + LED_MODE_RED_BLINK, + LED_MODE_BLUE, + LED_MODE_BLUE_BLINK, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +struct led_type_mode { + enum led_type type; + enum led_light_mode mode; + int type_mask; + int mode_value; +}; + +static struct led_type_mode led_type_mode_data[] = { + {LED_TYPE_SYS, LED_MODE_GREEN_BLINK, LED_TYPE_SYS_REG_MASK, LED_MODE_SYS_GREEN_BLINK_VALUE}, + {LED_TYPE_SYS, LED_MODE_GREEN, LED_TYPE_SYS_REG_MASK, LED_MODE_SYS_GREEN_VALUE}, + {LED_TYPE_SYS, LED_MODE_AMBER_BLINK, LED_TYPE_SYS_REG_MASK, LED_MODE_SYS_AMBER_BLINK_VALUE}, + {LED_TYPE_SYS, LED_MODE_AMBER, LED_TYPE_SYS_REG_MASK, LED_MODE_SYS_AMBER_VALUE}, + {LED_TYPE_SYS, LED_MODE_OFF, LED_TYPE_SYS_REG_MASK, LED_MODE_SYS_OFF_VALUE}, + {LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE}, + {LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE_1}, + {LED_TYPE_LOC, LED_MODE_GREEN, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_GREEN_VALUE}, + {LED_TYPE_LOC, LED_MODE_AMBER, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_AMBER_VALUE}, + {LED_TYPE_POE, LED_MODE_OFF, LED_TYPE_POE_REG_MASK, LED_MODE_POE_OFF_VALUE}, + {LED_TYPE_POE, LED_MODE_OFF, LED_TYPE_POE_REG_MASK, LED_MODE_POE_OFF_VALUE_1}, + {LED_TYPE_POE, LED_MODE_GREEN, LED_TYPE_POE_REG_MASK, LED_MODE_POE_GREEN_VALUE}, + {LED_TYPE_POE, LED_MODE_AMBER, LED_TYPE_POE_REG_MASK, LED_MODE_POE_AMBER_VALUE} +}; + +static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + if (type != led_type_mode_data[i].type) + continue; + + if ((led_type_mode_data[i].type_mask & reg_val) == + led_type_mode_data[i].mode_value) { + return led_type_mode_data[i].mode; + } + } + + return LED_MODE_UNKNOWN; +} + +static u8 led_light_mode_to_reg_val(enum led_type type, + enum led_light_mode mode, u8 reg_val) { + int i; + + for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) { + int type_mask, mode_value; + + if (type != led_type_mode_data[i].type) + continue; + + if (mode != led_type_mode_data[i].mode) + continue; + + type_mask = led_type_mode_data[i].type_mask; + mode_value = led_type_mode_data[i].mode_value; + reg_val = (reg_val & ~type_mask) | mode_value; + } + + return reg_val; +} + +static int as4625_led_read_value(u8 reg) +{ + return as4625_cpld_read(LED_CNTRLER_I2C_ADDRESS, reg); +} + +static int as4625_led_write_value(u8 reg, u8 value) +{ + return as4625_cpld_write(LED_CNTRLER_I2C_ADDRESS, reg, value); +} + +static void as4625_led_update(void) +{ + mutex_lock(&ledctl->update_lock); + + if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2) + || !ledctl->valid) { + int i; + + dev_dbg(&ledctl->pdev->dev, "Starting as4625_led update\n"); + ledctl->valid = 0; + + /* Update LED data + */ + for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) { + int status = as4625_led_read_value(led_reg[i]); + + if (status < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", + led_reg[i], status); + goto exit; + } else { + ledctl->reg_val[i] = status; + } + } + + ledctl->last_updated = jiffies; + ledctl->valid = 1; + } + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void as4625_led_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode, + u8 reg, enum led_type type) +{ + int reg_val; + + mutex_lock(&ledctl->update_lock); + reg_val = as4625_led_read_value(reg); + + if (reg_val < 0) { + dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val); + goto exit; + } + + reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val); + as4625_led_write_value(reg, reg_val); + ledctl->valid = 0; + +exit: + mutex_unlock(&ledctl->update_lock); +} + +static void as4625_led_auto_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ +} + +static enum led_brightness as4625_led_auto_get(struct led_classdev *cdev) +{ + return LED_MODE_AUTO; +} + +static void as4625_led_sys_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as4625_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_SYS); +} + +static enum led_brightness as4625_led_sys_get(struct led_classdev *cdev) +{ + as4625_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_SYS, ledctl->reg_val[0]); +} + +static enum led_brightness as4625_led_loc_get(struct led_classdev *cdev) +{ + as4625_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]); +} + +static void as4625_led_loc_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as4625_led_set(led_cdev, led_light_mode, led_reg[0], LED_TYPE_LOC); +} + +static enum led_brightness as4625_led_poe_get(struct led_classdev *cdev) +{ + as4625_led_update(); + return led_reg_val_to_light_mode(LED_TYPE_POE, ledctl->reg_val[1]); +} + +static void as4625_led_poe_set(struct led_classdev *led_cdev, + enum led_brightness led_light_mode) +{ + as4625_led_set(led_cdev, led_light_mode, led_reg[1], LED_TYPE_POE); +} + +static struct led_classdev as4625_leds[] = { + [LED_TYPE_SYS] = { + .name = "as4625_led::sys", + .default_trigger = "unused", + .brightness_set = as4625_led_sys_set, + .brightness_get = as4625_led_sys_get, + .max_brightness = LED_MODE_AMBER_BLINK, + }, + [LED_TYPE_LOC] = { + .name = "as4625_led::loc", + .default_trigger = "unused", + .brightness_set = as4625_led_loc_set, + .brightness_get = as4625_led_loc_get, + .max_brightness = LED_MODE_AMBER, + }, + [LED_TYPE_PSU1] = { + .name = "as4625_led::psu1", + .default_trigger = "unused", + .brightness_set = as4625_led_auto_set, + .brightness_get = as4625_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_PSU2] = { + .name = "as4625_led::psu2", + .default_trigger = "unused", + .brightness_set = as4625_led_auto_set, + .brightness_get = as4625_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_FAN] = { + .name = "as4625_led::fan", + .default_trigger = "unused", + .brightness_set = as4625_led_auto_set, + .brightness_get = as4625_led_auto_get, + .max_brightness = LED_MODE_AUTO, + }, + [LED_TYPE_POE] = { + .name = "as4625_led::poe", + .default_trigger = "unused", + .brightness_set = as4625_led_poe_set, + .brightness_get = as4625_led_poe_get, + .max_brightness = LED_MODE_AMBER, + } +}; + +static int as4625_led_probe(struct platform_device *pdev) +{ + int ret, i; + + for (i = 0; i < ARRAY_SIZE(as4625_leds); i++) { + ret = led_classdev_register(&pdev->dev, &as4625_leds[i]); + + if (ret < 0) + break; + } + + /* Check if all LEDs were successfully registered */ + if (i != ARRAY_SIZE(as4625_leds)){ + int j; + + /* only unregister the LEDs that were successfully registered */ + for (j = 0; j < i; j++) + led_classdev_unregister(&as4625_leds[i]); + } + + return ret; +} + +static int as4625_led_remove(struct platform_device *pdev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(as4625_leds); i++) + led_classdev_unregister(&as4625_leds[i]); + + return 0; +} + +static struct platform_driver as4625_led_driver = { + .probe = as4625_led_probe, + .remove = as4625_led_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +static int __init as4625_led_init(void) +{ + int ret; + + ret = platform_driver_register(&as4625_led_driver); + if (ret < 0) + goto exit; + + ledctl = kzalloc(sizeof(struct as4625_led_data), GFP_KERNEL); + if (!ledctl) { + ret = -ENOMEM; + goto exit_driver; + } + + mutex_init(&ledctl->update_lock); + + ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0); + if (IS_ERR(ledctl->pdev)) { + ret = PTR_ERR(ledctl->pdev); + goto exit_free; + } + + return 0; + +exit_free: + kfree(ledctl); +exit_driver: + platform_driver_unregister(&as4625_led_driver); +exit: + return ret; +} + +static void __exit as4625_led_exit(void) +{ + platform_device_unregister(ledctl->pdev); + platform_driver_unregister(&as4625_led_driver); + kfree(ledctl); +} + +late_initcall(as4625_led_init); +module_exit(as4625_led_exit); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as4625_led driver"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/accton/x86-64/as4625-54p/modules/builds/x86-64-accton-as4625-54p-psu.c b/packages/platforms/accton/x86-64/as4625-54p/modules/builds/x86-64-accton-as4625-54p-psu.c new file mode 100644 index 000000000..e3d4235b8 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/modules/builds/x86-64-accton-as4625-54p-psu.c @@ -0,0 +1,394 @@ +/* + * An hwmon driver for accton as4625_54p Power Module + * + * Copyright (C) 2014 Accton Technology Corporation. + * Brandon Chuang + * + * Based on ad7414.c + * Copyright 2006 Stefan Roese , DENX Software Engineering + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "as4625_54p_psu" + +#define PSU_STATUS_I2C_ADDR 0x64 +#define PSU_STATUS_I2C_REG_OFFSET 0x4 + +#define MODEL_NAME_LEN 13 +#define MODEL_NAME_REG_OFFSET 0x15 + +#define SERIAL_NUM_LEN 9 +#define SERIAL_NUM_REG_OFFSET 0x35 + +#define IS_POWER_GOOD(id, value) (!!(value & BIT(id*4+2))) +#define IS_PRESENT(id, value) (!(value & BIT(id*4))) + +#define FAN_DIR_LEN 3 +const char FAN_DIR_F2B[] = "F2B"; +const char FAN_DIR_B2F[] = "B2F"; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf); +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf); +extern int as4625_cpld_read(unsigned short cpld_addr, u8 reg); + +/* Addresses scanned + */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Each client has this additional data + */ +struct as4625_54p_psu_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; /* !=0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + u8 index; /* PSU index */ + u8 status; /* Status(present/power_good) register read from CPLD */ + char model_name[MODEL_NAME_LEN+1]; /* Model name, read from eeprom */ + char serial[SERIAL_NUM_LEN+1]; /* Serial number, read from eeprom*/ + char fan_dir[FAN_DIR_LEN+1]; +}; + +static struct as4625_54p_psu_data + *as4625_54p_psu_update_device(struct device *dev); + +enum as4625_54p_psu_sysfs_attributes { + PSU_PRESENT, + PSU_MODEL_NAME, + PSU_POWER_GOOD, + PSU_SERIAL_NUMBER, + PSU_FAN_DIR +}; + +/* sysfs attributes for hwmon + */ +static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, \ + PSU_PRESENT); +static SENSOR_DEVICE_ATTR(psu_model_name, S_IRUGO, show_string, NULL, \ + PSU_MODEL_NAME); +static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, \ + PSU_POWER_GOOD); +static SENSOR_DEVICE_ATTR(psu_serial_number, S_IRUGO, show_string, NULL, \ + PSU_SERIAL_NUMBER); +static SENSOR_DEVICE_ATTR(psu_fan_dir, S_IRUGO, show_string, NULL, \ + PSU_FAN_DIR); + +static struct attribute *as4625_54p_psu_attributes[] = { + &sensor_dev_attr_psu_present.dev_attr.attr, + &sensor_dev_attr_psu_model_name.dev_attr.attr, + &sensor_dev_attr_psu_power_good.dev_attr.attr, + &sensor_dev_attr_psu_serial_number.dev_attr.attr, + &sensor_dev_attr_psu_fan_dir.dev_attr.attr, + NULL +}; + +static ssize_t show_status(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as4625_54p_psu_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + u8 status = 0; + + mutex_lock(&data->update_lock); + + data = as4625_54p_psu_update_device(dev); + if (!data->valid) { + mutex_unlock(&data->update_lock); + return sprintf(buf, "0\n"); + } + + if (attr->index == PSU_PRESENT) + status = IS_PRESENT(data->index, data->status); + else /* PSU_POWER_GOOD */ + status = IS_POWER_GOOD(data->index, data->status); + + mutex_unlock(&data->update_lock); + return sprintf(buf, "%d\n", status); +} + +static ssize_t show_string(struct device *dev, struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as4625_54p_psu_data *data = i2c_get_clientdata(client); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + char *ptr = NULL; + int ret = 0; + + mutex_lock(&data->update_lock); + + data = as4625_54p_psu_update_device(dev); + if (!data->valid) { + ret = -EIO; + goto exit; + } + + switch (attr->index) { + case PSU_MODEL_NAME: + ptr = data->model_name; + break; + case PSU_SERIAL_NUMBER: + ptr = data->serial; + break; + case PSU_FAN_DIR: + ptr = data->fan_dir; + break; + default: + ret = -EINVAL; + goto exit; + } + + ret = sprintf(buf, "%s\n", ptr); + +exit: + mutex_unlock(&data->update_lock); + return ret; +} + +static const struct attribute_group as4625_54p_psu_group = { + .attrs = as4625_54p_psu_attributes, +}; + +static int as4625_54p_psu_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct as4625_54p_psu_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct as4625_54p_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, &as4625_54p_psu_group); + if (status) + goto exit_free; + + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, + DRVNAME, NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: psu '%s'\n", + dev_name(data->hwmon_dev), client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &as4625_54p_psu_group); +exit_free: + kfree(data); +exit: + return status; +} + +static int as4625_54p_psu_remove(struct i2c_client *client) +{ + struct as4625_54p_psu_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &as4625_54p_psu_group); + kfree(data); + + return 0; +} + +enum psu_index +{ + as4625_54p_psu1, + as4625_54p_psu2 +}; + +static const struct i2c_device_id as4625_54p_psu_id[] = { + { "as4625_54p_psu1", as4625_54p_psu1 }, + { "as4625_54p_psu2", as4625_54p_psu2 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, as4625_54p_psu_id); + +static struct i2c_driver as4625_54p_psu_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = as4625_54p_psu_probe, + .remove = as4625_54p_psu_remove, + .id_table = as4625_54p_psu_id, + .address_list = normal_i2c, +}; + +static int as4625_54p_psu_read_byte(struct i2c_client *client, u8 command, + u8 *data) +{ + int status = 0; + int retry_count = 5; + + while (retry_count) { + status = i2c_smbus_read_byte_data(client, command); + if (unlikely(status < 0)) { + msleep(10); + retry_count--; + continue; + } + + break; + } + + if (unlikely(status < 0)) { + dev_dbg(&client->dev, + "sfp read byte data failed, command(0x%2x), data(0x%2x)\r\n", + command, status); + goto abort; + } + + *data = (u8)status; + +abort: + return status; +} + +static int as4625_54p_psu_read_bytes(struct i2c_client *client, u8 command, + u8 *data, int data_len) +{ + int ret = 0; + + while (data_len) { + ssize_t status; + + status = as4625_54p_psu_read_byte(client, command, data); + if (status <= 0) { + ret = status; + break; + } + + data += 1; + command += 1; + data_len -= 1; + } + + return ret; +} + +static struct as4625_54p_psu_data *as4625_54p_psu_update_device( + struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct as4625_54p_psu_data *data = i2c_get_clientdata(client); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int status; + + dev_dbg(&client->dev, "Starting as4625_54p update\n"); + data->valid = 0; + + /* Read psu status */ + status = as4625_cpld_read(PSU_STATUS_I2C_ADDR, + PSU_STATUS_I2C_REG_OFFSET); + + if (status < 0) { + dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", + PSU_STATUS_I2C_ADDR, status); + goto exit; + } else { + data->status = status; + } + + memset(data->model_name, 0, sizeof(data->model_name)); + memset(data->serial, 0, sizeof(data->serial)); + memset(data->fan_dir, 0, sizeof(data->fan_dir)); + + if (IS_POWER_GOOD(data->index, data->status)) { + /* Read model name */ + status = as4625_54p_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 = as4625_54p_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'; + } + + if (strncmp(data->model_name, "UP1K21R-1085G", + ARRAY_SIZE(data->model_name)-1) == 0) + memcpy(data->fan_dir, FAN_DIR_F2B, + sizeof(FAN_DIR_F2B)); + else + data->fan_dir[0] = '\0'; + } + + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + return data; +} + +module_i2c_driver(as4625_54p_psu_driver); + +MODULE_AUTHOR("Brandon Chuang "); +MODULE_DESCRIPTION("as4625_54p_psu driver"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/Makefile b/packages/platforms/accton/x86-64/as4625-54p/onlp/Makefile new file mode 100644 index 000000000..502e772a7 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/PKG.yml b/packages/platforms/accton/x86-64/as4625-54p/onlp/PKG.yml new file mode 100644 index 000000000..264c7a849 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-accton-as4625-54p ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/Makefile b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/Makefile new file mode 100644 index 000000000..e7437cb23 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/lib/Makefile b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/lib/Makefile new file mode 100644 index 000000000..add5e9fb1 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/lib/Makefile @@ -0,0 +1,2 @@ +PLATFORM := x86-64-accton-as4625-54p +include $(ONL)/packages/base/any/onlp/builds/platform/libonlp-platform.mk diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/onlpdump/Makefile b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/onlpdump/Makefile new file mode 100644 index 000000000..dd4029260 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/onlpdump/Makefile @@ -0,0 +1,2 @@ +PLATFORM := x86-64-accton-as4625-54p +include $(ONL)/packages/base/any/onlp/builds/platform/onlps.mk diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/.gitignore b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/.module b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/.module new file mode 100644 index 000000000..5dc26317e --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/.module @@ -0,0 +1 @@ +name: x86_64_accton_as4625_54p diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/Makefile b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/Makefile new file mode 100644 index 000000000..c5f9a341c --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include $(ONL)/make/config.mk +MODULE := x86_64_accton_as4625_54p +AUTOMODULE := x86_64_accton_as4625_54p +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/README b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/README new file mode 100644 index 000000000..9976c0731 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/README @@ -0,0 +1,6 @@ +############################################################################### +# +# x86_64_accton_as4625_54p README +# +############################################################################### + diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/auto/make.mk b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/auto/make.mk new file mode 100644 index 000000000..661778bf5 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/auto/make.mk @@ -0,0 +1,8 @@ +############################################################################### +# +# x86_64_accton_as4625_54p Autogeneration +# +############################################################################### +x86_64_accton_as4625_54p_AUTO_DEFS := module/auto/x86_64_accton_as4625_54p.yml +x86_64_accton_as4625_54p_AUTO_DIRS := module/inc/x86_64_accton_as4625_54p module/src +include $(BUILDER)/auto.mk diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/auto/x86_64_accton_as4625_54p.yml b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/auto/x86_64_accton_as4625_54p.yml new file mode 100644 index 000000000..a2509695e --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/auto/x86_64_accton_as4625_54p.yml @@ -0,0 +1,50 @@ +############################################################################### +# +# x86_64_accton_as4625_54p Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- X86_64_ACCTON_AS4625_54P_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- X86_64_ACCTON_AS4625_54P_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- X86_64_ACCTON_AS4625_54P_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_STDLIB +- X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION: + doc: "Assume chassis fan direction is the same as the PSU fan direction." + default: 0 + + +definitions: + cdefs: + X86_64_ACCTON_AS4625_54P_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_accton_as4625_54p_config + + portingmacro: + x86_64_accton_as4625_54p: + macros: + - malloc + - free + - memset + - memcpy + + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/inc/x86_64_accton_as4625_54p/x86_64_accton_as4625_54p.x b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/inc/x86_64_accton_as4625_54p/x86_64_accton_as4625_54p.x new file mode 100644 index 000000000..ed539a7c3 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/inc/x86_64_accton_as4625_54p/x86_64_accton_as4625_54p.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/inc/x86_64_accton_as4625_54p/x86_64_accton_as4625_54p_config.h b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/inc/x86_64_accton_as4625_54p/x86_64_accton_as4625_54p_config.h new file mode 100644 index 000000000..27791b63a --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/inc/x86_64_accton_as4625_54p/x86_64_accton_as4625_54p_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_as4625_54p Configuration Header + * + * @addtogroup x86_64_accton_as4625_54p-config + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS4625_54P_CONFIG_H__ +#define __X86_64_ACCTON_AS4625_54P_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef X86_64_ACCTON_AS4625_54P_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_LOGGING +#define X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * X86_64_ACCTON_AS4625_54P_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef X86_64_ACCTON_AS4625_54P_CONFIG_LOG_OPTIONS_DEFAULT +#define X86_64_ACCTON_AS4625_54P_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * X86_64_ACCTON_AS4625_54P_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef X86_64_ACCTON_AS4625_54P_CONFIG_LOG_BITS_DEFAULT +#define X86_64_ACCTON_AS4625_54P_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * X86_64_ACCTON_AS4625_54P_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef X86_64_ACCTON_AS4625_54P_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define X86_64_ACCTON_AS4625_54P_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_STDLIB +#define X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_STDLIB +#endif + +/** + * X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_UCLI +#define X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_accton_as4625_54p_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_accton_as4625_54p_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_accton_as4625_54p_config_settings table. */ +extern x86_64_accton_as4625_54p_config_settings_t x86_64_accton_as4625_54p_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_accton_as4625_54p_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_accton_as4625_54p_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_accton_as4625_54p_porting.h" + +#endif /* __X86_64_ACCTON_AS4625_54P_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/inc/x86_64_accton_as4625_54p/x86_64_accton_as4625_54p_dox.h b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/inc/x86_64_accton_as4625_54p/x86_64_accton_as4625_54p_dox.h new file mode 100644 index 000000000..679607cc6 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/inc/x86_64_accton_as4625_54p/x86_64_accton_as4625_54p_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_accton_as4625_54p Doxygen Header + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS4625_54P_DOX_H__ +#define __X86_64_ACCTON_AS4625_54P_DOX_H__ + +/** + * @defgroup x86_64_accton_as4625_54p x86_64_accton_as4625_54p - x86_64_accton_as4625_54p Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_accton_as4625_54p-x86_64_accton_as4625_54p Public Interface + * @defgroup x86_64_accton_as4625_54p-config Compile Time Configuration + * @defgroup x86_64_accton_as4625_54p-porting Porting Macros + * + * @} + * + */ + +#endif /* __X86_64_ACCTON_AS4625_54P_DOX_H__ */ diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/inc/x86_64_accton_as4625_54p/x86_64_accton_as4625_54p_porting.h b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/inc/x86_64_accton_as4625_54p/x86_64_accton_as4625_54p_porting.h new file mode 100644 index 000000000..e5676ff6e --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/inc/x86_64_accton_as4625_54p/x86_64_accton_as4625_54p_porting.h @@ -0,0 +1,97 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_accton_as4625_54p Porting Macros. + * + * @addtogroup x86_64_accton_as4625_54p-porting + * @{ + * + *****************************************************************************/ +#ifndef __X86_64_ACCTON_AS4625_54P_PORTING_H__ +#define __X86_64_ACCTON_AS4625_54P_PORTING_H__ + + +/* */ +#if X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef X86_64_ACCTON_AS4625_54P_MALLOC + #if defined(GLOBAL_MALLOC) + #define X86_64_ACCTON_AS4625_54P_MALLOC GLOBAL_MALLOC + #elif X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS4625_54P_MALLOC malloc + #else + #error The macro X86_64_ACCTON_AS4625_54P_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS4625_54P_FREE + #if defined(GLOBAL_FREE) + #define X86_64_ACCTON_AS4625_54P_FREE GLOBAL_FREE + #elif X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS4625_54P_FREE free + #else + #error The macro X86_64_ACCTON_AS4625_54P_FREE is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS4625_54P_MEMSET + #if defined(GLOBAL_MEMSET) + #define X86_64_ACCTON_AS4625_54P_MEMSET GLOBAL_MEMSET + #elif X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS4625_54P_MEMSET memset + #else + #error The macro X86_64_ACCTON_AS4625_54P_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS4625_54P_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define X86_64_ACCTON_AS4625_54P_MEMCPY GLOBAL_MEMCPY + #elif X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS4625_54P_MEMCPY memcpy + #else + #error The macro X86_64_ACCTON_AS4625_54P_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS4625_54P_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define X86_64_ACCTON_AS4625_54P_VSNPRINTF GLOBAL_VSNPRINTF + #elif X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS4625_54P_VSNPRINTF vsnprintf + #else + #error The macro X86_64_ACCTON_AS4625_54P_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS4625_54P_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define X86_64_ACCTON_AS4625_54P_SNPRINTF GLOBAL_SNPRINTF + #elif X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS4625_54P_SNPRINTF snprintf + #else + #error The macro X86_64_ACCTON_AS4625_54P_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef X86_64_ACCTON_AS4625_54P_STRLEN + #if defined(GLOBAL_STRLEN) + #define X86_64_ACCTON_AS4625_54P_STRLEN GLOBAL_STRLEN + #elif X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_STDLIB == 1 + #define X86_64_ACCTON_AS4625_54P_STRLEN strlen + #else + #error The macro X86_64_ACCTON_AS4625_54P_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __X86_64_ACCTON_AS4625_54P_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/make.mk b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/make.mk new file mode 100644 index 000000000..70281df52 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_accton_as4625_54p_INCLUDES := -I $(THIS_DIR)inc +x86_64_accton_as4625_54p_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_accton_as4625_54p_DEPENDMODULE_ENTRIES := init:x86_64_accton_as4625_54p ucli:x86_64_accton_as4625_54p + diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/Makefile b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/Makefile new file mode 100644 index 000000000..873c68da3 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_accton_as4625_54p_ucli.c + diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/fani.c b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/fani.c new file mode 100644 index 000000000..c73545c2b --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/fani.c @@ -0,0 +1,279 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include +#include "platform_lib.h" + +#define PSU_PREFIX_PATH "/sys/bus/i2c/devices/" + +#define MAX_FAN_SPEED 23000 +#define MAX_PSU_FAN_SPEED 25500 + +enum fan_id { + FAN_1_ON_FAN_BOARD = 1, + FAN_2_ON_FAN_BOARD, + FAN_3_ON_FAN_BOARD, + FAN_1_ON_PSU_1, + FAN_1_ON_PSU_2, +}; + +#define CHASSIS_FAN_INFO(fid) { \ + { ONLP_FAN_ID_CREATE(FAN_##fid##_ON_FAN_BOARD), "Chassis Fan - "#fid, 0, {0} },\ + 0x0, \ + ONLP_FAN_CAPS_SET_PERCENTAGE | \ + ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE, \ + 0, \ + 0, \ + ONLP_FAN_MODE_INVALID, \ + } + +#define PSU_FAN_INFO(pid, fid) { \ + { ONLP_FAN_ID_CREATE(FAN_##fid##_ON_PSU_##pid), "PSU "#pid" - Fan "#fid, 0, {0} },\ + 0x0,\ + ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE, \ + 0,\ + 0,\ + ONLP_FAN_MODE_INVALID,\ + } + +/* Static fan information */ +onlp_fan_info_t finfo[] = { + { }, /* Not used */ + CHASSIS_FAN_INFO(1), + CHASSIS_FAN_INFO(2), + CHASSIS_FAN_INFO(3), + PSU_FAN_INFO(1,1), + PSU_FAN_INFO(2,1) +}; + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +_onlp_fani_info_get_fan(int fid, onlp_fan_info_t* info) +{ + int value; + + /* get fan present status + */ + info->status |= ONLP_FAN_STATUS_PRESENT; + + /* get fan fault status (turn on when any one fails) + */ + if (onlp_file_read_int(&value, "%s""fan%d_fault", + FAN_NODE_PATH, fid) < 0) { + AIM_LOG_ERROR("Unable to read fan fault status from (%s)\r\n", + FAN_NODE_PATH); + return ONLP_STATUS_E_INTERNAL; + } + if (value > 0) + info->status |= ONLP_FAN_STATUS_FAILED; + + + /* get fan direction (both : the same) + */ + info->status |= ONLP_FAN_STATUS_F2B; + + + /* get fan speed + */ + if (onlp_file_read_int(&value, "%s""fan%d_input", + FAN_NODE_PATH, fid) < 0) { + AIM_LOG_ERROR("Unable to read fan speed from (%s)\r\n", + FAN_NODE_PATH); + + return ONLP_STATUS_E_INTERNAL; + } + info->rpm = value; + + /* get pwm percentage + */ + if (onlp_file_read_int(&value, "%s""fan%d_pwm", + FAN_NODE_PATH, fid) < 0) { + AIM_LOG_ERROR("Unable to read fan duty from (%s)\r\n", + FAN_NODE_PATH); + return ONLP_STATUS_E_INTERNAL; + } + info->percentage = value; + + return ONLP_STATUS_OK; +} + +static uint32_t +_onlp_get_fan_direction_on_psu(void) +{ + /* Try to read direction from PSU1. + * If PSU1 is not valid, read from PSU2 + */ + int i = 0; + + for (i = PSU1_ID; i <= PSU2_ID; i++) { + psu_type_t psu_type; + psu_type = get_psu_type(i, NULL, 0); + + if (psu_type == PSU_TYPE_UNKNOWN) + continue; + + if (PSU_TYPE_UP1K21R_1085G_F2B == psu_type || + PSU_TYPE_UPD1501SA_1179G_F2B == psu_type) + return ONLP_FAN_STATUS_F2B; + else if(PSU_TYPE_UPD1501SA_1279G_B2F == psu_type) + return ONLP_FAN_STATUS_B2F; + else + return ONLP_FAN_STATUS_B2F; + } + + return 0; +} + +static int +_onlp_fani_info_get_fan_on_psu(int pid, onlp_fan_info_t* info) +{ + int val = 0; + + info->status |= ONLP_FAN_STATUS_PRESENT; + + /* get fan direction + */ + info->status |= _onlp_get_fan_direction_on_psu(); + + /* get fan fault status + */ + if (psu_pmbus_info_get(pid, "psu_fan1_fault", &val) + == ONLP_STATUS_OK) + info->status |= (val > 0) ? ONLP_FAN_STATUS_FAILED : 0; + + /* get fan speed + */ + if (psu_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) + == ONLP_STATUS_OK) { + info->rpm = val; + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + } + + return ONLP_STATUS_OK; +} + +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int +onlp_fani_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) +{ + int rc = 0; + int fid; + + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + *info = finfo[fid]; + + switch (fid) { + case FAN_1_ON_PSU_1: + rc = _onlp_fani_info_get_fan_on_psu(PSU1_ID, info); + break; + case FAN_1_ON_PSU_2: + rc = _onlp_fani_info_get_fan_on_psu(PSU2_ID, info); + break; + case FAN_1_ON_FAN_BOARD: + case FAN_2_ON_FAN_BOARD: + case FAN_3_ON_FAN_BOARD: + rc =_onlp_fani_info_get_fan(fid, info); + break; + default: + rc = ONLP_STATUS_E_INVALID; + break; + } + + return rc; +} + +/* + * This function sets the speed of the given fan in RPM. + * + * This function will only be called if the fan supprots the RPM_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_rpm_set(onlp_oid_t id, int rpm) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan speed of the given OID as a percentage. + * + * This will only be called if the OID has the PERCENTAGE_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_percentage_set(onlp_oid_t id, int p) +{ + int fid; + char *path = NULL; + + VALIDATE(id); + + fid = ONLP_OID_ID_GET(id); + + /* reject p=0 (p=0, stop fan) */ + if (p == 0) + return ONLP_STATUS_E_INVALID; + + switch (fid) { + case FAN_1_ON_FAN_BOARD: + path = FAN_NODE(fan1_pwm); + break; + case FAN_2_ON_FAN_BOARD: + path = FAN_NODE(fan2_pwm); + break; + case FAN_3_ON_FAN_BOARD: + path = FAN_NODE(fan3_pwm); + break; + default: + return ONLP_STATUS_E_INVALID; + } + + if (onlp_file_write_int(p, path) < 0) { + AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/ledi.c b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/ledi.c new file mode 100644 index 000000000..aec5d7337 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/ledi.c @@ -0,0 +1,239 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +#define LED_FORMAT "/sys/class/leds/as4625_led::%s/brightness" + +/* LED related data + */ +enum onlp_led_id { + LED_RESERVED = 0, + LED_SYS, + LED_LOC, + LED_PSU1, + LED_PSU2, + LED_FAN, + LED_POE +}; + +enum led_light_mode { + LED_MODE_OFF = 0, + LED_MODE_GREEN, + LED_MODE_AMBER, + LED_MODE_RED, + LED_MODE_BLUE, + LED_MODE_GREEN_BLINK, + LED_MODE_AMBER_BLINK, + LED_MODE_RED_BLINK, + LED_MODE_BLUE_BLINK, + LED_MODE_AUTO, + LED_MODE_UNKNOWN +}; + +typedef struct led_light_mode_map { + enum onlp_led_id id; + enum led_light_mode driver_led_mode; + enum onlp_led_mode_e onlp_led_mode; +} led_light_mode_map_t; + +led_light_mode_map_t led_map[] = { + {LED_SYS, LED_MODE_GREEN_BLINK, ONLP_LED_MODE_GREEN_BLINKING}, + {LED_SYS, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, + {LED_SYS, LED_MODE_AMBER_BLINK, ONLP_LED_MODE_ORANGE_BLINKING}, + {LED_SYS, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, + + {LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF}, + {LED_LOC, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, + {LED_LOC, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, + + {LED_PSU1, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + {LED_PSU2, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + {LED_FAN, LED_MODE_AUTO, ONLP_LED_MODE_AUTO}, + + {LED_POE, LED_MODE_OFF, ONLP_LED_MODE_OFF}, + {LED_POE, LED_MODE_GREEN, ONLP_LED_MODE_GREEN}, + {LED_POE, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE}, +}; + +static char *leds[] = { /* must map with onlp_led_id */ + NULL, + "sys", + "loc", + "psu1", + "psu2", + "fan", + "poe" +}; + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t linfo[] = +{ + { }, /* Not used */ + { + { ONLP_LED_ID_CREATE(LED_SYS), "LED 1 (SYS LED)", 0, {0} }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN_BLINKING | + ONLP_LED_CAPS_ORANGE_BLINKING, + }, + { + { ONLP_LED_ID_CREATE(LED_LOC), "LED 2 (LOC LED)", 0, {0} }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU1), "LED 3 (PSU1 LED)", 0, {0} }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_PSU2), "LED 4 (PSU2 LED)", 0, {0} }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_FAN), "LED 5 (FAN LED)", 0, {0} }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_POE), "LED 6 (POE LED)", 0, {0} }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE, + }, +}; + +static int driver_to_onlp_led_mode(enum onlp_led_id id, + enum led_light_mode driver_led_mode) +{ + int i, nsize = sizeof(led_map) / sizeof(led_map[0]); + + for (i = 0; i < nsize; i++) { + if (id == led_map[i].id && + driver_led_mode == led_map[i].driver_led_mode) + return led_map[i].onlp_led_mode; + } + + return 0; +} + +static int onlp_to_driver_led_mode(enum onlp_led_id id, + onlp_led_mode_t onlp_led_mode) +{ + int i, nsize = sizeof(led_map) / sizeof(led_map[0]); + + for(i = 0; i < nsize; i++) { + if (id == led_map[i].id && + onlp_led_mode == led_map[i].onlp_led_mode) + return led_map[i].driver_led_mode; + } + + return 0; +} + +/* + * This function will be called prior to any other onlp_ledi_* functions. + */ +int +onlp_ledi_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info) +{ + int lid, value; + VALIDATE(id); + + lid = ONLP_OID_ID_GET(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[ONLP_OID_ID_GET(id)]; + + /* Get LED mode */ + if (onlp_file_read_int(&value, LED_FORMAT, leds[lid]) < 0) + return ONLP_STATUS_E_INTERNAL; + + info->mode = driver_to_onlp_led_mode(lid, value); + + /* Set the on/off status */ + if (info->mode != ONLP_LED_MODE_OFF) + info->status |= ONLP_LED_STATUS_ON; + + return ONLP_STATUS_OK; +} + +/* + * Turn an LED on or off. + * + * This function will only be called if the LED OID supports the ONOFF + * capability. + * + * What 'on' means in terms of colors or modes for multimode LEDs is + * up to the platform to decide. This is intended as baseline toggle mechanism. + */ +int +onlp_ledi_set(onlp_oid_t id, int on_or_off) +{ + VALIDATE(id); + + if (!on_or_off) + return onlp_ledi_mode_set(id, ONLP_LED_MODE_OFF); + else + return onlp_ledi_mode_set(id, ONLP_LED_MODE_GREEN); +} + +/* + * This function puts the LED into the given mode. It is a more functional + * interface for multimode LEDs. + * + * Only modes reported in the LED's capabilities will be attempted. + */ +int +onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode) +{ + int lid; + VALIDATE(id); + + lid = ONLP_OID_ID_GET(id); + + if (onlp_file_write_int(onlp_to_driver_led_mode(lid , mode), + LED_FORMAT, leds[lid]) != 0) + return ONLP_STATUS_E_INTERNAL; + + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/make.mk b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/make.mk new file mode 100644 index 000000000..7f70a8c79 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_accton_as4625_54p +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/platform_lib.c b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/platform_lib.c new file mode 100644 index 000000000..442bdb57d --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/platform_lib.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include "platform_lib.h" +#include +#include "x86_64_accton_as4625_54p_log.h" + +#define PSU_MODEL_NAME_LEN 13 +#define I2C_PSU_FAN_DIR_LEN 3 + +psu_type_t get_psu_type(int id, char *data_buf, int data_len) +{ + int len = 0; + char *path[] = { PSU1_AC_EEPROM_PREFIX, PSU2_AC_EEPROM_PREFIX }; + char *str = NULL; + psu_type_t ptype = PSU_TYPE_UNKNOWN; + + /* Read attribute */ + len = onlp_file_read_str(&str, "%s%s", path[id-1], "psu_model_name"); + if (!str || len <= 0 || len < PSU_MODEL_NAME_LEN) { + AIM_FREE_IF_PTR(str); + return PSU_TYPE_UNKNOWN; + } + + /* Check AC model name */ + if (strncmp(str, "UP1K21R-1085G", strlen("UP1K21R-1085G")) == 0) + ptype = PSU_TYPE_UP1K21R_1085G_F2B; + else if(strncmp(str, "UPD1501SA-1179G", strlen("UPD1501SA-1179G")) == 0) + ptype = PSU_TYPE_UPD1501SA_1179G_F2B; + else if(strncmp(str, "UPD1501SA-1279G", strlen("UPD1501SA-1279G")) == 0) + ptype = PSU_TYPE_UPD1501SA_1279G_B2F; + else + ptype = PSU_TYPE_UNKNOWN; + + if (len < data_len) + aim_strlcpy(data_buf, str, len+1); + + AIM_FREE_IF_PTR(str); + return ptype; +} + +int psu_pmbus_info_get(int id, char *node, int *value) +{ + char *path[] = { PSU1_AC_PMBUS_PREFIX, PSU2_AC_PMBUS_PREFIX }; + *value = 0; + + return onlp_file_read_int(value, "%s%s", path[id-1], node); +} + +int get_psu_eeprom_str(int id, char *data_buf, int data_len, char *data_name) +{ + int len = 0; + char *path[] = { PSU1_AC_EEPROM_PREFIX, PSU2_AC_EEPROM_PREFIX }; + char *str = NULL; + + /* Read attribute */ + len = onlp_file_read_str(&str, "%s%s", path[id-1], data_name); + if (!str || len <= 0) { + AIM_FREE_IF_PTR(str); + return ONLP_STATUS_E_INTERNAL; + } + + if (len > data_len) { + AIM_FREE_IF_PTR(str); + return ONLP_STATUS_E_INVALID; + } + + aim_strlcpy(data_buf, str, len+1); + AIM_FREE_IF_PTR(str); + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/platform_lib.h b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/platform_lib.h new file mode 100644 index 000000000..111dcd522 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/platform_lib.h @@ -0,0 +1,84 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#ifndef __PLATFORM_LIB_H__ +#define __PLATFORM_LIB_H__ + +#include +#include "x86_64_accton_as4625_54p_log.h" + +#define CHASSIS_FAN_COUNT 3 +#define CHASSIS_THERMAL_COUNT 6 +#define CHASSIS_PSU_COUNT 2 +#define CHASSIS_LED_COUNT 6 + +#define NUM_OF_THERMAL_PER_PSU 2 + +#define NUM_OF_CPU_CORES 4 + +#define PSU1_ID 1 +#define PSU2_ID 2 + +#define PSU_NODE_MAX_INT_LEN 8 +#define PSU_NODE_MAX_PATH_LEN 64 + +#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/8-0058/" +#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/9-0059/" + +#define PSU1_AC_PMBUS_NODE(node) PSU1_AC_PMBUS_PREFIX#node +#define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node + +#define PSU1_AC_EEPROM_PREFIX "/sys/bus/i2c/devices/8-0050/" +#define PSU2_AC_EEPROM_PREFIX "/sys/bus/i2c/devices/9-0051/" + +#define CPLD_NODE_PATH "/sys/bus/i2c/devices/i2c-0/0-0064/" + +#define FAN_NODE_PATH "/sys/devices/platform/as4625_fan/hwmon*" +#define FAN_NODE(node) FAN_NODE_PATH#node + +#define IDPROM_PATH "/sys/bus/i2c/devices/7-0051/eeprom" + +int psu_pmbus_info_get(int id, char *node, int *value); + +typedef enum psu_type { + PSU_TYPE_UNKNOWN, + PSU_TYPE_UP1K21R_1085G_F2B, + PSU_TYPE_UPD1501SA_1179G_F2B, + PSU_TYPE_UPD1501SA_1279G_B2F +} psu_type_t; + +psu_type_t get_psu_type(int id, char* modelname, int modelname_len); +int get_psu_eeprom_str(int id, char *data_buf, int data_len, char *data_name); + +#define AIM_FREE_IF_PTR(p) \ + do \ + { \ + if (p) { \ + aim_free(p); \ + p = NULL; \ + } \ + } while (0) + +#endif /* __PLATFORM_LIB_H__ */ diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/psui.c b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/psui.c new file mode 100644 index 000000000..c9c2e37ad --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/psui.c @@ -0,0 +1,177 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include "platform_lib.h" + +#define PSU_STATUS_PRESENT 1 +#define PSU_STATUS_POWER_GOOD 1 + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +psu_status_info_get(int id, char *node, int *value) +{ + char *path[] = { PSU1_AC_EEPROM_PREFIX, PSU2_AC_EEPROM_PREFIX }; + *value = 0; + + return onlp_file_read_int(value, "%s%s", path[id-1], node); +} + +int +onlp_psui_init(void) +{ + return ONLP_STATUS_OK; +} + +static int +psu_ym2651y_info_get(onlp_psu_info_t* info) +{ + int val = 0; + int index = ONLP_OID_ID_GET(info->hdr.id); + + /* Set capability + */ + info->caps = ONLP_PSU_CAPS_AC; + + if (info->status & ONLP_PSU_STATUS_FAILED) + return ONLP_STATUS_OK; + + /* Set the associated oid_table */ + info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT); + + info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE((index-1) * + NUM_OF_THERMAL_PER_PSU + + CHASSIS_THERMAL_COUNT + + 1); + + info->hdr.coids[2] = ONLP_THERMAL_ID_CREATE((index-1) * + NUM_OF_THERMAL_PER_PSU + + CHASSIS_THERMAL_COUNT + + 2); + + /* Read voltage, current and power */ + if (psu_pmbus_info_get(index, "psu_v_out", &val) == 0) { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + if (psu_pmbus_info_get(index, "psu_i_out", &val) == 0) { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + if (psu_pmbus_info_get(index, "psu_p_out", &val) == 0) { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + get_psu_eeprom_str(index, info->serial, sizeof(info->serial), + "psu_serial_number"); + + return ONLP_STATUS_OK; +} + +/* + * Get all information about the given PSU oid. + */ +static onlp_psu_info_t pinfo[] = +{ + { }, /* Not used */ + { + { ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0 }, + }, + { + { ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0 }, + } +}; + +int +onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info) +{ + int val = 0; + int ret = ONLP_STATUS_OK; + int index = ONLP_OID_ID_GET(id); + psu_type_t psu_type; + + VALIDATE(id); + + memset(info, 0, sizeof(onlp_psu_info_t)); + *info = pinfo[index]; /* Set the onlp_oid_hdr_t */ + + /* Get the present state */ + if (psu_status_info_get(index, "psu_present", &val) != 0) { + AIM_LOG_ERROR("Unable to read PSU(%d) node(psu_present)\r\n", + index); + return ONLP_STATUS_E_INTERNAL; + } + + if (val != PSU_STATUS_PRESENT) { + info->status &= ~ONLP_PSU_STATUS_PRESENT; + return ONLP_STATUS_OK; + } + info->status |= ONLP_PSU_STATUS_PRESENT; + + + /* Get power good status */ + if (psu_status_info_get(index, "psu_power_good", &val) != 0) { + AIM_LOG_ERROR("Unable to read PSU(%d) node(psu_power_good)\r\n", + index); + return ONLP_STATUS_E_INTERNAL; + } + + /* Get PSU type */ + psu_type = get_psu_type(index, info->model, sizeof(info->model)); + + if ((val != PSU_STATUS_POWER_GOOD) && (psu_type == PSU_TYPE_UNKNOWN)) { + info->status |= ONLP_PSU_STATUS_UNPLUGGED; + } else if((val != PSU_STATUS_POWER_GOOD) && (psu_type != PSU_TYPE_UNKNOWN)){ + info->status |= ONLP_PSU_STATUS_FAILED; + } + + switch (psu_type) { + case PSU_TYPE_UP1K21R_1085G_F2B: + case PSU_TYPE_UPD1501SA_1179G_F2B: + case PSU_TYPE_UPD1501SA_1279G_B2F: + ret = psu_ym2651y_info_get(info); + break; + case PSU_TYPE_UNKNOWN: /* User insert a unknown PSU or unplugged.*/ + info->status |= ONLP_PSU_STATUS_UNPLUGGED; + info->status &= ~ONLP_PSU_STATUS_FAILED; + ret = ONLP_STATUS_OK; + break; + default: + ret = ONLP_STATUS_E_UNSUPPORTED; + break; + } + + return ret; +} diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/sfpi.c b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/sfpi.c new file mode 100644 index 000000000..44a9a6ff5 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/sfpi.c @@ -0,0 +1,358 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2013 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include "x86_64_accton_as4625_54p_int.h" +#include "x86_64_accton_as4625_54p_log.h" + +#define PORT_EEPROM_FORMAT "/sys/bus/i2c/devices/%d-0050/eeprom" +#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/0-0064/module_present_%d" +#define MODULE_RXLOS_FORMAT "/sys/bus/i2c/devices/0-0064/module_rx_los_%d" +#define MODULE_TXFAULT_FORMAT "/sys/bus/i2c/devices/0-0064/module_tx_fault_%d" +#define MODULE_TXDISABLE_FORMAT "/sys/bus/i2c/devices/0-0064/module_tx_disable_%d" +#define MODULE_RESET_FORMAT "/sys/bus/i2c/devices/0-0064/module_reset_%d" +#define MODULE_LPMODE_FORMAT "/sys/bus/i2c/devices/0-0064/module_lpmode_%d" +#define MODULE_PRESENT_ALL_ATTR "/sys/bus/i2c/devices/0-0064/module_present_all" +#define MODULE_RXLOS_ALL_ATTR "/sys/bus/i2c/devices/0-0064/module_rx_los_all" +/* QSFP device address of eeprom */ +#define PORT_EEPROM_DEVADDR 0x50 +/* QSFP tx disable offset */ +#define QSFP_EEPROM_OFFSET_TXDIS 0x56 + +int port_bus_index[] = { 10, 11, 12, 13, 14, 15 }; +#define PORT_BUS_INDEX(port) (port_bus_index[port-48]) + +#define VALIDATE_SFP(_port) \ + do { \ + if (_port < 48 || _port > 53) \ + return ONLP_STATUS_E_UNSUPPORTED; \ + } while(0) + + +/************************************************************ + * + * SFPI Entry Points + * + ***********************************************************/ +int +onlp_sfpi_init(void) +{ + /* Called at initialization time */ + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + /* + * Ports {48, 53} + */ + int p; + + for (p = 48; p < 54; p++) { + AIM_BITMAP_SET(bmap, p); + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_present(int port) +{ + /* + * Return 1 if present. + * Return 0 if not present. + * Return < 0 if error. + */ + int present; + VALIDATE_SFP(port); + + if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, port+1) < 0) { + AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", + port); + return ONLP_STATUS_E_INTERNAL; + } + + return present; +} + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + uint32_t byte; + FILE* fp; + + /* Read present status of port 48 ~ 53 */ + int count = 0; + + fp = fopen(MODULE_PRESENT_ALL_ATTR, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_present_all device file"); + return ONLP_STATUS_E_INTERNAL; + } + + count = fscanf(fp, "%x", &byte); + fclose(fp); + + if(count != 1) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read the module_present_all device file"); + return ONLP_STATUS_E_INTERNAL; + } + + /* Mask out non-existant SFP ports */ + byte &= 0x3F; + + /* Convert to 64 bit integer in port order */ + int i = 0; + uint64_t presence_all = byte; + + /* Populate bitmap */ + presence_all <<= 48; + + for(i = 0; presence_all; i++) { + AIM_BITMAP_MOD(dst, i, (presence_all & 1)); + presence_all >>= 1; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + uint32_t byte; + FILE* fp; + + uint32_t byte1; + FILE* fp1; + + /* Read rxlos status of port 48 ~ 53 */ + int count = 0; + + /* Read present status of port 48 ~ 53 */ + int count1 = 0; + + fp = fopen(MODULE_RXLOS_ALL_ATTR, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the module_rx_los_all device file"); + return ONLP_STATUS_E_INTERNAL; + } + + count = fscanf(fp, "%x", &byte); + fclose(fp); + + if(count != 1) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read the module_rx_los_all device file"); + return ONLP_STATUS_E_INTERNAL; + } + + fp1 = fopen(MODULE_PRESENT_ALL_ATTR, "r"); + if(fp1 == NULL) { + AIM_LOG_ERROR("Unable to open the module_present_all device file"); + return ONLP_STATUS_E_INTERNAL; + } + + count1 = fscanf(fp1, "%x", &byte1); + fclose(fp1); + + if(count1 != 1) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read the module_present_all device file"); + return ONLP_STATUS_E_INTERNAL; + } + + /* Mask out non-existant SFP ports */ + byte &= 0x3F; + byte &= byte1; + + /* Convert to 64 bit integer in port order */ + AIM_BITMAP_CLR_ALL(dst); + int i = 0; + uint64_t rx_los_all = byte; + + /* Populate bitmap */ + rx_los_all <<= 48; + for(i = 0; rx_los_all; i++) { + AIM_BITMAP_MOD(dst, i, (rx_los_all & 1)); + rx_los_all >>= 1; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + /* + * Read the SFP eeprom into data[] + * + * Return MISSING if SFP is missing. + * Return OK if eeprom is read + */ + int size = 0; + VALIDATE_SFP(port); + + memset(data, 0, 256); + + if (onlp_file_read(data, 256, &size, PORT_EEPROM_FORMAT, + PORT_BUS_INDEX(port)) != ONLP_STATUS_OK) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + if (size != 256) { + AIM_LOG_ERROR("Unable to read eeprom from port(%d), size is different!\r\n" + , port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + FILE* fp; + char file[64] = {0}; + + if(port < 48) + return ONLP_STATUS_E_UNSUPPORTED; + sprintf(file, PORT_EEPROM_FORMAT, PORT_BUS_INDEX(port)); + fp = fopen(file, "r"); + if(fp == NULL) { + AIM_LOG_ERROR("Unable to open the eeprom device file of port(%d)" + , port); + return ONLP_STATUS_E_INTERNAL; + } + + if (fseek(fp, 256, SEEK_CUR) != 0) { + fclose(fp); + AIM_LOG_ERROR("Unable to set the file position indicator of port(%d)" + , port); + return ONLP_STATUS_E_INTERNAL; + } + + int ret = fread(data, 1, 256, fp); + fclose(fp); + if (ret != 256) { + AIM_LOG_ERROR("Unable to read the module_eeprom device file of port(%d)" + , port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) +{ + switch(control) { + case ONLP_SFP_CONTROL_TX_DISABLE:{ + if (port >= 48 && port <= 53) { + if (onlp_file_write_int(value, MODULE_TXDISABLE_FORMAT + , (port+1)) < 0) { + AIM_LOG_ERROR("Unable to set tx_disable status to port(%d)\r\n" + , port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; + } else { + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_E_INTERNAL; + } + + default: + break; + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) +{ + + switch(control) { + case ONLP_SFP_CONTROL_RX_LOS: { + VALIDATE_SFP(port); + if (onlp_file_read_int(value, MODULE_RXLOS_FORMAT, (port+1)) + < 0) { + AIM_LOG_ERROR("Unable to read rx_loss status from port(%d)\r\n" + , port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; + } + + case ONLP_SFP_CONTROL_TX_FAULT: { + VALIDATE_SFP(port); + if (onlp_file_read_int(value, MODULE_TXFAULT_FORMAT, (port+1)) + < 0) { + AIM_LOG_ERROR("Unable to read tx_fault status from port(%d)\r\n" + , port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; + } + + case ONLP_SFP_CONTROL_TX_DISABLE: { + if (port >= 48 && port <= 53) + { + if (onlp_file_read_int(value, MODULE_TXDISABLE_FORMAT, + (port+1)) < 0) { + AIM_LOG_ERROR("Unable to read tx_disabled status from port(%d)\r\n" + , port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; + } else { + return ONLP_STATUS_E_INTERNAL; + } + + + return ONLP_STATUS_E_INTERNAL; + } + default: + break; + } + + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/sysi.c b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/sysi.c new file mode 100644 index 000000000..4efa0a91b --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/sysi.c @@ -0,0 +1,261 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" +#include "x86_64_accton_as4625_54p_int.h" +#include "x86_64_accton_as4625_54p_log.h" + +#define PREFIX_PATH_ON_CPLD_DEV "/sys/bus/i2c/devices/0-0064/" + +#define NUM_OF_CPLD 1 +#define FAN_DUTY_CYCLE_MAX (100) + +#define FAN_DUTY_CYCLE_DEFAULT 38 +#define SYS_TEMP_HIGH_THRESHOLD 202 +#define SYS_TEMP_LOW_THRESHOLD 135 +#define PWM_STATE_NORMAL 0 +#define PWM_STATE_CRITICAL 1 + +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-accton-as4625-54p-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)); + + /* 6 Thermal sensors on the chassis */ + for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* 6 LEDs on the chassis */ + for (i = 1; i <= CHASSIS_LED_COUNT; i++) { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* 2 PSUs on the chassis */ + for (i = 1; i <= CHASSIS_PSU_COUNT; i++) { + *e++ = ONLP_PSU_ID_CREATE(i); + } + + /* 3 Fans on the chassis */ + for (i = 1; i <= CHASSIS_FAN_COUNT; i++) { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + return 0; +} + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + int ver_major = 0, ver_minor = 0; + + if(onlp_file_read_int(&ver_major, "%s/version_major", PREFIX_PATH_ON_CPLD_DEV) < 0) + return ONLP_STATUS_E_INTERNAL; + + if(onlp_file_read_int(&ver_minor, "%s/version_minor", PREFIX_PATH_ON_CPLD_DEV) < 0) + return ONLP_STATUS_E_INTERNAL; + + pi->cpld_versions = aim_fstrdup("\r\nCPLD ver: %.2d.%.2d", ver_major, ver_minor); + + return 0; +} + +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) +{ + aim_free(pi->cpld_versions); +} + +int onlp_sysi_platform_manage_fans(void) +{ + static int prev_warning = 0; + static int warning = 0; + static int pwm_state = 0; + int shutdown = 0; + int sys_temp = 0; + int fan_status_error = 0, temp_status_error = 0; + int fan_fail = 0; + onlp_thermal_info_t thermali[5]; + int i = 0; + + prev_warning = warning; + + // 1. refresh fan status + fan_fail = 0; + fan_status_error = 0; + for(i = 1; i <= CHASSIS_FAN_COUNT; i++){ + onlp_fan_info_t fan_info; + if (onlp_fani_info_get(ONLP_FAN_ID_CREATE(i), &fan_info) + != ONLP_STATUS_OK) { + AIM_LOG_WARN("Unable to get fan(%d) status.\r\n", i); + fan_status_error = 1; + break; + } + + if (fan_info.status & ONLP_FAN_STATUS_FAILED || + !(fan_info.status & ONLP_FAN_STATUS_PRESENT)) { + AIM_LOG_WARN("Fan(%d) is not working\r\n", i); + fan_fail = 1; + break; + } + } + + // 2. refresh temperature status + temp_status_error = 0; + for(i = 0; i < CHASSIS_THERMAL_COUNT-1; i++){ + if (onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(i+2), &thermali[i]) + != ONLP_STATUS_OK) { + AIM_LOG_WARN("Unable to read thermal status.\n\r"); + temp_status_error = 1; + break; + } + + if(i != 3) // skip lm75 at 0x4E + sys_temp += (thermali[i].mcelsius / 1000); + } + + if(fan_status_error || temp_status_error){ + for(i = 1; i <= CHASSIS_FAN_COUNT; i++){ + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(i), FAN_DUTY_CYCLE_MAX); + AIM_LOG_WARN("Error occurred while updating fan and thermal status\n\r"); + } + return 0; + } + + // 2.1 check if current state is valid + if(pwm_state < PWM_STATE_NORMAL || pwm_state > PWM_STATE_CRITICAL) + pwm_state = PWM_STATE_NORMAL; + + // 2.2 check system temperature + if(sys_temp > SYS_TEMP_HIGH_THRESHOLD) + warning = 1; + else + warning = 0; + + if(pwm_state == PWM_STATE_CRITICAL){ + if(sys_temp < SYS_TEMP_LOW_THRESHOLD) + pwm_state = PWM_STATE_NORMAL; + } else { + if(sys_temp > SYS_TEMP_HIGH_THRESHOLD){ + pwm_state = PWM_STATE_CRITICAL; + AIM_LOG_WARN("system temperature(%d) reaches high threshold(%d)\n\r", + sys_temp, SYS_TEMP_HIGH_THRESHOLD); + } + } + + // 2.2 check temperature of each thermal sensor + for(i = 0; i < CHASSIS_THERMAL_COUNT-1; i++){ + if(thermali[i].mcelsius >= thermali[i].thresholds.shutdown){ + warning = 1; + shutdown = 1; + AIM_LOG_WARN("thermal(%s) temperature(%d) reach shutdown threshold(%d)\n\r", + thermali[i].hdr.description, thermali[i].mcelsius, thermali[i].thresholds.shutdown); + } else if(thermali[i].mcelsius >= thermali[i].thresholds.error){ + warning = 1; + AIM_LOG_WARN("thermal(%s) temperature(%d) reach high threshold(%d)\n\r", + thermali[i].hdr.description, thermali[i].mcelsius, thermali[i].thresholds.error); + } + } + + if(warning || shutdown) + pwm_state = PWM_STATE_CRITICAL; + + // 3. action + for(i = 1; i <= CHASSIS_FAN_COUNT; i++){ + if(fan_fail){ + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(i), FAN_DUTY_CYCLE_MAX); + } else { + if(pwm_state == PWM_STATE_NORMAL) + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(i), FAN_DUTY_CYCLE_DEFAULT); + else if(pwm_state == PWM_STATE_CRITICAL) + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(i), FAN_DUTY_CYCLE_MAX); + } + } + + if(prev_warning != warning){ + if(warning) + AIM_LOG_WARN("Alarm for temperature high is detected\n\r"); + else + AIM_LOG_INFO("Alarm for temperature high is cleared\n\r"); + } + + if(shutdown){ + AIM_LOG_WARN("Alarm-Critical for temperature critical is detected, disable PoE\n\r"); + onlp_file_write_int(0, PREFIX_PATH_ON_CPLD_DEV"pwr_enable_poe"); + + /* + Because the R0A hardware does not have the system thermal + shutdown (0x27) function, the power control (0x03) function + is used for thermal shutdown. So for the R0A hardware, this + thermal_shutdown sysfs is not functional. + */ + + AIM_LOG_WARN("Alarm-Critical for temperature critical is detected, trigger thermal shutdown\n\r"); + // Sync log buffer to disk for hardware revision R01 and above + system("sync;sync;sync"); + system("/sbin/fstrim -av"); + sleep(5); + onlp_file_write_int(1, PREFIX_PATH_ON_CPLD_DEV"thermal_shutdown"); + + AIM_LOG_WARN("Alarm-Critical for temperature critical is detected, shutdown DUT\n\r"); + // Sync log buffer to disk for hardware revision R0A + system("sync;sync;sync"); + system("/sbin/fstrim -av"); + sleep(5); + onlp_file_write_int(0, PREFIX_PATH_ON_CPLD_DEV"pwr_enable_mb"); + } + return 0; +} \ No newline at end of file diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/thermali.c b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/thermali.c new file mode 100644 index 000000000..fba033c86 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/thermali.c @@ -0,0 +1,190 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright 2014 Accton Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * Thermal Sensor Platform Implementation. + * + ***********************************************************/ +//#include +#include +#include +#include "platform_lib.h" + +#define CPU_CORE_ID_PATH_FORMAT "/sys/devices/system/cpu/cpu%d/topology/core_id" +#define CPU_CORETEMP_PATH_FORMAT "/sys/devices/platform/coretemp.0*temp%d_input" +#define THERMAL_PATH_FORMAT "/sys/bus/i2c/devices/%s/*temp1_input" +#define PSU_THERMAL_PATH_FORMAT "/sys/bus/i2c/devices/%s/*psu_temp1_input" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +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_1_ON_PSU1, + THERMAL_2_ON_PSU1, + THERMAL_1_ON_PSU2, + THERMAL_2_ON_PSU2, +}; + +static char* devfiles__[] = { /* must map with onlp_thermal_id */ + NULL, + NULL, /* CPU_CORE files */ + "/sys/bus/i2c/devices/3-004a*temp1_input", + "/sys/bus/i2c/devices/3-004b*temp1_input", + "/sys/bus/i2c/devices/3-004d*temp1_input", + "/sys/bus/i2c/devices/3-004e*temp1_input", + "/sys/bus/i2c/devices/3-004f*temp1_input", + "/sys/bus/i2c/devices/8-0058*psu_temp1_input", + "/sys/bus/i2c/devices/8-0058*psu_temp2_input", + "/sys/bus/i2c/devices/9-0059*psu_temp1_input", + "/sys/bus/i2c/devices/9-0059*psu_temp2_input" +}; + +/* Static values */ +static onlp_thermal_info_t linfo[] = { + { }, /* Not used */ + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE), "CPU Core", 0, {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 70000, 75000, 95000 } + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "MB_RightRear_temp(0x4A)", 0, {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 62000, 67000, 72000 } + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_MAIN_BROAD), "MB_RightCenter_temp(0x4B)", 0, {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 62000, 67000, 72000 } + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "MB_FrontCenter_temp(0x4D)", 0, {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 68000, 73000, 78000 } + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_4_ON_MAIN_BROAD), "MB_LeftCenter_temp(0x4E)", 0, {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 70000, 75000, 80000 } + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_5_ON_MAIN_BROAD), "MB_RightFront_temp(0x4F)", 0, {0} }, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 64000, 69000, 74000 } + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU1_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 65000, 70000, 90000 } + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU1), "PSU-1 Thermal Sensor 2", ONLP_PSU_ID_CREATE(PSU1_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 65000, 70000, 101000 } + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), "PSU-2 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU2_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 65000, 70000, 90000 } + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU2), "PSU-2 Thermal Sensor 2", ONLP_PSU_ID_CREATE(PSU2_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, { 65000, 70000, 101000 } + } +}; + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + return ONLP_STATUS_OK; +} + +int get_max_cpu_coretemp(int *max_cpu_coretemp) +{ + int core_id = 0; + int cpu_coretemp = 0; + int i = 0; + + for(i = 0; i < NUM_OF_CPU_CORES; i++){ + if(onlp_file_read_int(&core_id, CPU_CORE_ID_PATH_FORMAT, i) < 0) { + AIM_LOG_ERROR("Unable to read cpu core id from "CPU_CORE_ID_PATH_FORMAT"\r\n", + i); + *max_cpu_coretemp = 0; + return ONLP_STATUS_E_INTERNAL; + } + + if(onlp_file_read_int(&cpu_coretemp, CPU_CORETEMP_PATH_FORMAT, core_id+2) < 0) { + AIM_LOG_ERROR("Unable to read cpu coretemp from "CPU_CORETEMP_PATH_FORMAT"\r\n", + core_id+2); + *max_cpu_coretemp = 0; + return ONLP_STATUS_E_INTERNAL; + } + + if(cpu_coretemp > *max_cpu_coretemp) + *max_cpu_coretemp = cpu_coretemp; + } + + // read package temp, which is always in temp1_input + if(onlp_file_read_int(&cpu_coretemp, CPU_CORETEMP_PATH_FORMAT, 1) < 0) { + AIM_LOG_ERROR("Unable to read cpu package temp from "CPU_CORETEMP_PATH_FORMAT"\r\n", + 1); + *max_cpu_coretemp = 0; + return ONLP_STATUS_E_INTERNAL; + } + + *max_cpu_coretemp = (*max_cpu_coretemp > cpu_coretemp) ? + *max_cpu_coretemp : cpu_coretemp; + + return ONLP_STATUS_OK; +} + +/* + * Retrieve the information structure for the given thermal OID. + * + * If the OID is invalid, return ONLP_E_STATUS_INVALID. + * If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL. + * Otherwise, return ONLP_STATUS_OK with the OID's information. + * + * Note -- it is expected that you fill out the information + * structure even if the sensor described by the OID is not present. + */ +int +onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) +{ + int tid; + VALIDATE(id); + + tid = ONLP_OID_ID_GET(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[tid]; + + if (tid == THERMAL_CPU_CORE) { + return get_max_cpu_coretemp(&info->mcelsius); + } + + return onlp_file_read_int(&info->mcelsius, devfiles__[tid]); +} diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_config.c b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_config.c new file mode 100644 index 000000000..3baea2b7c --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_config.c @@ -0,0 +1,80 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_accton_as4625_54p_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_accton_as4625_54p_config_STRINGIFY_VALUE(_x) __x86_64_accton_as4625_54p_config_STRINGIFY_NAME(_x) +x86_64_accton_as4625_54p_config_settings_t x86_64_accton_as4625_54p_config_settings[] = +{ +#ifdef X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_LOGGING + { __x86_64_accton_as4625_54p_config_STRINGIFY_NAME(X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_LOGGING), __x86_64_accton_as4625_54p_config_STRINGIFY_VALUE(X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_LOGGING) }, +#else +{ X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_LOGGING(__x86_64_accton_as4625_54p_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS4625_54P_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_accton_as4625_54p_config_STRINGIFY_NAME(X86_64_ACCTON_AS4625_54P_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_accton_as4625_54p_config_STRINGIFY_VALUE(X86_64_ACCTON_AS4625_54P_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS4625_54P_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_accton_as4625_54p_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS4625_54P_CONFIG_LOG_BITS_DEFAULT + { __x86_64_accton_as4625_54p_config_STRINGIFY_NAME(X86_64_ACCTON_AS4625_54P_CONFIG_LOG_BITS_DEFAULT), __x86_64_accton_as4625_54p_config_STRINGIFY_VALUE(X86_64_ACCTON_AS4625_54P_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS4625_54P_CONFIG_LOG_BITS_DEFAULT(__x86_64_accton_as4625_54p_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS4625_54P_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_accton_as4625_54p_config_STRINGIFY_NAME(X86_64_ACCTON_AS4625_54P_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_accton_as4625_54p_config_STRINGIFY_VALUE(X86_64_ACCTON_AS4625_54P_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ X86_64_ACCTON_AS4625_54P_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_accton_as4625_54p_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_STDLIB + { __x86_64_accton_as4625_54p_config_STRINGIFY_NAME(X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_STDLIB), __x86_64_accton_as4625_54p_config_STRINGIFY_VALUE(X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_STDLIB) }, +#else +{ X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_STDLIB(__x86_64_accton_as4625_54p_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_accton_as4625_54p_config_STRINGIFY_NAME(X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_accton_as4625_54p_config_STRINGIFY_VALUE(X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ X86_64_ACCTON_AS4625_54P_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_accton_as4625_54p_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_UCLI + { __x86_64_accton_as4625_54p_config_STRINGIFY_NAME(X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_UCLI), __x86_64_accton_as4625_54p_config_STRINGIFY_VALUE(X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_UCLI) }, +#else +{ X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_UCLI(__x86_64_accton_as4625_54p_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_accton_as4625_54p_config_STRINGIFY_NAME(X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_accton_as4625_54p_config_STRINGIFY_VALUE(X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ X86_64_ACCTON_AS4625_54P_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_accton_as4625_54p_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_accton_as4625_54p_config_STRINGIFY_VALUE +#undef __x86_64_accton_as4625_54p_config_STRINGIFY_NAME + +const char* +x86_64_accton_as4625_54p_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_accton_as4625_54p_config_settings[i].name; i++) { + if(!strcmp(x86_64_accton_as4625_54p_config_settings[i].name, setting)) { + return x86_64_accton_as4625_54p_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_accton_as4625_54p_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_accton_as4625_54p_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_accton_as4625_54p_config_settings[i].name, x86_64_accton_as4625_54p_config_settings[i].value); + } + return i; +} + +/* */ diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_enums.c b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_enums.c new file mode 100644 index 000000000..ad7aa0f7c --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_int.h b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_int.h new file mode 100644 index 000000000..2ea67f730 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_accton_as4625_54p Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_accton_as4625_54p_INT_H__ +#define __x86_64_accton_as4625_54p_INT_H__ + +#include + + +#endif /* __x86_64_accton_as4625_54p_INT_H__ */ diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_log.c b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_log.c new file mode 100644 index 000000000..16084179c --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_as4625_54p_log.h" +/* + * x86_64_accton_as4625_54p log struct. + */ +AIM_LOG_STRUCT_DEFINE( + X86_64_ACCTON_AS4625_54P_CONFIG_LOG_OPTIONS_DEFAULT, + X86_64_ACCTON_AS4625_54P_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + X86_64_ACCTON_AS4625_54P_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_log.h b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_log.h new file mode 100644 index 000000000..56757b7b3 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_accton_as4625_54p_LOG_H__ +#define __x86_64_accton_as4625_54p_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_accton_as4625_54p +#include + +#endif /* __x86_64_accton_as4625_54p_LOG_H__ */ diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_module.c b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_module.c new file mode 100644 index 000000000..26c6e5e78 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_accton_as4625_54p_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_accton_as4625_54p_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_accton_as4625_54p_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_ucli.c b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_ucli.c new file mode 100644 index 000000000..4c88d61f7 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/onlp/builds/x86_64_accton_as4625_54p/module/src/x86_64_accton_as4625_54p_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if x86_64_accton_as4625_54p_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_accton_as4625_54p_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_accton_as4625_54p) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_accton_as4625_54p_ucli_module__ = + { + "x86_64_accton_as4625_54p_ucli", + NULL, + x86_64_accton_as4625_54p_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_accton_as4625_54p_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_accton_as4625_54p_ucli_module__); + n = ucli_node_create("x86_64_accton_as4625_54p", NULL, &x86_64_accton_as4625_54p_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_accton_as4625_54p")); + return n; +} + +#else +void* +x86_64_accton_as4625_54p_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/accton/x86-64/as4625-54p/platform-config/Makefile b/packages/platforms/accton/x86-64/as4625-54p/platform-config/Makefile new file mode 100644 index 000000000..502e772a7 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/accton/x86-64/as4625-54p/platform-config/r0/Makefile b/packages/platforms/accton/x86-64/as4625-54p/platform-config/r0/Makefile new file mode 100644 index 000000000..502e772a7 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk diff --git a/packages/platforms/accton/x86-64/as4625-54p/platform-config/r0/PKG.yml b/packages/platforms/accton/x86-64/as4625-54p/platform-config/r0/PKG.yml new file mode 100644 index 000000000..e41b24739 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=accton BASENAME=x86-64-accton-as4625-54p REVISION=r0 diff --git a/packages/platforms/accton/x86-64/as4625-54p/platform-config/r0/src/lib/x86-64-accton-as4625-54p-r0.yml b/packages/platforms/accton/x86-64/as4625-54p/platform-config/r0/src/lib/x86-64-accton-as4625-54p-r0.yml new file mode 100644 index 000000000..258766a17 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/platform-config/r0/src/lib/x86-64-accton-as4625-54p-r0.yml @@ -0,0 +1,30 @@ +--- + +###################################################################### +# +# platform-config for AS4625 +# +###################################################################### + +x86-64-accton-as4625-54p-r0: + + grub: + + serial: >- + --port=0x3f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-4-19 + + args: >- + console=ttyS0,115200n8 + intel_iommu=off + + network: + interfaces: + ma1: + name: eth2 diff --git a/packages/platforms/accton/x86-64/as4625-54p/platform-config/r0/src/python/x86_64_accton_as4625_54p_r0/__init__.py b/packages/platforms/accton/x86-64/as4625-54p/platform-config/r0/src/python/x86_64_accton_as4625_54p_r0/__init__.py new file mode 100644 index 000000000..059710107 --- /dev/null +++ b/packages/platforms/accton/x86-64/as4625-54p/platform-config/r0/src/python/x86_64_accton_as4625_54p_r0/__init__.py @@ -0,0 +1,58 @@ +from onl.platform.base import * +from onl.platform.accton import * + +class OnlPlatform_x86_64_accton_as4625_54p_r0(OnlPlatformAccton, + OnlPlatformPortConfig_48x1_6x10): + + PLATFORM='x86-64-accton-as4625-54p-r0' + MODEL="AS4625-54P" + SYS_OBJECT_ID=".4625.54.1" + + def baseconfig(self): + os.system("modprobe i2c-ismt") + os.system("modprobe at24") + self.insmod('optoe') + self.insmod('ym2651y') + + for m in [ 'cpld', 'fan', 'leds', 'psu' ]: + self.insmod("x86-64-accton-as4625-54p-%s.ko" % m) + + ########### initialize I2C bus 0, bus 1 ########### + self.new_i2c_devices([ + + #initiate CPLD + ('as4625_cpld1', 0x64, 0), + + # initialize multiplexer (PCA9548) + ('pca9548', 0x70, 1), + ('pca9548', 0x71, 1) + ]) + + self.new_i2c_devices([ + # inititate LM75 + ('lm75', 0x4a, 3), + ('lm75', 0x4b, 3), + ('lm75', 0x4d, 3), + ('lm75', 0x4e, 3), + ('lm75', 0x4f, 3) + ]) + + self.new_i2c_devices([ + # initiate PSU-1 + ('as4625_54p_psu1', 0x50, 8), + ('ym2651', 0x58, 8), + # initiate PSU-2 + ('as4625_54p_psu2', 0x51, 9), + ('ym2651', 0x59, 9), + ]) + + # initialize SFP port 49~54 + for port in range(49, 55): + self.new_i2c_device('optoe2', 0x50, port-39) + subprocess.call('echo port%d > /sys/bus/i2c/devices/%d-0050/port_name' % (port, port-39), shell=True) + + # initialize the LOC led to off + subprocess.call('echo 0 > /sys/class/leds/as4625_led::loc/brightness', shell=True) + + self.new_i2c_device('24c02', 0x51, 7) + return True