diff --git a/packages/platforms/delta/Makefile b/packages/platforms/delta/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/vendor-config/Makefile b/packages/platforms/delta/vendor-config/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/vendor-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/vendor-config/PKG.yml b/packages/platforms/delta/vendor-config/PKG.yml new file mode 100644 index 00000000..a203f54d --- /dev/null +++ b/packages/platforms/delta/vendor-config/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-vendor.yml VENDOR=delta Vendor=Delta diff --git a/packages/platforms/delta/vendor-config/src/python/delta/__init__.py b/packages/platforms/delta/vendor-config/src/python/delta/__init__.py new file mode 100644 index 00000000..d0f21891 --- /dev/null +++ b/packages/platforms/delta/vendor-config/src/python/delta/__init__.py @@ -0,0 +1,7 @@ +#!/usr/bin/python + +from onl.platform.base import * + +class OnlPlatformDelta(OnlPlatformBase): + MANUFACTURER='Delta' + PRIVATE_ENTERPRISE_NUMBER=2254 diff --git a/packages/platforms/delta/x86-64/Makefile b/packages/platforms/delta/x86-64/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/x86-64/modules/Makefile b/packages/platforms/delta/x86-64/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/x86-64/modules/PKG.yml b/packages/platforms/delta/x86-64/modules/PKG.yml new file mode 100644 index 00000000..2a3998b8 --- /dev/null +++ b/packages/platforms/delta/x86-64/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/arch-vendor-modules.yml ARCH=amd64 VENDOR=delta KERNELS="onl-kernel-3.16-lts-x86-64-all:amd64" diff --git a/packages/platforms/delta/x86-64/modules/builds/.gitignore b/packages/platforms/delta/x86-64/modules/builds/.gitignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/delta/x86-64/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/delta/x86-64/modules/builds/Makefile b/packages/platforms/delta/x86-64/modules/builds/Makefile new file mode 100644 index 00000000..2dc638e1 --- /dev/null +++ b/packages/platforms/delta/x86-64/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64 +KMODULES := $(wildcard *.c) +VENDOR := delta +BASENAME := common +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/delta/x86-64/modules/builds/i2c_cpld.c b/packages/platforms/delta/x86-64/modules/builds/i2c_cpld.c new file mode 100755 index 00000000..cd77cb36 --- /dev/null +++ b/packages/platforms/delta/x86-64/modules/builds/i2c_cpld.c @@ -0,0 +1,515 @@ +/* + * I2C for CPLD + * + * Copyright (C) 2017 Delta network Technology Corporation. + * Masan Xu + * + * This module supports cpld that read and write. + * + * Based on: + * i2c_x86-64-agc7648-cpld.c from Aaron Chang + * Copyright (C) 2017 Delta network Technology Corporation. + * + * 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 NUM_OF_CPLD1_CHANS 0x0 +#define I2C_CPLD_MUX_MAX_NCHANS NUM_OF_CPLD1_CHANS + + +static struct dmi_system_id cpld_dmi_table[] = +{ + { + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "DELTA"), + }, + }, +}; + +static LIST_HEAD(cpld_client_list); +static struct mutex list_lock; +static unsigned char gReg = 0; + +struct cpld_client_node +{ + struct i2c_client *client; + struct list_head list; +}; + +enum cpld_mux_type +{ + cpld +}; + +struct i2c_cpld_mux +{ + enum cpld_mux_type type; + struct i2c_adapter *virt_adaps[I2C_CPLD_MUX_MAX_NCHANS]; + u8 last_chan; /* last register value */ +}; + +struct chip_desc +{ + u8 nchans; + u8 deselectChan; +}; + +/* Provide specs for the PCA954x types we know about */ +static const struct chip_desc chips[] = +{ + [cpld] = { + .nchans = NUM_OF_CPLD1_CHANS, + .deselectChan = NUM_OF_CPLD1_CHANS, + }, +}; + +static const struct i2c_device_id i2c_cpld_mux_id[] = +{ + { "cpld", cpld }, + { } +}; +MODULE_DEVICE_TABLE(i2c, i2c_cpld_mux_id); + +int platform_cpld(void) +{ + return dmi_check_system(cpld_dmi_table); +} +EXPORT_SYMBOL(platform_cpld); + + +/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() + for this as they will try to lock adapter a second time */ +static int i2c_cpld_mux_reg_write(struct i2c_adapter *adap, + struct i2c_client *client, u8 val) +{ + unsigned long orig_jiffies; + unsigned short flags; + union i2c_smbus_data data; + int try; + s32 res = -EIO; + + data.byte = val; + flags = client->flags; + flags &= I2C_M_TEN | I2C_CLIENT_PEC; + + + if (adap->algo->smbus_xfer) + { + /* Retry automatically on arbitration loss */ + orig_jiffies = jiffies; + for (res = 0, try = 0; + try <= adap->retries; + try++) + { + res = adap->algo->smbus_xfer(adap, client->addr, flags, + I2C_SMBUS_WRITE, 0x2, + I2C_SMBUS_BYTE_DATA, &data); + if (res != -EAGAIN) + { + break; + } + if (time_after(jiffies, + orig_jiffies + adap->timeout)) + { + break; + } + } + } + + return res; +} + +static int i2c_cpld_mux_select_chan(struct i2c_adapter *adap, + void *client, u32 chan) +{ + struct i2c_cpld_mux *data = i2c_get_clientdata(client); + u8 regval; + int ret = 0; + + regval = chan; + + /* Only select the channel if its different from the last channel */ + if (data->last_chan != regval) + { + ret = i2c_cpld_mux_reg_write(adap, client, regval); + data->last_chan = regval; + } + + return ret; +} + +static int i2c_cpld_mux_deselect_mux(struct i2c_adapter *adap, + void *client, u32 chan) +{ + struct i2c_cpld_mux *data = i2c_get_clientdata(client); + + /* Deselect active channel */ + data->last_chan = chips[data->type].deselectChan; + + //return i2c_cpld_mux_reg_write(adap, client, data->last_chan); + i2c_cpld_mux_reg_write(adap, client, data->last_chan); + return 0; +} + +static void i2c_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 i2c_cpld_remove_client(struct i2c_client *client) +{ + struct list_head *list_node = NULL; + struct cpld_client_node *cpld_node = NULL; + int found = 0; + + mutex_lock(&list_lock); + + list_for_each(list_node, &cpld_client_list) + { + cpld_node = list_entry(list_node, struct cpld_client_node, list); + + if (cpld_node->client == client) + { + found = 1; + break; + } + } + + if (found) + { + list_del(list_node); + kfree(cpld_node); + } + + mutex_unlock(&list_lock); +} + +static ssize_t +set_cpld_reg(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned int val; + char *endp; + + val = simple_strtoul(buf, &endp, 16); + if (isspace(*endp)) + { + endp++; + } + + if (endp - buf != count) + { + return -1; + } + + if (val > 255) + { + return -1; + } + gReg = val; + + return count; + +} + +static ssize_t get_cpld_reg(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int len; + + len = sprintf(buf, "0x%x\n", gReg); + + return len; +} + + +static ssize_t +set_cpld_data(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client; + unsigned int val; + char *endp; + char ret = -1; + + val = simple_strtoul(buf, &endp, 16); + if (isspace(*endp)) + { + endp++; + } + + if (endp - buf != count) + { + return -1; + } + + if (val > 255) + { + return -1; + } + + mutex_lock(&list_lock); + client = to_i2c_client(dev); + + ret = i2c_smbus_write_byte_data(client, gReg, val); + + mutex_unlock(&list_lock); + return count; + +} + +static ssize_t +get_cpld_data(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct i2c_client *client; + int len; + + client = to_i2c_client(dev); + len = sprintf(buf, "0x%x\n", i2c_smbus_read_byte_data(client, gReg)); + + return len; +} + +static struct device_attribute gData = __ATTR(data, 0600, get_cpld_data, + set_cpld_data); +static struct device_attribute gAddr = __ATTR(addr, 0600, get_cpld_reg, + set_cpld_reg); + +static ssize_t show_cpld_version(struct device *dev, + struct device_attribute *attr, char *buf) +{ + u8 reg = 0x1; + struct i2c_client *client; + int len; + + client = to_i2c_client(dev); + len = sprintf(buf, "%d\n", i2c_smbus_read_byte_data(client, reg)); + + return len; +} + +static struct device_attribute ver = __ATTR(version, 0600, show_cpld_version, + NULL); + +/* + * I2C init/probing/exit functions + */ +static int i2c_cpld_mux_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + int chan = 0; + struct i2c_cpld_mux *data; + int ret = -ENODEV; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + { + goto err; + } + + data = kzalloc(sizeof(struct i2c_cpld_mux), GFP_KERNEL); + if (!data) + { + ret = -ENOMEM; + goto err; + } + + i2c_set_clientdata(client, data); + + data->type = id->driver_data; + data->last_chan = + chips[data->type].deselectChan; /* force the first selection */ + + /* Now create an adapter for each channel */ + for (chan = 0; chan < chips[data->type].nchans; chan++) + { + data->virt_adaps[chan] = i2c_add_mux_adapter(adap, &client->dev, client, 0, + chan, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) + I2C_CLASS_HWMON | I2C_CLASS_SPD, +#endif + i2c_cpld_mux_select_chan, + i2c_cpld_mux_deselect_mux); + if (data->virt_adaps[chan] == NULL) + { + ret = -ENODEV; + dev_err(&client->dev, "failed to register multiplexed adapter %d\n", chan); + goto virt_reg_failed; + } + } + + dev_info(&client->dev, "registered %d multiplexed busses for I2C mux %s\n", + chan, client->name); + + i2c_cpld_add_client(client); + + ret = sysfs_create_file(&client->dev.kobj, &ver.attr); + if (ret) + { + goto virt_reg_failed; + } + ret = sysfs_create_file(&client->dev.kobj, &gData.attr); + if (ret) + { + goto virt_reg_failed; + } + ret = sysfs_create_file(&client->dev.kobj, &gAddr.attr); + if (ret) + { + goto virt_reg_failed; + } + + return 0; + +virt_reg_failed: + for (chan--; chan >= 0; chan--) + { + i2c_del_mux_adapter(data->virt_adaps[chan]); + } + kfree(data); +err: + return ret; +} + +static int i2c_cpld_mux_remove(struct i2c_client *client) +{ + struct i2c_cpld_mux *data = i2c_get_clientdata(client); + const struct chip_desc *chip = &chips[data->type]; + int chan; + + sysfs_remove_file(&client->dev.kobj, &ver.attr); + + for (chan = 0; chan < chip->nchans; ++chan) + { + if (data->virt_adaps[chan]) + { + i2c_del_mux_adapter(data->virt_adaps[chan]); + data->virt_adaps[chan] = NULL; + } + } + + kfree(data); + i2c_cpld_remove_client(client); + + return 0; +} + +int i2c_cpld_read(int bus, 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->adapter->nr == bus) && + (cpld_node->client->addr == cpld_addr) ) + { + ret = i2c_smbus_read_byte_data(cpld_node->client, reg); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(i2c_cpld_read); + +int i2c_cpld_write(int bus, 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->adapter->nr == bus) && + (cpld_node->client->addr == cpld_addr) ) + { + ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value); + break; + } + } + + mutex_unlock(&list_lock); + + return ret; +} +EXPORT_SYMBOL(i2c_cpld_write); + +static struct i2c_driver i2c_cpld_mux_driver = +{ + .driver = { + .name = "cpld", + .owner = THIS_MODULE, + }, + .probe = i2c_cpld_mux_probe, + .remove = i2c_cpld_mux_remove, + .id_table = i2c_cpld_mux_id, +}; + +static int __init i2c_cpld_mux_init(void) +{ + mutex_init(&list_lock); + return i2c_add_driver(&i2c_cpld_mux_driver); +} + +static void __exit i2c_cpld_mux_exit(void) +{ + i2c_del_driver(&i2c_cpld_mux_driver); +} + +MODULE_AUTHOR("masan.xu@deltaww.com"); +MODULE_DESCRIPTION("I2C CPLD mux driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_cpld_mux_init); +module_exit(i2c_cpld_mux_exit); diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/.gitignore b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/.gitignore new file mode 100644 index 00000000..76483140 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/.gitignore @@ -0,0 +1,3 @@ +*x86*64*delta_agc7648a*.mk +onlpdump.mk + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/PKG.yml b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/PKG.yml new file mode 100644 index 00000000..3e29b63b --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-modules.yml VENDOR=delta BASENAME=x86-64-delta-agc7648a ARCH=amd64 KERNELS="onl-kernel-3.16-lts-x86-64-all:amd64" diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/.gitignore b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/.gitignore new file mode 100644 index 00000000..a65b4177 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/.gitignore @@ -0,0 +1 @@ +lib diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/Makefile new file mode 100644 index 00000000..865c7384 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/Makefile @@ -0,0 +1,6 @@ +KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64 +KMODULES := $(wildcard *.c) +VENDOR := delta +BASENAME := x86-64-delta-agc7648a +ARCH := x86_64 +include $(ONL)/make/kmodule.mk diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/agc7648a_dps800ab.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/agc7648a_dps800ab.c new file mode 100644 index 00000000..3ef88197 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/agc7648a_dps800ab.c @@ -0,0 +1,565 @@ +/* + * An hwmon driver for agc7648a PSU + * dps_800ab_16_d.c - Support for DPS-800AB-16 D Power Supply Module + * + * Copyright (C) 2017 Delta network Technology Corporation. + * Masan Xu + * + * Based on: + * dni_ag9032v1_psu.c from Aries Lin + * Copyright (C) 2016 Delta Network Technology Corporation + * + * Based on: + * ym2651y.c + * ad7414.c + * + * 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 MAX_FAN_DUTY_CYCLE 100 +#define PSU1_MUX_VAL 0x00 +#define PSU2_MUX_VAL 0x02 +#define MUX_SELECT(MUX_VAL) i2c_cpld_write(5, 0x30, 0x1f, MUX_VAL) + +u8 select_psu_num = 1; + +/* Address scanned */ +static const unsigned short normal_i2c[] = { 0x58, I2C_CLIENT_END }; + +/* This is additional data */ +struct dps_800ab_16_d_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; + unsigned long last_updated; /* In jiffies */ + + /* Registers value */ + u8 vout_mode; + u16 v_in; + u16 v_out; + u16 i_in; + u16 i_out; + u16 p_in; + u16 p_out; + u16 temp_input[2]; + u8 fan_fault; + u16 fan_duty_cycle[2]; + u16 fan_speed[2]; + u8 mfr_model[16]; + u8 mfr_serial[16]; +}; + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask); +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count); +static ssize_t for_linear_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t for_fan_fault(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t for_vout_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static int dps_800ab_16_d_read_byte(struct i2c_client *client, u8 reg); +static int dps_800ab_16_d_read_word(struct i2c_client *client, u8 reg); +static int dps_800ab_16_d_write_word(struct i2c_client *client, u8 reg, \ + u16 value); +static int dps_800ab_16_d_read_block(struct i2c_client *client, u8 command, \ + u8 *data, int data_len); +static struct dps_800ab_16_d_data *dps_800ab_16_d_update_device( \ + struct device *dev); +static ssize_t for_ascii(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t set_w_member_data(struct device *dev, struct device_attribute \ + *dev_att, const char *buf, size_t count); +static ssize_t for_r_member_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +extern int i2c_cpld_write(int bus, unsigned short cpld_addr, u8 reg, u8 value); + +enum dps_800ab_16_d_sysfs_attributes { + PSU_V_IN, + PSU_V_OUT, + PSU_I_IN, + PSU_I_OUT, + PSU_P_IN, + PSU_P_OUT, + PSU_TEMP1_INPUT, + PSU_FAN1_FAULT, + PSU_FAN1_DUTY_CYCLE, + PSU_FAN1_SPEED, + PSU_MFR_MODEL, + PSU_MFR_SERIAL, + PSU_SELECT_MEMBER, +}; + +static ssize_t set_w_member_data(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + long data; + int error; + if (attr->index == PSU_SELECT_MEMBER) { + error = kstrtol(buf, 10, &data); + if (error) + return error; + if (data == 1) { + select_psu_num = 1; + /* Select PSU MUX */ + MUX_SELECT(PSU1_MUX_VAL); + } else if (data == 2) { + select_psu_num = 2; + /* Select PSU MUX */ + MUX_SELECT(PSU2_MUX_VAL); + } else { + return -EINVAL; + } + } + + return count; +} + +static ssize_t for_r_member_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + return sprintf(buf, "%d\n", select_psu_num); +} + +static int two_complement_to_int(u16 data, u8 valid_bit, int mask) +{ + u16 valid_data = data & mask; + bool is_negative = valid_data >> (valid_bit - 1); + + return is_negative ? (-(((~valid_data) & mask) + 1)) : valid_data; +} + +static ssize_t set_fan_duty_cycle(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct i2c_client *client = to_i2c_client(dev); + struct dps_800ab_16_d_data *data = i2c_get_clientdata(client); + int nr = (attr->index == PSU_FAN1_DUTY_CYCLE) ? 0 : 1; + long speed; + int error; + + error = kstrtol(buf, 10, &speed); + if (error) + return error; + + if (speed < 0 || speed > MAX_FAN_DUTY_CYCLE) + return -EINVAL; + + /* Select PSU MUX */ + if(select_psu_num == 1){ + MUX_SELECT(PSU1_MUX_VAL); + }else if(select_psu_num == 2){ + MUX_SELECT(PSU2_MUX_VAL); + }else{ + return -EINVAL; + } + + mutex_lock(&data->update_lock); + data->fan_duty_cycle[nr] = speed; + dps_800ab_16_d_write_word(client, 0x3B + nr, data->fan_duty_cycle[nr]); + mutex_unlock(&data->update_lock); + + return count; +} + +static ssize_t for_linear_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + + u16 value = 0; + int exponent, mantissa; + int multiplier = 1000; + + switch (attr->index) { + case PSU_V_IN: + value = data->v_in; + break; + case PSU_I_IN: + value = data->i_in; + break; + case PSU_I_OUT: + value = data->i_out; + break; + case PSU_P_IN: + value = data->p_in; + break; + case PSU_P_OUT: + value = data->p_out; + break; + case PSU_TEMP1_INPUT: + value = data->temp_input[0]; + break; + case PSU_FAN1_DUTY_CYCLE: + multiplier = 1; + value = data->fan_duty_cycle[0]; + break; + case PSU_FAN1_SPEED: + multiplier = 1; + value = data->fan_speed[0]; + break; + default: + break; + } + + exponent = two_complement_to_int(value >> 11, 5, 0x1f); + mantissa = two_complement_to_int(value & 0x7ff, 11, 0x7ff); + + return (exponent >= 0) ? sprintf(buf, "%d\n", \ + (mantissa << exponent) * multiplier) : \ + sprintf(buf, "%d\n", (mantissa * multiplier) / (1 << -exponent)); +} + +static ssize_t for_fan_fault(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + + u8 shift = (attr->index == PSU_FAN1_FAULT) ? 7 : 6; + + return sprintf(buf, "%d\n", data->fan_fault >> shift); +} + +static ssize_t for_vout_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + int exponent, mantissa; + int multiplier = 1000; + + exponent = two_complement_to_int(data->vout_mode, 5, 0x1f); + mantissa = data->v_out; + + return (exponent > 0) ? sprintf(buf, "%d\n", \ + (mantissa << exponent) * multiplier) : \ + sprintf(buf, "%d\n", (mantissa << exponent) / (1 << -exponent)); + +} + +static ssize_t for_ascii(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct dps_800ab_16_d_data *data = dps_800ab_16_d_update_device(dev); + u8 *ptr = NULL; + + if (!data->valid) + return 0; + + switch (attr->index) { + case PSU_MFR_MODEL: + ptr = data->mfr_model + 1; + break; + case PSU_MFR_SERIAL: + ptr = data->mfr_serial + 1; + break; + default: + return 0; + } + return sprintf(buf, "%s\n", ptr); +} +static int dps_800ab_16_d_read_byte(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_byte_data(client, reg); +} + +static int dps_800ab_16_d_read_word(struct i2c_client *client, u8 reg) +{ + return i2c_smbus_read_word_data(client, reg); +} + +static int dps_800ab_16_d_write_word(struct i2c_client *client, u8 reg, \ + u16 value) +{ + union i2c_smbus_data data; + data.word = value; + return i2c_smbus_xfer(client->adapter, client->addr, + client->flags |= I2C_CLIENT_PEC, + I2C_SMBUS_WRITE, reg, + I2C_SMBUS_WORD_DATA, &data); + +} + +static int dps_800ab_16_d_read_block(struct i2c_client *client, u8 command, \ + u8 *data, int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, + data); + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + + result = 0; +abort: + return result; + +} + +struct reg_data_byte { + u8 reg; + u8 *value; +}; + +struct reg_data_word { + u8 reg; + u16 *value; +}; + +static struct dps_800ab_16_d_data *dps_800ab_16_d_update_device( \ + struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct dps_800ab_16_d_data *data = i2c_get_clientdata(client); + + mutex_lock(&data->update_lock); + + /* Select PSU MUX */ + if(select_psu_num == 1){ + MUX_SELECT(PSU1_MUX_VAL); + }else if(select_psu_num == 2){ + MUX_SELECT(PSU2_MUX_VAL); + }else{ + return -EINVAL; + } + + if (time_after(jiffies, data->last_updated)) { + int i, status; + u8 command; + struct reg_data_byte regs_byte[] = { + {0x20, &data->vout_mode}, + {0x81, &data->fan_fault} + }; + struct reg_data_word regs_word[] = { + {0x88, &data->v_in}, + {0x8b, &data->v_out}, + {0x89, &data->i_in}, + {0x8c, &data->i_out}, + {0x96, &data->p_out}, + {0x97, &data->p_in}, + {0x8d, &(data->temp_input[0])}, + {0x8e, &(data->temp_input[1])}, + {0x3b, &(data->fan_duty_cycle[0])}, + {0x90, &(data->fan_speed[0])}, + }; + + dev_dbg(&client->dev, "start data update\n"); + + /* one milliseconds from now */ + data->last_updated = jiffies + HZ / 1000; + + for (i = 0; i < ARRAY_SIZE(regs_byte); i++) { + status = dps_800ab_16_d_read_byte(client, + regs_byte[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_byte[i].reg, status); + } else { + *(regs_byte[i].value) = status; + } + } + + for (i = 0; i < ARRAY_SIZE(regs_word); i++) { + status = dps_800ab_16_d_read_word(client, + regs_word[i].reg); + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", + regs_word[i].reg, status); + } else { + *(regs_word[i].value) = status; + } + } + + command = 0x9a; /* PSU mfr_model */ + status = dps_800ab_16_d_read_block(client, command, + data->mfr_model, ARRAY_SIZE(data->mfr_model) - 1); + data->mfr_model[ARRAY_SIZE(data->mfr_model) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, + status); + } + + command = 0x9e; /* PSU mfr_serial */ + status = dps_800ab_16_d_read_block(client, command, + data->mfr_serial, ARRAY_SIZE(data->mfr_serial) - 1); + data->mfr_serial[ARRAY_SIZE(data->mfr_serial) - 1] = '\0'; + if (status < 0) { + dev_dbg(&client->dev, "reg %d, err %d\n", command, + status); + } + + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; + +} + +/* sysfs attributes for hwmon */ +static SENSOR_DEVICE_ATTR(psu_v_in, S_IRUGO, for_linear_data, NULL, PSU_V_IN); +static SENSOR_DEVICE_ATTR(psu_v_out, S_IRUGO, for_vout_data, NULL, PSU_V_OUT); +static SENSOR_DEVICE_ATTR(psu_i_in, S_IRUGO, for_linear_data, NULL, PSU_I_IN); +static SENSOR_DEVICE_ATTR(psu_i_out, S_IRUGO, for_linear_data, NULL, PSU_I_OUT); +static SENSOR_DEVICE_ATTR(psu_p_in, S_IRUGO, for_linear_data, NULL, PSU_P_IN); +static SENSOR_DEVICE_ATTR(psu_p_out, S_IRUGO, for_linear_data, NULL, PSU_P_OUT); +static SENSOR_DEVICE_ATTR(psu_temp1_input, \ + S_IRUGO, for_linear_data, NULL, PSU_TEMP1_INPUT); +static SENSOR_DEVICE_ATTR(psu_fan1_fault, \ + S_IRUGO, for_fan_fault, NULL, PSU_FAN1_FAULT); +static SENSOR_DEVICE_ATTR(psu_fan1_duty_cycle_percentage, S_IWUGO | S_IRUGO, \ + for_linear_data, set_fan_duty_cycle, PSU_FAN1_DUTY_CYCLE); +static SENSOR_DEVICE_ATTR(psu_fan1_speed_rpm, \ + S_IRUGO, for_linear_data, NULL, PSU_FAN1_SPEED); +static SENSOR_DEVICE_ATTR(psu_mfr_model, \ + S_IRUGO, for_ascii, NULL, PSU_MFR_MODEL); +static SENSOR_DEVICE_ATTR(psu_mfr_serial, \ + S_IRUGO, for_ascii, NULL, PSU_MFR_SERIAL); +static SENSOR_DEVICE_ATTR(psu_select_member, S_IWUGO | S_IRUGO, \ + for_r_member_data, set_w_member_data, PSU_SELECT_MEMBER); + +static struct attribute *dps_800ab_16_d_attributes[] = { + &sensor_dev_attr_psu_v_in.dev_attr.attr, + &sensor_dev_attr_psu_v_out.dev_attr.attr, + &sensor_dev_attr_psu_i_in.dev_attr.attr, + &sensor_dev_attr_psu_i_out.dev_attr.attr, + &sensor_dev_attr_psu_p_in.dev_attr.attr, + &sensor_dev_attr_psu_p_out.dev_attr.attr, + &sensor_dev_attr_psu_temp1_input.dev_attr.attr, + &sensor_dev_attr_psu_fan1_fault.dev_attr.attr, + &sensor_dev_attr_psu_fan1_duty_cycle_percentage.dev_attr.attr, + &sensor_dev_attr_psu_fan1_speed_rpm.dev_attr.attr, + &sensor_dev_attr_psu_mfr_model.dev_attr.attr, + &sensor_dev_attr_psu_mfr_serial.dev_attr.attr, + &sensor_dev_attr_psu_select_member.dev_attr.attr, + NULL +}; + +static const struct attribute_group dps_800ab_16_d_group = { + .attrs = dps_800ab_16_d_attributes, +}; + +static int dps_800ab_16_d_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct dps_800ab_16_d_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->valid = 0; + mutex_init(&data->update_lock); + + dev_info(&client->dev, "new chip found\n"); + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &dps_800ab_16_d_group); + if (status) + goto exit_sysfs_create_group; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_hwmon_device_register; + } + + return 0; + +exit_hwmon_device_register: + sysfs_remove_group(&client->dev.kobj, &dps_800ab_16_d_group); +exit_sysfs_create_group: + kfree(data); +exit: + return status; +} + +static int dps_800ab_16_d_remove(struct i2c_client *client) +{ + struct dps_800ab_16_d_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &dps_800ab_16_d_group); + kfree(data); + + return 0; +} + +enum id_name { + agc7648a_dps800ab +}; + +static const struct i2c_device_id dps_800ab_16_d_id[] = { + { "agc7648a_dps800ab", agc7648a_dps800ab }, + {} +}; +MODULE_DEVICE_TABLE(i2c, dps_800ab_16_d_id); + +/* This is the driver that will be inserted */ +static struct i2c_driver dps_800ab_16_d_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "dps_800ab_16_d", + }, + .probe = dps_800ab_16_d_probe, + .remove = dps_800ab_16_d_remove, + .id_table = dps_800ab_16_d_id, + .address_list = normal_i2c, +}; + +static int __init dps_800ab_16_d_init(void) +{ + return i2c_add_driver(&dps_800ab_16_d_driver); +} + +static void __exit dps_800ab_16_d_exit(void) +{ + i2c_del_driver(&dps_800ab_16_d_driver); +} + + +MODULE_AUTHOR("masan.xu@deltaww.com"); +MODULE_DESCRIPTION("DPS_800AB_16_D Driver"); +MODULE_LICENSE("GPL"); + +module_init(dps_800ab_16_d_init); +module_exit(dps_800ab_16_d_exit); diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/agc7648a_emc2305.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/agc7648a_emc2305.c new file mode 100755 index 00000000..fdcc903e --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/agc7648a_emc2305.c @@ -0,0 +1,325 @@ +/* + * + * + * Copyright (C) 2017 Delta network Technology Corporation. + * Masan Xu + * + * Based on: + * dni_emc2305.c from Aaron Chang + * Copyright (C) 2017 Delta network Technology Corporation. + * + * Based on: + * emc2305.c + * Copyright 2013, 2014 BigSwitch Networks, Inc. + * + * This program is free software; you can redistribute it + * and/or modify it under the terms ofthe GNU General Public License as + * published by the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * + * + * + * + * A hwmon driver for the SMSC EMC2305 fan controller + * Complete datasheet is available (6/2013) at: + * http://www.smsc.com/media/Downloads_Public/Data_Sheets/2305.pdf + */ + +#include +#include +#include +#include +#include + +extern int i2c_cpld_read(int bus, unsigned short cpld_addr, u8 reg); +extern int i2c_cpld_write(int bus, unsigned short cpld_addr, u8 reg, u8 value); + +static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count); +static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, + char *buf); +static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, + char *buf); +static ssize_t set_fan(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count); + +static const unsigned short normal_i2c[] = { 0x2C, 0x2D, 0x2E, 0x2F, 0x4C, + 0x4D, I2C_CLIENT_END + }; + + +#define EMC2305_REG_DEVICE 0xFD +#define EMC2305_REG_VENDOR 0xFE + +//#define FAN_MINIMUN 0x33 /*20%*/ +#define FAN_MINIMUN 0x0 /*0%*/ +#define FAN_RPM_BASED 0xAB + +#define EMC2305_REG_FAN_DRIVE(n) (0x30 + 0x10 * n) +#define EMC2305_REG_FAN_MIN_DRIVE(n) (0x38 + 0x10 * n) +#define EMC2305_REG_FAN_TACH(n) (0x3E + 0x10 * n) +#define EMC2305_REG_FAN_CONF(n) (0x32 + 0x10 * n) +#define EMC2305_REG_FAN_REAR_H_RPM(n) (0x3D + 0x10 * n) +#define EMC2305_REG_FAN_REAR_L_RPM(n) (0x3C + 0x10 * n) + +#define EMC2305_DEVICE 0x34 +#define EMC2305_VENDOR 0x5D + +#define MUX_SELECT i2c_cpld_write(5, 0x30, 0x67, 0x05) + +struct emc2305_data +{ + struct device *hwmon_dev; + struct attribute_group attrs; + struct mutex lock; +}; + +static int emc2305_probe(struct i2c_client *client, + const struct i2c_device_id *id); +static int emc2305_detect(struct i2c_client *client, + struct i2c_board_info *info); +static int emc2305_remove(struct i2c_client *client); + +static const struct i2c_device_id emc2305_id[] = +{ + { "agc7648a_emc2305", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, emc2305_id); + +static struct i2c_driver emc2305_driver = +{ + .class = I2C_CLASS_HWMON, + .driver = { + .name = "agc7648a_emc2305", + }, + .probe = emc2305_probe, + .remove = emc2305_remove, + .id_table = emc2305_id, + .detect = emc2305_detect, + .address_list = normal_i2c, +}; + +static SENSOR_DEVICE_ATTR(fan1_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 0); +static SENSOR_DEVICE_ATTR(fan2_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 1); +static SENSOR_DEVICE_ATTR(fan3_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 2); +static SENSOR_DEVICE_ATTR(fan4_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 3); +static SENSOR_DEVICE_ATTR(fan5_input, S_IWUSR | S_IRUGO, show_fan, set_fan, 4); +static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); +static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); +static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); +static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); +static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 4); + +static struct attribute *emc2305_attr[] = +{ + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan2_input.dev_attr.attr, + &sensor_dev_attr_fan3_input.dev_attr.attr, + &sensor_dev_attr_fan4_input.dev_attr.attr, + &sensor_dev_attr_fan5_input.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm2.dev_attr.attr, + &sensor_dev_attr_pwm3.dev_attr.attr, + &sensor_dev_attr_pwm4.dev_attr.attr, + &sensor_dev_attr_pwm5.dev_attr.attr, + NULL +}; + + +static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + int val; + + MUX_SELECT; + + mutex_lock(&data->lock); + val = i2c_smbus_read_word_swapped(client, + EMC2305_REG_FAN_TACH(attr->index)); + mutex_unlock(&data->lock); + /* Left shift 3 bits for showing correct RPM */ + val = val >> 3; + return sprintf(buf, "%d\n", 3932160 * 2 / (val > 0 ? val : 1)); +} + +static ssize_t set_fan(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + unsigned long hsb, lsb; + unsigned long tech; + unsigned long val; + int ret; + + MUX_SELECT; + ret = kstrtoul(buf, 10, &val); + if (ret) + { + return ret; + } + if (val > 23000) + { + return -EINVAL; + } + + if (val <= 960) + { + hsb = 0xff; /*high bit*/ + lsb = 0xe0; /*low bit*/ + } + else + { + tech = (3932160 * 2) / (val > 0 ? val : 1); + hsb = (uint8_t)(((tech << 3) >> 8) & 0x0ff); + lsb = (uint8_t)((tech << 3) & 0x0f8); + } + + mutex_lock(&data->lock); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_REAR_H_RPM(attr->index), hsb); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_REAR_L_RPM(attr->index), lsb); + mutex_unlock(&data->lock); + return count; +} + +static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + int val; + + MUX_SELECT; + mutex_lock(&data->lock); + val = i2c_smbus_read_byte_data(client, + EMC2305_REG_FAN_DRIVE(attr->index)); + mutex_unlock(&data->lock); + return sprintf(buf, "%d\n", val); +} + +static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct i2c_client *client = to_i2c_client(dev); + struct emc2305_data *data = i2c_get_clientdata(client); + unsigned long val; + int ret; + + MUX_SELECT; + ret = kstrtoul(buf, 10, &val); + if (ret) + { + return ret; + } + if (val > 255) + { + return -EINVAL; + } + + mutex_lock(&data->lock); + i2c_smbus_write_byte_data(client, + EMC2305_REG_FAN_DRIVE(attr->index), + val); + mutex_unlock(&data->lock); + return count; +} + +static int emc2305_detect(struct i2c_client *client, + struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + int vendor, device; + + MUX_SELECT; + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | + I2C_FUNC_SMBUS_WORD_DATA)) + { + return -ENODEV; + } + + vendor = i2c_smbus_read_byte_data(client, EMC2305_REG_VENDOR); + if (vendor != EMC2305_VENDOR) + { + return -ENODEV; + } + + device = i2c_smbus_read_byte_data(client, EMC2305_REG_DEVICE); + if (device != EMC2305_DEVICE) + { + return -ENODEV; + } + + strlcpy(info->type, "emc2305", I2C_NAME_SIZE); + + return 0; +} + +static int emc2305_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct emc2305_data *data; + int err; + int i; + + data = devm_kzalloc(&client->dev, sizeof(struct emc2305_data), + GFP_KERNEL); + if (!data) + { + return -ENOMEM; + } + + i2c_set_clientdata(client, data); + mutex_init(&data->lock); + + dev_info(&client->dev, "%s chip found\n", client->name); + + data->attrs.attrs = emc2305_attr; + err = sysfs_create_group(&client->dev.kobj, &data->attrs); + if (err) + { + return err; + } + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) + { + err = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + for (i = 0; i < 5; i++) + { + /* set minimum drive to 0% */ + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_MIN_DRIVE(i), FAN_MINIMUN); + i2c_smbus_write_byte_data(client, EMC2305_REG_FAN_CONF(i), FAN_RPM_BASED); + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->attrs); + return err; +} + +static int emc2305_remove(struct i2c_client *client) +{ + struct emc2305_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->attrs); + return 0; +} + +module_i2c_driver(emc2305_driver); + +MODULE_AUTHOR("masan.xu@deltaww.com"); +MODULE_DESCRIPTION("SMSC EMC2305 fan controller driver"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/agc7648a_sfp.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/agc7648a_sfp.c new file mode 100644 index 00000000..f9b984cb --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/agc7648a_sfp.c @@ -0,0 +1,677 @@ +/* + * An hwmon driver for agc7648a sfp + * + * Copyright (C) 2017 Delta network Technology Corporation. + * Aries Lin + * + * Based on: + * ad7414.c + * + * 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 I2C_BUS_5 5 +#define SWPLD_U21 0x30 +#define SWPLD_U134 0x31 +#define SWPLD_U215 0x32 + +#define SFP_PRESENCE_1 0x30 +#define SFP_PRESENCE_2 0x31 +#define SFP_PRESENCE_3 0x32 +#define SFP_PRESENCE_4 0x33 +#define SFP_PRESENCE_5 0x34 +#define SFP_PRESENCE_6 0x35 +#define QSFP_PRESENCE_1 0x63 +#define QSFP_LP_MODE_1 0x62 +#define QSFP_RESET_1 0x3C + +#define DEFAULT_DISABLE 0x00 +#define QSFP_DEFAULT_DISABLE 0x1F +#define QSFP_SEL_I2C_MUX 0x20 +#define SFP_SEL_I2C_MUX 0x21 + +/* Check cpld read results */ +#define VALIDATED_READ(_buf, _rv, _read, _invert) \ + do { \ + _rv = _read; \ + if (_rv < 0) { \ + return sprintf(_buf, "READ ERROR\n"); \ + } \ + if (_invert) { \ + _rv = ~_rv; \ + } \ + _rv &= 0xFF; \ + } while(0) \ + + +int sfp_port_data = 0; + +static const u8 cpld_to_port_table[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, + 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31, + 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 }; + +/* Addresses scanned */ +static const unsigned short normal_i2c[] = { 0x50, I2C_CLIENT_END }; + +/* Each client has this additional data */ +struct agc7648a_sfp_data { + struct device *hwmon_dev; + struct mutex update_lock; + char valid; + unsigned long last_updated; + int port; + char eeprom[256]; +}; + +static ssize_t for_eeprom(struct device *dev, struct device_attribute *dev_attr, + char *buf); +static int agc7648a_sfp_read_block(struct i2c_client *client, u8 command, + u8 *data, int data_len); +static struct agc7648a_sfp_data *agc7648a_sfp_update_device( \ + struct device *dev); +static ssize_t for_status(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t set_w_port_data(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count); +static ssize_t for_r_port_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf); +static ssize_t set_w_lp_mode_data(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count); +static ssize_t set_w_reset_data(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count); + +extern int i2c_cpld_read(int bus, unsigned short cpld_addr, u8 reg); +extern int i2c_cpld_write(int bus, unsigned short cpld_addr, u8 reg, u8 value); + +enum agc7648a_sfp_sysfs_attributes { + SFP_EEPROM, + SFP_SELECT_PORT, + SFP_IS_PRESENT, + SFP_IS_PRESENT_ALL, + SFP_LP_MODE, + SFP_RESET +}; + +static ssize_t set_w_port_data(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count) +{ + long data; + int error; + u8 port_t = 0; + u8 reg_t = 0x00; + + error = kstrtol(buf, 10, &data); + if (error) + return error; + + port_t = data; + + if (port_t > 0 && port_t < 9) { /* SFP Port 1-8 */ + reg_t = SFP_SEL_I2C_MUX; + } else if (port_t > 8 && port_t < 17) { /* SFP Port 9-16 */ + reg_t = SFP_SEL_I2C_MUX; + } else if (port_t > 16 && port_t < 25) { /* SFP Port 17-24 */ + reg_t = SFP_SEL_I2C_MUX; + } else if (port_t > 24 && port_t < 33) { /* SFP Port 25-32 */ + reg_t = SFP_SEL_I2C_MUX; + } else if (port_t > 32 && port_t < 41) { /* SFP Port 33-40 */ + reg_t = SFP_SEL_I2C_MUX; + } else if (port_t > 40 && port_t < 49) { /* SFP Port 41-48 */ + reg_t = SFP_SEL_I2C_MUX; + } else if (port_t > 48 && port_t < 55) { /* QSFP Port 49-54 */ + reg_t = QSFP_SEL_I2C_MUX; + } else { + /* Disable SFP channel */ + if (i2c_cpld_write(I2C_BUS_5, SWPLD_U134, SFP_SEL_I2C_MUX, + DEFAULT_DISABLE) < 0) { + return -EIO; + } + /* Disable QSFP channel */ + if (i2c_cpld_write(I2C_BUS_5, SWPLD_U134, QSFP_SEL_I2C_MUX, + QSFP_DEFAULT_DISABLE) < 0) { + return -EIO; + } + + goto exit; + } + + /* Disable SFP channel */ + if (i2c_cpld_write(I2C_BUS_5, SWPLD_U134, SFP_SEL_I2C_MUX, + DEFAULT_DISABLE) < 0) { + return -EIO; + } + /* Disable QSFP channel */ + if (i2c_cpld_write(I2C_BUS_5, SWPLD_U134, QSFP_SEL_I2C_MUX, + QSFP_DEFAULT_DISABLE) < 0) { + return -EIO; + } + + /* Select SFP or QSFP port channel */ + if (i2c_cpld_write(I2C_BUS_5, SWPLD_U134, reg_t, + cpld_to_port_table[port_t]) < 0) { + return -EIO; + } + +exit: + sfp_port_data = data; + + return count; +} + +static ssize_t for_r_port_data(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + if (sfp_port_data == DEFAULT_DISABLE) { + /* Disable SFP channel */ + if (i2c_cpld_write(I2C_BUS_5, SWPLD_U134, + SFP_SEL_I2C_MUX, DEFAULT_DISABLE) < 0) { + return -EIO; + } + /* Disable QSFP channel */ + if (i2c_cpld_write(I2C_BUS_5, SWPLD_U134, + QSFP_SEL_I2C_MUX, QSFP_DEFAULT_DISABLE) < 0) { + return -EIO; + } + } + return sprintf(buf, "%d\n", sfp_port_data); +} + +static ssize_t set_w_lp_mode_data(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count) +{ + long data; + int error; + u8 port_t = 0; + int bit_t = 0x00; + int values = 0x00; + + error = kstrtol(buf, 10, &data); + if (error) + return error; + + port_t = sfp_port_data; + + if (port_t > 47 && port_t < 54) { /* QSFP Port 48-53 */ + values = i2c_cpld_read(I2C_BUS_5, SWPLD_U21, QSFP_LP_MODE_1); + if (values < 0) + return -EIO; + + /* Indicate the module is in LP mode or not + * 0 = Disable + * 1 = Enable + */ + if (data == 0) { + bit_t = ~(1 << ((port_t - 1) % 8)); + values = values & bit_t; + } else if (data == 1) { + bit_t = 1 << ((port_t - 1) % 8); + values = values | bit_t; + } else { + return -EINVAL; + } + + if (i2c_cpld_write(I2C_BUS_5, SWPLD_U21, QSFP_LP_MODE_1, + values) < 0) { + return -EIO; + } + } + + return count; +} + +static ssize_t set_w_reset_data(struct device *dev, struct device_attribute \ + *dev_attr, const char *buf, size_t count) +{ + long data; + int error; + u8 port_t = 0; + int bit_t = 0x00; + int values = 0x00; + + error = kstrtol(buf, 10, &data); + if (error) + return error; + + port_t = sfp_port_data; + + if (port_t > 47 && port_t < 54) { /* QSFP Port 48-53 */ + values = i2c_cpld_read(I2C_BUS_5, SWPLD_U21, QSFP_RESET_1); + if (values < 0) + return -EIO; + + /* Indicate the module Reset or not + * 0 = Reset + * 1 = Normal + */ + if (data == 0) { + bit_t = ~(1 << ((port_t - 1) % 8)); + values = values & bit_t; + } else if (data == 1) { + bit_t = 1 << ((port_t - 1) % 8); + values = values | bit_t; + } else { + return -EINVAL; + } + + if (i2c_cpld_write(I2C_BUS_5, SWPLD_U21, QSFP_RESET_1, + values) < 0) { + return -EIO; + } + } + + return count; +} + +static ssize_t for_status(struct device *dev, struct device_attribute \ + *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + u8 port_t = 0; + u8 reg_t = 0x00; + u8 cpld_addr_t = 0x00; + int values[7] = {'\0'}; + int bit_t = 0x00; + + switch (attr->index) { + case SFP_IS_PRESENT: + port_t = sfp_port_data; + + if (port_t > 0 && port_t < 9) { /* SFP Port 1-8 */ + cpld_addr_t = SWPLD_U215; + reg_t = SFP_PRESENCE_1; + } else if (port_t > 8 && port_t < 17) { /* SFP Port 9-16 */ + cpld_addr_t = SWPLD_U215; + reg_t = SFP_PRESENCE_2; + } else if (port_t > 16 && port_t < 25) { /* SFP Port 17-24 */ + cpld_addr_t = SWPLD_U215; + reg_t = SFP_PRESENCE_3; + } else if (port_t > 24 && port_t < 33) { /* SFP Port 25-32 */ + cpld_addr_t = SWPLD_U215; + reg_t = SFP_PRESENCE_4; + } else if (port_t > 32 && port_t < 41) { /* SFP Port 33-40 */ + cpld_addr_t = SWPLD_U215; + reg_t = SFP_PRESENCE_5; + } else if (port_t > 40 && port_t < 49) { /* SFP Port 41-48 */ + cpld_addr_t = SWPLD_U215; + reg_t = SFP_PRESENCE_6; + } else if (port_t > 48 && port_t < 55) { /* QSFP Port 49-54 */ + cpld_addr_t = SWPLD_U21; + reg_t = QSFP_PRESENCE_1; + } else { + values[0] = 1; /* return 1, module NOT present */ + return sprintf(buf, "%d\n", values[0]); + } + + VALIDATED_READ(buf, values[0], i2c_cpld_read(I2C_BUS_5, + cpld_addr_t, reg_t), 0); + + /* SWPLD QSFP module respond */ + bit_t = 1 << ((port_t - 1) % 8); + values[0] = values[0] & bit_t; + values[0] = values[0] / bit_t; + + /* sfp_is_present value + * return 0 is module present + * return 1 is module NOT present + */ + return sprintf(buf, "%d\n", values[0]); + + case SFP_IS_PRESENT_ALL: + /* + * Report the SFP ALL PRESENCE status + * This data information form CPLD. + */ + + /* SFP_PRESENT Ports 1-8 */ + VALIDATED_READ(buf, values[0], + i2c_cpld_read(I2C_BUS_5, SWPLD_U215, SFP_PRESENCE_1), 0); + /* SFP_PRESENT Ports 9-16 */ + VALIDATED_READ(buf, values[1], + i2c_cpld_read(I2C_BUS_5, SWPLD_U215, SFP_PRESENCE_2), 0); + /* SFP_PRESENT Ports 17-24 */ + VALIDATED_READ(buf, values[2], + i2c_cpld_read(I2C_BUS_5, SWPLD_U215, SFP_PRESENCE_3), 0); + /* SFP_PRESENT Ports 25-32 */ + VALIDATED_READ(buf, values[3], + i2c_cpld_read(I2C_BUS_5, SWPLD_U215, SFP_PRESENCE_4), 0); + /* SFP_PRESENT Ports 33-40 */ + VALIDATED_READ(buf, values[4], + i2c_cpld_read(I2C_BUS_5, SWPLD_U215, SFP_PRESENCE_5), 0); + /* SFP_PRESENT Ports 41-48 */ + VALIDATED_READ(buf, values[5], + i2c_cpld_read(I2C_BUS_5, SWPLD_U215, SFP_PRESENCE_6), 0); + /* QSFP_PRESENT Ports 49-54 */ + VALIDATED_READ(buf, values[6], + i2c_cpld_read(I2C_BUS_5, SWPLD_U21, QSFP_PRESENCE_1), 0); + + + /* sfp_is_present_all value + * return 0 is module present + * return 1 is module NOT present + */ + return sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X\n", + values[0], values[1], values[2], + values[3], values[4], values[5], + values[6]); + case SFP_LP_MODE: + port_t = sfp_port_data; + if (port_t > 48 && port_t < 55) { /* QSFP Port 49-54 */ + VALIDATED_READ(buf, values[0], i2c_cpld_read(I2C_BUS_5, + SWPLD_U21, QSFP_LP_MODE_1), 0); + } else { + /* In AGC7648 only QSFP support control LP MODE */ + values[0] = 0; + return sprintf(buf, "%d\n", values[0]); + } + + /* SWPLD QSFP module respond */ + bit_t = 1 << ((port_t - 1) % 8); + values[0] = values[0] & bit_t; + values[0] = values[0] / bit_t; + + /* sfp_lp_mode value + * return 0 is module NOT in LP mode + * return 1 is module in LP mode + */ + return sprintf(buf, "%d\n", values[0]); + case SFP_RESET: + port_t = sfp_port_data; + if (port_t > 48 && port_t < 55) { /* QSFP Port 49-54 */ + VALIDATED_READ(buf, values[0], i2c_cpld_read(I2C_BUS_5, + SWPLD_U21, QSFP_RESET_1), 0); + } else { + /* In AGC7648 only QSFP support control RESET MODE */ + values[0] = 1; + return sprintf(buf, "%d\n", values[0]); + } + + /* SWPLD QSFP module respond */ + bit_t = 1 << ((port_t - 1) % 8); + values[0] = values[0] & bit_t; + values[0] = values[0] / bit_t; + + /* sfp_reset value + * return 0 is module Reset + * return 1 is module Normal + */ + return sprintf(buf, "%d\n", values[0]); + default: + return (attr->index); + } +} + +static ssize_t for_eeprom(struct device *dev, struct device_attribute *dev_attr, + char *buf) +{ + struct agc7648a_sfp_data *data = agc7648a_sfp_update_device(dev); + if (!data->valid) { + return 0; + } + memcpy(buf, data->eeprom, sizeof(data->eeprom)); + return sizeof(data->eeprom); +} + +static int agc7648a_sfp_read_block(struct i2c_client *client, u8 command, \ + u8 *data, int data_len) +{ + int result = i2c_smbus_read_i2c_block_data(client, command, data_len, + data); + if (unlikely(result < 0)) + goto abort; + if (unlikely(result != data_len)) { + result = -EIO; + goto abort; + } + result = 0; +abort: + return result; +} + +static struct agc7648a_sfp_data *agc7648a_sfp_update_device( \ + struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct agc7648a_sfp_data *data = i2c_get_clientdata(client); + u8 port_t = 0; + u8 reg_t = 0x00; + + port_t = sfp_port_data; + + memset(data->eeprom, 0, sizeof(data->eeprom)); + + if (port_t > 0 && port_t < 9) { /* SFP Port 1-8 */ + reg_t = SFP_SEL_I2C_MUX; + } else if (port_t > 8 && port_t < 17) { /* SFP Port 9-16 */ + reg_t = SFP_SEL_I2C_MUX; + } else if (port_t > 16 && port_t < 25) { /* SFP Port 17-24 */ + reg_t = SFP_SEL_I2C_MUX; + } else if (port_t > 24 && port_t < 33) { /* SFP Port 25-32 */ + reg_t = SFP_SEL_I2C_MUX; + } else if (port_t > 32 && port_t < 41) { /* SFP Port 33-40 */ + reg_t = SFP_SEL_I2C_MUX; + } else if (port_t > 40 && port_t < 49) { /* SFP Port 41-48 */ + reg_t = SFP_SEL_I2C_MUX; + } else if (port_t > 48 && port_t < 55) { /* QSFP Port 49-54 */ + reg_t = QSFP_SEL_I2C_MUX; + } else { + memset(data->eeprom, 0, sizeof(data->eeprom)); + + /* Disable SFP channel */ + if (i2c_cpld_write(I2C_BUS_5, SWPLD_U134, SFP_SEL_I2C_MUX, + DEFAULT_DISABLE) < 0) { + goto exit; + } + + /* Disable QSFP channel */ + if (i2c_cpld_write(I2C_BUS_5, SWPLD_U134, QSFP_SEL_I2C_MUX, + QSFP_DEFAULT_DISABLE) < 0) { + goto exit; + } + + goto exit; + } + + /* Disable SFP channel */ + if (i2c_cpld_write(I2C_BUS_5, SWPLD_U134, SFP_SEL_I2C_MUX, + DEFAULT_DISABLE) < 0) { + memset(data->eeprom, 0, sizeof(data->eeprom)); + goto exit; + } + /* Disable QSFP channel */ + if (i2c_cpld_write(I2C_BUS_5, SWPLD_U134, QSFP_SEL_I2C_MUX, + QSFP_DEFAULT_DISABLE) < 0) { + memset(data->eeprom, 0, sizeof(data->eeprom)); + goto exit; + } + + /* Select SFP or QSFP port channel */ + if (i2c_cpld_write(I2C_BUS_5, SWPLD_U134, reg_t, + cpld_to_port_table[port_t]) < 0) { + memset(data->eeprom, 0, sizeof(data->eeprom)); + goto exit; + } + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated) || !data->valid) { + int status = -1; + int i = 0; + data->valid = 0; + memset(data->eeprom, 0, sizeof(data->eeprom)); + + for (i = 0; i < sizeof(data->eeprom)/ \ + I2C_SMBUS_BLOCK_MAX; i++) { + status = agc7648a_sfp_read_block( + client, + i * I2C_SMBUS_BLOCK_MAX, + data->eeprom + (i * I2C_SMBUS_BLOCK_MAX), + I2C_SMBUS_BLOCK_MAX + ); + if (status < 0) { + printk(KERN_INFO "status = %d\n", status); + dev_dbg(&client->dev, + "unable to read eeprom from port(%d)\n", data->port); + + goto exit; + } + } + data->last_updated = jiffies; + data->valid = 1; + } + +exit: + mutex_unlock(&data->update_lock); + return data; +} + +/* sysfs attributes for hwmon */ +static SENSOR_DEVICE_ATTR(sfp_eeprom, S_IRUGO, for_eeprom, NULL, + SFP_EEPROM); +static SENSOR_DEVICE_ATTR(sfp_select_port, S_IWUSR | S_IRUGO, + for_r_port_data, set_w_port_data, SFP_SELECT_PORT); +static SENSOR_DEVICE_ATTR(sfp_is_present, S_IRUGO, for_status, NULL, + SFP_IS_PRESENT); +static SENSOR_DEVICE_ATTR(sfp_is_present_all, S_IRUGO, for_status, NULL, + SFP_IS_PRESENT_ALL); +static SENSOR_DEVICE_ATTR(sfp_lp_mode, S_IWUSR | S_IRUGO, + for_status, set_w_lp_mode_data, SFP_LP_MODE); +static SENSOR_DEVICE_ATTR(sfp_reset, S_IWUSR | S_IRUGO, + for_status, set_w_reset_data, SFP_RESET); + +static struct attribute *agc7648a_sfp_attributes[] = { + &sensor_dev_attr_sfp_eeprom.dev_attr.attr, + &sensor_dev_attr_sfp_select_port.dev_attr.attr, + &sensor_dev_attr_sfp_is_present.dev_attr.attr, + &sensor_dev_attr_sfp_is_present_all.dev_attr.attr, + &sensor_dev_attr_sfp_lp_mode.dev_attr.attr, + &sensor_dev_attr_sfp_reset.dev_attr.attr, + NULL +}; + +static const struct attribute_group agc7648a_sfp_group = { + .attrs = agc7648a_sfp_attributes, +}; + +static int agc7648a_sfp_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct agc7648a_sfp_data *data; + int status; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_I2C_BLOCK)) { + status = -EIO; + goto exit; + } + + data = kzalloc(sizeof(struct agc7648a_sfp_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + mutex_init(&data->update_lock); + data->port = id->driver_data; + i2c_set_clientdata(client, data); + + dev_info(&client->dev, "chip found\n"); + + status = sysfs_create_group(&client->dev.kobj, &agc7648a_sfp_group); + if (status) + goto exit_sysfs_create_group; + + data->hwmon_dev = hwmon_device_register(&client->dev); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_hwmon_device_register; + } + + dev_info(&client->dev, "%s: sfp '%s'\n", dev_name(data->hwmon_dev), + client->name); + + return 0; + +exit_hwmon_device_register: + sysfs_remove_group(&client->dev.kobj, &agc7648a_sfp_group); +exit_sysfs_create_group: + kfree(data); +exit: + return status; +} + +static int agc7648a_sfp_remove(struct i2c_client *client) +{ + struct agc7648a_sfp_data *data = i2c_get_clientdata(client); + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &agc7648a_sfp_group); + kfree(data); + return 0; +} + +enum id_name { + agc7648a_sfp +}; + +static const struct i2c_device_id agc7648a_sfp_id[] = { + { "agc7648a_sfp", agc7648a_sfp }, + {} +}; +MODULE_DEVICE_TABLE(i2c, agc7648a_sfp_id); + + +static struct i2c_driver agc7648a_sfp_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "agc7648a_sfp", + }, + .probe = agc7648a_sfp_probe, + .remove = agc7648a_sfp_remove, + .id_table = agc7648a_sfp_id, + .address_list = normal_i2c, +}; + +static int __init agc7648a_sfp_init(void) +{ + return i2c_add_driver(&agc7648a_sfp_driver); +} + +static void __exit agc7648a_sfp_exit(void) +{ + i2c_del_driver(&agc7648a_sfp_driver); +} + +MODULE_AUTHOR("Aries Lin "); +MODULE_DESCRIPTION("agc7648a SFP Driver"); +MODULE_LICENSE("GPL"); + +module_init(agc7648a_sfp_init); +module_exit(agc7648a_sfp_exit); + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/tmp421.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/tmp421.c new file mode 100644 index 00000000..7bab7a9b --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/modules/builds/tmp421.c @@ -0,0 +1,309 @@ +/* tmp421.c + * + * Copyright (C) 2009 Andre Prendel + * Preliminary support by: + * Melvin Rook, Raymond Ng + * + * 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. + */ + +/* + * Driver for the Texas Instruments TMP421 SMBus temperature sensor IC. + * Supported models: TMP421, TMP422, TMP423 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { 0x2a, 0x4c, 0x4d, 0x4e, 0x4f, + I2C_CLIENT_END }; + +enum chips { tmp421, tmp422, tmp423 }; + +/* The TMP421 registers */ +#define TMP421_CONFIG_REG_1 0x09 +#define TMP421_CONVERSION_RATE_REG 0x0B +#define TMP421_MANUFACTURER_ID_REG 0xFE +#define TMP421_DEVICE_ID_REG 0xFF + +static const u8 TMP421_TEMP_MSB[4] = { 0x00, 0x01, 0x02, 0x03 }; +static const u8 TMP421_TEMP_LSB[4] = { 0x10, 0x11, 0x12, 0x13 }; + +/* Flags */ +#define TMP421_CONFIG_SHUTDOWN 0x40 +#define TMP421_CONFIG_RANGE 0x04 + +/* Manufacturer / Device ID's */ +#define TMP421_MANUFACTURER_ID 0x55 +#define TMP421_DEVICE_ID 0x21 +#define TMP422_DEVICE_ID 0x22 +#define TMP423_DEVICE_ID 0x23 + +static const struct i2c_device_id tmp421_id[] = { + { "tmp421", 2 }, + { "tmp422", 3 }, + { "tmp423", 4 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tmp421_id); + +struct tmp421_data { + struct i2c_client *client; + struct mutex update_lock; + char valid; + unsigned long last_updated; + int channels; + u8 config; + s16 temp[4]; +}; + +static int temp_from_s16(s16 reg) +{ + /* Mask out status bits */ + int temp = reg & ~0xf; + + return (temp * 1000 + 128) / 256; +} + +static int temp_from_u16(u16 reg) +{ + /* Mask out status bits */ + int temp = reg & ~0xf; + + /* Add offset for extended temperature range. */ + temp -= 64 * 256; + + return (temp * 1000 + 128) / 256; +} + +static struct tmp421_data *tmp421_update_device(struct device *dev) +{ + struct tmp421_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int i; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { + data->config = i2c_smbus_read_byte_data(client, + TMP421_CONFIG_REG_1); + + for (i = 0; i < data->channels; i++) { + data->temp[i] = i2c_smbus_read_byte_data(client, + TMP421_TEMP_MSB[i]) << 8; + data->temp[i] |= i2c_smbus_read_byte_data(client, + TMP421_TEMP_LSB[i]); + } + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +static ssize_t show_temp_value(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct tmp421_data *data = tmp421_update_device(dev); + int temp; + + mutex_lock(&data->update_lock); + if (data->config & TMP421_CONFIG_RANGE) + temp = temp_from_u16(data->temp[index]); + else + temp = temp_from_s16(data->temp[index]); + mutex_unlock(&data->update_lock); + + return sprintf(buf, "%d\n", temp); +} + +static ssize_t show_fault(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + int index = to_sensor_dev_attr(devattr)->index; + struct tmp421_data *data = tmp421_update_device(dev); + + /* + * The OPEN bit signals a fault. This is bit 0 of the temperature + * register (low byte). + */ + if (data->temp[index] & 0x01) + return sprintf(buf, "1\n"); + else + return sprintf(buf, "0\n"); +} + +static umode_t tmp421_is_visible(struct kobject *kobj, struct attribute *a, + int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct tmp421_data *data = dev_get_drvdata(dev); + struct device_attribute *devattr; + unsigned int index; + + devattr = container_of(a, struct device_attribute, attr); + index = to_sensor_dev_attr(devattr)->index; + + if (index < data->channels) + return a->mode; + + return 0; +} + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_value, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_value, NULL, 1); +static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_fault, NULL, 1); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_value, NULL, 2); +static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_fault, NULL, 2); +static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_value, NULL, 3); +static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_fault, NULL, 3); + +static struct attribute *tmp421_attr[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp2_fault.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp3_fault.dev_attr.attr, + &sensor_dev_attr_temp4_input.dev_attr.attr, + &sensor_dev_attr_temp4_fault.dev_attr.attr, + NULL +}; + +static const struct attribute_group tmp421_group = { + .attrs = tmp421_attr, + .is_visible = tmp421_is_visible, +}; + +static const struct attribute_group *tmp421_groups[] = { + &tmp421_group, + NULL +}; + +static int tmp421_init_client(struct i2c_client *client) +{ + int config, config_orig; + + /* Set the conversion rate to 2 Hz */ + i2c_smbus_write_byte_data(client, TMP421_CONVERSION_RATE_REG, 0x05); + + /* Start conversions (disable shutdown if necessary) */ + config = i2c_smbus_read_byte_data(client, TMP421_CONFIG_REG_1); + if (config < 0) { + dev_err(&client->dev, + "Could not read configuration register (%d)\n", config); + return config; + } + + config_orig = config; + config &= ~TMP421_CONFIG_SHUTDOWN; + + if (config != config_orig) { + dev_info(&client->dev, "Enable monitoring chip\n"); + i2c_smbus_write_byte_data(client, TMP421_CONFIG_REG_1, config); + } + + return 0; +} + +static int tmp421_detect(struct i2c_client *client, + struct i2c_board_info *info) +{ + enum chips kind; + struct i2c_adapter *adapter = client->adapter; + const char *names[] = { "TMP421", "TMP422", "TMP423" }; + u8 reg; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + reg = i2c_smbus_read_byte_data(client, TMP421_MANUFACTURER_ID_REG); + if (reg != TMP421_MANUFACTURER_ID) + return -ENODEV; + + reg = i2c_smbus_read_byte_data(client, TMP421_DEVICE_ID_REG); + switch (reg) { + case TMP421_DEVICE_ID: + kind = tmp421; + break; + case TMP422_DEVICE_ID: + kind = tmp422; + break; + case TMP423_DEVICE_ID: + kind = tmp423; + break; + default: + return -ENODEV; + } + + strlcpy(info->type, tmp421_id[kind].name, I2C_NAME_SIZE); + dev_info(&adapter->dev, "Detected TI %s chip at 0x%02x\n", + names[kind], client->addr); + + return 0; +} + +static int tmp421_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct device *hwmon_dev; + struct tmp421_data *data; + int err; + + data = devm_kzalloc(dev, sizeof(struct tmp421_data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + mutex_init(&data->update_lock); + data->channels = id->driver_data; + data->client = client; + + err = tmp421_init_client(client); + if (err) + return err; + + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, tmp421_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static struct i2c_driver tmp421_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "tmp421", + }, + .probe = tmp421_probe, + .id_table = tmp421_id, + .detect = tmp421_detect, + .address_list = normal_i2c, +}; + +module_i2c_driver(tmp421_driver); + +MODULE_AUTHOR("Andre Prendel "); +MODULE_DESCRIPTION("Texas Instruments TMP421/422/423 temperature sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/PKG.yml b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/PKG.yml new file mode 100644 index 00000000..0e1c8c52 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-delta-agc7648a ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/Makefile new file mode 100644 index 00000000..e7437cb2 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/Makefile @@ -0,0 +1,2 @@ +FILTER=src +include $(ONL)/make/subdirs.mk diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/lib/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/lib/Makefile new file mode 100644 index 00000000..799494b1 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/lib/Makefile @@ -0,0 +1,45 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.eclipse.org/legal/epl-v10.html +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +# either express or implied. See the License for the specific +# language governing permissions and limitations under the +# License. +# +# +############################################################ +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +MODULE := libonlp-x86-64-delta-agc7648a +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF x86_64_delta_agc7648a onlplib +DEPENDMODULE_HEADERS := sff + +include $(BUILDER)/dependmodules.mk + +SHAREDLIB := libonlp-x86-64-delta-agc7648a.so +$(SHAREDLIB)_TARGETS := $(ALL_TARGETS) +include $(BUILDER)/so.mk +.DEFAULT_GOAL := $(SHAREDLIB) + +GLOBAL_CFLAGS += -I$(onlp_BASEDIR)/module/inc +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -fPIC +GLOBAL_LINK_LIBS += -lpthread + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/lib/libonlp-x86-64-delta-agc7648a.mk b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/lib/libonlp-x86-64-delta-agc7648a.mk new file mode 100644 index 00000000..b74a7f6f --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/lib/libonlp-x86-64-delta-agc7648a.mk @@ -0,0 +1,10 @@ + +############################################################################### +# +# Inclusive Makefile for the libonlp-x86-64-delta-agc7648a module. +# +# Autogenerated 2017-03-15 04:06:44.303111 +# +############################################################################### +libonlp-x86-64-delta-agc7648a_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/onlpdump/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/onlpdump/Makefile new file mode 100644 index 00000000..286d2150 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/onlpdump/Makefile @@ -0,0 +1,46 @@ +############################################################ +# +# +# Copyright 2014 BigSwitch Networks, Inc. +# +# Licensed under the Eclipse Public License, Version 1.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.eclipse.org/legal/epl-v10.html +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +# either express or implied. See the License for the specific +# language governing permissions and limitations under the +# License. +# +# +############################################################ +# +# +# +############################################################ +include $(ONL)/make/config.amd64.mk + +.DEFAULT_GOAL := onlpdump + +MODULE := onlpdump +include $(BUILDER)/standardinit.mk + +DEPENDMODULES := AIM IOF onlp x86_64_delta_agc7648a onlplib onlp_platform_defaults sff cjson cjson_util timer_wheel OS + +include $(BUILDER)/dependmodules.mk + +BINARY := onlpdump +$(BINARY)_LIBRARIES := $(LIBRARY_TARGETS) +include $(BUILDER)/bin.mk + +GLOBAL_CFLAGS += -DAIM_CONFIG_AIM_MAIN_FUNCTION=onlpdump_main +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MODULES_INIT=1 +GLOBAL_CFLAGS += -DAIM_CONFIG_INCLUDE_MAIN=1 +GLOBAL_LINK_LIBS += -lpthread -lm + +include $(BUILDER)/targets.mk + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/.module b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/.module new file mode 100644 index 00000000..4ead6358 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/.module @@ -0,0 +1 @@ +name: x86_64_delta_agc7648a diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/Makefile new file mode 100644 index 00000000..c5a687e1 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### +include ../../init.mk +MODULE := x86_64_delta_agc7648a +AUTOMODULE := x86_64_delta_agc7648a +include $(BUILDER)/definemodule.mk diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/README b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/README new file mode 100644 index 00000000..bc91c63c --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/README @@ -0,0 +1,6 @@ +############################################################################### +# +# x86_64_delta_agc7648a README +# +############################################################################### + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/auto/make.mk b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/auto/make.mk new file mode 100644 index 00000000..15ac889f --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/auto/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# x86_64_delta_agc7648a Autogeneration +# +############################################################################### +x86_64_delta_agc7648a_AUTO_DEFS := module/auto/x86_64_delta_agc7648a.yml +x86_64_delta_agc7648a_AUTO_DIRS := module/inc/x86_64_delta_agc7648a module/src +include $(BUILDER)/auto.mk + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/auto/x86_64_delta_agc7648a.yml b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/auto/x86_64_delta_agc7648a.yml new file mode 100644 index 00000000..dd6e1b65 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/auto/x86_64_delta_agc7648a.yml @@ -0,0 +1,50 @@ +############################################################################### +# +# x86_64_delta_agc7648a Autogeneration Definitions. +# +############################################################################### + +cdefs: &cdefs +- x86_64_delta_agc7648a_CONFIG_INCLUDE_LOGGING: + doc: "Include or exclude logging." + default: 1 +- x86_64_delta_agc7648a_CONFIG_LOG_OPTIONS_DEFAULT: + doc: "Default enabled log options." + default: AIM_LOG_OPTIONS_DEFAULT +- x86_64_delta_agc7648a_CONFIG_LOG_BITS_DEFAULT: + doc: "Default enabled log bits." + default: AIM_LOG_BITS_DEFAULT +- x86_64_delta_agc7648a_CONFIG_LOG_CUSTOM_BITS_DEFAULT: + doc: "Default enabled custom log bits." + default: 0 +- x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB: + doc: "Default all porting macros to use the C standard libraries." + default: 1 +- x86_64_delta_agc7648a_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS: + doc: "Include standard library headers for stdlib porting macros." + default: x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB +- x86_64_delta_agc7648a_CONFIG_INCLUDE_UCLI: + doc: "Include generic uCli support." + default: 0 +- x86_64_delta_agc7648a_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION: + doc: "Assume chassis fan direction is the same as the PSU fan direction." + default: 0 + + +definitions: + cdefs: + x86_64_delta_agc7648a_CONFIG_HEADER: + defs: *cdefs + basename: x86_64_delta_agc7648a_config + + portingmacro: + x86_64_delta_agc7648a: + macros: + - malloc + - free + - memset + - memcpy + - strncpy + - vsnprintf + - snprintf + - strlen diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/inc/x86_64_delta_agc7648a/x86_64_delta_agc7648a.x b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/inc/x86_64_delta_agc7648a/x86_64_delta_agc7648a.x new file mode 100644 index 00000000..8308c436 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/inc/x86_64_delta_agc7648a/x86_64_delta_agc7648a.x @@ -0,0 +1,14 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.xmacro(ALL).define> */ +/* */ + +/* <--auto.start.xenum(ALL).define> */ +/* */ + + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/inc/x86_64_delta_agc7648a/x86_64_delta_agc7648a_config.h b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/inc/x86_64_delta_agc7648a/x86_64_delta_agc7648a_config.h new file mode 100644 index 00000000..43ff45af --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/inc/x86_64_delta_agc7648a/x86_64_delta_agc7648a_config.h @@ -0,0 +1,137 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_delta_agc7648a Configuration Header + * + * @addtogroup x86_64_delta_agc7648a-config + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_delta_agc7648a_CONFIG_H__ +#define __x86_64_delta_agc7648a_CONFIG_H__ + +#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG +#include +#endif +#ifdef x86_64_delta_agc7648a_INCLUDE_CUSTOM_CONFIG +#include +#endif + +/* */ +#include +/** + * x86_64_delta_agc7648a_CONFIG_INCLUDE_LOGGING + * + * Include or exclude logging. */ + + +#ifndef x86_64_delta_agc7648a_CONFIG_INCLUDE_LOGGING +#define x86_64_delta_agc7648a_CONFIG_INCLUDE_LOGGING 1 +#endif + +/** + * x86_64_delta_agc7648a_CONFIG_LOG_OPTIONS_DEFAULT + * + * Default enabled log options. */ + + +#ifndef x86_64_delta_agc7648a_CONFIG_LOG_OPTIONS_DEFAULT +#define x86_64_delta_agc7648a_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT +#endif + +/** + * x86_64_delta_agc7648a_CONFIG_LOG_BITS_DEFAULT + * + * Default enabled log bits. */ + + +#ifndef x86_64_delta_agc7648a_CONFIG_LOG_BITS_DEFAULT +#define x86_64_delta_agc7648a_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT +#endif + +/** + * x86_64_delta_agc7648a_CONFIG_LOG_CUSTOM_BITS_DEFAULT + * + * Default enabled custom log bits. */ + + +#ifndef x86_64_delta_agc7648a_CONFIG_LOG_CUSTOM_BITS_DEFAULT +#define x86_64_delta_agc7648a_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0 +#endif + +/** + * x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB + * + * Default all porting macros to use the C standard libraries. */ + + +#ifndef x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB +#define x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB 1 +#endif + +/** + * x86_64_delta_agc7648a_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + * + * Include standard library headers for stdlib porting macros. */ + + +#ifndef x86_64_delta_agc7648a_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS +#define x86_64_delta_agc7648a_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB +#endif + +/** + * x86_64_delta_agc7648a_CONFIG_INCLUDE_UCLI + * + * Include generic uCli support. */ + + +#ifndef x86_64_delta_agc7648a_CONFIG_INCLUDE_UCLI +#define x86_64_delta_agc7648a_CONFIG_INCLUDE_UCLI 0 +#endif + +/** + * x86_64_delta_agc7648a_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + * + * Assume chassis fan direction is the same as the PSU fan direction. */ + + +#ifndef x86_64_delta_agc7648a_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION +#define x86_64_delta_agc7648a_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0 +#endif + + + +/** + * All compile time options can be queried or displayed + */ + +/** Configuration settings structure. */ +typedef struct x86_64_delta_agc7648a_config_settings_s { + /** name */ + const char* name; + /** value */ + const char* value; +} x86_64_delta_agc7648a_config_settings_t; + +/** Configuration settings table. */ +/** x86_64_delta_agc7648a_config_settings table. */ +extern x86_64_delta_agc7648a_config_settings_t x86_64_delta_agc7648a_config_settings[]; + +/** + * @brief Lookup a configuration setting. + * @param setting The name of the configuration option to lookup. + */ +const char* x86_64_delta_agc7648a_config_lookup(const char* setting); + +/** + * @brief Show the compile-time configuration. + * @param pvs The output stream. + */ +int x86_64_delta_agc7648a_config_show(struct aim_pvs_s* pvs); + +/* */ + +#include "x86_64_delta_agc7648a_porting.h" + +#endif /* __x86_64_delta_agc7648a_CONFIG_H__ */ +/* @} */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/inc/x86_64_delta_agc7648a/x86_64_delta_agc7648a_dox.h b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/inc/x86_64_delta_agc7648a/x86_64_delta_agc7648a_dox.h new file mode 100644 index 00000000..22f0ec79 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/inc/x86_64_delta_agc7648a/x86_64_delta_agc7648a_dox.h @@ -0,0 +1,26 @@ +/**************************************************************************//** + * + * x86_64_delta_agc7648a Doxygen Header + * + *****************************************************************************/ +#ifndef __x86_64_delta_agc7648a_DOX_H__ +#define __x86_64_delta_agc7648a_DOX_H__ + +/** + * @defgroup x86_64_delta_agc7648a x86_64_delta_agc7648a - x86_64_delta_agc7648a Description + * + +The documentation overview for this module should go here. + + * + * @{ + * + * @defgroup x86_64_delta_agc7648a-x86_64_delta_agc7648a Public Interface + * @defgroup x86_64_delta_agc7648a-config Compile Time Configuration + * @defgroup x86_64_delta_agc7648a-porting Porting Macros + * + * @} + * + */ + +#endif /* __x86_64_delta_agc7648a_DOX_H__ */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/inc/x86_64_delta_agc7648a/x86_64_delta_agc7648a_porting.h b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/inc/x86_64_delta_agc7648a/x86_64_delta_agc7648a_porting.h new file mode 100644 index 00000000..d44ecab4 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/inc/x86_64_delta_agc7648a/x86_64_delta_agc7648a_porting.h @@ -0,0 +1,107 @@ +/**************************************************************************//** + * + * @file + * @brief x86_64_delta_agc7648a Porting Macros. + * + * @addtogroup x86_64_delta_agc7648a-porting + * @{ + * + *****************************************************************************/ +#ifndef __x86_64_delta_agc7648a_PORTING_H__ +#define __x86_64_delta_agc7648a_PORTING_H__ + + +/* */ +#if x86_64_delta_agc7648a_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1 +#include +#include +#include +#include +#include +#endif + +#ifndef x86_64_delta_agc7648a_MALLOC + #if defined(GLOBAL_MALLOC) + #define x86_64_delta_agc7648a_MALLOC GLOBAL_MALLOC + #elif x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB == 1 + #define x86_64_delta_agc7648a_MALLOC malloc + #else + #error The macro x86_64_delta_agc7648a_MALLOC is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_delta_agc7648a_FREE + #if defined(GLOBAL_FREE) + #define x86_64_delta_agc7648a_FREE GLOBAL_FREE + #elif x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB == 1 + #define x86_64_delta_agc7648a_FREE free + #else + #error The macro x86_64_delta_agc7648a_FREE is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_delta_agc7648a_MEMSET + #if defined(GLOBAL_MEMSET) + #define x86_64_delta_agc7648a_MEMSET GLOBAL_MEMSET + #elif x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB == 1 + #define x86_64_delta_agc7648a_MEMSET memset + #else + #error The macro x86_64_delta_agc7648a_MEMSET is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_delta_agc7648a_MEMCPY + #if defined(GLOBAL_MEMCPY) + #define x86_64_delta_agc7648a_MEMCPY GLOBAL_MEMCPY + #elif x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB == 1 + #define x86_64_delta_agc7648a_MEMCPY memcpy + #else + #error The macro x86_64_delta_agc7648a_MEMCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_delta_agc7648a_STRNCPY + #if defined(GLOBAL_STRNCPY) + #define x86_64_delta_agc7648a_STRNCPY GLOBAL_STRNCPY + #elif x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB == 1 + #define x86_64_delta_agc7648a_STRNCPY strncpy + #else + #error The macro x86_64_delta_agc7648a_STRNCPY is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_delta_agc7648a_VSNPRINTF + #if defined(GLOBAL_VSNPRINTF) + #define x86_64_delta_agc7648a_VSNPRINTF GLOBAL_VSNPRINTF + #elif x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB == 1 + #define x86_64_delta_agc7648a_VSNPRINTF vsnprintf + #else + #error The macro x86_64_delta_agc7648a_VSNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_delta_agc7648a_SNPRINTF + #if defined(GLOBAL_SNPRINTF) + #define x86_64_delta_agc7648a_SNPRINTF GLOBAL_SNPRINTF + #elif x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB == 1 + #define x86_64_delta_agc7648a_SNPRINTF snprintf + #else + #error The macro x86_64_delta_agc7648a_SNPRINTF is required but cannot be defined. + #endif +#endif + +#ifndef x86_64_delta_agc7648a_STRLEN + #if defined(GLOBAL_STRLEN) + #define x86_64_delta_agc7648a_STRLEN GLOBAL_STRLEN + #elif x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB == 1 + #define x86_64_delta_agc7648a_STRLEN strlen + #else + #error The macro x86_64_delta_agc7648a_STRLEN is required but cannot be defined. + #endif +#endif + +/* */ + + +#endif /* __x86_64_delta_agc7648a_PORTING_H__ */ +/* @} */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/make.mk b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/make.mk new file mode 100644 index 00000000..b655be7b --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/make.mk @@ -0,0 +1,10 @@ +############################################################################### +# +# +# +############################################################################### +THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST))) +x86_64_delta_agc7648a_INCLUDES := -I $(THIS_DIR)inc +x86_64_delta_agc7648a_INTERNAL_INCLUDES := -I $(THIS_DIR)src +x86_64_delta_agc7648a_DEPENDMODULE_ENTRIES := init:x86_64_delta_agc7648a ucli:x86_64_delta_agc7648a + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/Makefile new file mode 100644 index 00000000..5ae92f42 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/Makefile @@ -0,0 +1,9 @@ +############################################################################### +# +# Local source generation targets. +# +############################################################################### + +ucli: + @../../../../tools/uclihandlers.py x86_64_delta_agc7648a_ucli.c + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/debug.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/debug.c new file mode 100644 index 00000000..f9c3da7e --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/debug.c @@ -0,0 +1,45 @@ +#include "x86_64_delta_agc7648a_int.h" + +#if X86_64_DELTA_AGC7648A_CONFIG_INCLUDE_DEBUG == 1 + +#include + +static char help__[] = + "Usage: debug [options]\n" + " -c CPLD Versions\n" + " -h Help\n" + ; + +int +x86_64_delta_agc7648a_debug_main(int argc, char* argv[]) +{ + int c = 0; + int help = 0; + int rv = 0; + + while( (c = getopt(argc, argv, "ch")) != -1) { + switch(c) + { + case 'c': c = 1; break; + case 'h': help = 1; rv = 0; break; + default: help = 1; rv = 1; break; + } + + } + + if(help || argc == 1) { + printf("%s", help__); + return rv; + } + + if(c) { + printf("Not implemented.\n"); + } + + + return 0; +} + +#endif + + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/fani.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/fani.c new file mode 100644 index 00000000..001b65d4 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/fani.c @@ -0,0 +1,389 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta network Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * Fan Platform Implementation Defaults. + * + ***********************************************************/ +#include +#include +#include +#include "platform_lib.h" +#include + +typedef struct fan_path_S +{ + char *status; + char *speed; + char *ctrl_speed; +}fan_path_T; + +static fan_path_T fan_path[] = /* must map with onlp_fan_id in platform_lib.h */ +{ + { NULL, NULL, NULL }, + { "3-002c/fan1_fault", "3-002c/fan1_input", "3-002c/fan1_input" }, + { "3-002c/fan2_fault", "3-002c/fan2_input", "3-002c/fan2_input" }, + { "3-002c/fan3_fault", "3-002c/fan3_input", "3-002c/fan3_input" }, + { "3-002c/fan4_fault", "3-002c/fan4_input", "3-002c/fan4_input" }, + { "3-002d/fan1_fault", "3-002d/fan1_input", "3-002d/fan1_input" }, + { "3-002d/fan2_fault", "3-002d/fan2_input", "3-002d/fan2_input" }, + { "3-002d/fan3_fault", "3-002d/fan3_input", "3-002d/fan3_input" }, + { "3-002d/fan4_fault", "3-002d/fan4_input", "3-002d/fan4_input" }, + { "4-0058/psu_fan1_fault", "4-0058/psu_fan1_speed_rpm", "4-0058/psu_fan1_duty_cycle_percentage" }, + { "4-0058/psu_fan1_fault", "4-0058/psu_fan1_speed_rpm", "4-0058/psu_fan1_duty_cycle_percentage" } +}; + +#define MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(id) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##id##_ON_MAIN_BOARD), "Chassis Fan "#id, 0 }, \ + 0x0, \ + (ONLP_FAN_CAPS_SET_RPM | ONLP_FAN_CAPS_GET_RPM), \ + 0, \ + 0, \ + ONLP_FAN_MODE_INVALID, \ + } + +#define MAKE_FAN_INFO_NODE_ON_PSU(psu_id, fan_id) \ + { \ + { ONLP_FAN_ID_CREATE(FAN_##fan_id##_ON_PSU##psu_id), "Chassis PSU-"#psu_id " Fan "#fan_id, 0 }, \ + 0x0, \ + (ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \ + 0, \ + 0, \ + ONLP_FAN_MODE_INVALID, \ + } + +/* Static fan information */ +onlp_fan_info_t linfo[] = { + { }, /* Not used */ + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(1), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(2), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(3), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(4), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(5), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(6), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(7), + MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(8), + MAKE_FAN_INFO_NODE_ON_PSU(1,1), + MAKE_FAN_INFO_NODE_ON_PSU(2,1), +}; + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_FAN(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +dni_fani_info_get_fan(int local_id, onlp_fan_info_t* info) +{ + int rpm = 0; + char fullpath[100] = {0}; + + /* Update fan rpm */ + sprintf(fullpath, "%s/%s", SYS_DEV_PATH, fan_path[local_id].speed); + rpm = dni_i2c_lock_read_attribute(NULL, fullpath); + + /* Return 960 if fan stop */ + if(rpm == 960) + { + rpm = 0; + } + info->rpm = rpm; + + /* Update fan speed percentage based from rpm */ + switch(local_id) + { + case FAN_1_ON_MAIN_BOARD: + case FAN_2_ON_MAIN_BOARD: + case FAN_3_ON_MAIN_BOARD: + case FAN_4_ON_MAIN_BOARD: + info->percentage = (info->rpm * 100)/MAX_FRONT_FAN_SPEED; + break; + case FAN_5_ON_MAIN_BOARD: + case FAN_6_ON_MAIN_BOARD: + case FAN_7_ON_MAIN_BOARD: + case FAN_8_ON_MAIN_BOARD: + info->percentage = (info->rpm * 100)/MAX_REAR_FAN_SPEED; + break; + default: + AIM_LOG_ERROR("Error local_id"); + break; + } + + /* Update present bit of fan status */ + mux_info_t mux_info; + mux_info.bus = I2C_BUS_5; + mux_info.addr = SWPLD; + mux_info.offset = FAN_MUX_REG; + mux_info.channel = 0x07; + + dev_info_t dev_info; + dev_info.bus = I2C_BUS_3; + dev_info.addr = FAN_IO_CTRL; + dev_info.offset = 0x00; + dev_info.size = 1; + dev_info.flags = 0; + + int fantray_present_val = dni_i2c_lock_read(&mux_info, &dev_info); + + switch(local_id) + { + case FAN_1_ON_MAIN_BOARD: + case FAN_5_ON_MAIN_BOARD: + if((fantray_present_val & 0x01) == 0x00) + info->status |= ONLP_FAN_STATUS_PRESENT; + break; + case FAN_2_ON_MAIN_BOARD: + case FAN_6_ON_MAIN_BOARD: + if((fantray_present_val & 0x02) == 0x00) + info->status |= ONLP_FAN_STATUS_PRESENT; + break; + case FAN_3_ON_MAIN_BOARD: + case FAN_7_ON_MAIN_BOARD: + if((fantray_present_val & 0x04) == 0x00) + info->status |= ONLP_FAN_STATUS_PRESENT; + break; + case FAN_4_ON_MAIN_BOARD: + case FAN_8_ON_MAIN_BOARD: + if((fantray_present_val & 0x08) == 0x00) + info->status |= ONLP_FAN_STATUS_PRESENT; + break; + } + + return ONLP_STATUS_OK; +} + + +static int +dni_fani_info_get_fan_on_psu(int local_id, onlp_fan_info_t* info) +{ + int r_data = 0, psu_present_val = 0; + char fullpath[80] = {0}, psu_num[2]; + + /* Read cpld psu present bit for updating psu present status */ + psu_present_val = dni_lock_cpld_read_attribute(SWPLD_PATH, PSU_PRESENT_REG); + if(local_id == FAN_1_ON_PSU1 && + ((psu_present_val & 0x01) == 0x00)) + { + info->status |= ONLP_FAN_STATUS_PRESENT; + } + else if(local_id == FAN_1_ON_PSU2 && + ((psu_present_val & 0x02) == 0x00)) + { + info->status |= ONLP_FAN_STATUS_PRESENT; + } + + + /* Configure MUX settings */ + if(local_id == FAN_1_ON_PSU1) + { + sprintf(psu_num, "%d", 1); + } + else if(local_id == FAN_1_ON_PSU2) + { + sprintf(psu_num, "%d", 2); + } + + /* Set MUX */ + dni_i2c_lock_write_attribute(NULL, psu_num, PSU_SEL_PATH); + + /* Get psu fan fault status */ + sprintf(fullpath, "%s/%s", SYS_DEV_PATH, fan_path[local_id].status); + r_data = dni_i2c_lock_read_attribute(NULL, fullpath); + if (r_data > 0) + info->status |= ONLP_FAN_STATUS_FAILED; + + /* Get psu fan rpm */ + sprintf(fullpath, "%s/%s", SYS_DEV_PATH, fan_path[local_id].speed); + r_data = dni_i2c_lock_read_attribute(NULL, fullpath); + info->rpm = r_data; + + /* Calculate psu fan duty cycle based on rpm */ + info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED; + + return ONLP_STATUS_OK; +} + +/* + * This function will be called prior to all of onlp_fani_* functions. + */ +int +onlp_fani_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info) +{ + int rc = 0; + int local_id; + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + *info = linfo[local_id]; + + + switch (local_id) + { + case FAN_1_ON_PSU1: + case FAN_1_ON_PSU2: + rc = dni_fani_info_get_fan_on_psu(local_id, info); + break; + case FAN_1_ON_MAIN_BOARD: + case FAN_2_ON_MAIN_BOARD: + case FAN_3_ON_MAIN_BOARD: + case FAN_4_ON_MAIN_BOARD: + case FAN_5_ON_MAIN_BOARD: + case FAN_6_ON_MAIN_BOARD: + case FAN_7_ON_MAIN_BOARD: + case FAN_8_ON_MAIN_BOARD: + rc = dni_fani_info_get_fan(local_id, info); + break; + default: + rc = ONLP_STATUS_E_INVALID; + break; + } + + return rc; +} + + +/* + * This function sets the speed of the given fan in RPM. + * + * This function will only be called if the fan supprots the RPM_SET + * capability. + * + * It is optional if you have no fans at all with this feature. + */ +int +onlp_fani_rpm_set(onlp_oid_t id, int rpm) +{ + int local_id; + char data[10] = {0}; + char fullpath[256] = {0}; + VALIDATE(id); + local_id = ONLP_OID_ID_GET(id); + + /* get fullpath */ + switch (local_id) + { + case FAN_1_ON_MAIN_BOARD: + case FAN_2_ON_MAIN_BOARD: + case FAN_3_ON_MAIN_BOARD: + case FAN_4_ON_MAIN_BOARD: + case FAN_5_ON_MAIN_BOARD: + case FAN_6_ON_MAIN_BOARD: + case FAN_7_ON_MAIN_BOARD: + case FAN_8_ON_MAIN_BOARD: + sprintf(fullpath, "%s/%s", SYS_DEV_PATH, fan_path[local_id].ctrl_speed); + break; + default: + return ONLP_STATUS_E_INVALID; + } + sprintf(data, "%d", rpm); + + dni_i2c_lock_write_attribute(NULL, data, fullpath); + + return ONLP_STATUS_OK; +} + +/* + * 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 local_id; + char data[10], fullpath[256] = {0}, psu_num[2]; + VALIDATE(id); + local_id = ONLP_OID_ID_GET(id); + + /* Configure MUX settings and fan percentage attribute path */ + switch(local_id) + { + case FAN_1_ON_PSU1: + sprintf(psu_num, "%d", 1); + sprintf(fullpath, "%s/%s", SYS_DEV_PATH, fan_path[local_id].ctrl_speed); + break; + case FAN_1_ON_PSU2: + sprintf(psu_num, "%d", 2); + sprintf(fullpath, "%s/%s", SYS_DEV_PATH, fan_path[local_id].ctrl_speed); + break; + default: + return ONLP_STATUS_E_INVALID; + } + + /* Set MUX */ + dni_i2c_lock_write_attribute(NULL, psu_num, PSU_SEL_PATH); + + /* Set fan percentage */ + sprintf(data, "%d", p); + dni_i2c_lock_write_attribute(NULL, data, fullpath); + + return ONLP_STATUS_OK; +} + + +/* + * This function sets the fan speed of the given OID as per + * the predefined ONLP fan speed modes: off, slow, normal, fast, max. + * + * Interpretation of these modes is up to the platform. + * + */ +int +onlp_fani_mode_set(onlp_oid_t id, onlp_fan_mode_t mode) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * This function sets the fan direction of the given OID. + * + * This function is only relevant if the fan OID supports both direction + * capabilities. + * + * This function is optional unless the functionality is available. + */ +int +onlp_fani_dir_set(onlp_oid_t id, onlp_fan_dir_t dir) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +/* + * Generic fan ioctl. Optional. + */ +int +onlp_fani_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/ledi.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/ledi.c new file mode 100755 index 00000000..cf11bc82 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/ledi.c @@ -0,0 +1,426 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta network Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" + +#define ALL_FAN_TRAY_EXIST 4 +#define PREFIX_PATH_ON_BOARD "/sys/bus/i2c/devices/" + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_LED(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +/* + * Get the information for the given LED OID. + */ +static onlp_led_info_t linfo[] = +{ + { }, /* Not used */ + { + { ONLP_LED_ID_CREATE(LED_FRONT_FAN), "FRONT LED (FAN LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_FRONT_SYS), "FRONT LED (SYS LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_GREEN_BLINKING | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_FRONT_PWR), "FRONT LED (PWR LED)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_ORANGE_BLINKING | ONLP_LED_CAPS_GREEN, + }, + { + { ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_1), "REAR LED (FAN TRAY 1)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_2), "REAR LED (FAN TRAY 2)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_3), "REAR LED (FAN TRAY 3)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_AUTO, + }, + { + { ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_4), "REAR LED (FAN TRAY 4)", 0 }, + ONLP_LED_STATUS_PRESENT, + ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_ORANGE | ONLP_LED_CAPS_AUTO, + } +}; +/* + * 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 r_data = 0, r_data1 = 0, fantray_present = -1; + VALIDATE(id); + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[ONLP_OID_ID_GET(id)]; + + mux_info_t mux_info; + mux_info.bus = I2C_BUS_5; + mux_info.addr = SWPLD; + mux_info.offset = FAN_MUX_REG; + mux_info.channel = 0x07; + mux_info.flags = DEFAULT_FLAG; + + dev_info_t dev_info; + dev_info.bus = I2C_BUS_3; + dev_info.offset = 0x00; + dev_info.flags = DEFAULT_FLAG; + + /* Set front panel's mode of leds */ + r_data = dni_lock_cpld_read_attribute(SWPLD_PATH, LED_REG); + r_data1 = dni_lock_cpld_read_attribute(SWPLD_PATH, FAN_TRAY_LED_REG); + int local_id = ONLP_OID_ID_GET(id); + switch(local_id) + { + case LED_FRONT_FAN: + if((r_data & 0x02) == 0x02) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x01) == 0x01) + info->mode = ONLP_LED_MODE_ORANGE; + break; + case LED_FRONT_SYS: + if((r_data & 0x10) == 0x10) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x20) == 0x20) + info->mode = ONLP_LED_MODE_ORANGE; + else + return ONLP_STATUS_E_INTERNAL; + break; + case LED_FRONT_PWR: + if((r_data & 0x08) == 0x08) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data & 0x04) == 0x04) + info->mode = ONLP_LED_MODE_ORANGE; + else + info->mode = ONLP_LED_MODE_OFF; + break; + case LED_REAR_FAN_TRAY_1: + mux_info.channel= 0x00; + dev_info.addr = FAN_TRAY_1; + dev_info.bus = I2C_BUS_3; + fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); + if(fantray_present >= 0) + { + if((r_data1 & 0x40) == 0x40) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data1 & 0x80) == 0x80) + info->mode = ONLP_LED_MODE_ORANGE; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + case LED_REAR_FAN_TRAY_2: + mux_info.channel= 0x01; + dev_info.addr = FAN_TRAY_2; + dev_info.bus = I2C_BUS_3; + fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); + if(fantray_present >= 0) + { + if((r_data1 & 0x10) == 0x10) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data1 & 0x20) == 0x20) + info->mode = ONLP_LED_MODE_ORANGE; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + case LED_REAR_FAN_TRAY_3: + mux_info.channel= 0x02; + dev_info.addr = FAN_TRAY_3; + dev_info.bus = I2C_BUS_3; + fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); + if(fantray_present >= 0) + { + if((r_data1 & 0x04) == 0x04) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data1 & 0x08) == 0x08) + info->mode = ONLP_LED_MODE_ORANGE; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + case LED_REAR_FAN_TRAY_4: + mux_info.channel= 0x03; + dev_info.addr = FAN_TRAY_4; + dev_info.bus = I2C_BUS_3; + fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); + if(fantray_present >= 0) + { + if((r_data1 & 0x01) == 0x01) + info->mode = ONLP_LED_MODE_GREEN; + else if((r_data1 & 0x02) == 0x02) + info->mode = ONLP_LED_MODE_ORANGE; + } + else + info->mode = ONLP_LED_MODE_OFF; + break; + + default: + break; + } + + /* Set the on/off status */ + if (info->mode == ONLP_LED_MODE_OFF) { + info->status |= ONLP_LED_STATUS_FAILED; + } else { + info->status |=ONLP_LED_STATUS_PRESENT; + } + + + 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 == 0) + onlp_ledi_mode_set(id, ONLP_LED_MODE_OFF); + else + onlp_ledi_mode_set(id,ONLP_LED_MODE_AUTO); + + return ONLP_STATUS_OK; +} + +/* + * 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) +{ + VALIDATE(id); + int local_id = ONLP_OID_ID_GET(id); + int i = 0, count = 0 ; + int fantray_present = -1 ,rpm = 0,rpm1 = 0; + uint8_t front_panel_led_value, fan_tray_led_value, power_state; + + + mux_info_t mux_info; + mux_info.bus = I2C_BUS_5; + mux_info.addr = SWPLD; + mux_info.offset = FAN_MUX_REG; + mux_info.channel = 0x07; + mux_info.flags = DEFAULT_FLAG; + + dev_info_t dev_info; + dev_info.bus = I2C_BUS_3; + dev_info.offset = 0x00; + dev_info.flags = DEFAULT_FLAG; + + + front_panel_led_value = dni_lock_cpld_read_attribute(SWPLD_PATH,LED_REG); + fan_tray_led_value = dni_lock_cpld_read_attribute(SWPLD_PATH,FAN_TRAY_LED_REG); + switch(local_id) + { + case LED_FRONT_FAN: + /* Clean the bit 1,0 */ + front_panel_led_value &= ~0x3; + /* Read fan eeprom to check present */ + for(i = 0;i < 4; i++) + { + mux_info.channel = i; + /* FAN TRAT 1~4: 0x52 , 0x53, 0x54, 0x55 */ + dev_info.addr = FAN_TRAY_1 + i; + fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); + if( fantray_present >= 0 ) + count++; + } + /* Set front light of FAN */ + if(count == ALL_FAN_TRAY_EXIST) + { + front_panel_led_value|=0x02; + dni_lock_cpld_write_attribute(SWPLD_PATH, LED_REG, front_panel_led_value); + } + else + { + front_panel_led_value|=0x01; + dni_lock_cpld_write_attribute(SWPLD_PATH, LED_REG, front_panel_led_value); + } + + break; + case LED_FRONT_PWR: + /* Clean bit 3,2 */ + front_panel_led_value &= ~0x0C; + /* switch CPLD to PSU 1 */ + dev_info.bus = I2C_BUS_4; + dev_info.addr = PSU_EEPROM; + mux_info.channel = 0x00; + + /* Check the state of PSU 1, "state = 1, PSU exists' */ + power_state = dni_lock_cpld_read_attribute(SWPLD_PATH, PSU_PWR_REG); + /* Set the light of PSU */ + if((power_state&0x80) != 0x80) + { + /* Red */ + front_panel_led_value|=0x04; + dni_lock_cpld_write_attribute(SWPLD_PATH, LED_REG, front_panel_led_value); + } + else if((power_state&0x80)==0x80) + { + /* Green */ + front_panel_led_value|=0x08; + dni_lock_cpld_write_attribute(SWPLD_PATH, LED_REG, front_panel_led_value); + } + else + dni_lock_cpld_write_attribute(SWPLD_PATH,LED_REG, front_panel_led_value); + break; + + case LED_REAR_FAN_TRAY_1: + mux_info.channel= 0x00; + dev_info.addr = FAN_TRAY_1; + dev_info.bus = I2C_BUS_3; + fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); + rpm = dni_i2c_lock_read_attribute(NULL, FAN4_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN4_REAR); + fan_tray_led_value &= ~0xC0; + if(fantray_present >= 0 && rpm != 960 && rpm != 0 && rpm1 != 960 && rpm1 != 0 ) + { + /* Green */ + fan_tray_led_value |=0x40; + dni_lock_cpld_write_attribute(SWPLD_PATH,FAN_TRAY_LED_REG,fan_tray_led_value); + } + else + { + /* Red */ + fan_tray_led_value |=0x80; + dni_lock_cpld_write_attribute(SWPLD_PATH,FAN_TRAY_LED_REG,fan_tray_led_value); + } + break; + case LED_REAR_FAN_TRAY_2: + mux_info.channel= 0x01; + dev_info.addr = FAN_TRAY_2; + dev_info.bus = I2C_BUS_3; + fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); + rpm = dni_i2c_lock_read_attribute(NULL, FAN3_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN3_REAR); + fan_tray_led_value &= ~0x30; + + if(fantray_present >= 0 && rpm != 960 && rpm != 0 && rpm1 != 960 && rpm1 != 0 ) + { + /* Green */ + fan_tray_led_value |=0x10; + dni_lock_cpld_write_attribute(SWPLD_PATH,FAN_TRAY_LED_REG,fan_tray_led_value); + } + else + { + /* Red */ + fan_tray_led_value |=0x20; + dni_lock_cpld_write_attribute(SWPLD_PATH,FAN_TRAY_LED_REG,fan_tray_led_value); + } + break; + case LED_REAR_FAN_TRAY_3: + mux_info.channel= 0x02; + dev_info.bus = I2C_BUS_3; + dev_info.addr = FAN_TRAY_3; + fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); + rpm = dni_i2c_lock_read_attribute(NULL, FAN2_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN2_REAR); + fan_tray_led_value &= ~0x0c; + if(fantray_present >= 0 && rpm != 960 && rpm != 0 && rpm1 != 960 && rpm1 != 0 ) + { + /* Green */ + fan_tray_led_value |=0x04; + dni_lock_cpld_write_attribute(SWPLD_PATH,FAN_TRAY_LED_REG,fan_tray_led_value); + } + else + { + /* Red */ + fan_tray_led_value |=0x08; + dni_lock_cpld_write_attribute(SWPLD_PATH,FAN_TRAY_LED_REG,fan_tray_led_value); + } + break; + case LED_REAR_FAN_TRAY_4: + mux_info.channel= 0x03; + dev_info.addr = FAN_TRAY_4; + dev_info.bus = I2C_BUS_3; + fantray_present = dni_i2c_lock_read(&mux_info, &dev_info); + rpm = dni_i2c_lock_read_attribute(NULL, FAN1_FRONT); + rpm1 = dni_i2c_lock_read_attribute(NULL, FAN1_REAR); + fan_tray_led_value &= ~0x03; + if(fantray_present >= 0 && rpm != 960 && rpm != 0 && rpm1 != 960 && rpm1 != 0 ) + { + /* Green */ + fan_tray_led_value |=0x01; + dni_lock_cpld_write_attribute(SWPLD_PATH,FAN_TRAY_LED_REG,fan_tray_led_value); + } + else + { + /* Red */ + fan_tray_led_value |=0x02; + dni_lock_cpld_write_attribute(SWPLD_PATH,FAN_TRAY_LED_REG,fan_tray_led_value); + } + break; + } + return ONLP_STATUS_OK; +} +/* + * Generic LED ioctl interface. + */ +int +onlp_ledi_ioctl(onlp_oid_t id, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + + + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/make.mk b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/make.mk new file mode 100644 index 00000000..b2c2ef01 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/make.mk @@ -0,0 +1,9 @@ +############################################################################### +# +# +# +############################################################################### + +LIBRARY := x86_64_delta_agc7648a +$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST))) +include $(BUILDER)/lib.mk diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/platform_lib.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/platform_lib.c new file mode 100644 index 00000000..6ce94b29 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/platform_lib.c @@ -0,0 +1,289 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta network Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "platform_lib.h" +#include +#include +#include + +int dni_i2c_read_attribute_binary(char *filename, char *buffer, int buf_size, int data_len) +{ + int fd; + int len; + + if ((buffer == NULL) || (buf_size < 0)) { + return -1; + } + + if ((fd = open(filename, O_RDONLY)) == -1) { + return -1; + } + + if ((len = read(fd, buffer, buf_size)) < 0) { + close(fd); + return -1; + } + + if ((close(fd) == -1)) { + return -1; + } + + if ((len > buf_size) || (data_len != 0 && len != data_len)) { + return -1; + } + + return 0; +} + +int dni_i2c_read_attribute_string(char *filename, char *buffer, int buf_size, int data_len) +{ + int ret; + + if (data_len >= buf_size) { + return -1; + } + + ret = dni_i2c_read_attribute_binary(filename, buffer, buf_size-1, data_len); + + if (ret == 0) { + buffer[buf_size-1] = '\0'; + } + + return ret; +} + +/* Lock function */ +int dni_i2c_lock_read( mux_info_t * mux_info, dev_info_t * dev_info) +{ + int r_data=0; + + pthread_mutex_lock(&mutex); + if(mux_info != NULL) + { + char cpld_path[100] = {0}; + sprintf(cpld_path, "%s/%d-%04x", SYS_DEV_PATH, mux_info->bus, mux_info->addr); + dni_lock_cpld_write_attribute(cpld_path, mux_info->offset, mux_info->channel); + } + + if(dev_info->size == 1) + r_data = onlp_i2c_readb(dev_info->bus, dev_info->addr, dev_info->offset, dev_info->flags); + else + r_data = onlp_i2c_readw(dev_info->bus, dev_info->addr, dev_info->offset, dev_info->flags); + pthread_mutex_unlock(&mutex); + + return r_data; +} + +int dni_i2c_lock_write( mux_info_t * mux_info, dev_info_t * dev_info) +{ + pthread_mutex_lock(&mutex); + if(mux_info != NULL) + { + char cpld_path[100] = {0}; + sprintf(cpld_path, "%s/%d-%04x", SYS_DEV_PATH, mux_info->bus, mux_info->addr); + dni_lock_cpld_write_attribute(cpld_path, mux_info->offset, mux_info->channel); + } + + /* Write size */ + if(dev_info->size == 1) + onlp_i2c_write(dev_info->bus, dev_info->addr, dev_info->offset, 1, &dev_info->data_8, dev_info->flags); + else + onlp_i2c_writew(dev_info->bus, dev_info->addr, dev_info->offset, dev_info->data_16, dev_info->flags); + pthread_mutex_unlock(&mutex); + + return 0; +} + +int dni_i2c_lock_read_attribute(mux_info_t * mux_info, char * fullpath) +{ + int fd, len, nbytes = 10; + char r_data[10] = {0}; + + pthread_mutex_lock(&mutex); + if(mux_info != NULL) + { + char cpld_path[100] = {0}; + sprintf(cpld_path, "%s/%d-%04x", SYS_DEV_PATH, mux_info->bus, mux_info->addr); + dni_lock_cpld_write_attribute(cpld_path, mux_info->offset, mux_info->channel); + } + + if ((fd = open(fullpath, O_RDONLY)) == -1) + { + goto ERR_HANDLE; + } + if ((len = read(fd, r_data, nbytes)) <= 0) + { + goto ERR_HANDLE; + } + close(fd); + pthread_mutex_unlock(&mutex); + + return atoi(r_data); + +ERR_HANDLE: + close(fd); + pthread_mutex_unlock(&mutex); + return -1; +} + +int dni_i2c_lock_write_attribute(mux_info_t * mux_info, char * data, char * fullpath) +{ + int fd, len, nbytes = 10; + + pthread_mutex_lock(&mutex); + if(mux_info != NULL) + { + char cpld_path[100] = {0}; + sprintf(cpld_path, "%s/%d-%04x", SYS_DEV_PATH, mux_info->bus, mux_info->addr); + dni_lock_cpld_write_attribute(cpld_path, mux_info->offset, mux_info->channel); + } + + /* Create output file descriptor */ + fd = open(fullpath, O_WRONLY, 0644); + if (fd == -1) + { + goto ERR_HANDLE; + } + + len = write (fd, data, nbytes); + if (len != nbytes) + { + goto ERR_HANDLE; + } + close(fd); + pthread_mutex_unlock(&mutex); + + return 0; + +ERR_HANDLE: + close(fd); + pthread_mutex_unlock(&mutex); + return -1; +} + +/* Use this function to select MUX and read data on CPLD */ +int dni_lock_cpld_read_attribute(char *cpld_path, int addr) +{ + int fd, len, nbytes = 10,data = 0; + char r_data[10] = {0}; + char address[10] = {0}; + char cpld_data_path[100] = {0}; + char cpld_addr_path[100] = {0}; + + sprintf(cpld_data_path, "%s/data", cpld_path); + sprintf(cpld_addr_path, "%s/addr", cpld_path); + sprintf(address, "%02x", addr); + + pthread_mutex_lock(&mutex1); + /* Create output file descriptor */ + fd = open(cpld_addr_path, O_WRONLY, 0644); + if (fd == -1) + { + goto ERR_HANDLE; + } + + len = write (fd, address, 2); + if (len <= 0) + { + goto ERR_HANDLE; + } + close(fd); + + if ((fd = open(cpld_data_path, O_RDONLY)) == -1) + { + goto ERR_HANDLE; + } + + if ((len = read(fd, r_data, nbytes)) <= 0) + { + goto ERR_HANDLE; + } + close(fd); + pthread_mutex_unlock(&mutex1); + + sscanf(r_data, "%x", &data); + return data; + +ERR_HANDLE: + close(fd); + pthread_mutex_unlock(&mutex1); + return -1; +} + +/* Use this function to select MUX and write data on CPLD */ +int dni_lock_cpld_write_attribute(char *cpld_path, int addr, int data) +{ + int fd, len; + char address[10] = {0}; + char cpld_data_path[100] = {0}; + char cpld_addr_path[100] = {0}; + + sprintf(cpld_data_path, "%s/data", cpld_path); + sprintf(cpld_addr_path, "%s/addr", cpld_path); + sprintf(address, "%02x", addr); + + pthread_mutex_lock(&mutex1); + /* Create output file descriptor */ + fd = open(cpld_addr_path, O_WRONLY, 0644); + if (fd == -1) + { + goto ERR_HANDLE; + } + len = write(fd, address, 2); + if(len <= 0) + { + goto ERR_HANDLE; + } + close(fd); + + fd = open(cpld_data_path, O_WRONLY, 0644); + if (fd == -1) + { + goto ERR_HANDLE; + } + sprintf(address, "%02x", data); + len = write (fd, address, 2); + if(len <= 0) + { + goto ERR_HANDLE; + } + close(fd); + pthread_mutex_unlock(&mutex1); + + return 0; + +ERR_HANDLE: + close(fd); + pthread_mutex_unlock(&mutex1); + return -1; +} diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/platform_lib.h b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/platform_lib.h new file mode 100755 index 00000000..706147ad --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/platform_lib.h @@ -0,0 +1,229 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta network Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#ifndef __PLATFORM_LIB_H__ +#define __PLATFORM_LIB_H__ + +#include "x86_64_delta_agc7648a_log.h" + +#define CHASSIS_FAN_COUNT 8 +#define CHASSIS_THERMAL_COUNT 8 + +#define PSU1_ID 1 +#define PSU2_ID 2 + +#define SYS_DEV_PATH "/sys/bus/i2c/devices" +#define CPU_CPLD_PATH SYS_DEV_PATH "/2-0031" +#define SWPLD_PATH SYS_DEV_PATH "/5-0030" +#define SWPLD1_PATH SYS_DEV_PATH "/5-0031" +#define SWPLD2_PATH SYS_DEV_PATH "/5-0032" +#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/4-0058/" +#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/4-0058/" + +#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_HWMON_PREFIX "/sys/bus/i2c/devices/35-0038/" +#define PSU2_AC_HWMON_PREFIX "/sys/bus/i2c/devices/36-003b/" + +#define PSU1_AC_HWMON_NODE(node) PSU1_AC_HWMON_PREFIX#node +#define PSU2_AC_HWMON_NODE(node) PSU2_AC_HWMON_PREFIX#node + + +#define FAN1_FRONT "/sys/bus/i2c/devices/3-002c/fan1_input" +#define FAN1_REAR "/sys/bus/i2c/devices/3-002d/fan1_input" +#define FAN2_FRONT "/sys/bus/i2c/devices/3-002c/fan2_input" +#define FAN2_REAR "/sys/bus/i2c/devices/3-002d/fan2_input" +#define FAN3_FRONT "/sys/bus/i2c/devices/3-002c/fan3_input" +#define FAN3_REAR "/sys/bus/i2c/devices/3-002d/fan3_input" +#define FAN4_FRONT "/sys/bus/i2c/devices/3-002c/fan4_input" +#define FAN4_REAR "/sys/bus/i2c/devices/3-002d/fan4_input" + +#define SFP_SELECT_PORT_PATH "/sys/bus/i2c/devices/8-0050/sfp_select_port" +#define SFP_IS_PRESENT_PATH "/sys/bus/i2c/devices/8-0050/sfp_is_present" +#define SFP_IS_PRESENT_ALL_PATH "/sys/bus/i2c/devices/8-0050/sfp_is_present_all" +#define SFP_EEPROM_PATH "/sys/bus/i2c/devices/8-0050/sfp_eeprom" +#define SFP_RESET_PATH "/sys/bus/i2c/devices/8-0050/sfp_reset" +#define SFP_LP_MODE_PATH "/sys/bus/i2c/devices/8-0050/sfp_lp_mode" + +#define PSU_SEL_PATH "/sys/bus/i2c/devices/4-0058/psu_select_member" + +#define IDPROM_PATH "/sys/devices/pci0000:00/0000:00:13.0/i2c-1/i2c-2/2-0053/eeprom" + +/* I2C bus */ +#define I2C_BUS_0 (0) +#define I2C_BUS_1 (1) +#define I2C_BUS_2 (2) +#define I2C_BUS_3 (3) +#define I2C_BUS_4 (4) +#define I2C_BUS_5 (5) +#define I2C_BUS_6 (6) +#define I2C_BUS_7 (7) +#define I2C_BUS_8 (8) + +/* Device address */ +#define SWPLD (0x30) +#define SWPLD1 (0x31) +#define SWPLD2 (0x32) +#define SWPLD2 (0x32) +#define FAN_IO_CTRL (0x27) +#define PSU_EEPROM (0x50) +#define EMC2305_FRONT_FAN (0x2C) +#define EMC2305_REAR_FAN (0x2D) +#define FAN_TRAY_LED_REG (0x65) +#define FAN_TRAY_1 (0x52) +#define FAN_TRAY_2 (0x53) +#define FAN_TRAY_3 (0x54) +#define FAN_TRAY_4 (0x55) +#define PORT_ADDR (0x50) + +/* CPU CPLD Register */ +#define SWPLD_VERSION_ADDR (0x01) + +/* SWPLD(U21) Register */ +#define QSFP_RESPOND_REG (0x64) +#define FAN_MUX_REG (0x67) +#define PSU_PRESENT_REG (0x0D) +#define PSU_PWR_REG (0x0B) +#define LED_REG (0x1C) + + +/* Not Yet classified */ +#define PSU1_MUX_MASK (0x00) +#define PSU2_MUX_MASK (0x02) +#define CLOSE_RESPOND (0xFF) +#define PSU_FAN1 (0x00) +#define PSU_FAN2 (0x20) +#define FAN_DATA_HALF_SPEED (0x0032) +#define FAN_DATA_FULL_SPEED (0x0064) +#define FAN_DATA_STOP_D10_D3 (0xFF) +#define FAN_DATA_STOP_D2_D0 (0xE0) +#define TURN_OFF (0) +#define TURN_ON (1) + +#define MAX_REAR_FAN_SPEED 20500 +#define MAX_FRONT_FAN_SPEED 23000 +#define MAX_PSU_FAN_SPEED 19000 + +#define NUM_OF_THERMAL 8 +#define NUM_OF_FAN_ON_MAIN_BROAD 8 +#define NUM_OF_PSU_ON_MAIN_BROAD 2 +#define NUM_OF_LED_ON_MAIN_BROAD 7 +#define NUM_OF_CPLD 4 + +#define DEFAULT_FLAG (0x00) + +#define NUM_OF_SFP 48 +#define NUM_OF_QSFP 6 +#define NUM_OF_PORT NUM_OF_SFP + NUM_OF_QSFP + +int dni_i2c_read_attribute_binary(char *filename, char *buffer, int buf_size, int data_len); +int dni_i2c_read_attribute_string(char *filename, char *buffer, int buf_size, int data_len); + +typedef struct dev_info_s +{ + int bus; + int size; + uint8_t addr; + uint8_t data_8; + uint16_t data_16; + uint8_t offset; + uint32_t flags; + +}dev_info_t; + +typedef struct mux_info_s +{ + int bus; + uint8_t addr; + uint8_t offset; + uint8_t channel; + char data[10]; + char path[80]; + uint32_t flags; +}mux_info_t; + +pthread_mutex_t mutex; +pthread_mutex_t mutex1; +int dni_i2c_lock_read(mux_info_t * mux_info, dev_info_t * dev_info); +int dni_i2c_lock_write(mux_info_t * mux_info, dev_info_t * dev_info); +int dni_i2c_lock_read_attribute(mux_info_t * mux_info, char * fullpath); +int dni_i2c_lock_write_attribute(mux_info_t * mux_info, char *data, char * fullpath); +int dni_lock_cpld_read_attribute(char *cpld_path, int addr); +int dni_lock_cpld_write_attribute(char *cpld_path, int addr, int data); +int dni_psu_present_get(int index); + +#define DEBUG_MODE 0 + +#if (DEBUG_MODE == 1) + #define DEBUG_PRINT(format, ...) printf(format, __VA_ARGS__) +#else + #define DEBUG_PRINT(format, ...) +#endif + +typedef enum +{ + THERMAL_RESERVED = 0, + THERMAL_CPU_CORE, + THERMAL_1_ON_CPU_BROAD, + THERMAL_2_ON_FAN_BROAD, + THERMAL_3_ON_MAIN_BROAD, + THERMAL_4_ON_MAIN_BROAD, + THERMAL_5_ON_MAIN_BROAD, + THERMAL_6_ON_MAIN_BROAD, + THERMAL_7_ON_MAIN_BROAD, + THERMAL_1_ON_PSU1, + THERMAL_1_ON_PSU2, +} onlp_thermal_id; + +typedef enum +{ + FAN_RESERVED = 0, + FAN_1_ON_MAIN_BOARD, + FAN_2_ON_MAIN_BOARD, + FAN_3_ON_MAIN_BOARD, + FAN_4_ON_MAIN_BOARD, + FAN_5_ON_MAIN_BOARD, + FAN_6_ON_MAIN_BOARD, + FAN_7_ON_MAIN_BOARD, + FAN_8_ON_MAIN_BOARD, + FAN_1_ON_PSU1, + FAN_1_ON_PSU2 +} onlp_fan_id; + +typedef enum +{ + LED_RESERVED = 0, + LED_FRONT_FAN, + LED_FRONT_SYS, + LED_FRONT_PWR, + LED_REAR_FAN_TRAY_1, + LED_REAR_FAN_TRAY_2, + LED_REAR_FAN_TRAY_3, + LED_REAR_FAN_TRAY_4 +}onlp_led_id; + +#endif /* __PLATFORM_LIB_H__ */ + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/psui.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/psui.c new file mode 100755 index 00000000..5a3a8b1f --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/psui.c @@ -0,0 +1,231 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta network Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include +#include +#include +#include "platform_lib.h" +#include + +#define PSU_STATUS_PRESENT 1 +#define PSU_STATUS_POWER_GOOD 1 + +#define PSU_NODE_MAX_INT_LEN 8 +#define PSU_NODE_MAX_PATH_LEN 64 + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_PSU(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static int +dni_psu_pmbus_info_get(int id, char *node, int *value) +{ + int ret = 0; + char buf[PSU_NODE_MAX_INT_LEN + 1] = {0}; + char node_path[PSU_NODE_MAX_PATH_LEN] = {0}; + + *value = 0; + + if (PSU1_ID == id) { + sprintf(node_path, "%s%s", PSU1_AC_PMBUS_PREFIX, node); + } + else { + sprintf(node_path, "%s%s", PSU2_AC_PMBUS_PREFIX, node); + } + + ret = dni_i2c_read_attribute_string(node_path, buf, sizeof(buf), 0); + + if (ret == 0) { + *value = atoi(buf); + } + + return ret; +} + +int +onlp_psui_init(void) +{ + return ONLP_STATUS_OK; +} + +int +dni_psu_present_get(int index) +{ + int state = 0; + uint8_t present_val; + + present_val = dni_lock_cpld_read_attribute(SWPLD_PATH, PSU_PRESENT_REG); + + if(index == 1) { + if((present_val & 0x01) == 0x00) { + state = 1; + } else { + state = 0; + } + } else { + if((present_val & 0x02) == 0x00) { + state = 1; + } else { + state = 0; + } + } + return state; +} + +static int +dni_psu_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 + CHASSIS_THERMAL_COUNT); + + + char val_char[16] = { '\0' }; + char node_path[PSU_NODE_MAX_PATH_LEN] = { '\0' }; + sprintf(node_path, "%s%s", PSU1_AC_PMBUS_PREFIX, "psu_mfr_model"); + dni_i2c_read_attribute_string(node_path, val_char, sizeof(val_char), 0); + strcpy(info->model, val_char); + + sprintf(node_path, "%s%s", PSU1_AC_PMBUS_PREFIX, "psu_mfr_serial"); + dni_i2c_read_attribute_string(node_path, val_char, sizeof(val_char), 0); + strcpy(info->serial, val_char); + + /* Read voltage, current and power */ + if (dni_psu_pmbus_info_get(index, "psu_v_out", &val) == 0) { + info->mvout = val; + info->caps |= ONLP_PSU_CAPS_VOUT; + } + + if (dni_psu_pmbus_info_get(index, "psu_v_in", &val) == 0) { + info->mvin = val; + info->caps |= ONLP_PSU_CAPS_VIN; + } + + if (dni_psu_pmbus_info_get(index, "psu_i_out", &val) == 0) { + info->miout = val; + info->caps |= ONLP_PSU_CAPS_IOUT; + } + + if (dni_psu_pmbus_info_get(index, "psu_i_in", &val) == 0) { + info->miin = val; + info->caps |= ONLP_PSU_CAPS_IIN; + } + + if (dni_psu_pmbus_info_get(index, "psu_p_out", &val) == 0) { + info->mpout = val; + info->caps |= ONLP_PSU_CAPS_POUT; + } + + if (dni_psu_pmbus_info_get(index, "psu_p_in", &val) == 0) { + info->mpin = val; + info->caps |= ONLP_PSU_CAPS_PIN; + } + + 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, ret; + int index = ONLP_OID_ID_GET(id); + uint8_t power_good_val; + + *info = pinfo[index]; /* Set the onlp_oid_hdr_t */ + + if(dni_psu_present_get(index) != 1) { + /* PSU(%d) present fail */ + info->status |= ~ONLP_PSU_STATUS_PRESENT; + return ONLP_STATUS_OK; + } else { + info->status |= ONLP_PSU_STATUS_PRESENT; + } + + /* Get power good status */ + power_good_val = dni_lock_cpld_read_attribute(SWPLD_PATH, PSU_PWR_REG); + if(index == 1){ + if((power_good_val & 0x80) == 0x80) { + val = PSU_STATUS_POWER_GOOD; + } else { + val = 0; + } + } else if(index == 2) { + if((power_good_val & 0x40) == 0x40) { + val = PSU_STATUS_POWER_GOOD; + } else { + val = 0; + } + } + if(val != PSU_STATUS_POWER_GOOD) { + /* Unable to read PSU(%d) node(psu_power_good) */ + info->status |= ONLP_PSU_STATUS_UNPLUGGED; + } + + /* select PSU(%d) module */ + char index_data[2]; + sprintf(index_data, "%d", index); + dni_i2c_lock_write_attribute(NULL, index_data, PSU_SEL_PATH); + + ret = dni_psu_info_get(info); + + return ret; +} + +int +onlp_psui_ioctl(onlp_oid_t pid, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/sfpi.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/sfpi.c new file mode 100644 index 00000000..e809b506 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/sfpi.c @@ -0,0 +1,475 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta network 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 /* For O_RDWR && open */ +#include +#include +#include +#include +#include +#include + +#include "platform_lib.h" + +/******************* Utility Function *****************************************/ +int +delta_agc7648a_get_respond_reg(int port) +{ + if(port >= NUM_OF_SFP && port < (NUM_OF_SFP + NUM_OF_QSFP)){ + return QSFP_RESPOND_REG; + } + else{ + return -1; + } +} + +int +delta_agc7648a_get_respond_val(int port) +{ + if(port >= NUM_OF_SFP && port < (NUM_OF_SFP + NUM_OF_QSFP)){ + return (port%8); + } + else{ + return -1; + } +} +/******************************************************************************/ + + +/************************************************************ + * + * SFPI Entry Points + * + ***********************************************************/ +int +onlp_sfpi_init(void) +{ + /* Called at initialization time */ + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap) +{ + int p; + AIM_BITMAP_CLR_ALL(bmap); + + for(p = 0; p < NUM_OF_PORT; p++) { + AIM_BITMAP_SET(bmap, p); + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_is_present(int port) +{ + char port_data[2]; + int present_val, present; + + /* Select port */ + sprintf(port_data, "%d", port + 1); + dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); + + /* Read sfp_is_present attribute of sfp module is presented or not */ + present_val = dni_i2c_lock_read_attribute(NULL, SFP_IS_PRESENT_PATH); + + /* From sfp_is_present value, + * return 0 = The module is preset + * return 1 = The module is NOT present + */ + if(present_val == 0) { + present = 1; + } else if (present_val == 1) { + present = 0; + AIM_LOG_ERROR("Unble to present status from port(%d)\r\n", port); + } else { + AIM_LOG_ERROR("Error to present status from port(%d)\r\n", port); + present = -1; + } + + return present; +} + +int +onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + char present_all_data[21] = {0}; + uint32_t bytes[7]; + + /* Read presence bitmap from SWPLD QSFP28 Presence Register + * if only port 0 is present, return 7F FF FF FF + * if only port 0 and 1 present, return 3F FF FF FF + */ + if(dni_i2c_read_attribute_string(SFP_IS_PRESENT_ALL_PATH, present_all_data, + sizeof(present_all_data), 0) < 0) { + return -1; + } + + + int count = sscanf(present_all_data, "%x %x %x %x %x %x %x", + bytes+0, + bytes+1, + bytes+2, + bytes+3, + bytes+4, + bytes+5, + bytes+6 + ); + + if(count != AIM_ARRAYSIZE(bytes)) { + /* Likely a CPLD read timeout. */ + AIM_LOG_ERROR("Unable to read all fields from the sfp_is_present_all device file."); + return ONLP_STATUS_E_INTERNAL; + } + + /* Mask out non-existant QSFP ports */ + bytes[6] &= 0x3F; + + /* Convert to 64 bit integer in port order */ + int i = 0; + uint64_t presence_all = 0 ; + for(i = AIM_ARRAYSIZE(bytes)-1; i >= 0; i--) { + presence_all <<= 8; + presence_all |= bytes[i]; + } + + /* Populate bitmap */ + for(i = 0; i < NUM_OF_PORT; i++) { + AIM_BITMAP_MOD(dst, i, !(presence_all & 1)); + presence_all >>= 1; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_eeprom_read(int port, uint8_t data[256]) +{ + char port_data[2]; + int sfp_respond_reg, sfp_respond_val; + + /* Get respond register if port have it */ + sfp_respond_reg = delta_agc7648a_get_respond_reg(port); + if(sfp_respond_reg >= 0) + { + /* Set respond val */ + sfp_respond_val = delta_agc7648a_get_respond_val(port); + dni_lock_cpld_write_attribute(SWPLD_PATH, sfp_respond_reg, sfp_respond_val); + } + + /* Select port */ + sprintf(port_data, "%d", port + 1); + dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); + + /* Read eeprom information into data[] */ + if (dni_i2c_read_attribute_binary(SFP_EEPROM_PATH, (char *)data, 256, 256) + != 0) + { + AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port); + return ONLP_STATUS_E_INTERNAL; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr) +{ + char port_data[2]; + int sfp_respond_reg, sfp_respond_val; + dev_info_t dev_info; + + /* Get respond register if port have it */ + sfp_respond_reg = delta_agc7648a_get_respond_reg(port); + if(sfp_respond_reg >= 0) + { + /* Set respond val */ + sfp_respond_val = delta_agc7648a_get_respond_val(port); + dni_lock_cpld_write_attribute(SWPLD_PATH, sfp_respond_reg, sfp_respond_val); + } + + /* Select port */ + sprintf(port_data, "%d", port + 1); + dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); + + dev_info.bus = I2C_BUS_8; + dev_info.addr = PORT_ADDR; + dev_info.offset = addr; + dev_info.flags = ONLP_I2C_F_FORCE; + dev_info.size = 1; /* Read 1 byte */ + + return dni_i2c_lock_read(NULL, &dev_info); +} + +int +onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value) +{ + char port_data[2]; + int sfp_respond_reg, sfp_respond_val; + dev_info_t dev_info; + + /* Get respond register if port have it */ + sfp_respond_reg = delta_agc7648a_get_respond_reg(port); + if(sfp_respond_reg >= 0) + { + /* Set respond val */ + sfp_respond_val = delta_agc7648a_get_respond_val(port); + dni_lock_cpld_write_attribute(SWPLD_PATH, sfp_respond_reg, sfp_respond_val); + } + + /* Select port */ + sprintf(port_data, "%d", port + 1); + dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); + + dev_info.bus = I2C_BUS_8; + dev_info.addr = PORT_ADDR; + dev_info.offset = addr; + dev_info.flags = ONLP_I2C_F_FORCE; + dev_info.size = 1; /* Write 1 byte */ + dev_info.data_8 = value; + + return dni_i2c_lock_write(NULL, &dev_info); +} + +int +onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr) +{ + char port_data[2]; + int sfp_respond_reg, sfp_respond_val; + dev_info_t dev_info; + + /* Get respond register if port have it */ + sfp_respond_reg = delta_agc7648a_get_respond_reg(port); + if(sfp_respond_reg >= 0) + { + /* Set respond val */ + sfp_respond_val = delta_agc7648a_get_respond_val(port); + dni_lock_cpld_write_attribute(SWPLD_PATH, sfp_respond_reg, sfp_respond_val); + } + + /* Select port */ + sprintf(port_data, "%d", port + 1); + dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); + + dev_info.bus = I2C_BUS_8; + dev_info.addr = PORT_ADDR; + dev_info.offset = addr; + dev_info.flags = ONLP_I2C_F_FORCE; + dev_info.size = 2; /* Read 1 byte */ + + return dni_i2c_lock_read(NULL, &dev_info); +} + +int +onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value) +{ + char port_data[2]; + int sfp_respond_reg, sfp_respond_val; + dev_info_t dev_info; + + /* Get respond register if port have it */ + sfp_respond_reg = delta_agc7648a_get_respond_reg(port); + if(sfp_respond_reg >= 0) + { + /* Set respond val */ + sfp_respond_val = delta_agc7648a_get_respond_val(port); + dni_lock_cpld_write_attribute(SWPLD_PATH, sfp_respond_reg, sfp_respond_val); + } + + /* Select port */ + sprintf(port_data, "%d", port + 1); + dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); + + dev_info.bus = I2C_BUS_8; + dev_info.addr = PORT_ADDR; + dev_info.offset = addr; + dev_info.flags = ONLP_I2C_F_FORCE; + dev_info.size = 2; /* Write 2 byte */ + dev_info.data_16 = value; + + return dni_i2c_lock_write(NULL, &dev_info); +} + +int +onlp_sfpi_control_supported(int port, onlp_sfp_control_t control, int* rv) +{ + char port_data[2]; + + /* Select QSFP port */ + sprintf(port_data, "%d", port + 1); + dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); + + switch (control) { + case ONLP_SFP_CONTROL_RESET_STATE: + if(port >= NUM_OF_SFP && port < (NUM_OF_SFP + NUM_OF_QSFP)){ + *rv = 1; + } + else{ + *rv = 0; + } + break; + case ONLP_SFP_CONTROL_RX_LOS: + *rv = 0; + break; + case ONLP_SFP_CONTROL_TX_DISABLE: + *rv = 0; + break; + case ONLP_SFP_CONTROL_LP_MODE: + if(port >= NUM_OF_SFP && port < (NUM_OF_SFP + NUM_OF_QSFP)){ + *rv = 1; + } + else{ + *rv = 0; + } + break; + default: + break; + } + + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value) +{ + uint8_t value_t; + char port_data[2]; + + /* Select QSFP port */ + sprintf(port_data, "%d", port + 1); + dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); + + switch (control) { + case ONLP_SFP_CONTROL_RESET_STATE: + sprintf(port_data, "%d", value); + dni_i2c_lock_write_attribute(NULL, port_data, SFP_RESET_PATH); + value_t = ONLP_STATUS_OK; + break; + case ONLP_SFP_CONTROL_RX_LOS: + value_t = ONLP_STATUS_E_UNSUPPORTED; + break; + case ONLP_SFP_CONTROL_TX_DISABLE: + value_t = ONLP_STATUS_E_UNSUPPORTED; + break; + case ONLP_SFP_CONTROL_LP_MODE: + sprintf(port_data, "%d", value); + dni_i2c_lock_write_attribute(NULL, port_data, SFP_LP_MODE_PATH); + value_t = ONLP_STATUS_OK; + break; + default: + value_t = ONLP_STATUS_E_UNSUPPORTED; + break; + } + + return value_t; +} + +int +onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value) +{ + uint8_t value_t; + char port_data[2]; + + /* Select QSFP port */ + sprintf(port_data, "%d", port + 1); + dni_i2c_lock_write_attribute(NULL, port_data, SFP_SELECT_PORT_PATH); + + switch (control) { + case ONLP_SFP_CONTROL_RESET_STATE: + *value = dni_i2c_lock_read_attribute(NULL, SFP_RESET_PATH); + /* From sfp_reset value, + * return 0 = The module is in Reset + * return 1 = The module is NOT in Reset + */ + if (*value == 0){ + *value = 1; + } + else if(*value == 1){ + *value = 0; + } + value_t = ONLP_STATUS_OK; + break; + case ONLP_SFP_CONTROL_RX_LOS: + *value = 0; + value_t = ONLP_STATUS_E_UNSUPPORTED; + break; + case ONLP_SFP_CONTROL_TX_DISABLE: + *value = 0; + value_t = ONLP_STATUS_E_UNSUPPORTED; + break; + case ONLP_SFP_CONTROL_LP_MODE: + /* From sfp_lp_mode value, + * return 0 = The module is NOT in LP mode + * return 1 = The moduel is in LP mode + */ + *value = dni_i2c_lock_read_attribute(NULL, SFP_LP_MODE_PATH); + value_t = ONLP_STATUS_OK; + break; + default: + value_t = ONLP_STATUS_E_UNSUPPORTED; + break; + } + + return value_t; +} + +int +onlp_sfpi_denit(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_dom_read(int port, uint8_t data[256]) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +int +onlp_sfpi_post_insert(int port, sff_info_t* info) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} + +void +onlp_sfpi_debug(int port, aim_pvs_t* pvs) +{ + +} + +int +onlp_sfpi_ioctl(int port, va_list vargs) +{ + return ONLP_STATUS_E_UNSUPPORTED; +} diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/sysi.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/sysi.c new file mode 100755 index 00000000..2b23f336 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/sysi.c @@ -0,0 +1,292 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta network Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * + * + ***********************************************************/ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "x86_64_delta_agc7648a_int.h" +#include "x86_64_delta_agc7648a_log.h" + +#include "platform_lib.h" + +typedef struct cpld_dev_s{ + char name[32]; + char path[64]; +}cpld_dev_t; + +static cpld_dev_t cpld_dev[NUM_OF_CPLD] = +{ + {"CPUCPLD" , CPU_CPLD_PATH}, + {"SWPLD(U21)" , SWPLD_PATH }, + {"SWPLD(U134)", SWPLD1_PATH }, + {"SWPLD(U215)", SWPLD2_PATH } +}; + +/******************* Utility Function *****************************************/ +int +decide_percentage(int *percentage, int temper) +{ + int level; + + if(temper <= 25) + { + *percentage = 40; + level = 0; + } + else if(temper > 25 && temper <= 40) + { + *percentage = 60; + level = 1; + } + else if(temper > 40 && temper <= 55) + { + *percentage = 80; + level = 2; + } + else if(temper > 55 && temper <= 75) + { + *percentage = 90; + level = 3; + } + else if(temper > 75) + { + *percentage = 100; + level = 4; + } + else + { + *percentage = 100; + level = 5; + } + + return level; +} +/******************************************************************************/ +const char* +onlp_sysi_platform_get(void) +{ + return "x86-64-delta-agc7648a-r0"; +} + +int +onlp_sysi_init(void) +{ + return ONLP_STATUS_OK; +} + +int +onlp_sysi_onie_info_get(onlp_onie_info_t* onie) +{ + onie->platform_name = aim_strdup("x86-64-delta_agc7648a-r0"); + return ONLP_STATUS_OK; +} + +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_UNSUPPORTED; +} + +int +onlp_sysi_platform_info_get(onlp_platform_info_t* pi) +{ + char fullpath[128], buf[128], cpld_ver[256] = {0}; + int i, v[NUM_OF_CPLD] = {0}; + + for(i = 0; i < NUM_OF_CPLD; ++i) + { + sprintf(fullpath, "%s/version", cpld_dev[i].path); + v[i] = dni_i2c_lock_read_attribute(NULL, fullpath); + sprintf(buf, "%s=%d ", cpld_dev[i].name, v[i]); + strcat(cpld_ver, buf); + } + + pi->cpld_versions = aim_fstrdup("%s", cpld_ver); + + return ONLP_STATUS_OK; +} + +void +onlp_sysi_platform_info_free(onlp_platform_info_t* pi) +{ + aim_free(pi->cpld_versions); +} + + +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)); + + for (i = 1; i <= NUM_OF_THERMAL; i++) + { + *e++ = ONLP_THERMAL_ID_CREATE(i); + } + + /* 4 LEDs on the chassis */ + for (i = 1; i <= NUM_OF_LED_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_LED_ID_CREATE(i); + } + + /* 4 Fans on the chassis */ + for (i = 1; i <= NUM_OF_FAN_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_FAN_ID_CREATE(i); + } + + /* 2 PSUs on the chassis */ + for (i = 1; i <= NUM_OF_PSU_ON_MAIN_BROAD; i++) + { + *e++ = ONLP_PSU_ID_CREATE(i); + } + + return 0; +} + +int +onlp_sysi_platform_manage_fans(void) +{ + int i, new_percentage, highest_temp = 0; + onlp_thermal_info_t thermal; + + /* Get all thermal current temperature and decide fan percentage */ + for(i = 1; i <= NUM_OF_THERMAL; ++i) + { + if(onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(i), &thermal) != ONLP_STATUS_OK) + { + AIM_LOG_ERROR("Unable to read thermal status"); + return ONLP_STATUS_E_INTERNAL; + } + + thermal.mcelsius /= 1000; + if(thermal.mcelsius > highest_temp) + { + highest_temp = thermal.mcelsius; + } + + decide_percentage(&new_percentage, highest_temp); + } + + /* Set fantray RPM and PSU fan percentage */ + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_1_ON_MAIN_BOARD), MAX_FRONT_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_2_ON_MAIN_BOARD), MAX_FRONT_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_3_ON_MAIN_BOARD), MAX_FRONT_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_4_ON_MAIN_BOARD), MAX_FRONT_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_5_ON_MAIN_BOARD), MAX_REAR_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_6_ON_MAIN_BOARD), MAX_REAR_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_7_ON_MAIN_BOARD), MAX_REAR_FAN_SPEED * new_percentage / 100); + onlp_fani_rpm_set(ONLP_FAN_ID_CREATE(FAN_8_ON_MAIN_BOARD), MAX_REAR_FAN_SPEED * new_percentage / 100); + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(FAN_1_ON_PSU1), new_percentage); + onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(FAN_1_ON_PSU2), new_percentage); + + return ONLP_STATUS_OK; +} + +int +onlp_sysi_platform_manage_leds(void) +{ + + uint8_t present_bit = 0 ,addr = 0; + + /* set PWR led in front panel */ + addr = dni_lock_cpld_read_attribute(SWPLD_PATH,LED_REG); + + /* Turn the fan led on or off */ + if((addr & 0x3) == 0 || (addr & 0x3) == 0x3 ) + { + onlp_ledi_set(ONLP_LED_ID_CREATE(LED_FRONT_FAN), TURN_OFF); + } + else + { + onlp_ledi_set(ONLP_LED_ID_CREATE(LED_FRONT_FAN), TURN_ON); + } + + if(dni_psu_present_get(1) == 1) + { /* PSU1 is present */ + onlp_ledi_set(ONLP_LED_ID_CREATE(LED_FRONT_PWR), TURN_ON); + } + else + { + onlp_ledi_set(ONLP_LED_ID_CREATE(LED_FRONT_PWR), TURN_OFF); + } + /* Rare light fan tray 1-4 */ + present_bit = dni_lock_cpld_read_attribute(SWPLD_PATH,FAN_TRAY_LED_REG); + + if ((present_bit& 0x08) == 0x00) + { + onlp_ledi_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_1), TURN_ON); + } + else + { + onlp_ledi_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_1), TURN_OFF); + } + if ((present_bit& 0x04) == 0x00) + { + onlp_ledi_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_2), TURN_ON); + } + else + { + onlp_ledi_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_2), TURN_OFF); + } + if ((present_bit& 0x02) == 0x00) + { + onlp_ledi_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_3), TURN_ON); + } + else + { + onlp_ledi_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_3), TURN_OFF); + } + if ((present_bit& 0x01) == 0x00) + { + onlp_ledi_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_4), TURN_ON); + } + else + { + onlp_ledi_set(ONLP_LED_ID_CREATE(LED_REAR_FAN_TRAY_4), TURN_OFF); + } + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/thermali.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/thermali.c new file mode 100644 index 00000000..a068c029 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/thermali.c @@ -0,0 +1,181 @@ +/************************************************************ + * + * + * Copyright 2014 Big Switch Networks, Inc. + * Copyright (C) 2017 Delta network Technology Corporation. + * + * Licensed under the Eclipse Public License, Version 1.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + * + * + ************************************************************ + * + * Thermal Sensor Platform Implementation. + * + ***********************************************************/ +#include +#include +#include +#include +#include +#include "platform_lib.h" +#include + +#define VALIDATE(_id) \ + do { \ + if(!ONLP_OID_IS_THERMAL(_id)) { \ + return ONLP_STATUS_E_INVALID; \ + } \ + } while(0) + +static char* last_path[] = /* must map with onlp_thermal_id */ +{ + "reserved", + NULL, /* CPU Core */ + "2-004d/hwmon/hwmon3/temp1_input", + "3-004f/hwmon/hwmon4/temp1_input", + "6-004c/hwmon/hwmon6/temp1_input", + "6-004c/hwmon/hwmon6/temp2_input", + "6-004e/hwmon/hwmon5/temp1_input", + "6-004f/hwmon/hwmon7/temp1_input", + "7-004c/hwmon/hwmon8/temp1_input", + "4-0058/psu_temp1_input", + "4-0058/psu_temp1_input", +}; + +static char* cpu_coretemp_files[] = +{ + "/sys/devices/platform/coretemp.0/hwmon/hwmon0/temp2_input", + "/sys/devices/platform/coretemp.0/hwmon/hwmon0/temp3_input", + "/sys/devices/platform/coretemp.0/hwmon/hwmon0/temp4_input", + "/sys/devices/platform/coretemp.0/hwmon/hwmon0/temp5_input", + NULL, +}; + +/* Static values */ +static onlp_thermal_info_t linfo[] = { + { }, /* Not used */ + { { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE), "CPU Core", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_CPU_BROAD), "CPU below side thermal sensor (U57, Below of CPU)", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_FAN_BROAD), "FAN board thermal sensor (U334)", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "MAC up side thermal sensor, local (U3, up side of MAC)", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_4_ON_MAIN_BROAD), "MAC up side thermal sensor, remote (U3, up side of MAC)", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_5_ON_MAIN_BROAD), "MAC down side thermal sensor (U24, down side of MAC)", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_6_ON_MAIN_BROAD), "MAC up side thermal sensor (U25, up side of MAC)", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_7_ON_MAIN_BROAD), "Thermal sensor on main board (U17)", 0}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1), "PSU-1 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU1_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + }, + { { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2), "PSU-2 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU2_ID)}, + ONLP_THERMAL_STATUS_PRESENT, + ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS + } +}; + +/* + * This will be called to intiialize the thermali subsystem. + */ +int +onlp_thermali_init(void) +{ + return ONLP_STATUS_OK; +} + +/* + * Retrieve the information structure for the given thermal OID. + * + * If the OID is invalid, return ONLP_E_STATUS_INVALID. + * If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL. + * Otherwise, return ONLP_STATUS_OK with the OID's information. + * + * Note -- it is expected that you fill out the information + * structure even if the sensor described by the OID is not present. + */ +int +onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info) +{ + int local_id, r_data; + char fullpath[256], psu_num[2]; + mux_info_t mux_info; + + VALIDATE(id); + + local_id = ONLP_OID_ID_GET(id); + + /* Set the onlp_oid_hdr_t and capabilities */ + *info = linfo[local_id]; + + if(local_id == THERMAL_CPU_CORE) { + int rv = onlp_file_read_int_max(&info->mcelsius, cpu_coretemp_files); + return rv; + } + + /* Configure attribute path of thermal */ + sprintf(fullpath, "%s/%s", SYS_DEV_PATH, last_path[local_id]); + + /* Configure MUX settings */ + switch (local_id) { + case THERMAL_2_ON_FAN_BROAD: + mux_info.addr = SWPLD; + mux_info.flags = 0x00; + mux_info.bus = I2C_BUS_5; + mux_info.offset = FAN_MUX_REG; + mux_info.channel = 0x06; + break; + case THERMAL_1_ON_PSU1: + sprintf(psu_num, "%d", 1); + dni_i2c_lock_write_attribute(NULL, psu_num, PSU_SEL_PATH); + break; + case THERMAL_1_ON_PSU2: + sprintf(psu_num, "%d", 2); + dni_i2c_lock_write_attribute(NULL, psu_num, PSU_SEL_PATH); + break; + } + + /* Read temperature into r_data */ + if(local_id == THERMAL_2_ON_FAN_BROAD){ + r_data = dni_i2c_lock_read_attribute(&mux_info, fullpath); + }else{ + r_data = dni_i2c_lock_read_attribute(NULL, fullpath); + } + + info->mcelsius = r_data; + + return ONLP_STATUS_OK; +} + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_config.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_config.c new file mode 100644 index 00000000..502c5c9f --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_config.c @@ -0,0 +1,81 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* */ +#define __x86_64_delta_agc7648a_config_STRINGIFY_NAME(_x) #_x +#define __x86_64_delta_agc7648a_config_STRINGIFY_VALUE(_x) __x86_64_delta_agc7648a_config_STRINGIFY_NAME(_x) +x86_64_delta_agc7648a_config_settings_t x86_64_delta_agc7648a_config_settings[] = +{ +#ifdef x86_64_delta_agc7648a_CONFIG_INCLUDE_LOGGING + { __x86_64_delta_agc7648a_config_STRINGIFY_NAME(x86_64_delta_agc7648a_CONFIG_INCLUDE_LOGGING), __x86_64_delta_agc7648a_config_STRINGIFY_VALUE(x86_64_delta_agc7648a_CONFIG_INCLUDE_LOGGING) }, +#else +{ x86_64_delta_agc7648a_CONFIG_INCLUDE_LOGGING(__x86_64_delta_agc7648a_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_delta_agc7648a_CONFIG_LOG_OPTIONS_DEFAULT + { __x86_64_delta_agc7648a_config_STRINGIFY_NAME(x86_64_delta_agc7648a_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_delta_agc7648a_config_STRINGIFY_VALUE(x86_64_delta_agc7648a_CONFIG_LOG_OPTIONS_DEFAULT) }, +#else +{ x86_64_delta_agc7648a_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_delta_agc7648a_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_delta_agc7648a_CONFIG_LOG_BITS_DEFAULT + { __x86_64_delta_agc7648a_config_STRINGIFY_NAME(x86_64_delta_agc7648a_CONFIG_LOG_BITS_DEFAULT), __x86_64_delta_agc7648a_config_STRINGIFY_VALUE(x86_64_delta_agc7648a_CONFIG_LOG_BITS_DEFAULT) }, +#else +{ x86_64_delta_agc7648a_CONFIG_LOG_BITS_DEFAULT(__x86_64_delta_agc7648a_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_delta_agc7648a_CONFIG_LOG_CUSTOM_BITS_DEFAULT + { __x86_64_delta_agc7648a_config_STRINGIFY_NAME(x86_64_delta_agc7648a_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_delta_agc7648a_config_STRINGIFY_VALUE(x86_64_delta_agc7648a_CONFIG_LOG_CUSTOM_BITS_DEFAULT) }, +#else +{ x86_64_delta_agc7648a_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_delta_agc7648a_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB + { __x86_64_delta_agc7648a_config_STRINGIFY_NAME(x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB), __x86_64_delta_agc7648a_config_STRINGIFY_VALUE(x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB) }, +#else +{ x86_64_delta_agc7648a_CONFIG_PORTING_STDLIB(__x86_64_delta_agc7648a_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_delta_agc7648a_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS + { __x86_64_delta_agc7648a_config_STRINGIFY_NAME(x86_64_delta_agc7648a_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_delta_agc7648a_config_STRINGIFY_VALUE(x86_64_delta_agc7648a_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) }, +#else +{ x86_64_delta_agc7648a_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_delta_agc7648a_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_delta_agc7648a_CONFIG_INCLUDE_UCLI + { __x86_64_delta_agc7648a_config_STRINGIFY_NAME(x86_64_delta_agc7648a_CONFIG_INCLUDE_UCLI), __x86_64_delta_agc7648a_config_STRINGIFY_VALUE(x86_64_delta_agc7648a_CONFIG_INCLUDE_UCLI) }, +#else +{ x86_64_delta_agc7648a_CONFIG_INCLUDE_UCLI(__x86_64_delta_agc7648a_config_STRINGIFY_NAME), "__undefined__" }, +#endif +#ifdef x86_64_delta_agc7648a_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION + { __x86_64_delta_agc7648a_config_STRINGIFY_NAME(x86_64_delta_agc7648a_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_delta_agc7648a_config_STRINGIFY_VALUE(x86_64_delta_agc7648a_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) }, +#else +{ x86_64_delta_agc7648a_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_delta_agc7648a_config_STRINGIFY_NAME), "__undefined__" }, +#endif + { NULL, NULL } +}; +#undef __x86_64_delta_agc7648a_config_STRINGIFY_VALUE +#undef __x86_64_delta_agc7648a_config_STRINGIFY_NAME + +const char* +x86_64_delta_agc7648a_config_lookup(const char* setting) +{ + int i; + for(i = 0; x86_64_delta_agc7648a_config_settings[i].name; i++) { + if(strcmp(x86_64_delta_agc7648a_config_settings[i].name, setting)) { + return x86_64_delta_agc7648a_config_settings[i].value; + } + } + return NULL; +} + +int +x86_64_delta_agc7648a_config_show(struct aim_pvs_s* pvs) +{ + int i; + for(i = 0; x86_64_delta_agc7648a_config_settings[i].name; i++) { + aim_printf(pvs, "%s = %s\n", x86_64_delta_agc7648a_config_settings[i].name, x86_64_delta_agc7648a_config_settings[i].value); + } + return i; +} + +/* */ + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_enums.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_enums.c new file mode 100644 index 00000000..b5cfe06b --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_enums.c @@ -0,0 +1,10 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +/* <--auto.start.enum(ALL).source> */ +/* */ + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_int.h b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_int.h new file mode 100644 index 00000000..b1e599e4 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_int.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * x86_64_delta_agc7648a Internal Header + * + *****************************************************************************/ +#ifndef __x86_64_delta_agc7648a_INT_H__ +#define __x86_64_delta_agc7648a_INT_H__ + +#include + + +#endif /* __x86_64_delta_agc7648a_INT_H__ */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_log.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_log.c new file mode 100644 index 00000000..1964d0c5 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_log.c @@ -0,0 +1,18 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_delta_agc7648a_log.h" +/* + * x86_64_delta_agc7648a log struct. + */ +AIM_LOG_STRUCT_DEFINE( + x86_64_delta_agc7648a_CONFIG_LOG_OPTIONS_DEFAULT, + x86_64_delta_agc7648a_CONFIG_LOG_BITS_DEFAULT, + NULL, /* Custom log map */ + x86_64_delta_agc7648a_CONFIG_LOG_CUSTOM_BITS_DEFAULT + ); + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_log.h b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_log.h new file mode 100644 index 00000000..f0326529 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_log.h @@ -0,0 +1,12 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#ifndef __x86_64_delta_agc7648a_LOG_H__ +#define __x86_64_delta_agc7648a_LOG_H__ + +#define AIM_LOG_MODULE_NAME x86_64_delta_agc7648a +#include + +#endif /* __x86_64_delta_agc7648a_LOG_H__ */ diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_module.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_module.c new file mode 100644 index 00000000..174f8bbd --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_module.c @@ -0,0 +1,24 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#include "x86_64_delta_agc7648a_log.h" + +static int +datatypes_init__(void) +{ +#define x86_64_delta_agc7648a_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL); +#include + return 0; +} + +void __x86_64_delta_agc7648a_module_init__(void) +{ + AIM_LOG_STRUCT_REGISTER(); + datatypes_init__(); +} + +int __onlp_platform_version__ = 1; diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_ucli.c b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_ucli.c new file mode 100644 index 00000000..4f01a9aa --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/onlp/builds/src/module/src/x86_64_delta_agc7648a_ucli.c @@ -0,0 +1,50 @@ +/**************************************************************************//** + * + * + * + *****************************************************************************/ +#include + +#if x86_64_delta_agc7648a_CONFIG_INCLUDE_UCLI == 1 + +#include +#include +#include + +static ucli_status_t +x86_64_delta_agc7648a_ucli_ucli__config__(ucli_context_t* uc) +{ + UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_delta_agc7648a) +} + +/* */ +/* */ + +static ucli_module_t +x86_64_delta_agc7648a_ucli_module__ = + { + "x86_64_delta_agc7648a_ucli", + NULL, + x86_64_delta_agc7648a_ucli_ucli_handlers__, + NULL, + NULL, + }; + +ucli_node_t* +x86_64_delta_agc7648a_ucli_node_create(void) +{ + ucli_node_t* n; + ucli_module_init(&x86_64_delta_agc7648a_ucli_module__); + n = ucli_node_create("x86_64_delta_agc7648a", NULL, &x86_64_delta_agc7648a_ucli_module__); + ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_delta_agc7648a")); + return n; +} + +#else +void* +x86_64_delta_agc7648a_ucli_node_create(void) +{ + return NULL; +} +#endif + diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/platform-config/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/platform-config/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/platform-config/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/platform-config/r0/Makefile b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/platform-config/r0/Makefile new file mode 100644 index 00000000..003238cf --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/platform-config/r0/Makefile @@ -0,0 +1 @@ +include $(ONL)/make/pkg.mk \ No newline at end of file diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/platform-config/r0/PKG.yml b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/platform-config/r0/PKG.yml new file mode 100644 index 00000000..d706651a --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/platform-config/r0/PKG.yml @@ -0,0 +1 @@ +!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=delta BASENAME=x86-64-delta-agc7648a REVISION=r0 diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/platform-config/r0/src/lib/x86-64-delta-agc7648a-r0.yml b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/platform-config/r0/src/lib/x86-64-delta-agc7648a-r0.yml new file mode 100644 index 00000000..8adf6838 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/platform-config/r0/src/lib/x86-64-delta-agc7648a-r0.yml @@ -0,0 +1,30 @@ +--- + +###################################################################### +# +# platform-config for AGC7648A +# +###################################################################### + +x86-64-delta-agc7648a-r0: + grub: + + serial: >- + --port=0x3f8 + --speed=115200 + --word=8 + --parity=no + --stop=1 + + kernel: + <<: *kernel-3-16 + + args: >- + nopat + console=ttyS0,115200n8 + + ##network + ## interfaces: + ## ma1: + ## name: ~ + ## syspath: pci0000:00/0000:00:14.0 diff --git a/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/platform-config/r0/src/python/x86_64_delta_agc7648a_r0/__init__.py b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/platform-config/r0/src/python/x86_64_delta_agc7648a_r0/__init__.py new file mode 100644 index 00000000..5f4edf48 --- /dev/null +++ b/packages/platforms/delta/x86-64/x86-64-delta-agc7648a/platform-config/r0/src/python/x86_64_delta_agc7648a_r0/__init__.py @@ -0,0 +1,56 @@ +from onl.platform.base import * +from onl.platform.delta import * + +class OnlPlatform_x86_64_delta_agc7648a_r0(OnlPlatformDelta, + OnlPlatformPortConfig_32x100): + PLATFORM='x86-64-delta-agc7648a-r0' + MODEL="AGC7648A" + SYS_OBJECT_ID=".7648" + + def baseconfig(self): + # Insert kernel module + self.insmod('i2c_cpld') + self.insmod('agc7648a_emc2305') + self.insmod('tmp421') + self.insmod('agc7648a_dps800ab') + self.insmod('agc7648a_sfp') + + # Register multuplexer + self.new_i2c_device('pca9547', 0x71, 1) + + # Register cpld + self.new_i2c_device('cpld', 0x31, 2) + self.new_i2c_device('cpld', 0x30, 5) + self.new_i2c_device('cpld', 0x31, 5) + self.new_i2c_device('cpld', 0x32, 5) + + # Register eeprom + self.new_i2c_device('24c02', 0x53, 2) + + # Register fan control + os.system("echo 0x67 > /sys/bus/i2c/devices/5-0030/addr") + os.system("echo 0x05 > /sys/bus/i2c/devices/5-0030/data") + self.new_i2c_device('agc7648a_emc2305', 0x2c, 3) + self.new_i2c_device('agc7648a_emc2305', 0x2d, 3) + + # Register thermal + self.new_i2c_device('tmp75', 0x4d, 2) + os.system("echo 0x06 > /sys/bus/i2c/devices/5-0030/data") + self.new_i2c_device('tmp75', 0x4f, 3) + self.new_i2c_device('tmp75', 0x4e, 6) + self.new_i2c_device('adt7461', 0x4c, 6) + self.new_i2c_device('tmp75', 0x4f, 6) + self.new_i2c_device('tmp423', 0x4c, 7) + + # Register PSU + os.system("echo 0x1f > /sys/bus/i2c/devices/5-0030/addr") + os.system("echo 0x00 > /sys/bus/i2c/devices/5-0030/data") + self.new_i2c_device('agc7648a_dps800ab', 0x58, 4) + + # Register SFP + self.new_i2c_device('agc7648a_sfp', 0x50, 8) + + # Set front panel green light of sys led + os.system("echo 0x30 > /sys/bus/i2c/devices/5-0030/addr") + os.system("echo 0x10 > /sys/bus/i2c/devices/5-0030/data") + return True