Merge pull request #558 from phani-karanam/Adding_AS7926_80xk

Added Accton AS7926_80xk support
This commit is contained in:
Jeffrey Townsend
2019-06-12 10:46:27 -07:00
committed by GitHub
47 changed files with 4706 additions and 1 deletions

View File

@@ -525,7 +525,11 @@ class OnlPlatformPortConfig_32x100(object):
class OnlPlatformPortConfig_64x100(object):
PORT_COUNT=64
PORT_CONFIG="64x100"
class OnlPlatformPortConfig_80x100(object):
PORT_COUNT=80
PORT_CONFIG="80x100"
class OnlPlatformPortConfig_128x100(object):
PORT_COUNT=128
PORT_CONFIG="128x100"

View File

@@ -410,6 +410,17 @@ static ssize_t show_ascii(struct device *dev, struct device_attribute *da,
switch (attr->index) {
case PSU_FAN_DIRECTION: /* psu_fan_dir */
ptr = data->fan_dir + 1; /* Skip the first byte since it is the length of string. */
/* FAN direction for PTT1600's PSU, depends on
4th and 3rd bit of return value of 0xC3 command */
if (strncmp((data->mfr_model + 1),"PTT1600", strlen("PTT1600")) == 0) {
/* Check if 4th bit is '1' and 3rd bit is '0' for "F2B (AFO)" FAN direction */
if((((data->fan_dir[0] >> 3) & 1) == 0) && (((data->fan_dir[0] >> 4) & 1) == 1)) {
strcpy(ptr,"AFO");
}/* Check if 4th bit is '0' and 3rd bit is '1' for "B2F (AFI)" FAN direction */
else if ((((data->fan_dir[0] >> 3) & 1) == 1) && (((data->fan_dir[0] >> 4) & 1) == 0)) {
strcpy(ptr,"AFI");
}
}
break;
case PSU_MFR_ID: /* psu_mfr_id */
ptr = data->mfr_id + 1; /* The first byte is the count byte of string. */;

View File

@@ -0,0 +1,3 @@
*x86*64*accton*as7816*64x*.mk
onlpdump.mk

View File

@@ -0,0 +1 @@
include $(ONL)/make/pkg.mk

View File

@@ -0,0 +1 @@
include $(ONL)/make/pkg.mk

View File

@@ -0,0 +1 @@
!include $ONL_TEMPLATES/platform-modules.yml VENDOR=accton BASENAME=x86-64-accton-as7926-80xk ARCH=amd64 KERNELS="onl-kernel-4.14-lts-x86-64-all:amd64"

View File

@@ -0,0 +1,6 @@
KERNELS := onl-kernel-4.14-lts-x86-64-all:amd64
KMODULES := $(wildcard *.c)
VENDOR := accton
BASENAME := x86-64-accton-as7926-80xk
ARCH := x86_64
include $(ONL)/make/kmodule.mk

View File

@@ -0,0 +1,658 @@
/*
* A hwmon driver for the as7926_80xk_cpld
*
* Copyright (C) 2018 Accton Technology Corporation.
* Brandon Chuang <brandon_chuang@accton.com.tw>
*
* Based on ad7414.c
* Copyright 2006 Stefan Roese <sr at denx.de>, DENX Software Engineering
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/list.h>
static LIST_HEAD(cpld_client_list);
static struct mutex list_lock;
struct cpld_client_node {
struct i2c_client *client;
struct list_head list;
};
#define I2C_RW_RETRY_COUNT 10
#define I2C_RW_RETRY_INTERVAL 60 /* ms */
static ssize_t show_present(struct device *dev, struct device_attribute *da,
char *buf);
struct as7926_80xk_cpld_data {
struct device *hwmon_dev;
struct mutex update_lock;
u8 index; /* CPLD index */
};
/* Addresses scanned for as7926_80xk_cpld
*/
static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index
enum as7926_80xk_cpld1_sysfs_attributes {
/* transceiver attributes */
TRANSCEIVER_PRESENT_ATTR_ID(1),
TRANSCEIVER_PRESENT_ATTR_ID(2),
TRANSCEIVER_PRESENT_ATTR_ID(3),
TRANSCEIVER_PRESENT_ATTR_ID(4),
TRANSCEIVER_PRESENT_ATTR_ID(5),
TRANSCEIVER_PRESENT_ATTR_ID(6),
TRANSCEIVER_PRESENT_ATTR_ID(7),
TRANSCEIVER_PRESENT_ATTR_ID(8),
TRANSCEIVER_PRESENT_ATTR_ID(9),
TRANSCEIVER_PRESENT_ATTR_ID(10),
TRANSCEIVER_PRESENT_ATTR_ID(11),
TRANSCEIVER_PRESENT_ATTR_ID(12),
TRANSCEIVER_PRESENT_ATTR_ID(13),
TRANSCEIVER_PRESENT_ATTR_ID(14),
TRANSCEIVER_PRESENT_ATTR_ID(15),
TRANSCEIVER_PRESENT_ATTR_ID(16),
TRANSCEIVER_PRESENT_ATTR_ID(17),
TRANSCEIVER_PRESENT_ATTR_ID(18),
TRANSCEIVER_PRESENT_ATTR_ID(19),
TRANSCEIVER_PRESENT_ATTR_ID(20),
TRANSCEIVER_PRESENT_ATTR_ID(21),
TRANSCEIVER_PRESENT_ATTR_ID(22),
TRANSCEIVER_PRESENT_ATTR_ID(23),
TRANSCEIVER_PRESENT_ATTR_ID(24),
TRANSCEIVER_PRESENT_ATTR_ID(25),
TRANSCEIVER_PRESENT_ATTR_ID(26),
TRANSCEIVER_PRESENT_ATTR_ID(27),
TRANSCEIVER_PRESENT_ATTR_ID(28),
TRANSCEIVER_PRESENT_ATTR_ID(29),
TRANSCEIVER_PRESENT_ATTR_ID(30),
TRANSCEIVER_PRESENT_ATTR_ID(31),
TRANSCEIVER_PRESENT_ATTR_ID(32),
TRANSCEIVER_PRESENT_ATTR_ID(33),
TRANSCEIVER_PRESENT_ATTR_ID(34),
TRANSCEIVER_PRESENT_ATTR_ID(35),
TRANSCEIVER_PRESENT_ATTR_ID(36),
TRANSCEIVER_PRESENT_ATTR_ID(37),
TRANSCEIVER_PRESENT_ATTR_ID(38),
TRANSCEIVER_PRESENT_ATTR_ID(39),
TRANSCEIVER_PRESENT_ATTR_ID(40),
TRANSCEIVER_PRESENT_ATTR_ID(41),
TRANSCEIVER_PRESENT_ATTR_ID(42),
TRANSCEIVER_PRESENT_ATTR_ID(43),
TRANSCEIVER_PRESENT_ATTR_ID(44),
TRANSCEIVER_PRESENT_ATTR_ID(45),
TRANSCEIVER_PRESENT_ATTR_ID(46),
TRANSCEIVER_PRESENT_ATTR_ID(47),
TRANSCEIVER_PRESENT_ATTR_ID(48),
TRANSCEIVER_PRESENT_ATTR_ID(49),
TRANSCEIVER_PRESENT_ATTR_ID(50),
TRANSCEIVER_PRESENT_ATTR_ID(51),
TRANSCEIVER_PRESENT_ATTR_ID(52),
TRANSCEIVER_PRESENT_ATTR_ID(53),
TRANSCEIVER_PRESENT_ATTR_ID(54),
TRANSCEIVER_PRESENT_ATTR_ID(55),
TRANSCEIVER_PRESENT_ATTR_ID(56),
TRANSCEIVER_PRESENT_ATTR_ID(57),
TRANSCEIVER_PRESENT_ATTR_ID(58),
TRANSCEIVER_PRESENT_ATTR_ID(59),
TRANSCEIVER_PRESENT_ATTR_ID(60),
TRANSCEIVER_PRESENT_ATTR_ID(61),
TRANSCEIVER_PRESENT_ATTR_ID(62),
TRANSCEIVER_PRESENT_ATTR_ID(63),
TRANSCEIVER_PRESENT_ATTR_ID(64),
TRANSCEIVER_PRESENT_ATTR_ID(65),
TRANSCEIVER_PRESENT_ATTR_ID(66),
TRANSCEIVER_PRESENT_ATTR_ID(67),
TRANSCEIVER_PRESENT_ATTR_ID(68),
TRANSCEIVER_PRESENT_ATTR_ID(69),
TRANSCEIVER_PRESENT_ATTR_ID(70),
TRANSCEIVER_PRESENT_ATTR_ID(71),
TRANSCEIVER_PRESENT_ATTR_ID(72),
TRANSCEIVER_PRESENT_ATTR_ID(73),
TRANSCEIVER_PRESENT_ATTR_ID(74),
TRANSCEIVER_PRESENT_ATTR_ID(75),
TRANSCEIVER_PRESENT_ATTR_ID(76),
TRANSCEIVER_PRESENT_ATTR_ID(77),
TRANSCEIVER_PRESENT_ATTR_ID(78),
TRANSCEIVER_PRESENT_ATTR_ID(79),
TRANSCEIVER_PRESENT_ATTR_ID(80),
};
/* sysfs attributes for hwmon
*/
/* transceiver attributes */
#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \
static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_present, NULL, MODULE_PRESENT_##index)
#define DECLARE_TRANSCEIVER_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr
/* transceiver attributes */
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(1);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(2);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(3);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(4);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(5);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(6);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(7);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(8);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(9);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(10);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(11);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(12);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(13);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(14);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(15);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(16);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(17);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(18);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(19);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(20);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(21);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(22);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(23);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(24);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(25);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(26);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(27);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(28);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(29);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(30);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(31);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(32);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(33);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(34);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(35);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(36);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(37);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(38);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(39);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(40);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(41);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(42);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(43);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(44);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(45);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(46);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(47);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(48);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(49);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(50);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(51);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(52);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(53);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(54);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(55);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(56);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(57);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(58);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(59);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(60);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(61);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(62);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(63);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(64);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(65);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(66);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(67);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(68);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(69);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(70);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(71);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(72);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(73);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(74);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(75);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(76);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(77);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(78);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(79);
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(80);
static struct attribute *as7926_80xk_cpld1_attributes[] = {
/* transceiver attributes */
DECLARE_TRANSCEIVER_ATTR(1),
DECLARE_TRANSCEIVER_ATTR(2),
DECLARE_TRANSCEIVER_ATTR(3),
DECLARE_TRANSCEIVER_ATTR(4),
DECLARE_TRANSCEIVER_ATTR(5),
DECLARE_TRANSCEIVER_ATTR(6),
DECLARE_TRANSCEIVER_ATTR(7),
DECLARE_TRANSCEIVER_ATTR(8),
DECLARE_TRANSCEIVER_ATTR(9),
DECLARE_TRANSCEIVER_ATTR(10),
DECLARE_TRANSCEIVER_ATTR(11),
DECLARE_TRANSCEIVER_ATTR(12),
DECLARE_TRANSCEIVER_ATTR(13),
DECLARE_TRANSCEIVER_ATTR(14),
DECLARE_TRANSCEIVER_ATTR(15),
DECLARE_TRANSCEIVER_ATTR(16),
DECLARE_TRANSCEIVER_ATTR(17),
DECLARE_TRANSCEIVER_ATTR(18),
DECLARE_TRANSCEIVER_ATTR(19),
DECLARE_TRANSCEIVER_ATTR(20),
NULL
};
static struct attribute *as7926_80xk_cpld2_attributes[] = {
DECLARE_TRANSCEIVER_ATTR(21),
DECLARE_TRANSCEIVER_ATTR(22),
DECLARE_TRANSCEIVER_ATTR(23),
DECLARE_TRANSCEIVER_ATTR(24),
DECLARE_TRANSCEIVER_ATTR(25),
DECLARE_TRANSCEIVER_ATTR(26),
DECLARE_TRANSCEIVER_ATTR(27),
DECLARE_TRANSCEIVER_ATTR(28),
DECLARE_TRANSCEIVER_ATTR(29),
DECLARE_TRANSCEIVER_ATTR(30),
DECLARE_TRANSCEIVER_ATTR(31),
DECLARE_TRANSCEIVER_ATTR(32),
DECLARE_TRANSCEIVER_ATTR(33),
DECLARE_TRANSCEIVER_ATTR(34),
DECLARE_TRANSCEIVER_ATTR(35),
DECLARE_TRANSCEIVER_ATTR(36),
DECLARE_TRANSCEIVER_ATTR(37),
DECLARE_TRANSCEIVER_ATTR(38),
DECLARE_TRANSCEIVER_ATTR(39),
DECLARE_TRANSCEIVER_ATTR(40),
NULL
};
static struct attribute *as7926_80xk_cpld3_attributes[] = {
DECLARE_TRANSCEIVER_ATTR(41),
DECLARE_TRANSCEIVER_ATTR(42),
DECLARE_TRANSCEIVER_ATTR(43),
DECLARE_TRANSCEIVER_ATTR(44),
DECLARE_TRANSCEIVER_ATTR(45),
DECLARE_TRANSCEIVER_ATTR(46),
DECLARE_TRANSCEIVER_ATTR(47),
DECLARE_TRANSCEIVER_ATTR(48),
DECLARE_TRANSCEIVER_ATTR(49),
DECLARE_TRANSCEIVER_ATTR(50),
DECLARE_TRANSCEIVER_ATTR(51),
DECLARE_TRANSCEIVER_ATTR(52),
DECLARE_TRANSCEIVER_ATTR(53),
DECLARE_TRANSCEIVER_ATTR(54),
DECLARE_TRANSCEIVER_ATTR(55),
DECLARE_TRANSCEIVER_ATTR(56),
DECLARE_TRANSCEIVER_ATTR(57),
DECLARE_TRANSCEIVER_ATTR(58),
DECLARE_TRANSCEIVER_ATTR(59),
DECLARE_TRANSCEIVER_ATTR(60),
NULL
};
static struct attribute *as7926_80xk_cpld4_attributes[] = {
DECLARE_TRANSCEIVER_ATTR(61),
DECLARE_TRANSCEIVER_ATTR(62),
DECLARE_TRANSCEIVER_ATTR(63),
DECLARE_TRANSCEIVER_ATTR(64),
DECLARE_TRANSCEIVER_ATTR(65),
DECLARE_TRANSCEIVER_ATTR(66),
DECLARE_TRANSCEIVER_ATTR(67),
DECLARE_TRANSCEIVER_ATTR(68),
DECLARE_TRANSCEIVER_ATTR(69),
DECLARE_TRANSCEIVER_ATTR(70),
DECLARE_TRANSCEIVER_ATTR(71),
DECLARE_TRANSCEIVER_ATTR(72),
DECLARE_TRANSCEIVER_ATTR(73),
DECLARE_TRANSCEIVER_ATTR(74),
DECLARE_TRANSCEIVER_ATTR(75),
DECLARE_TRANSCEIVER_ATTR(76),
DECLARE_TRANSCEIVER_ATTR(77),
DECLARE_TRANSCEIVER_ATTR(78),
DECLARE_TRANSCEIVER_ATTR(79),
DECLARE_TRANSCEIVER_ATTR(80),
NULL
};
static const struct attribute_group as7926_80xk_cpld1_group = {
.attrs = as7926_80xk_cpld1_attributes,
};
static const struct attribute_group as7926_80xk_cpld2_group = {
.attrs = as7926_80xk_cpld2_attributes,
};
static const struct attribute_group as7926_80xk_cpld3_group = {
.attrs = as7926_80xk_cpld3_attributes,
};
static const struct attribute_group as7926_80xk_cpld4_group = {
.attrs = as7926_80xk_cpld4_attributes,
};
int as7926_80xk_cpld_read(int bus_num, unsigned short cpld_addr, u8 reg)
{
struct list_head *list_node = NULL;
struct cpld_client_node *cpld_node = NULL;
int ret = -EPERM;
mutex_lock(&list_lock);
list_for_each(list_node, &cpld_client_list)
{
cpld_node = list_entry(list_node, struct cpld_client_node, list);
if (cpld_node->client->addr == cpld_addr
&& cpld_node->client->adapter->nr == bus_num) {
ret = i2c_smbus_read_byte_data(cpld_node->client, reg);
break;
}
}
mutex_unlock(&list_lock);
return ret;
}
EXPORT_SYMBOL(as7926_80xk_cpld_read);
int as7926_80xk_cpld_write(int bus_num, unsigned short cpld_addr, u8 reg, u8 value)
{
struct list_head *list_node = NULL;
struct cpld_client_node *cpld_node = NULL;
int ret = -EIO;
mutex_lock(&list_lock);
list_for_each(list_node, &cpld_client_list)
{
cpld_node = list_entry(list_node, struct cpld_client_node, list);
if (cpld_node->client->addr == cpld_addr
&& cpld_node->client->adapter->nr == bus_num) {
ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value);
break;
}
}
mutex_unlock(&list_lock);
return ret;
}
EXPORT_SYMBOL(as7926_80xk_cpld_write);
static ssize_t show_present(struct device *dev, struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct i2c_client *client = to_i2c_client(dev);
struct as7926_80xk_cpld_data *data = i2c_get_clientdata(client);
int status = 0;
u8 reg = 0, mask = 0;
switch (attr->index) {
case MODULE_PRESENT_1 ... MODULE_PRESENT_8:
reg = 0x10;
mask = 0x1 << (attr->index - MODULE_PRESENT_1);
break;
case MODULE_PRESENT_9 ... MODULE_PRESENT_16:
reg = 0x11;
mask = 0x1 << (attr->index - MODULE_PRESENT_9);
break;
case MODULE_PRESENT_17 ... MODULE_PRESENT_20:
reg = 0x12;
mask = 0x1 << (attr->index - MODULE_PRESENT_17);
break;
case MODULE_PRESENT_21 ... MODULE_PRESENT_28:
reg = 0x10;
mask = 0x1 << (attr->index - MODULE_PRESENT_21);
break;
case MODULE_PRESENT_29 ... MODULE_PRESENT_36:
reg = 0x11;
mask = 0x1 << (attr->index - MODULE_PRESENT_29);
break;
case MODULE_PRESENT_37 ... MODULE_PRESENT_40:
reg = 0x12;
mask = 0x1 << (attr->index - MODULE_PRESENT_37);
break;
case MODULE_PRESENT_41 ... MODULE_PRESENT_48:
reg = 0x10;
mask = 0x1 << (attr->index - MODULE_PRESENT_41);
break;
case MODULE_PRESENT_49 ... MODULE_PRESENT_56:
reg = 0x11;
mask = 0x1 << (attr->index - MODULE_PRESENT_49);
break;
case MODULE_PRESENT_57 ... MODULE_PRESENT_60:
reg = 0x12;
mask = 0x1 << (attr->index - MODULE_PRESENT_57);
break;
case MODULE_PRESENT_61 ... MODULE_PRESENT_68:
reg = 0x10;
mask = 0x1 << (attr->index - MODULE_PRESENT_61);
break;
case MODULE_PRESENT_69 ... MODULE_PRESENT_76:
reg = 0x11;
mask = 0x1 << (attr->index - MODULE_PRESENT_69);
break;
case MODULE_PRESENT_77 ... MODULE_PRESENT_80:
reg = 0x12;
mask = 0x1 << (attr->index - MODULE_PRESENT_77);
break;
default:
return 0;
}
mutex_lock(&data->update_lock);
switch(data->index) {
/* Port 1-20 plug-unplug read from i2c bus number '12'
and CPLD slave address 0x62 */
case 0: status = as7926_80xk_cpld_read(12,0x62, reg);
break;
/* Port 21-40 plug-unplug read from i2c bus number '13'
and CPLD slave address 0x63 */
case 1: status = as7926_80xk_cpld_read(13,0x63, reg);
break;
/* Port 41-60 plug-unplug read from i2c bus number '76'
and CPLD slave address 0x62 */
case 2: status = as7926_80xk_cpld_read(76,0x62, reg);
break;
/* Port 61-80 plug-unplug read from i2c bus number '77'
and CPLD slave address 0x63 */
case 3: status = as7926_80xk_cpld_read(77,0x63, reg);
break;
default: status = -1;
break;
}
if (unlikely(status < 0)) {
goto exit;
}
mutex_unlock(&data->update_lock);
return sprintf(buf, "%d\n", !(status & mask));
exit:
mutex_unlock(&data->update_lock);
return status;
}
static void as7926_80xk_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 as7926_80xk_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 int as7926_80xk_cpld_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
{
int status;
struct as7926_80xk_cpld_data *data = NULL;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr);
status = -EIO;
goto exit;
}
data = kzalloc(sizeof(struct as7926_80xk_cpld_data), GFP_KERNEL);
if (!data) {
status = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
data->index = dev_id->driver_data;
mutex_init(&data->update_lock);
dev_info(&client->dev, "chip found\n");
/* Register sysfs hooks */
switch(data->index) {
case 0: status = sysfs_create_group(&client->dev.kobj, &as7926_80xk_cpld1_group);
break;
case 1: status = sysfs_create_group(&client->dev.kobj, &as7926_80xk_cpld2_group);
break;
case 2: status = sysfs_create_group(&client->dev.kobj, &as7926_80xk_cpld3_group);
break;
case 3: status = sysfs_create_group(&client->dev.kobj, &as7926_80xk_cpld4_group);
break;
default:status = 1;
break;
}
if (status) {
goto exit_free;
}
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
status = PTR_ERR(data->hwmon_dev);
goto exit_remove;
}
as7926_80xk_cpld_add_client(client);
dev_info(&client->dev, "%s: cpld '%s'\n",
dev_name(data->hwmon_dev), client->name);
return 0;
exit_remove:
sysfs_remove_group(&client->dev.kobj, &as7926_80xk_cpld1_group);
sysfs_remove_group(&client->dev.kobj, &as7926_80xk_cpld2_group);
sysfs_remove_group(&client->dev.kobj, &as7926_80xk_cpld3_group);
sysfs_remove_group(&client->dev.kobj, &as7926_80xk_cpld4_group);
exit_free:
kfree(data);
exit:
return status;
}
static int as7926_80xk_cpld_remove(struct i2c_client *client)
{
struct as7926_80xk_cpld_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &as7926_80xk_cpld1_group);
sysfs_remove_group(&client->dev.kobj, &as7926_80xk_cpld2_group);
sysfs_remove_group(&client->dev.kobj, &as7926_80xk_cpld3_group);
sysfs_remove_group(&client->dev.kobj, &as7926_80xk_cpld4_group);
kfree(data);
as7926_80xk_cpld_remove_client(client);
return 0;
}
static const struct i2c_device_id as7926_80xk_cpld_id[] = {
{ "as7926_80xk_cpld1", 0 },
{ "as7926_80xk_cpld2", 1 },
{ "as7926_80xk_cpld3", 2 },
{ "as7926_80xk_cpld4", 3 },
{}
};
MODULE_DEVICE_TABLE(i2c, as7926_80xk_cpld_id);
static struct i2c_driver as7926_80xk_cpld_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "as7926_80xk_cpld1",
},
.probe = as7926_80xk_cpld_probe,
.remove = as7926_80xk_cpld_remove,
.id_table = as7926_80xk_cpld_id,
.address_list = normal_i2c,
};
static int __init as7926_80xk_cpld_init(void)
{
mutex_init(&list_lock);
return i2c_add_driver(&as7926_80xk_cpld_driver);
}
static void __exit as7926_80xk_cpld_exit(void)
{
i2c_del_driver(&as7926_80xk_cpld_driver);
}
module_init(as7926_80xk_cpld_init);
module_exit(as7926_80xk_cpld_exit);
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
MODULE_DESCRIPTION("as7926_80xk_cpld driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,587 @@
/*
* A hwmon driver for the Accton as7926-80xk fan
*
* Copyright (C) 2019 Accton Technology Corporation.
* Phani Karanam <phani_karanam@accton.com.tw>
*
* 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 <linux/module.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/dmi.h>
#define DRVNAME "as7926_80xk_fan"
static struct as7926_80xk_fan_data *as7926_80xk_fan_update_device(struct device *dev);
static ssize_t fan_show_value(struct device *dev, struct device_attribute *da, char *buf);
static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da,
const char *buf, size_t count);
/* fan related data, the index should match sysfs_fan_attributes
*/
static const u8 fan_reg[] = {
0x0F, /* fan 1-8 present status in FAN board*/
0x11, /* fan PWM(for all fan) */
0x12, /* front fan 1 speed(rpm) */
0x13, /* front fan 2 speed(rpm) */
0x14, /* front fan 3 speed(rpm) */
0x15, /* front fan 4 speed(rpm) */
0x16, /* front fan 5 speed(rpm) */
0x17, /* front fan 6 speed(rpm) */
0x18, /* front fan 7 speed(rpm) */
0x19, /* front fan 8 speed(rpm) */
0x22, /* rear fan 1 speed(rpm) */
0x23, /* rear fan 2 speed(rpm) */
0x24, /* rear fan 3 speed(rpm) */
0x25, /* rear fan 4 speed(rpm) */
0x26, /* rear fan 5 speed(rpm) */
0x27, /* rear fan 6 speed(rpm) */
0x28, /* rear fan 7 speed(rpm) */
0x29, /* rear fan 8 speed(rpm) */
0x55, /* CPU temp */
0x56, /* Main board bottom temp1 */
0x57, /* Main board bottom temp2 */
0x58, /* Main board bottom temp3 */
0x52, /* Main board bottom temp4 */
0x53, /* Main board bottom temp5 */
0x54, /* Main board bottom temp6 */
0x60, /* Main board top temp1 */
0x61, /* Main board top temp2 */
0x62, /* Main board top temp3 */
0x63, /* Main board top temp4 */
0x64, /* Main board top temp5 */
0x65, /* Main board top temp6 */
};
/* Each client has this additional data */
struct as7926_80xk_fan_data {
struct device *hwmon_dev;
struct mutex update_lock;
char valid; /* != 0 if registers are valid */
unsigned long last_updated; /* In jiffies */
u8 reg_val[ARRAY_SIZE(fan_reg)]; /* Register value */
};
enum fan_id {
FAN1_ID,
FAN2_ID,
FAN3_ID,
FAN4_ID,
FAN5_ID,
FAN6_ID,
FAN7_ID,
FAN8_ID
};
enum sysfs_fan_attributes {
FAN_PRESENT_REG,
FAN_DUTY_CYCLE_PERCENTAGE, /* Only one CPLD register to control duty cycle for all fans */
FAN1_FRONT_SPEED_RPM,
FAN2_FRONT_SPEED_RPM,
FAN3_FRONT_SPEED_RPM,
FAN4_FRONT_SPEED_RPM,
FAN5_FRONT_SPEED_RPM,
FAN6_FRONT_SPEED_RPM,
FAN7_FRONT_SPEED_RPM,
FAN8_FRONT_SPEED_RPM,
FAN1_REAR_SPEED_RPM,
FAN2_REAR_SPEED_RPM,
FAN3_REAR_SPEED_RPM,
FAN4_REAR_SPEED_RPM,
FAN5_REAR_SPEED_RPM,
FAN6_REAR_SPEED_RPM,
FAN7_REAR_SPEED_RPM,
FAN8_REAR_SPEED_RPM,
FAN1_PRESENT,
FAN2_PRESENT,
FAN3_PRESENT,
FAN4_PRESENT,
FAN5_PRESENT,
FAN6_PRESENT,
FAN7_PRESENT,
FAN8_PRESENT,
FAN1_FAULT,
FAN2_FAULT,
FAN3_FAULT,
FAN4_FAULT,
FAN5_FAULT,
FAN6_FAULT,
FAN7_FAULT,
FAN8_FAULT,
TEMP1_INPUT,
TEMP2_INPUT,
TEMP3_INPUT,
TEMP4_INPUT,
TEMP5_INPUT,
TEMP6_INPUT,
TEMP7_INPUT,
TEMP8_INPUT,
TEMP9_INPUT,
TEMP10_INPUT,
TEMP11_INPUT,
TEMP12_INPUT,
TEMP13_INPUT,
};
/* Define attributes
*/
#define DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, fan_show_value, NULL, FAN##index##_FAULT)
#define DECLARE_FAN_FAULT_ATTR(index) &sensor_dev_attr_fan##index##_fault.dev_attr.attr
#define DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_duty_cycle_percentage, S_IWUSR | S_IRUGO, fan_show_value, set_duty_cycle, FAN##index##_DUTY_CYCLE_PERCENTAGE)
#define DECLARE_FAN_DUTY_CYCLE_ATTR(index) &sensor_dev_attr_fan##index##_duty_cycle_percentage.dev_attr.attr
#define DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_present, S_IRUGO, fan_show_value, NULL, FAN##index##_PRESENT)
#define DECLARE_FAN_PRESENT_ATTR(index) &sensor_dev_attr_fan##index##_present.dev_attr.attr
#define DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(fan##index##_front_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_FRONT_SPEED_RPM);\
static SENSOR_DEVICE_ATTR(fan##index##_rear_speed_rpm, S_IRUGO, fan_show_value, NULL, FAN##index##_REAR_SPEED_RPM)
#define DECLARE_FAN_SPEED_RPM_ATTR(index) &sensor_dev_attr_fan##index##_front_speed_rpm.dev_attr.attr, \
&sensor_dev_attr_fan##index##_rear_speed_rpm.dev_attr.attr
#define DECLARE_TEMP_SENSOR_DEV_ATTR(index) \
static SENSOR_DEVICE_ATTR(temp##index##_input, S_IRUGO, fan_show_value, NULL, TEMP##index##_INPUT)
#define DECLARE_TEMP_SENSOR_ATTR(index) &sensor_dev_attr_temp##index##_input.dev_attr.attr
/* 10 fan fault attributes in this platform */
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(1);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(2);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(3);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(4);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(5);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(6);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(7);
DECLARE_FAN_FAULT_SENSOR_DEV_ATTR(8);
/* 10 fan speed(rpm) attributes in this platform */
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(1);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(2);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(3);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(4);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(5);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(6);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(7);
DECLARE_FAN_SPEED_RPM_SENSOR_DEV_ATTR(8);
/* 10 fan present attributes in this platform */
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(1);
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(2);
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(3);
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(4);
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(5);
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(6);
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(7);
DECLARE_FAN_PRESENT_SENSOR_DEV_ATTR(8);
/* 1 fan duty cycle attribute in this platform */
DECLARE_FAN_DUTY_CYCLE_SENSOR_DEV_ATTR();
/* 13 thermal sensor attributes in this platform */
DECLARE_TEMP_SENSOR_DEV_ATTR(1);
DECLARE_TEMP_SENSOR_DEV_ATTR(2);
DECLARE_TEMP_SENSOR_DEV_ATTR(3);
DECLARE_TEMP_SENSOR_DEV_ATTR(4);
DECLARE_TEMP_SENSOR_DEV_ATTR(5);
DECLARE_TEMP_SENSOR_DEV_ATTR(6);
DECLARE_TEMP_SENSOR_DEV_ATTR(7);
DECLARE_TEMP_SENSOR_DEV_ATTR(8);
DECLARE_TEMP_SENSOR_DEV_ATTR(9);
DECLARE_TEMP_SENSOR_DEV_ATTR(10);
DECLARE_TEMP_SENSOR_DEV_ATTR(11);
DECLARE_TEMP_SENSOR_DEV_ATTR(12);
DECLARE_TEMP_SENSOR_DEV_ATTR(13);
static struct attribute *as7926_80xk_fan_attributes[] = {
/* fan related attributes */
DECLARE_FAN_FAULT_ATTR(1),
DECLARE_FAN_FAULT_ATTR(2),
DECLARE_FAN_FAULT_ATTR(3),
DECLARE_FAN_FAULT_ATTR(4),
DECLARE_FAN_FAULT_ATTR(5),
DECLARE_FAN_FAULT_ATTR(6),
DECLARE_FAN_FAULT_ATTR(7),
DECLARE_FAN_FAULT_ATTR(8),
DECLARE_FAN_SPEED_RPM_ATTR(1),
DECLARE_FAN_SPEED_RPM_ATTR(2),
DECLARE_FAN_SPEED_RPM_ATTR(3),
DECLARE_FAN_SPEED_RPM_ATTR(4),
DECLARE_FAN_SPEED_RPM_ATTR(5),
DECLARE_FAN_SPEED_RPM_ATTR(6),
DECLARE_FAN_SPEED_RPM_ATTR(7),
DECLARE_FAN_SPEED_RPM_ATTR(8),
DECLARE_FAN_PRESENT_ATTR(1),
DECLARE_FAN_PRESENT_ATTR(2),
DECLARE_FAN_PRESENT_ATTR(3),
DECLARE_FAN_PRESENT_ATTR(4),
DECLARE_FAN_PRESENT_ATTR(5),
DECLARE_FAN_PRESENT_ATTR(6),
DECLARE_FAN_PRESENT_ATTR(7),
DECLARE_FAN_PRESENT_ATTR(8),
DECLARE_FAN_DUTY_CYCLE_ATTR(),
/* temperature related attributes */
DECLARE_TEMP_SENSOR_ATTR(1),
DECLARE_TEMP_SENSOR_ATTR(2),
DECLARE_TEMP_SENSOR_ATTR(3),
DECLARE_TEMP_SENSOR_ATTR(4),
DECLARE_TEMP_SENSOR_ATTR(5),
DECLARE_TEMP_SENSOR_ATTR(6),
DECLARE_TEMP_SENSOR_ATTR(7),
DECLARE_TEMP_SENSOR_ATTR(8),
DECLARE_TEMP_SENSOR_ATTR(9),
DECLARE_TEMP_SENSOR_ATTR(10),
DECLARE_TEMP_SENSOR_ATTR(11),
DECLARE_TEMP_SENSOR_ATTR(12),
DECLARE_TEMP_SENSOR_ATTR(13),
NULL
};
#define FAN_DUTY_CYCLE_REG_MASK 0xF
#define FAN_MAX_DUTY_CYCLE 100
#define FAN_REG_VAL_TO_SPEED_RPM_STEP 100
static int as7926_80xk_fan_read_value(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
}
static int as7926_80xk_fan_write_value(struct i2c_client *client, u8 reg, u8 value)
{
return i2c_smbus_write_byte_data(client, reg, value);
}
/* fan utility functions
*/
static u32 reg_val_to_duty_cycle(u8 reg_val)
{
reg_val &= FAN_DUTY_CYCLE_REG_MASK;
if (!reg_val) {
return 0;
}
if (reg_val == 0xF) {
return FAN_MAX_DUTY_CYCLE;
}
return (reg_val * 6) + 10;
}
static u8 duty_cycle_to_reg_val(u8 duty_cycle)
{
if (duty_cycle < 16) {
return 0;
}
if (duty_cycle >= 100) {
return 0xF;
}
return (duty_cycle - 10) / 6;
}
static u32 reg_val_to_speed_rpm(u8 reg_val)
{
return (u32)reg_val * FAN_REG_VAL_TO_SPEED_RPM_STEP;
}
static u8 reg_val_to_is_present(u8 reg_val, enum fan_id id)
{
u8 mask = (1 << id);
return !(reg_val & mask);
}
static u8 is_fan_fault(struct as7926_80xk_fan_data *data, enum fan_id id)
{
u8 ret = 1;
int front_fan_index = FAN1_FRONT_SPEED_RPM + id;
int rear_fan_index = FAN1_REAR_SPEED_RPM + id;
/* Check if the speed of front or rear fan is ZERO,
*/
if (reg_val_to_speed_rpm(data->reg_val[front_fan_index]) &&
reg_val_to_speed_rpm(data->reg_val[rear_fan_index])) {
ret = 0;
}
return ret;
}
static ssize_t set_duty_cycle(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
int error, value;
struct i2c_client *client = to_i2c_client(dev);
error = kstrtoint(buf, 10, &value);
if (error)
return error;
if (value < 0 || value > FAN_MAX_DUTY_CYCLE)
return -EINVAL;
as7926_80xk_fan_write_value(client, 0x28, 0); /* Disable fan speed watch dog */
as7926_80xk_fan_write_value(client, fan_reg[FAN_DUTY_CYCLE_PERCENTAGE], duty_cycle_to_reg_val(value));
return count;
}
static int twos_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 int reg_val_to_thermal_value(u8 reg_val)
{
int thermal_data;
thermal_data = twos_complement_to_int((unsigned short)reg_val, 8, 0xff);
return thermal_data;
}
static ssize_t fan_show_value(struct device *dev, struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct as7926_80xk_fan_data *data = as7926_80xk_fan_update_device(dev);
ssize_t ret = 0;
if (data->valid) {
switch (attr->index) {
case FAN_DUTY_CYCLE_PERCENTAGE:
{
u32 duty_cycle = reg_val_to_duty_cycle(data->reg_val[FAN_DUTY_CYCLE_PERCENTAGE]);
ret = sprintf(buf, "%u\n", duty_cycle);
break;
}
case FAN1_FRONT_SPEED_RPM:
case FAN2_FRONT_SPEED_RPM:
case FAN3_FRONT_SPEED_RPM:
case FAN4_FRONT_SPEED_RPM:
case FAN5_FRONT_SPEED_RPM:
case FAN6_FRONT_SPEED_RPM:
case FAN7_FRONT_SPEED_RPM:
case FAN8_FRONT_SPEED_RPM:
case FAN1_REAR_SPEED_RPM:
case FAN2_REAR_SPEED_RPM:
case FAN3_REAR_SPEED_RPM:
case FAN4_REAR_SPEED_RPM:
case FAN5_REAR_SPEED_RPM:
case FAN6_REAR_SPEED_RPM:
case FAN7_REAR_SPEED_RPM:
case FAN8_REAR_SPEED_RPM:
{
ret = sprintf(buf, "%u\n", reg_val_to_speed_rpm(data->reg_val[attr->index]));
break;
}
case FAN1_PRESENT:
case FAN2_PRESENT:
case FAN3_PRESENT:
case FAN4_PRESENT:
case FAN5_PRESENT:
case FAN6_PRESENT:
case FAN7_PRESENT:
case FAN8_PRESENT:
{
ret = sprintf(buf, "%d\n",
reg_val_to_is_present(data->reg_val[FAN_PRESENT_REG],
attr->index - FAN1_PRESENT));
break;
}
case FAN1_FAULT:
case FAN2_FAULT:
case FAN3_FAULT:
case FAN4_FAULT:
case FAN5_FAULT:
case FAN6_FAULT:
case FAN7_FAULT:
case FAN8_FAULT:
{
ret = sprintf(buf, "%d\n", is_fan_fault(data, attr->index - FAN1_FAULT));
break;
}
case TEMP1_INPUT:
case TEMP2_INPUT:
case TEMP3_INPUT:
case TEMP4_INPUT:
case TEMP5_INPUT:
case TEMP6_INPUT:
case TEMP7_INPUT:
case TEMP8_INPUT:
case TEMP9_INPUT:
case TEMP10_INPUT:
case TEMP11_INPUT:
case TEMP12_INPUT:
case TEMP13_INPUT:
{
ret = sprintf(buf, "%u\n",
(1000 * (reg_val_to_thermal_value(data->reg_val[attr->index - FAN7_REAR_SPEED_RPM]))));
break;
}
default:
break;
}
}
return ret;
}
static const struct attribute_group as7926_80xk_fan_group = {
.attrs = as7926_80xk_fan_attributes,
};
static struct as7926_80xk_fan_data *as7926_80xk_fan_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct as7926_80xk_fan_data *data = i2c_get_clientdata(client);
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2) ||
!data->valid) {
int i;
dev_dbg(&client->dev, "Starting as7926_80xk_fan update\n");
data->valid = 0;
/* Update fan data
*/
for (i = 0; i < ARRAY_SIZE(data->reg_val); i++) {
int status = as7926_80xk_fan_read_value(client, fan_reg[i]);
if (status < 0) {
data->valid = 0;
mutex_unlock(&data->update_lock);
dev_dbg(&client->dev, "reg %d, err %d\n", fan_reg[i], status);
return data;
}
else {
data->reg_val[i] = status;
}
}
data->last_updated = jiffies;
data->valid = 1;
}
mutex_unlock(&data->update_lock);
return data;
}
static int as7926_80xk_fan_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
{
struct as7926_80xk_fan_data *data;
int status;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
status = -EIO;
goto exit;
}
data = kzalloc(sizeof(struct as7926_80xk_fan_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, "chip found\n");
/* Register sysfs hooks */
status = sysfs_create_group(&client->dev.kobj, &as7926_80xk_fan_group);
if (status) {
goto exit_free;
}
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
status = PTR_ERR(data->hwmon_dev);
goto exit_remove;
}
dev_info(&client->dev, "%s: fan '%s'\n",
dev_name(data->hwmon_dev), client->name);
return 0;
exit_remove:
sysfs_remove_group(&client->dev.kobj, &as7926_80xk_fan_group);
exit_free:
kfree(data);
exit:
return status;
}
static int as7926_80xk_fan_remove(struct i2c_client *client)
{
struct as7926_80xk_fan_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &as7926_80xk_fan_group);
return 0;
}
/* Addresses to scan */
static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
static const struct i2c_device_id as7926_80xk_fan_id[] = {
{ "as7926_80xk_fan", 0 },
{}
};
MODULE_DEVICE_TABLE(i2c, as7926_80xk_fan_id);
static struct i2c_driver as7926_80xk_fan_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = DRVNAME,
},
.probe = as7926_80xk_fan_probe,
.remove = as7926_80xk_fan_remove,
.id_table = as7926_80xk_fan_id,
.address_list = normal_i2c,
};
static int __init as7926_80xk_fan_init(void)
{
return i2c_add_driver(&as7926_80xk_fan_driver);
}
static void __exit as7926_80xk_fan_exit(void)
{
i2c_del_driver(&as7926_80xk_fan_driver);
}
module_init(as7926_80xk_fan_init);
module_exit(as7926_80xk_fan_exit);
MODULE_AUTHOR("Phani karanam <phani_karanam@accton.com.tw>");
MODULE_DESCRIPTION("as7926_80xk_fan driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,456 @@
/*
* A LED driver for the as7926_80xk_led
*
* Copyright (C) 2019 Accton Technology Corporation.
* Phani Karanam <phani_karanam@accton.com.tw>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*#define DEBUG*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/leds.h>
#include <linux/slab.h>
#include <linux/dmi.h>
extern int as7926_80xk_cpld_read(int bus_num, unsigned short cpld_addr, u8 reg);
extern int as7926_80xk_cpld_write(int bus_num, unsigned short cpld_addr, u8 reg, u8 value);
#define DRVNAME "as7926_80xk_led"
struct as7926_80xk_led_data {
struct platform_device *pdev;
struct mutex update_lock;
char valid; /* != 0 if registers are valid */
unsigned long last_updated; /* In jiffies */
u8 reg_val[2]; /* only 2 register*/
};
static struct as7926_80xk_led_data *ledctl = NULL;
/* LED related data
*/
#define LED_CPLD_I2C_BUS_NUM 13
#define LED_CNTRLER_I2C_ADDRESS (0x63)
#define LED_TYPE_DIAG_REG_MASK (0x07)
#define LED_MODE_DIAG_GREEN_VALUE (0x05)
#define LED_MODE_DIAG_OFF_VALUE (0x07)
#define LED_TYPE_LOC_REG_MASK (0x70)
#define LED_MODE_LOC_GREEN_VALUE (0x50)
#define LED_MODE_LOC_OFF_VALUE (0x70)
#define LED_TYPE_FAN_REG_MASK (0x70)
#define LED_MODE_FAN_GREEN_VALUE (0x50)
#define LED_MODE_FAN_YELLOW_VALUE (0x40)
#define LED_MODE_FAN_RED_VALUE (0x60)
#define LED_MODE_FAN_OFF_VALUE (0x70)
#define LED_TYPE_PSU_REG_MASK (0x07)
#define LED_MODE_PSU_GREEN_VALUE (0x05)
#define LED_MODE_PSU_YELLOW_VALUE (0x04)
#define LED_MODE_PSU_RED_VALUE (0x06)
#define LED_MODE_PSU_OFF_VALUE (0x07)
enum led_type {
LED_TYPE_DIAG,
LED_TYPE_LOC,
LED_TYPE_FAN,
LED_TYPE_PSU
};
struct led_reg {
u32 types;
u8 reg_addr;
};
static const struct led_reg led_reg_map[] = {
{(1 << LED_TYPE_LOC) | (1 << LED_TYPE_DIAG) , 0x30},
{(1 << LED_TYPE_FAN) | (1 << LED_TYPE_PSU) , 0x31},
};
enum led_light_mode {
LED_MODE_OFF,
LED_MODE_RED = 10,
LED_MODE_RED_BLINKING = 11,
LED_MODE_ORANGE = 12,
LED_MODE_ORANGE_BLINKING = 13,
LED_MODE_YELLOW = 14,
LED_MODE_YELLOW_BLINKING = 15,
LED_MODE_GREEN = 16,
LED_MODE_GREEN_BLINKING = 17,
LED_MODE_BLUE = 18,
LED_MODE_BLUE_BLINKING = 19,
LED_MODE_PURPLE = 20,
LED_MODE_PURPLE_BLINKING = 21,
LED_MODE_AUTO = 22,
LED_MODE_AUTO_BLINKING = 23,
LED_MODE_WHITE = 24,
LED_MODE_WHITE_BLINKING = 25,
LED_MODE_CYAN = 26,
LED_MODE_CYAN_BLINKING = 27,
LED_MODE_UNKNOWN = 99
};
struct led_type_mode {
enum led_type type;
enum led_light_mode mode;
int reg_bit_mask;
int mode_value;
};
static struct led_type_mode led_type_mode_data[] = {
{LED_TYPE_LOC, LED_MODE_OFF, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_OFF_VALUE},
{LED_TYPE_LOC, LED_MODE_GREEN, LED_TYPE_LOC_REG_MASK, LED_MODE_LOC_GREEN_VALUE},
{LED_TYPE_DIAG, LED_MODE_OFF, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_OFF_VALUE},
{LED_TYPE_DIAG, LED_MODE_GREEN, LED_TYPE_DIAG_REG_MASK, LED_MODE_DIAG_GREEN_VALUE},
{LED_TYPE_FAN, LED_MODE_OFF, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_OFF_VALUE},
{LED_TYPE_FAN, LED_MODE_GREEN, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_GREEN_VALUE},
{LED_TYPE_FAN, LED_MODE_YELLOW, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_YELLOW_VALUE},
{LED_TYPE_FAN, LED_MODE_RED, LED_TYPE_FAN_REG_MASK, LED_MODE_FAN_RED_VALUE},
{LED_TYPE_PSU, LED_MODE_OFF, LED_TYPE_PSU_REG_MASK, LED_MODE_PSU_OFF_VALUE},
{LED_TYPE_PSU, LED_MODE_GREEN, LED_TYPE_PSU_REG_MASK, LED_MODE_PSU_GREEN_VALUE},
{LED_TYPE_PSU, LED_MODE_YELLOW, LED_TYPE_PSU_REG_MASK, LED_MODE_PSU_YELLOW_VALUE},
{LED_TYPE_PSU, LED_MODE_RED, LED_TYPE_PSU_REG_MASK, LED_MODE_PSU_RED_VALUE},
};
static int get_led_reg(enum led_type type, u8 *reg)
{
int i;
for (i = 0; i < ARRAY_SIZE(led_reg_map); i++) {
if(led_reg_map[i].types & (1 << type)) {
*reg = led_reg_map[i].reg_addr;
return 0;
}
}
return 1;
}
static int led_reg_val_to_light_mode(enum led_type type, u8 reg_val)
{
int i;
for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) {
if (type != led_type_mode_data[i].type)
continue;
if ((led_type_mode_data[i].reg_bit_mask & reg_val) ==
led_type_mode_data[i].mode_value)
{
return led_type_mode_data[i].mode;
}
}
return 0;
}
static u8 led_light_mode_to_reg_val(enum led_type type,
enum led_light_mode mode, u8 reg_val) {
int i;
for (i = 0; i < ARRAY_SIZE(led_type_mode_data); i++) {
if (type != led_type_mode_data[i].type)
continue;
if (mode != led_type_mode_data[i].mode)
continue;
reg_val = led_type_mode_data[i].mode_value |
(reg_val & (~led_type_mode_data[i].reg_bit_mask));
break;
}
return reg_val;
}
static int as7926_80xk_led_read_value(u8 reg)
{
return as7926_80xk_cpld_read(LED_CPLD_I2C_BUS_NUM, LED_CNTRLER_I2C_ADDRESS, reg);
}
static int as7926_80xk_led_write_value(u8 reg, u8 value)
{
return as7926_80xk_cpld_write(LED_CPLD_I2C_BUS_NUM, LED_CNTRLER_I2C_ADDRESS, reg, value);
}
static void as7926_80xk_led_update(void)
{
mutex_lock(&ledctl->update_lock);
if (time_after(jiffies, ledctl->last_updated + HZ + HZ / 2)
|| !ledctl->valid) {
int i;
dev_dbg(&ledctl->pdev->dev, "Starting as7926_80xk_led update\n");
/* Update LED data
*/
for (i = 0; i < ARRAY_SIZE(ledctl->reg_val); i++) {
int status = as7926_80xk_led_read_value(led_reg_map[i].reg_addr);
if (status < 0) {
ledctl->valid = 0;
dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", led_reg_map[i].reg_addr, status);
goto exit;
}
else
{
ledctl->reg_val[i] = status;
}
}
ledctl->last_updated = jiffies;
ledctl->valid = 1;
}
exit:
mutex_unlock(&ledctl->update_lock);
}
static void as7926_80xk_led_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode,
enum led_type type)
{
int reg_val;
u8 reg;
mutex_lock(&ledctl->update_lock);
if( !get_led_reg(type, &reg)) {
dev_dbg(&ledctl->pdev->dev, "Not match register for %d.\n", type);
}
reg_val = as7926_80xk_led_read_value(reg);
if (reg_val < 0) {
dev_dbg(&ledctl->pdev->dev, "reg %d, err %d\n", reg, reg_val);
goto exit;
}
reg_val = led_light_mode_to_reg_val(type, led_light_mode, reg_val);
as7926_80xk_led_write_value(reg, reg_val);
/* to prevent the slow-update issue */
ledctl->valid = 0;
exit:
mutex_unlock(&ledctl->update_lock);
}
static void as7926_80xk_led_diag_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode)
{
as7926_80xk_led_set(led_cdev, led_light_mode, LED_TYPE_DIAG);
}
static enum led_brightness as7926_80xk_led_diag_get(struct led_classdev *cdev)
{
as7926_80xk_led_update();
return led_reg_val_to_light_mode(LED_TYPE_DIAG, ledctl->reg_val[0]);
}
static void as7926_80xk_led_loc_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode)
{
as7926_80xk_led_set(led_cdev, led_light_mode, LED_TYPE_LOC);
}
static enum led_brightness as7926_80xk_led_loc_get(struct led_classdev *cdev)
{
as7926_80xk_led_update();
return led_reg_val_to_light_mode(LED_TYPE_LOC, ledctl->reg_val[0]);
}
static void as7926_80xk_led_fan_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode)
{
as7926_80xk_led_set(led_cdev, led_light_mode, LED_TYPE_FAN);
}
static enum led_brightness as7926_80xk_led_fan_get(struct led_classdev *cdev)
{
as7926_80xk_led_update();
return led_reg_val_to_light_mode(LED_TYPE_FAN, ledctl->reg_val[1]);
}
static void as7926_80xk_led_psu_set(struct led_classdev *led_cdev,
enum led_brightness led_light_mode)
{
as7926_80xk_led_set(led_cdev, led_light_mode, LED_TYPE_PSU);
}
static enum led_brightness as7926_80xk_led_psu_get(struct led_classdev *cdev)
{
as7926_80xk_led_update();
return led_reg_val_to_light_mode(LED_TYPE_PSU, ledctl->reg_val[1]);
}
static struct led_classdev as7926_80xk_leds[] = {
[LED_TYPE_DIAG] = {
.name = "as7926_80xk_led::diag",
.default_trigger = "unused",
.brightness_set = as7926_80xk_led_diag_set,
.brightness_get = as7926_80xk_led_diag_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_GREEN,
},
[LED_TYPE_LOC] = {
.name = "as7926_80xk_led::loc",
.default_trigger = "unused",
.brightness_set = as7926_80xk_led_loc_set,
.brightness_get = as7926_80xk_led_loc_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_GREEN,
},
[LED_TYPE_FAN] = {
.name = "as7926_80xk_led::fan",
.default_trigger = "unused",
.brightness_set = as7926_80xk_led_fan_set,
.brightness_get = as7926_80xk_led_fan_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_GREEN,
},
[LED_TYPE_PSU] = {
.name = "as7926_80xk_led::psu",
.default_trigger = "unused",
.brightness_set = as7926_80xk_led_psu_set,
.brightness_get = as7926_80xk_led_psu_get,
.flags = LED_CORE_SUSPENDRESUME,
.max_brightness = LED_MODE_GREEN,
},
};
static int as7926_80xk_led_suspend(struct platform_device *dev,
pm_message_t state)
{
int i = 0;
for (i = 0; i < ARRAY_SIZE(as7926_80xk_leds); i++) {
led_classdev_suspend(&as7926_80xk_leds[i]);
}
return 0;
}
static int as7926_80xk_led_resume(struct platform_device *dev)
{
int i = 0;
for (i = 0; i < ARRAY_SIZE(as7926_80xk_leds); i++) {
led_classdev_resume(&as7926_80xk_leds[i]);
}
return 0;
}
static int as7926_80xk_led_probe(struct platform_device *pdev)
{
int ret, i;
for (i = 0; i < ARRAY_SIZE(as7926_80xk_leds); i++) {
ret = led_classdev_register(&pdev->dev, &as7926_80xk_leds[i]);
if (ret < 0)
break;
}
/* Check if all LEDs were successfully registered */
if (i != ARRAY_SIZE(as7926_80xk_leds)){
int j;
/* only unregister the LEDs that were successfully registered */
for (j = 0; j < i; j++) {
led_classdev_unregister(&as7926_80xk_leds[i]);
}
}
return ret;
}
static int as7926_80xk_led_remove(struct platform_device *pdev)
{
int i;
for (i = 0; i < ARRAY_SIZE(as7926_80xk_leds); i++) {
led_classdev_unregister(&as7926_80xk_leds[i]);
}
return 0;
}
static struct platform_driver as7926_80xk_led_driver = {
.probe = as7926_80xk_led_probe,
.remove = as7926_80xk_led_remove,
.suspend = as7926_80xk_led_suspend,
.resume = as7926_80xk_led_resume,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
},
};
static int __init as7926_80xk_led_init(void)
{
int ret;
ret = platform_driver_register(&as7926_80xk_led_driver);
if (ret < 0) {
goto exit;
}
ledctl = kzalloc(sizeof(struct as7926_80xk_led_data), GFP_KERNEL);
if (!ledctl) {
ret = -ENOMEM;
platform_driver_unregister(&as7926_80xk_led_driver);
goto exit;
}
mutex_init(&ledctl->update_lock);
ledctl->pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
if (IS_ERR(ledctl->pdev)) {
ret = PTR_ERR(ledctl->pdev);
platform_driver_unregister(&as7926_80xk_led_driver);
kfree(ledctl);
goto exit;
}
exit:
return ret;
}
static void __exit as7926_80xk_led_exit(void)
{
platform_device_unregister(ledctl->pdev);
platform_driver_unregister(&as7926_80xk_led_driver);
kfree(ledctl);
}
module_init(as7926_80xk_led_init);
module_exit(as7926_80xk_led_exit);
MODULE_AUTHOR("Phani Karanam <phani_karanam@accton.com.tw>");
MODULE_DESCRIPTION("as7926_80xk_led driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,252 @@
/*
* An hwmon driver for accton as7926_80xk Power Module
*
* Copyright (C) 2019 Accton Technology Corporation.
* Phani Karanam <phani_karanam@accton.com.tw>
*
* Based on ad7414.c
* Copyright 2006 Stefan Roese <sr at denx.de>, DENX Software Engineering
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/dmi.h>
static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf);
extern int accton_i2c_cpld_read (unsigned short cpld_addr, u8 reg);
/* Addresses scanned
*/
static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
/* Each client has this additional data
*/
struct as7926_80xk_psu_data {
struct device *hwmon_dev;
struct mutex update_lock;
char valid; /* !=0 if registers are valid */
unsigned long last_updated; /* In jiffies */
u8 index; /* PSU index */
u8 psu_present; /* Status(present) register read from CPLD */
u8 psu_power_good; /* Status(power_good) register read from CPLD */
};
static struct as7926_80xk_psu_data *as7926_80xk_psu_update_device(struct device *dev);
enum as7926_80xk_psu_sysfs_attributes {
PSU_PRESENT,
PSU_POWER_GOOD
};
/* sysfs attributes for hwmon
*/
static SENSOR_DEVICE_ATTR(psu_present, S_IRUGO, show_status, NULL, PSU_PRESENT);
static SENSOR_DEVICE_ATTR(psu_power_good, S_IRUGO, show_status, NULL, PSU_POWER_GOOD);
static struct attribute *as7926_80xk_psu_attributes[] = {
&sensor_dev_attr_psu_present.dev_attr.attr,
&sensor_dev_attr_psu_power_good.dev_attr.attr,
NULL
};
static ssize_t show_status(struct device *dev, struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct as7926_80xk_psu_data *data = as7926_80xk_psu_update_device(dev);
u8 status = 0;
if (!data->valid) {
return -EIO;
}
if (attr->index == PSU_PRESENT) {
status = !((data->psu_present >> data->index) & 0x1);
}
else { /* PSU_POWER_GOOD */
status = ((data->psu_power_good >> data->index) & 0x1);
}
return sprintf(buf, "%d\n", status);
}
static const struct attribute_group as7926_80xk_psu_group = {
.attrs = as7926_80xk_psu_attributes,
};
static int as7926_80xk_psu_probe(struct i2c_client *client,
const struct i2c_device_id *dev_id)
{
struct as7926_80xk_psu_data *data;
int status;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
status = -EIO;
goto exit;
}
data = kzalloc(sizeof(struct as7926_80xk_psu_data), GFP_KERNEL);
if (!data) {
status = -ENOMEM;
goto exit;
}
i2c_set_clientdata(client, data);
data->valid = 0;
data->index = dev_id->driver_data;
mutex_init(&data->update_lock);
dev_info(&client->dev, "chip found\n");
/* Register sysfs hooks */
status = sysfs_create_group(&client->dev.kobj, &as7926_80xk_psu_group);
if (status) {
goto exit_free;
}
data->hwmon_dev = hwmon_device_register_with_info(&client->dev, "as7926_80xk_psu",
NULL, NULL, NULL);
if (IS_ERR(data->hwmon_dev)) {
status = PTR_ERR(data->hwmon_dev);
goto exit_remove;
}
dev_info(&client->dev, "%s: psu '%s'\n",
dev_name(data->hwmon_dev), client->name);
return 0;
exit_remove:
sysfs_remove_group(&client->dev.kobj, &as7926_80xk_psu_group);
exit_free:
kfree(data);
exit:
return status;
}
static int as7926_80xk_psu_remove(struct i2c_client *client)
{
struct as7926_80xk_psu_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &as7926_80xk_psu_group);
kfree(data);
return 0;
}
enum psu_index
{
as7926_80xk_psu1,
as7926_80xk_psu2,
as7926_80xk_psu3,
as7926_80xk_psu4
};
static const struct i2c_device_id as7926_80xk_psu_id[] = {
{ "as7926_80xk_psu1", as7926_80xk_psu1 },
{ "as7926_80xk_psu2", as7926_80xk_psu2 },
{ "as7926_80xk_psu3", as7926_80xk_psu3 },
{ "as7926_80xk_psu4", as7926_80xk_psu4 },
{}
};
MODULE_DEVICE_TABLE(i2c, as7926_80xk_psu_id);
static struct i2c_driver as7926_80xk_psu_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "as7926_80xk_psu",
},
.probe = as7926_80xk_psu_probe,
.remove = as7926_80xk_psu_remove,
.id_table = as7926_80xk_psu_id,
.address_list = normal_i2c,
};
static struct as7926_80xk_psu_data *as7926_80xk_psu_update_device(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct as7926_80xk_psu_data *data = i2c_get_clientdata(client);
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) {
int psu_present = 0;
int power_good = 0;
data->valid = 0;
dev_dbg(&client->dev, "Starting as7926_80xk update\n");
/* Read psu present */
psu_present = accton_i2c_cpld_read(0x60, 0x51);
if (psu_present < 0) {
dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", psu_present);
goto exit;
}
else {
data->psu_present = psu_present;
}
/* Read psu power good */
power_good = accton_i2c_cpld_read(0x60, 0x52);
if (power_good < 0) {
dev_dbg(&client->dev, "cpld reg 0x60 err %d\n", power_good);
goto exit;
}
else {
data->psu_power_good = power_good;
}
data->last_updated = jiffies;
data->valid = 1;
}
exit:
mutex_unlock(&data->update_lock);
return data;
}
static int __init as7926_80xk_psu_init(void)
{
return i2c_add_driver(&as7926_80xk_psu_driver);
}
static void __exit as7926_80xk_psu_exit(void)
{
i2c_del_driver(&as7926_80xk_psu_driver);
}
module_init(as7926_80xk_psu_init);
module_exit(as7926_80xk_psu_exit);
MODULE_AUTHOR("Phani Karanam <phani_karanam@accton.com.tw>");
MODULE_DESCRIPTION("as7926_80xk_psu driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1 @@
include $(ONL)/make/pkg.mk

View File

@@ -0,0 +1 @@
!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-accton-as7926-80xk ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu

View File

@@ -0,0 +1,2 @@
FILTER=src
include $(ONL)/make/subdirs.mk

View File

@@ -0,0 +1,45 @@
############################################################
# <bsn.cl fy=2014 v=onl>
#
# 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.
#
# </bsn.cl>
############################################################
#
#
############################################################
include $(ONL)/make/config.amd64.mk
MODULE := libonlp-x86-64-accton-as7926-80xk
include $(BUILDER)/standardinit.mk
DEPENDMODULES := AIM IOF x86_64_accton_as7926_80xk onlplib
DEPENDMODULE_HEADERS := sff
include $(BUILDER)/dependmodules.mk
SHAREDLIB := libonlp-x86-64-accton-as7926-80xk.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

View File

@@ -0,0 +1,46 @@
############################################################
# <bsn.cl fy=2014 v=onl>
#
# 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.
#
# </bsn.cl>
############################################################
#
#
#
############################################################
include $(ONL)/make/config.amd64.mk
.DEFAULT_GOAL := onlpdump
MODULE := onlpdump
include $(BUILDER)/standardinit.mk
DEPENDMODULES := AIM IOF onlp x86_64_accton_as7926_80xk 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

View File

@@ -0,0 +1 @@
name: x86_64_accton_as7926_80xk

View File

@@ -0,0 +1,9 @@
###############################################################################
#
#
#
###############################################################################
include $(ONL)/make/config.mk
MODULE := x86_64_accton_as7926_80xk
AUTOMODULE := x86_64_accton_as7926_80xk
include $(BUILDER)/definemodule.mk

View File

@@ -0,0 +1,6 @@
###############################################################################
#
# x86_64_accton_as7926_80xk README
#
###############################################################################

View File

@@ -0,0 +1,50 @@
###############################################################################
#
# x86_64_accton_as7926_80xk Autogeneration Definitions.
#
###############################################################################
cdefs: &cdefs
- X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_LOGGING:
doc: "Include or exclude logging."
default: 1
- X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_OPTIONS_DEFAULT:
doc: "Default enabled log options."
default: AIM_LOG_OPTIONS_DEFAULT
- X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_BITS_DEFAULT:
doc: "Default enabled log bits."
default: AIM_LOG_BITS_DEFAULT
- X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT:
doc: "Default enabled custom log bits."
default: 0
- X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB:
doc: "Default all porting macros to use the C standard libraries."
default: 1
- X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS:
doc: "Include standard library headers for stdlib porting macros."
default: X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB
- X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_UCLI:
doc: "Include generic uCli support."
default: 0
- X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION:
doc: "Assume chassis fan direction is the same as the PSU fan direction."
default: 0
definitions:
cdefs:
X86_64_ACCTON_AS7926_80XK_CONFIG_HEADER:
defs: *cdefs
basename: x86_64_accton_as7926_80xk_config
portingmacro:
x86_64_accton_as7926_80xk:
macros:
- malloc
- free
- memset
- memcpy
- strncpy
- vsnprintf
- snprintf
- strlen

View File

@@ -0,0 +1,14 @@
/**************************************************************************//**
*
*
*
*****************************************************************************/
#include <x86_64_accton_as7926_80xk/x86_64_accton_as7926_80xk_config.h>
/* <--auto.start.xmacro(ALL).define> */
/* <auto.end.xmacro(ALL).define> */
/* <--auto.start.xenum(ALL).define> */
/* <auto.end.xenum(ALL).define> */

View File

@@ -0,0 +1,137 @@
/**************************************************************************//**
*
* @file
* @brief x86_64_accton_as7926_80xk Configuration Header
*
* @addtogroup x86_64_accton_as7926_80xk-config
* @{
*
*****************************************************************************/
#ifndef __X86_64_ACCTON_AS7926_80XK_CONFIG_H__
#define __X86_64_ACCTON_AS7926_80XK_CONFIG_H__
#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG
#include <global_custom_config.h>
#endif
#ifdef X86_64_ACCTON_AS7926_80XK_INCLUDE_CUSTOM_CONFIG
#include <x86_64_accton_as7926_80xk_custom_config.h>
#endif
/* <auto.start.cdefs(X86_64_ACCTON_AS7926_80XK_CONFIG_HEADER).header> */
#include <AIM/aim.h>
/**
* X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_LOGGING
*
* Include or exclude logging. */
#ifndef X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_LOGGING
#define X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_LOGGING 1
#endif
/**
* X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_OPTIONS_DEFAULT
*
* Default enabled log options. */
#ifndef X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_OPTIONS_DEFAULT
#define X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT
#endif
/**
* X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_BITS_DEFAULT
*
* Default enabled log bits. */
#ifndef X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_BITS_DEFAULT
#define X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT
#endif
/**
* X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT
*
* Default enabled custom log bits. */
#ifndef X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT
#define X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0
#endif
/**
* X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB
*
* Default all porting macros to use the C standard libraries. */
#ifndef X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB
#define X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB 1
#endif
/**
* X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS
*
* Include standard library headers for stdlib porting macros. */
#ifndef X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS
#define X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB
#endif
/**
* X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_UCLI
*
* Include generic uCli support. */
#ifndef X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_UCLI
#define X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_UCLI 0
#endif
/**
* X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION
*
* Assume chassis fan direction is the same as the PSU fan direction. */
#ifndef X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION
#define X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0
#endif
/**
* All compile time options can be queried or displayed
*/
/** Configuration settings structure. */
typedef struct x86_64_accton_as7926_80xk_config_settings_s {
/** name */
const char* name;
/** value */
const char* value;
} x86_64_accton_as7926_80xk_config_settings_t;
/** Configuration settings table. */
/** x86_64_accton_as7926_80xk_config_settings table. */
extern x86_64_accton_as7926_80xk_config_settings_t x86_64_accton_as7926_80xk_config_settings[];
/**
* @brief Lookup a configuration setting.
* @param setting The name of the configuration option to lookup.
*/
const char* x86_64_accton_as7926_80xk_config_lookup(const char* setting);
/**
* @brief Show the compile-time configuration.
* @param pvs The output stream.
*/
int x86_64_accton_as7926_80xk_config_show(struct aim_pvs_s* pvs);
/* <auto.end.cdefs(X86_64_ACCTON_AS7926_80XK_CONFIG_HEADER).header> */
#include "x86_64_accton_as7926_80xk_porting.h"
#endif /* __X86_64_ACCTON_AS7926_80XK_CONFIG_H__ */
/* @} */

View File

@@ -0,0 +1,26 @@
/**************************************************************************//**
*
* x86_64_accton_as7926_80xk Doxygen Header
*
*****************************************************************************/
#ifndef __X86_64_ACCTON_AS7926_80XK_DOX_H__
#define __X86_64_ACCTON_AS7926_80XK_DOX_H__
/**
* @defgroup x86_64_accton_as7926_80xk x86_64_accton_as7926_80xk - x86_64_accton_as7926_80xk Description
*
The documentation overview for this module should go here.
*
* @{
*
* @defgroup x86_64_accton_as7926_80xk-x86_64_accton_as7926_80xk Public Interface
* @defgroup x86_64_accton_as7926_80xk-config Compile Time Configuration
* @defgroup x86_64_accton_as7926_80xk-porting Porting Macros
*
* @}
*
*/
#endif /* __X86_64_ACCTON_AS7926_80XK_DOX_H__ */

View File

@@ -0,0 +1,107 @@
/**************************************************************************//**
*
* @file
* @brief x86_64_accton_as7926_80xk Porting Macros.
*
* @addtogroup x86_64_accton_as7926_80xk-porting
* @{
*
*****************************************************************************/
#ifndef __X86_64_ACCTON_AS7926_80XK_PORTING_H__
#define __X86_64_ACCTON_AS7926_80XK_PORTING_H__
/* <auto.start.portingmacro(ALL).define> */
#if X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS == 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <memory.h>
#endif
#ifndef X86_64_ACCTON_AS7926_80XK_MALLOC
#if defined(GLOBAL_MALLOC)
#define X86_64_ACCTON_AS7926_80XK_MALLOC GLOBAL_MALLOC
#elif X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB == 1
#define X86_64_ACCTON_AS7926_80XK_MALLOC malloc
#else
#error The macro X86_64_ACCTON_AS7926_80XK_MALLOC is required but cannot be defined.
#endif
#endif
#ifndef X86_64_ACCTON_AS7926_80XK_FREE
#if defined(GLOBAL_FREE)
#define X86_64_ACCTON_AS7926_80XK_FREE GLOBAL_FREE
#elif X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB == 1
#define X86_64_ACCTON_AS7926_80XK_FREE free
#else
#error The macro X86_64_ACCTON_AS7926_80XK_FREE is required but cannot be defined.
#endif
#endif
#ifndef X86_64_ACCTON_AS7926_80XK_MEMSET
#if defined(GLOBAL_MEMSET)
#define X86_64_ACCTON_AS7926_80XK_MEMSET GLOBAL_MEMSET
#elif X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB == 1
#define X86_64_ACCTON_AS7926_80XK_MEMSET memset
#else
#error The macro X86_64_ACCTON_AS7926_80XK_MEMSET is required but cannot be defined.
#endif
#endif
#ifndef X86_64_ACCTON_AS7926_80XK_MEMCPY
#if defined(GLOBAL_MEMCPY)
#define X86_64_ACCTON_AS7926_80XK_MEMCPY GLOBAL_MEMCPY
#elif X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB == 1
#define X86_64_ACCTON_AS7926_80XK_MEMCPY memcpy
#else
#error The macro X86_64_ACCTON_AS7926_80XK_MEMCPY is required but cannot be defined.
#endif
#endif
#ifndef X86_64_ACCTON_AS7926_80XK_STRNCPY
#if defined(GLOBAL_STRNCPY)
#define X86_64_ACCTON_AS7926_80XK_STRNCPY GLOBAL_STRNCPY
#elif X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB == 1
#define X86_64_ACCTON_AS7926_80XK_STRNCPY strncpy
#else
#error The macro X86_64_ACCTON_AS7926_80XK_STRNCPY is required but cannot be defined.
#endif
#endif
#ifndef X86_64_ACCTON_AS7926_80XK_VSNPRINTF
#if defined(GLOBAL_VSNPRINTF)
#define X86_64_ACCTON_AS7926_80XK_VSNPRINTF GLOBAL_VSNPRINTF
#elif X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB == 1
#define X86_64_ACCTON_AS7926_80XK_VSNPRINTF vsnprintf
#else
#error The macro X86_64_ACCTON_AS7926_80XK_VSNPRINTF is required but cannot be defined.
#endif
#endif
#ifndef X86_64_ACCTON_AS7926_80XK_SNPRINTF
#if defined(GLOBAL_SNPRINTF)
#define X86_64_ACCTON_AS7926_80XK_SNPRINTF GLOBAL_SNPRINTF
#elif X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB == 1
#define X86_64_ACCTON_AS7926_80XK_SNPRINTF snprintf
#else
#error The macro X86_64_ACCTON_AS7926_80XK_SNPRINTF is required but cannot be defined.
#endif
#endif
#ifndef X86_64_ACCTON_AS7926_80XK_STRLEN
#if defined(GLOBAL_STRLEN)
#define X86_64_ACCTON_AS7926_80XK_STRLEN GLOBAL_STRLEN
#elif X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB == 1
#define X86_64_ACCTON_AS7926_80XK_STRLEN strlen
#else
#error The macro X86_64_ACCTON_AS7926_80XK_STRLEN is required but cannot be defined.
#endif
#endif
/* <auto.end.portingmacro(ALL).define> */
#endif /* __X86_64_ACCTON_AS7926_80XK_PORTING_H__ */
/* @} */

View File

@@ -0,0 +1,9 @@
###############################################################################
#
# Local source generation targets.
#
###############################################################################
ucli:
@../../../../tools/uclihandlers.py x86_64_accton_as7926_80xk_ucli.c

View File

@@ -0,0 +1,253 @@
/************************************************************
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
* Copyright 2017 Accton Technology Corporation.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*
* </bsn.cl>
************************************************************
*
* Fan Platform Implementation Defaults.
*
***********************************************************/
#include <onlplib/file.h>
#include <onlp/platformi/fani.h>
#include "platform_lib.h"
enum fan_id {
FAN_1_ON_FAN_BOARD = 1,
FAN_2_ON_FAN_BOARD,
FAN_3_ON_FAN_BOARD,
FAN_4_ON_FAN_BOARD,
FAN_5_ON_FAN_BOARD,
FAN_6_ON_FAN_BOARD,
FAN_7_ON_FAN_BOARD,
FAN_8_ON_FAN_BOARD,
FAN_1_ON_PSU_1,
FAN_1_ON_PSU_2,
FAN_1_ON_PSU_3,
FAN_1_ON_PSU_4
};
#define MAX_FAN_SPEED 25500
#define MAX_PSU_FAN_SPEED 25500
#define CHASSIS_FAN_INFO(fid) \
{ \
{ ONLP_FAN_ID_CREATE(FAN_##fid##_ON_FAN_BOARD), "Chassis Fan - "#fid, 0 },\
0x0,\
ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE,\
0,\
0,\
ONLP_FAN_MODE_INVALID,\
}
#define PSU_FAN_INFO(pid, fid) \
{ \
{ ONLP_FAN_ID_CREATE(FAN_##fid##_ON_PSU_##pid), "PSU "#pid" - Fan "#fid, 0 },\
0x0,\
ONLP_FAN_CAPS_SET_PERCENTAGE | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE,\
0,\
0,\
ONLP_FAN_MODE_INVALID,\
}
/* Static fan information */
onlp_fan_info_t finfo[] = {
{ }, /* Not used */
CHASSIS_FAN_INFO(1),
CHASSIS_FAN_INFO(2),
CHASSIS_FAN_INFO(3),
CHASSIS_FAN_INFO(4),
CHASSIS_FAN_INFO(5),
CHASSIS_FAN_INFO(6),
CHASSIS_FAN_INFO(7),
CHASSIS_FAN_INFO(8),
PSU_FAN_INFO(1,1),
PSU_FAN_INFO(2,1),
PSU_FAN_INFO(3,1),
PSU_FAN_INFO(4,1)
};
#define VALIDATE(_id) \
do { \
if(!ONLP_OID_IS_FAN(_id)) { \
return ONLP_STATUS_E_INVALID; \
} \
} while(0)
static int
_onlp_fani_info_get_fan(int fid, onlp_fan_info_t* info)
{
int value;
/* get fan present status
*/
if (onlp_file_read_int(&value, "%s""fan%d_present", FAN_BOARD_PATH, fid) < 0) {
AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH);
return ONLP_STATUS_E_INTERNAL;
}
if (value == 0) {
return ONLP_STATUS_OK; /* fan is not present */
}
info->status |= ONLP_FAN_STATUS_PRESENT;
/* get fan fault status (turn on when any one fails)
*/
if (onlp_file_read_int(&value, "%s""fan%d_fault", FAN_BOARD_PATH, fid) < 0) {
AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH);
return ONLP_STATUS_E_INTERNAL;
}
if (value > 0) {
info->status |= ONLP_FAN_STATUS_FAILED;
}
/* get front fan speed
*/
if (onlp_file_read_int(&value, "%s""fan%d_front_speed_rpm", FAN_BOARD_PATH, fid) < 0) {
AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH);
return ONLP_STATUS_E_INTERNAL;
}
info->rpm = value;
/* get rear fan speed
*/
if (onlp_file_read_int(&value, "%s""fan%d_rear_speed_rpm", FAN_BOARD_PATH, fid) < 0) {
AIM_LOG_ERROR("Unable to read status from (%s)\r\n", FAN_BOARD_PATH);
return ONLP_STATUS_E_INTERNAL;
}
/* take the min value from front/rear fan speed
*/
if (info->rpm > value) {
info->rpm = value;
}
/* get speed percentage from rpm
*/
info->percentage = (info->rpm * 100)/MAX_FAN_SPEED;
return ONLP_STATUS_OK;
}
static uint32_t
_onlp_get_fan_direction_on_psu(void)
{
/* Try to read direction from PSU1.
* If PSU1 is not valid, read from PSU4
*/
int i = 0;
for (i = PSU1_ID; i <= PSU4_ID; i++) {
psu_type_t psu_type;
psu_type = psu_type_get(i, NULL, 0);
if (psu_type == PSU_TYPE_UNKNOWN) {
continue;
}
if (PSU_TYPE_AC_F2B == psu_type) {
return ONLP_FAN_STATUS_F2B;
}
else {
return ONLP_FAN_STATUS_B2F;
}
}
return 0;
}
static int
_onlp_fani_info_get_fan_on_psu(int pid, onlp_fan_info_t* info)
{
int val = 0;
info->status |= ONLP_FAN_STATUS_PRESENT;
/* get fan direction
*/
info->status |= _onlp_get_fan_direction_on_psu();
/* get fan fault status
*/
if (psu_ym2651y_pmbus_info_get(pid, "psu_fan1_fault", &val) == ONLP_STATUS_OK) {
info->status |= (val > 0) ? ONLP_FAN_STATUS_FAILED : 0;
}
/* get fan speed
*/
if (psu_ym2651y_pmbus_info_get(pid, "psu_fan1_speed_rpm", &val) == ONLP_STATUS_OK) {
info->rpm = val;
info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED;
}
return ONLP_STATUS_OK;
}
/*
* This function will be called prior to all of onlp_fani_* functions.
*/
int
onlp_fani_init(void)
{
return ONLP_STATUS_OK;
}
int
onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info)
{
int rc = 0;
int fid;
VALIDATE(id);
fid = ONLP_OID_ID_GET(id);
*info = finfo[fid];
switch (fid)
{
case FAN_1_ON_PSU_1:
rc = _onlp_fani_info_get_fan_on_psu(PSU1_ID, info);
break;
case FAN_1_ON_PSU_2:
rc = _onlp_fani_info_get_fan_on_psu(PSU2_ID, info);
break;
case FAN_1_ON_PSU_3:
rc = _onlp_fani_info_get_fan_on_psu(PSU3_ID, info);
break;
case FAN_1_ON_PSU_4:
rc = _onlp_fani_info_get_fan_on_psu(PSU4_ID, info);
break;
case FAN_1_ON_FAN_BOARD:
case FAN_2_ON_FAN_BOARD:
case FAN_3_ON_FAN_BOARD:
case FAN_4_ON_FAN_BOARD:
case FAN_5_ON_FAN_BOARD:
case FAN_6_ON_FAN_BOARD:
case FAN_7_ON_FAN_BOARD:
case FAN_8_ON_FAN_BOARD:
rc =_onlp_fani_info_get_fan(fid, info);
break;
default:
rc = ONLP_STATUS_E_INVALID;
break;
}
return rc;
}

View File

@@ -0,0 +1,244 @@
/************************************************************
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
* Copyright 2017 Accton Technology Corporation.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*
* </bsn.cl>
************************************************************
*
*
*
***********************************************************/
#include <onlplib/file.h>
#include <onlp/platformi/ledi.h>
#include "platform_lib.h"
#define LED_FORMAT "/sys/class/leds/as7926_80xk_led::%s/brightness"
#define VALIDATE(_id) \
do { \
if(!ONLP_OID_IS_LED(_id)) { \
return ONLP_STATUS_E_INVALID; \
} \
} while(0)
/* LED related data
*/
enum led_light_mode {
LED_MODE_OFF,
LED_MODE_RED = 10,
LED_MODE_RED_BLINKING = 11,
LED_MODE_ORANGE = 12,
LED_MODE_ORANGE_BLINKING = 13,
LED_MODE_YELLOW = 14,
LED_MODE_YELLOW_BLINKING = 15,
LED_MODE_GREEN = 16,
LED_MODE_GREEN_BLINKING = 17,
LED_MODE_BLUE = 18,
LED_MODE_BLUE_BLINKING = 19,
LED_MODE_PURPLE = 20,
LED_MODE_PURPLE_BLINKING = 21,
LED_MODE_AUTO = 22,
LED_MODE_AUTO_BLINKING = 23,
LED_MODE_WHITE = 24,
LED_MODE_WHITE_BLINKING = 25,
LED_MODE_CYAN = 26,
LED_MODE_CYAN_BLINKING = 27,
LED_MODE_UNKNOWN = 99
};
typedef struct led_light_mode_map {
enum onlp_led_id id;
enum led_light_mode driver_led_mode;
enum onlp_led_mode_e onlp_led_mode;
} led_light_mode_map_t;
led_light_mode_map_t led_map[] = {
{LED_LOC, LED_MODE_OFF, ONLP_LED_MODE_OFF},
{LED_LOC, LED_MODE_GREEN, ONLP_LED_MODE_GREEN},
{LED_LOC, LED_MODE_RED, ONLP_LED_MODE_RED},
{LED_LOC, LED_MODE_GREEN_BLINKING, ONLP_LED_MODE_GREEN_BLINKING},
{LED_DIAG, LED_MODE_OFF, ONLP_LED_MODE_OFF},
{LED_DIAG, LED_MODE_GREEN, ONLP_LED_MODE_GREEN},
{LED_DIAG, LED_MODE_RED, ONLP_LED_MODE_RED},
{LED_DIAG, LED_MODE_GREEN_BLINKING, ONLP_LED_MODE_GREEN_BLINKING},
{LED_DIAG, LED_MODE_BLUE, ONLP_LED_MODE_BLUE},
{LED_FAN, LED_MODE_OFF, ONLP_LED_MODE_OFF},
{LED_FAN, LED_MODE_GREEN, ONLP_LED_MODE_GREEN},
{LED_FAN, LED_MODE_YELLOW, ONLP_LED_MODE_YELLOW},
{LED_FAN, LED_MODE_RED, ONLP_LED_MODE_RED},
{LED_PSU, LED_MODE_OFF, ONLP_LED_MODE_OFF},
{LED_PSU, LED_MODE_GREEN, ONLP_LED_MODE_GREEN},
{LED_PSU, LED_MODE_YELLOW, ONLP_LED_MODE_YELLOW},
{LED_PSU, LED_MODE_RED, ONLP_LED_MODE_RED},
};
static char *leds[] = /* must map with onlp_led_id */
{
"reserved",
"psu",
"fan",
"diag",
"loc",
};
/*
* Get the information for the given LED OID.
*/
static onlp_led_info_t linfo[] =
{
{ }, /* Not used */
{
{ ONLP_LED_ID_CREATE(LED_PSU), "Chassis LED 1 (PSU LED)", 0 },
ONLP_LED_STATUS_PRESENT,
ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_YELLOW | ONLP_LED_CAPS_RED,
},
{
{ ONLP_LED_ID_CREATE(LED_FAN), "Chassis LED 2 (FAN LED)", 0 },
ONLP_LED_STATUS_PRESENT,
ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_YELLOW | ONLP_LED_CAPS_RED,
},
{
{ ONLP_LED_ID_CREATE(LED_DIAG), "Chassis LED 3 (DIAG LED)", 0 },
ONLP_LED_STATUS_PRESENT,
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED |
ONLP_LED_MODE_GREEN_BLINKING | ONLP_LED_CAPS_BLUE,
},
{
{ ONLP_LED_ID_CREATE(LED_LOC), "Chassis LED 4 (LOC LED)", 0 },
ONLP_LED_STATUS_PRESENT,
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED |
ONLP_LED_MODE_GREEN_BLINKING,
}
};
static int driver_to_onlp_led_mode(enum onlp_led_id id, enum led_light_mode driver_led_mode)
{
int i, nsize = sizeof(led_map)/sizeof(led_map[0]);
for (i = 0; i < nsize; i++)
{
if (id == led_map[i].id && driver_led_mode == led_map[i].driver_led_mode)
{
return led_map[i].onlp_led_mode;
}
}
return 0;
}
static int onlp_to_driver_led_mode(enum onlp_led_id id, onlp_led_mode_t onlp_led_mode)
{
int i, nsize = sizeof(led_map)/sizeof(led_map[0]);
for(i = 0; i < nsize; i++)
{
if (id == led_map[i].id && onlp_led_mode == led_map[i].onlp_led_mode)
{
return led_map[i].driver_led_mode;
}
}
return 0;
}
/*
* This function will be called prior to any other onlp_ledi_* functions.
*/
int
onlp_ledi_init(void)
{
/*
* LED GREEN
*/
onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_DIAG), ONLP_LED_MODE_GREEN);
onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_LOC), ONLP_LED_MODE_GREEN);
return ONLP_STATUS_OK;
}
int
onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info)
{
int lid, value;
VALIDATE(id);
lid = ONLP_OID_ID_GET(id);
/* Set the onlp_oid_hdr_t and capabilities */
*info = linfo[ONLP_OID_ID_GET(id)];
/* Get LED mode */
if (onlp_file_read_int(&value, LED_FORMAT, leds[lid]) < 0) {
DEBUG_PRINT("Unable to read status from file "LED_FORMAT, leds[lid]);
return ONLP_STATUS_E_INTERNAL;
}
info->mode = driver_to_onlp_led_mode(lid, value);
/* Set the on/off status */
if (info->mode != ONLP_LED_MODE_OFF) {
info->status |= ONLP_LED_STATUS_ON;
}
return ONLP_STATUS_OK;
}
/*
* Turn an LED on or off.
*
* This function will only be called if the LED OID supports the ONOFF
* capability.
*
* What 'on' means in terms of colors or modes for multimode LEDs is
* up to the platform to decide. This is intended as baseline toggle mechanism.
*/
int
onlp_ledi_set(onlp_oid_t id, int on_or_off)
{
VALIDATE(id);
if (!on_or_off) {
return onlp_ledi_mode_set(id, ONLP_LED_MODE_OFF);
}
return ONLP_STATUS_E_UNSUPPORTED;
}
/*
* This function puts the LED into the given mode. It is a more functional
* interface for multimode LEDs.
*
* Only modes reported in the LED's capabilities will be attempted.
*/
int
onlp_ledi_mode_set(onlp_oid_t id, onlp_led_mode_t mode)
{
int lid;
VALIDATE(id);
lid = ONLP_OID_ID_GET(id);
if (onlp_file_write_int(onlp_to_driver_led_mode(lid , mode), LED_FORMAT, leds[lid]) < 0) {
return ONLP_STATUS_E_INTERNAL;
}
return ONLP_STATUS_OK;
}

View File

@@ -0,0 +1,275 @@
/************************************************************
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
* Copyright 2014 Accton Technology Corporation.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*
* </bsn.cl>
************************************************************
*
*
*
***********************************************************/
#include <onlp/onlp.h>
#include <onlplib/file.h>
#include <onlplib/i2c.h>
#include <AIM/aim.h>
#include "platform_lib.h"
#include <linux/i2c-devices.h>
#include <unistd.h>
#include <fcntl.h>
#define PSU_MODEL_NAME_LEN 17
#define PSU_SERIAL_NUMBER_LEN 18
#define PSU_NODE_MAX_PATH_LEN 64
#define PSU_FAN_DIR_LEN 3
int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len)
{
int fd;
int len;
if ((buffer == NULL) || (buf_size < 0)) {
return -1;
}
if ((fd = open(filename, O_RDONLY)) == -1) {
return -1;
}
if ((len = read(fd, buffer, buf_size)) < 0) {
close(fd);
return -1;
}
if ((close(fd) == -1)) {
return -1;
}
if ((len > buf_size) || (data_len != 0 && len != data_len)) {
return -1;
}
return 0;
}
int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len)
{
int ret;
if (data_len >= buf_size) {
return -1;
}
ret = onlp_file_read_binary(filename, buffer, buf_size-1, data_len);
if (ret == 0) {
buffer[buf_size-1] = '\0';
}
return ret;
}
int psu_serial_number_get(int id, char *serial, int serial_len)
{
int size = 0;
int ret = ONLP_STATUS_OK;
char *prefix = NULL;
if (serial == NULL || serial_len < PSU_SERIAL_NUMBER_LEN) {
return ONLP_STATUS_E_PARAM;
}
switch(id)
{
case PSU1_ID: prefix = PSU1_AC_PMBUS_PREFIX;
break;
case PSU2_ID: prefix = PSU2_AC_PMBUS_PREFIX;
break;
case PSU3_ID: prefix = PSU3_AC_PMBUS_PREFIX;
break;
case PSU4_ID: prefix = PSU4_AC_PMBUS_PREFIX;
break;
default: break;
}
ret = onlp_file_read((uint8_t*)serial, PSU_SERIAL_NUMBER_LEN, &size, "%s%s", prefix, "psu_mfr_serial");
if (ret != ONLP_STATUS_OK || size != PSU_SERIAL_NUMBER_LEN) {
return ONLP_STATUS_E_INTERNAL;
}
serial[PSU_SERIAL_NUMBER_LEN] = '\0';
return ONLP_STATUS_OK;
}
psu_type_t psu_type_get(int id, char* modelname, int modelname_len)
{
char *node = NULL;
char model_name[PSU_MODEL_NAME_LEN + 1] = {0};
char fan_dir[PSU_FAN_DIR_LEN + 1] = {0};
/* Check AC model name */
switch(id)
{
case PSU1_ID: node = PSU1_AC_PMBUS_NODE(psu_mfr_model);
break;
case PSU2_ID: node = PSU2_AC_PMBUS_NODE(psu_mfr_model);
break;
case PSU3_ID: node = PSU3_AC_PMBUS_NODE(psu_mfr_model);
break;
case PSU4_ID: node = PSU4_AC_PMBUS_NODE(psu_mfr_model);
break;
default: break;
}
if (onlp_file_read_string(node, model_name, sizeof(model_name), 0) != 0) {
return PSU_TYPE_UNKNOWN;
}
if ((strncmp(model_name, "PTT1600", strlen("PTT1600")) != 0) &&
(strncmp(model_name, "FSJ001", strlen("FSJ001")) != 0)) {
return PSU_TYPE_UNKNOWN;
}
if (modelname) {
strncpy(modelname, model_name, PSU_MODEL_NAME_LEN - 1);
}
switch(id)
{
case PSU1_ID: node = PSU1_AC_PMBUS_NODE(psu_fan_dir);
break;
case PSU2_ID: node = PSU2_AC_PMBUS_NODE(psu_fan_dir);
break;
case PSU3_ID: node = PSU3_AC_PMBUS_NODE(psu_fan_dir);
break;
case PSU4_ID: node = PSU4_AC_PMBUS_NODE(psu_fan_dir);
break;
default: break;
}
if (onlp_file_read_string(node, fan_dir, sizeof(fan_dir), 0) != 0) {
return PSU_TYPE_UNKNOWN;
}
if (strncmp(model_name, "PTT1600", strlen("PTT1600")) == 0) {
if ((strncmp(fan_dir, "B2F", strlen("B2F")) == 0) ||
(strncmp(fan_dir, "AFI", strlen("AFI")) == 0)) {
return PSU_TYPE_AC_B2F;
}
else if ((strncmp(fan_dir, "F2B", strlen("F2B")) == 0) ||
(strncmp(fan_dir, "AFO", strlen("AFO")) == 0)) {
return PSU_TYPE_AC_F2B;
}
}
return PSU_TYPE_AC_F2B;
}
int psu_ym2651y_pmbus_info_get(int id, char *node, int *value)
{
char *prefix = NULL;
*value = 0;
switch(id)
{
case PSU1_ID: prefix = PSU1_AC_PMBUS_PREFIX;
break;
case PSU2_ID: prefix = PSU2_AC_PMBUS_PREFIX;
break;
case PSU3_ID: prefix = PSU3_AC_PMBUS_PREFIX;
break;
case PSU4_ID: prefix = PSU4_AC_PMBUS_PREFIX;
break;
default: break;
}
if (onlp_file_read_int(value, "%s%s", prefix, node) < 0) {
AIM_LOG_ERROR("Unable to read status from file(%s%s)\r\n", prefix, node);
return ONLP_STATUS_E_INTERNAL;
}
return ONLP_STATUS_OK;
}
int psu_ym2651y_pmbus_info_set(int id, char *node, int value)
{
char *prefix = NULL;
switch(id)
{
case PSU1_ID: prefix = PSU1_AC_PMBUS_PREFIX;
break;
case PSU2_ID: prefix = PSU2_AC_PMBUS_PREFIX;
break;
case PSU3_ID: prefix = PSU3_AC_PMBUS_PREFIX;
break;
case PSU4_ID: prefix = PSU4_AC_PMBUS_PREFIX;
break;
default: break;
}
if (onlp_file_write_int(value, "%s%s", prefix, node) < 0) {
AIM_LOG_ERROR("Unable to write data to file (%s%s)\r\n", prefix, node);
return ONLP_STATUS_E_INTERNAL;
}
return ONLP_STATUS_OK;
}
int sfpi_i2c_read(int bus, uint8_t addr, uint8_t offset, int size,
uint8_t* rdata, uint32_t flags)
{
int i;
int fd;
fd = onlp_i2c_open(bus, addr, flags);
if(fd < 0) {
return fd;
}
for(i = 0; i < size; i++) {
int rv = -1;
int retries = (flags & ONLP_I2C_F_DISABLE_READ_RETRIES) ? 1: ONLPLIB_CONFIG_I2C_READ_RETRY_COUNT;
while(retries-- && rv < 0) {
rv = i2c_smbus_read_byte_data(fd, offset+i);
}
if(rv < 0) {
goto error;
}
else {
rdata[i] = rv;
}
}
close(fd);
return 0;
error:
close(fd);
return ONLP_STATUS_E_I2C;
}
int sfpi_i2c_readb(int bus, uint8_t addr, uint8_t offset, uint32_t flags)
{
uint8_t byte;
int rv = sfpi_i2c_read(bus, addr, offset, 1, &byte, flags);
return (rv < 0) ? rv : byte;
}

View File

@@ -0,0 +1,117 @@
/************************************************************
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
* Copyright 2014 Accton Technology Corporation.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*
* </bsn.cl>
************************************************************
*
*
*
***********************************************************/
#ifndef __PLATFORM_LIB_H__
#define __PLATFORM_LIB_H__
#include "x86_64_accton_as7926_80xk_log.h"
#define CHASSIS_FAN_COUNT 8
#define CHASSIS_THERMAL_COUNT 13
#define CHASSIS_LED_COUNT 4
#define CHASSIS_PSU_COUNT 4
#define PSU1_ID 1
#define PSU2_ID 2
#define PSU3_ID 3
#define PSU4_ID 4
#define PSU1_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/18-005b/"
#define PSU2_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/18-0059/"
#define PSU3_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/18-005a/"
#define PSU4_AC_PMBUS_PREFIX "/sys/bus/i2c/devices/18-0058/"
#define PSU1_AC_PMBUS_NODE(node) PSU1_AC_PMBUS_PREFIX#node
#define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node
#define PSU3_AC_PMBUS_NODE(node) PSU3_AC_PMBUS_PREFIX#node
#define PSU4_AC_PMBUS_NODE(node) PSU4_AC_PMBUS_PREFIX#node
#define PSU1_AC_HWMON_PREFIX "/sys/bus/i2c/devices/18-0053/"
#define PSU2_AC_HWMON_PREFIX "/sys/bus/i2c/devices/18-0051/"
#define PSU3_AC_HWMON_PREFIX "/sys/bus/i2c/devices/18-0052/"
#define PSU4_AC_HWMON_PREFIX "/sys/bus/i2c/devices/18-0050/"
#define FAN_BOARD_PATH "/sys/bus/i2c/devices/22-0066/"
#define FAN_NODE(node) FAN_BOARD_PATH#node
#define IDPROM_PATH "/sys/bus/i2c/devices/0-0057/eeprom"
enum onlp_led_id
{
LED_RESERVED = 0,
LED_PSU,
LED_FAN,
LED_DIAG,
LED_LOC
};
enum onlp_thermal_id
{
THERMAL_RESERVED = 0,
THERMAL_CPU_CORE,
THERMAL_1_ON_MAIN_BOTTOM_BOARD,
THERMAL_2_ON_MAIN_BOTTOM_BOARD,
THERMAL_3_ON_MAIN_BOTTOM_BOARD,
THERMAL_4_ON_MAIN_BOTTOM_BOARD,
THERMAL_5_ON_MAIN_BOTTOM_BOARD,
THERMAL_6_ON_MAIN_BOTTOM_BOARD,
THERMAL_1_ON_MAIN_TOP_BOARD,
THERMAL_2_ON_MAIN_TOP_BOARD,
THERMAL_3_ON_MAIN_TOP_BOARD,
THERMAL_4_ON_MAIN_TOP_BOARD,
THERMAL_5_ON_MAIN_TOP_BOARD,
THERMAL_6_ON_MAIN_TOP_BOARD,
THERMAL_1_ON_PSU1,
THERMAL_1_ON_PSU2,
THERMAL_1_ON_PSU3,
THERMAL_1_ON_PSU4,
};
typedef enum psu_type {
PSU_TYPE_UNKNOWN,
PSU_TYPE_AC_F2B,
PSU_TYPE_AC_B2F
} psu_type_t;
psu_type_t psu_type_get(int id, char* modelname, int modelname_len);
int psu_serial_number_get(int id, char *serial, int serial_len);
int psu_ym2651y_pmbus_info_get(int id, char *node, int *value);
int psu_ym2651y_pmbus_info_set(int id, char *node, int value);
int sfpi_i2c_read(int bus, uint8_t addr, uint8_t offset, int size,
uint8_t* rdata, uint32_t flags);
int sfpi_i2c_readb(int bus, uint8_t addr, uint8_t offset, uint32_t flags);
#define DEBUG_MODE 0
#if (DEBUG_MODE == 1)
#define DEBUG_PRINT(fmt, args...) \
printf("%s:%s[%d]: " fmt "\r\n", __FILE__, __FUNCTION__, __LINE__, ##args)
#else
#define DEBUG_PRINT(fmt, args...)
#endif
#endif /* __PLATFORM_LIB_H__ */

View File

@@ -0,0 +1,176 @@
/************************************************************
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
* Copyright 2014 Accton Technology Corporation.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*
* </bsn.cl>
************************************************************
*
*
*
***********************************************************/
#include <onlp/platformi/psui.h>
#include <onlplib/file.h>
#include "platform_lib.h"
#define PSU_STATUS_PRESENT 1
#define PSU_STATUS_POWER_GOOD 1
#define VALIDATE(_id) \
do { \
if(!ONLP_OID_IS_PSU(_id)) { \
return ONLP_STATUS_E_INVALID; \
} \
} while(0)
int
onlp_psui_init(void)
{
return ONLP_STATUS_OK;
}
static int
psu_ym2651y_info_get(onlp_psu_info_t* info)
{
int val = 0;
int index = ONLP_OID_ID_GET(info->hdr.id);
/* Set capability
*/
info->caps = ONLP_PSU_CAPS_AC;
if (info->status & ONLP_PSU_STATUS_FAILED) {
return ONLP_STATUS_OK;
}
/* Set the associated oid_table */
info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT);
info->hdr.coids[1] = ONLP_THERMAL_ID_CREATE(index + CHASSIS_THERMAL_COUNT);
/* Read voltage, current and power */
if (psu_ym2651y_pmbus_info_get(index, "psu_v_out", &val) == 0) {
info->mvout = val;
info->caps |= ONLP_PSU_CAPS_VOUT;
}
if (psu_ym2651y_pmbus_info_get(index, "psu_i_out", &val) == 0) {
info->miout = val;
info->caps |= ONLP_PSU_CAPS_IOUT;
}
if (psu_ym2651y_pmbus_info_get(index, "psu_p_out", &val) == 0) {
info->mpout = val;
info->caps |= ONLP_PSU_CAPS_POUT;
}
psu_serial_number_get(index, info->serial, sizeof(info->serial));
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 },
},
{
{ ONLP_PSU_ID_CREATE(PSU3_ID), "PSU-3", 0 },
},
{
{ ONLP_PSU_ID_CREATE(PSU4_ID), "PSU-4", 0 },
}
};
int
onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info)
{
int val = 0;
int ret = ONLP_STATUS_OK;
int index = ONLP_OID_ID_GET(id);
psu_type_t psu_type;
char *prefix = NULL;
VALIDATE(id);
memset(info, 0, sizeof(onlp_psu_info_t));
*info = pinfo[index]; /* Set the onlp_oid_hdr_t */
switch(index)
{
case PSU1_ID: prefix = PSU1_AC_HWMON_PREFIX;
break;
case PSU2_ID: prefix = PSU2_AC_HWMON_PREFIX;
break;
case PSU3_ID: prefix = PSU3_AC_HWMON_PREFIX;
break;
case PSU4_ID: prefix = PSU4_AC_HWMON_PREFIX;
break;
default: break;
}
if (onlp_file_read_int(&val, "%s%s", prefix, "psu_present") < 0) {
AIM_LOG_ERROR("Unable to read present status from PSU(%d)\r\n", index);
return ONLP_STATUS_E_INTERNAL;
}
if (val != PSU_STATUS_PRESENT) {
info->status &= ~ONLP_PSU_STATUS_PRESENT;
return ONLP_STATUS_OK;
}
info->status |= ONLP_PSU_STATUS_PRESENT;
/* Get power good status */
if (onlp_file_read_int(&val, "%s%s", prefix, "psu_power_good") < 0) {
AIM_LOG_ERROR("Unable to read power status from PSU(%d)\r\n", index);
return ONLP_STATUS_E_INTERNAL;
}
if (val != PSU_STATUS_POWER_GOOD) {
info->status |= ONLP_PSU_STATUS_FAILED;
}
/* Get PSU type
*/
psu_type = psu_type_get(index, info->model, sizeof(info->model));
switch (psu_type) {
case PSU_TYPE_AC_F2B:
case PSU_TYPE_AC_B2F:
ret = psu_ym2651y_info_get(info);
break;
case PSU_TYPE_UNKNOWN: /* User insert a unknown PSU or unplugged.*/
info->status |= ONLP_PSU_STATUS_UNPLUGGED;
info->status &= ~ONLP_PSU_STATUS_FAILED;
ret = ONLP_STATUS_OK;
break;
default:
ret = ONLP_STATUS_E_UNSUPPORTED;
break;
}
return ret;
}

View File

@@ -0,0 +1,191 @@
/************************************************************
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
* Copyright 2017 Accton Technology Corporation.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*
* </bsn.cl>
************************************************************
*
*
*
***********************************************************/
#include <onlp/platformi/sfpi.h>
#include <onlplib/i2c.h>
#include <onlplib/file.h>
#include "platform_lib.h"
#define EEPROM_I2C_ADDR 0x50
#define EEPROM_START_OFFSET 0x0
#define NUM_OF_SFP_PORT 80
static const int port_bus_index[NUM_OF_SFP_PORT] = {
33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, 54, 55, 56,
57, 58, 59, 60, 61, 62, 63, 64,
65, 66, 67, 68, 69, 70, 71, 72,
97, 98, 99, 100, 101, 102, 103,
104, 105, 106, 107, 108, 109,
110, 111, 112, 113, 114, 115,
116, 117, 118, 119, 120, 121,
122, 123, 124, 125, 126, 127,
128, 129, 130, 131, 132, 133,
134, 135, 136,
};
#define PORT_BUS_INDEX(port) (port_bus_index[port])
#define PORT_FORMAT "/sys/bus/i2c/devices/%d-0050/%s"
#define MODULE_PRESENT_BOTTOM_BOARD_CPLD1_FORMAT "/sys/bus/i2c/devices/12-0062/module_present_%d"
#define MODULE_PRESENT_BOTTOM_BOARD_CPLD2_FORMAT "/sys/bus/i2c/devices/13-0063/module_present_%d"
#define MODULE_PRESENT_TOP_BOARD_CPLD3_FORMAT "/sys/bus/i2c/devices/76-0062/module_present_%d"
#define MODULE_PRESENT_TOP_BOARD_CPLD4_FORMAT "/sys/bus/i2c/devices/77-0063/module_present_%d"
/************************************************************
*
* SFPI Entry Points
*
***********************************************************/
int
onlp_sfpi_init(void)
{
/* Called at initialization time */
return ONLP_STATUS_OK;
}
int
onlp_sfpi_bitmap_get(onlp_sfp_bitmap_t* bmap)
{
/*
* Ports {0, 80}
*/
int p;
AIM_BITMAP_CLR_ALL(bmap);
for(p = 0; p < NUM_OF_SFP_PORT; p++) {
AIM_BITMAP_SET(bmap, p);
}
return ONLP_STATUS_OK;
}
int
onlp_sfpi_is_present(int port)
{
/*
* Return 1 if present.
* Return 0 if not present.
* Return < 0 if error.
*/
int present;
if (port >= 0 && port <=19) {
if (onlp_file_read_int(&present, MODULE_PRESENT_BOTTOM_BOARD_CPLD1_FORMAT, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
}
else if (port >= 20 && port <=39){
if (onlp_file_read_int(&present, MODULE_PRESENT_BOTTOM_BOARD_CPLD2_FORMAT, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
}
else if (port >= 40 && port <=59){
if (onlp_file_read_int(&present, MODULE_PRESENT_TOP_BOARD_CPLD3_FORMAT, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
}
else if (port >= 60 && port <=79){
if (onlp_file_read_int(&present, MODULE_PRESENT_TOP_BOARD_CPLD4_FORMAT, (port+1)) < 0) {
AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
}
return present;
}
int
onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
{
return ONLP_STATUS_E_UNSUPPORTED;
}
int
onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst)
{
return ONLP_STATUS_OK;
}
int
onlp_sfpi_eeprom_read(int port, uint8_t data[256])
{
/*
* Read the SFP eeprom into data[]
*
* Return MISSING if SFP is missing.
* Return OK if eeprom is read
*/
int size = 0;
if(onlp_file_read(data, 256, &size, PORT_FORMAT, PORT_BUS_INDEX(port), "eeprom") != ONLP_STATUS_OK) {
AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port);
return ONLP_STATUS_E_INTERNAL;
}
if(size != 256) {
return ONLP_STATUS_E_INTERNAL;
}
return ONLP_STATUS_OK;
}
int
onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr)
{
int bus = PORT_BUS_INDEX(port);
return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE);
}
int
onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value)
{
int bus = PORT_BUS_INDEX(port);
return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE);
}
int
onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr)
{
int bus = PORT_BUS_INDEX(port);
return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE);
}
int
onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value)
{
int bus = PORT_BUS_INDEX(port);
return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE);
}
int
onlp_sfpi_denit(void)
{
return ONLP_STATUS_OK;
}

View File

@@ -0,0 +1,361 @@
/************************************************************
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
* Copyright 2017 Accton Technology Corporation.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*
* </bsn.cl>
************************************************************
*
*
*
***********************************************************/
#include <unistd.h>
#include <fcntl.h>
#include <onlplib/file.h>
#include <onlp/platformi/sysi.h>
#include <onlp/platformi/ledi.h>
#include <onlp/platformi/thermali.h>
#include <onlp/platformi/fani.h>
#include <onlp/platformi/psui.h>
#include "platform_lib.h"
#include "x86_64_accton_as7926_80xk_int.h"
#include "x86_64_accton_as7926_80xk_log.h"
#define CPLD_VERSION_FORMAT "/sys/bus/i2c/devices/%s/version"
#define NUM_OF_CPLD 4
static char* cpld_path[NUM_OF_CPLD] =
{
"11-0060",
"12-0062",
"13-0063",
"22-0066"
};
const char*
onlp_sysi_platform_get(void)
{
return "x86-64-accton-as7926-80xk-r0";
}
int
onlp_sysi_onie_data_get(uint8_t** data, int* size)
{
uint8_t* rdata = aim_zmalloc(256);
if(onlp_file_read(rdata, 256, size, IDPROM_PATH) == ONLP_STATUS_OK) {
if(*size == 256) {
*data = rdata;
return ONLP_STATUS_OK;
}
}
aim_free(rdata);
*size = 0;
return ONLP_STATUS_E_INTERNAL;
}
int
onlp_sysi_oids_get(onlp_oid_t* table, int max)
{
int i;
onlp_oid_t* e = table;
memset(table, 0, max*sizeof(onlp_oid_t));
/* 13 Thermal sensors on the chassis */
for (i = 1; i <= CHASSIS_THERMAL_COUNT; i++) {
*e++ = ONLP_THERMAL_ID_CREATE(i);
}
/* 4 LEDs on the chassis */
for (i = 1; i <= CHASSIS_LED_COUNT; i++) {
*e++ = ONLP_LED_ID_CREATE(i);
}
/* 4 PSUs on the chassis */
for (i = 1; i <= CHASSIS_PSU_COUNT; i++) {
*e++ = ONLP_PSU_ID_CREATE(i);
}
/* 8 Fans on the chassis */
for (i = 1; i <= CHASSIS_FAN_COUNT; i++) {
*e++ = ONLP_FAN_ID_CREATE(i);
}
return 0;
}
int
onlp_sysi_platform_info_get(onlp_platform_info_t* pi)
{
int i, v[NUM_OF_CPLD] = {0};
for (i = 0; i < AIM_ARRAYSIZE(cpld_path); i++) {
v[i] = 0;
if(onlp_file_read_int(v+i, CPLD_VERSION_FORMAT , cpld_path[i]) < 0) {
return ONLP_STATUS_E_INTERNAL;
}
}
pi->cpld_versions = aim_fstrdup("%d.%d.%d.%d", v[0], v[1], v[2], v[3]);
return ONLP_STATUS_OK;
}
void
onlp_sysi_platform_info_free(onlp_platform_info_t* pi)
{
aim_free(pi->cpld_versions);
}
int
onlp_sysi_platform_manage_init(void)
{
return 0;
}
#define FAN_DUTY_MAX (100)
#define FAN_DUTY_MIN (52)
static int
sysi_fanctrl_fan_fault_policy(onlp_fan_info_t fi[CHASSIS_FAN_COUNT],
onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT],
int *adjusted)
{
int i;
*adjusted = 0;
/* Bring fan speed to FAN_DUTY_MAX if any fan is not operational */
for (i = 0; i < CHASSIS_FAN_COUNT; i++) {
if (!(fi[i].status & ONLP_FAN_STATUS_FAILED)) {
continue;
}
*adjusted = 1;
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX);
}
return ONLP_STATUS_OK;
}
static int
sysi_fanctrl_fan_absent_policy(onlp_fan_info_t fi[CHASSIS_FAN_COUNT],
onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT],
int *adjusted)
{
int i;
*adjusted = 0;
/* Bring fan speed to FAN_DUTY_MAX if fan is not present */
for (i = 0; i < CHASSIS_FAN_COUNT; i++) {
if (fi[i].status & ONLP_FAN_STATUS_PRESENT) {
continue;
}
*adjusted = 1;
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX);
}
return ONLP_STATUS_OK;
}
static int
sysi_fanctrl_fan_unknown_speed_policy(onlp_fan_info_t fi[CHASSIS_FAN_COUNT],
onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT],
int *adjusted)
{
int i, match = 0;
int fanduty;
int legal_duties[] = {FAN_DUTY_MIN, 64, 76, 88, FAN_DUTY_MAX};
*adjusted = 0;
if (onlp_file_read_int(&fanduty, FAN_NODE(fan_duty_cycle_percentage)) < 0) {
*adjusted = 1;
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MIN);
}
/* Bring fan speed to min if current speed is not expected
*/
for (i = 0; i < AIM_ARRAYSIZE(legal_duties); i++) {
if (fanduty != legal_duties[i]) {
continue;
}
match = 1;
break;
}
if (!match) {
*adjusted = 1;
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MIN);
}
return ONLP_STATUS_OK;
}
static int
sysi_fanctrl_overall_thermal_sensor_policy(onlp_fan_info_t fi[CHASSIS_FAN_COUNT],
onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT],
int *adjusted)
{
int i, num_of_sensor = 0, temp_avg = 0;
for (i = (THERMAL_1_ON_MAIN_BOTTOM_BOARD); i <= (THERMAL_6_ON_MAIN_TOP_BOARD); i++) {
num_of_sensor++;
temp_avg += ti[i-1].mcelsius;
}
temp_avg /= num_of_sensor;
*adjusted = 1;
if (temp_avg > 57000) {
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX);
}
else if (temp_avg > 52000) {
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), 88);
}
else if (temp_avg > 46000) {
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), 76);
}
else if (temp_avg > 43000) {
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), 64);
}
return onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MIN);
}
typedef int (*fan_control_policy)(onlp_fan_info_t fi[CHASSIS_FAN_COUNT],
onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT],
int *adjusted);
fan_control_policy fan_control_policies[] = {
sysi_fanctrl_fan_fault_policy,
sysi_fanctrl_fan_absent_policy,
sysi_fanctrl_fan_unknown_speed_policy,
sysi_fanctrl_overall_thermal_sensor_policy,
};
int
onlp_sysi_platform_manage_fans(void)
{
int i, rc;
onlp_fan_info_t fi[CHASSIS_FAN_COUNT];
onlp_thermal_info_t ti[CHASSIS_THERMAL_COUNT];
memset(fi, 0, sizeof(fi));
memset(ti, 0, sizeof(ti));
/* Get fan status
*/
for (i = 0; i < CHASSIS_FAN_COUNT; i++) {
rc = onlp_fani_info_get(ONLP_FAN_ID_CREATE(i+1), &fi[i]);
if (rc != ONLP_STATUS_OK) {
onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX);
AIM_LOG_ERROR("Unable to get fan(%d) status\r\n", i+1);
return ONLP_STATUS_E_INTERNAL;
}
}
/* Get thermal sensor status
*/
for (i = 0; i < CHASSIS_THERMAL_COUNT; i++) {
rc = onlp_thermali_info_get(ONLP_THERMAL_ID_CREATE(i+1), &ti[i]);
if (rc != ONLP_STATUS_OK) {
onlp_fani_percentage_set(ONLP_FAN_ID_CREATE(1), FAN_DUTY_MAX);
AIM_LOG_ERROR("Unable to get thermal(%d) status\r\n", i+1);
return ONLP_STATUS_E_INTERNAL;
}
}
/* Apply thermal policy according the policy list,
* If fan duty is adjusted by one of the policies, skip the others
*/
for (i = 0; i < AIM_ARRAYSIZE(fan_control_policies); i++) {
int adjusted = 0;
rc = fan_control_policies[i](fi, ti, &adjusted);
if (!adjusted) {
continue;
}
return rc;
}
return ONLP_STATUS_OK;
}
int
onlp_sysi_platform_manage_leds(void)
{
int i = 0, fan_fault = 0, psu_fault = 0;
/* Get each fan status
*/
for (i = 1; i <= CHASSIS_FAN_COUNT; i++)
{
onlp_fan_info_t fan_info;
if (onlp_fani_info_get(ONLP_FAN_ID_CREATE(i), &fan_info) != ONLP_STATUS_OK) {
AIM_LOG_ERROR("Unable to get fan(%d) status\r\n", i);
return ONLP_STATUS_E_INTERNAL;
}
if ((!(fan_info.status & ONLP_FAN_STATUS_PRESENT)) | (fan_info.status & ONLP_FAN_STATUS_FAILED)) {
AIM_LOG_ERROR("Fan(%d) is not present or not working\r\n", i);
fan_fault = fan_fault + 1;
}
}
if (fan_fault > 1) {
onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FAN), ONLP_LED_MODE_RED);
}else if (fan_fault == 1) {
onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FAN), ONLP_LED_MODE_YELLOW);
}else {
onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_FAN), ONLP_LED_MODE_GREEN);
}
/* Get each psu status
*/
for (i = 1; i <= CHASSIS_PSU_COUNT; i++)
{
onlp_psu_info_t psu_info;
if (onlp_psui_info_get(ONLP_PSU_ID_CREATE(i), &psu_info) != ONLP_STATUS_OK) {
AIM_LOG_ERROR("Unable to get psu(%d) status\r\n", i);
return ONLP_STATUS_E_INTERNAL;
}
if ((!(psu_info.status & ONLP_PSU_STATUS_PRESENT)) | (psu_info.status & ONLP_PSU_STATUS_FAILED)) {
AIM_LOG_ERROR("Psu(%d) is not present or not working\r\n", i);
psu_fault = psu_fault + 1;
}
}
if (psu_fault > 1) {
onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_PSU), ONLP_LED_MODE_RED);
}else if (psu_fault == 1) {
onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_PSU), ONLP_LED_MODE_YELLOW);
}else {
onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_PSU), ONLP_LED_MODE_GREEN);
}
return ONLP_STATUS_OK;
}

View File

@@ -0,0 +1,164 @@
/************************************************************
* <bsn.cl fy=2014 v=onl>
*
* Copyright 2014 Big Switch Networks, Inc.
* Copyright 2014 Accton Technology Corporation.
*
* Licensed under the Eclipse Public License, Version 1.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*
* </bsn.cl>
************************************************************
*
* Thermal Sensor Platform Implementation.
*
***********************************************************/
#include <onlplib/file.h>
#include <onlp/platformi/thermali.h>
#include "platform_lib.h"
#define VALIDATE(_id) \
do { \
if(!ONLP_OID_IS_THERMAL(_id)) { \
return ONLP_STATUS_E_INVALID; \
} \
} while(0)
static char* devfiles__[] = /* must map with onlp_thermal_id */
{
"reserved",
"/sys/bus/i2c/devices/22-0066*temp1_input",
"/sys/bus/i2c/devices/22-0066*temp2_input",
"/sys/bus/i2c/devices/22-0066*temp3_input",
"/sys/bus/i2c/devices/22-0066*temp4_input",
"/sys/bus/i2c/devices/22-0066*temp5_input",
"/sys/bus/i2c/devices/22-0066*temp6_input",
"/sys/bus/i2c/devices/22-0066*temp7_input",
"/sys/bus/i2c/devices/22-0066*temp8_input",
"/sys/bus/i2c/devices/22-0066*temp9_input",
"/sys/bus/i2c/devices/22-0066*temp10_input",
"/sys/bus/i2c/devices/22-0066*temp11_input",
"/sys/bus/i2c/devices/22-0066*temp12_input",
"/sys/bus/i2c/devices/22-0066*temp13_input",
"/sys/bus/i2c/devices/18-005b*psu_temp1_input",
"/sys/bus/i2c/devices/18-0059*psu_temp1_input",
"/sys/bus/i2c/devices/18-005a*psu_temp1_input",
"/sys/bus/i2c/devices/18-0058*psu_temp1_input",
};
/* Static values */
static onlp_thermal_info_t linfo[] = {
{ }, /* Not used */
{ { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE), "CPU Core", 0},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BOTTOM_BOARD), "Chassis Thermal Sensor 1", 0},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_MAIN_BOTTOM_BOARD), "Chassis Thermal Sensor 2", 0},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BOTTOM_BOARD), "Chassis Thermal Sensor 3", 0},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_4_ON_MAIN_BOTTOM_BOARD), "Chassis Thermal Sensor 4", 0},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_5_ON_MAIN_BOTTOM_BOARD), "Chassis Thermal Sensor 5", 0},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_6_ON_MAIN_BOTTOM_BOARD), "Chassis Phani Thermal Sensor 6", 0},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_TOP_BOARD), "Chassis Raja Thermal Sensor 7", 0},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_MAIN_TOP_BOARD), "Chassis Rao Thermal Sensor 8", 0},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_TOP_BOARD), "Chassis Karanam Thermal Sensor 9", 0},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_4_ON_MAIN_TOP_BOARD), "Chassis Thermal Sensor 10", 0},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_5_ON_MAIN_TOP_BOARD), "Chassis Thermal Sensor 11", 0},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_6_ON_MAIN_TOP_BOARD), "Chassis Thermal Sensor 12", 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
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU3), "PSU-3 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU3_ID)},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
},
{ { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU4), "PSU-4 Thermal Sensor 1", ONLP_PSU_ID_CREATE(PSU4_ID)},
ONLP_THERMAL_STATUS_PRESENT,
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
}
};
/*
* This will be called to intiialize the thermali subsystem.
*/
int
onlp_thermali_init(void)
{
return ONLP_STATUS_OK;
}
/*
* Retrieve the information structure for the given thermal OID.
*
* If the OID is invalid, return ONLP_E_STATUS_INVALID.
* If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL.
* Otherwise, return ONLP_STATUS_OK with the OID's information.
*
* Note -- it is expected that you fill out the information
* structure even if the sensor described by the OID is not present.
*/
int
onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info)
{
int tid;
VALIDATE(id);
tid = ONLP_OID_ID_GET(id);
/* Set the onlp_oid_hdr_t and capabilities */
*info = linfo[tid];
return onlp_file_read_int(&info->mcelsius, devfiles__[tid]);
}

View File

@@ -0,0 +1,80 @@
/**************************************************************************//**
*
*
*
*****************************************************************************/
#include <x86_64_accton_as7926_80xk/x86_64_accton_as7926_80xk_config.h>
/* <auto.start.cdefs(X86_64_ACCTON_AS7926_80XK_CONFIG_HEADER).source> */
#define __x86_64_accton_as7926_80xk_config_STRINGIFY_NAME(_x) #_x
#define __x86_64_accton_as7926_80xk_config_STRINGIFY_VALUE(_x) __x86_64_accton_as7926_80xk_config_STRINGIFY_NAME(_x)
x86_64_accton_as7926_80xk_config_settings_t x86_64_accton_as7926_80xk_config_settings[] =
{
#ifdef X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_LOGGING
{ __x86_64_accton_as7926_80xk_config_STRINGIFY_NAME(X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_LOGGING), __x86_64_accton_as7926_80xk_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_LOGGING) },
#else
{ X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_LOGGING(__x86_64_accton_as7926_80xk_config_STRINGIFY_NAME), "__undefined__" },
#endif
#ifdef X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_OPTIONS_DEFAULT
{ __x86_64_accton_as7926_80xk_config_STRINGIFY_NAME(X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_accton_as7926_80xk_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_OPTIONS_DEFAULT) },
#else
{ X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_accton_as7926_80xk_config_STRINGIFY_NAME), "__undefined__" },
#endif
#ifdef X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_BITS_DEFAULT
{ __x86_64_accton_as7926_80xk_config_STRINGIFY_NAME(X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_BITS_DEFAULT), __x86_64_accton_as7926_80xk_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_BITS_DEFAULT) },
#else
{ X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_BITS_DEFAULT(__x86_64_accton_as7926_80xk_config_STRINGIFY_NAME), "__undefined__" },
#endif
#ifdef X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT
{ __x86_64_accton_as7926_80xk_config_STRINGIFY_NAME(X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_accton_as7926_80xk_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT) },
#else
{ X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_accton_as7926_80xk_config_STRINGIFY_NAME), "__undefined__" },
#endif
#ifdef X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB
{ __x86_64_accton_as7926_80xk_config_STRINGIFY_NAME(X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB), __x86_64_accton_as7926_80xk_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB) },
#else
{ X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_STDLIB(__x86_64_accton_as7926_80xk_config_STRINGIFY_NAME), "__undefined__" },
#endif
#ifdef X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS
{ __x86_64_accton_as7926_80xk_config_STRINGIFY_NAME(X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_accton_as7926_80xk_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) },
#else
{ X86_64_ACCTON_AS7926_80XK_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_accton_as7926_80xk_config_STRINGIFY_NAME), "__undefined__" },
#endif
#ifdef X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_UCLI
{ __x86_64_accton_as7926_80xk_config_STRINGIFY_NAME(X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_UCLI), __x86_64_accton_as7926_80xk_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_UCLI) },
#else
{ X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_UCLI(__x86_64_accton_as7926_80xk_config_STRINGIFY_NAME), "__undefined__" },
#endif
#ifdef X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION
{ __x86_64_accton_as7926_80xk_config_STRINGIFY_NAME(X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_accton_as7926_80xk_config_STRINGIFY_VALUE(X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) },
#else
{ X86_64_ACCTON_AS7926_80XK_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_accton_as7926_80xk_config_STRINGIFY_NAME), "__undefined__" },
#endif
{ NULL, NULL }
};
#undef __x86_64_accton_as7926_80xk_config_STRINGIFY_VALUE
#undef __x86_64_accton_as7926_80xk_config_STRINGIFY_NAME
const char*
x86_64_accton_as7926_80xk_config_lookup(const char* setting)
{
int i;
for(i = 0; x86_64_accton_as7926_80xk_config_settings[i].name; i++) {
if(!strcmp(x86_64_accton_as7926_80xk_config_settings[i].name, setting)) {
return x86_64_accton_as7926_80xk_config_settings[i].value;
}
}
return NULL;
}
int
x86_64_accton_as7926_80xk_config_show(struct aim_pvs_s* pvs)
{
int i;
for(i = 0; x86_64_accton_as7926_80xk_config_settings[i].name; i++) {
aim_printf(pvs, "%s = %s\n", x86_64_accton_as7926_80xk_config_settings[i].name, x86_64_accton_as7926_80xk_config_settings[i].value);
}
return i;
}
/* <auto.end.cdefs(X86_64_ACCTON_AS7926_80XK_CONFIG_HEADER).source> */

View File

@@ -0,0 +1,10 @@
/**************************************************************************//**
*
*
*
*****************************************************************************/
#include <x86_64_accton_as7926_80xk/x86_64_accton_as7926_80xk_config.h>
/* <--auto.start.enum(ALL).source> */
/* <auto.end.enum(ALL).source> */

View File

@@ -0,0 +1,12 @@
/**************************************************************************//**
*
* x86_64_accton_as7926_80xk Internal Header
*
*****************************************************************************/
#ifndef __x86_64_accton_as7926_80xk_INT_H__
#define __x86_64_accton_as7926_80xk_INT_H__
#include <x86_64_accton_as7926_80xk/x86_64_accton_as7926_80xk_config.h>
#endif /* __x86_64_accton_as7926_80xk_INT_H__ */

View File

@@ -0,0 +1,18 @@
/**************************************************************************//**
*
*
*
*****************************************************************************/
#include <x86_64_accton_as7926_80xk/x86_64_accton_as7926_80xk_config.h>
#include "x86_64_accton_as7926_80xk_log.h"
/*
* x86_64_accton_as7926_80xk log struct.
*/
AIM_LOG_STRUCT_DEFINE(
X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_OPTIONS_DEFAULT,
X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_BITS_DEFAULT,
NULL, /* Custom log map */
X86_64_ACCTON_AS7926_80XK_CONFIG_LOG_CUSTOM_BITS_DEFAULT
);

View File

@@ -0,0 +1,12 @@
/**************************************************************************//**
*
*
*
*****************************************************************************/
#ifndef __x86_64_accton_as7926_80xk_LOG_H__
#define __x86_64_accton_as7926_80xk_LOG_H__
#define AIM_LOG_MODULE_NAME x86_64_accton_as7926_80xk
#include <AIM/aim_log.h>
#endif /* __x86_64_accton_as7926_80xk_LOG_H__ */

View File

@@ -0,0 +1,24 @@
/**************************************************************************//**
*
*
*
*****************************************************************************/
#include <x86_64_accton_as7926_80xk/x86_64_accton_as7926_80xk_config.h>
#include "x86_64_accton_as7926_80xk_log.h"
static int
datatypes_init__(void)
{
#define x86_64_accton_as7926_80xk_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL);
#include <x86_64_accton_as7926_80xk/x86_64_accton_as7926_80xk.x>
return 0;
}
void __x86_64_accton_as7926_80xk_module_init__(void)
{
AIM_LOG_STRUCT_REGISTER();
datatypes_init__();
}
int __onlp_platform_version__ = 1;

View File

@@ -0,0 +1,50 @@
/**************************************************************************//**
*
*
*
*****************************************************************************/
#include <x86_64_accton_as7926_80xk/x86_64_accton_as7926_80xk_config.h>
#if x86_64_accton_as7926_80xk_CONFIG_INCLUDE_UCLI == 1
#include <uCli/ucli.h>
#include <uCli/ucli_argparse.h>
#include <uCli/ucli_handler_macros.h>
static ucli_status_t
x86_64_accton_as7926_80xk_ucli_ucli__config__(ucli_context_t* uc)
{
UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_accton_as7926_80xk)
}
/* <auto.ucli.handlers.start> */
/* <auto.ucli.handlers.end> */
static ucli_module_t
x86_64_accton_as7926_80xk_ucli_module__ =
{
"x86_64_accton_as7926_80xk_ucli",
NULL,
x86_64_accton_as7926_80xk_ucli_ucli_handlers__,
NULL,
NULL,
};
ucli_node_t*
x86_64_accton_as7926_80xk_ucli_node_create(void)
{
ucli_node_t* n;
ucli_module_init(&x86_64_accton_as7926_80xk_ucli_module__);
n = ucli_node_create("x86_64_accton_as7926_80xk", NULL, &x86_64_accton_as7926_80xk_ucli_module__);
ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_accton_as7926_80xk"));
return n;
}
#else
void*
x86_64_accton_as7926_80xk_ucli_node_create(void)
{
return NULL;
}
#endif

View File

@@ -0,0 +1 @@
include $(ONL)/make/pkg.mk

View File

@@ -0,0 +1 @@
include $(ONL)/make/pkg.mk

View File

@@ -0,0 +1 @@
!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=accton BASENAME=x86-64-accton-as7926-80xk REVISION=r0

View File

@@ -0,0 +1,33 @@
---
######################################################################
#
# platform-config for AS7816
#
######################################################################
x86-64-accton-as7926-80xk-r0:
grub:
serial: >-
--port=0x3f8
--speed=115200
--word=8
--parity=no
--stop=1
kernel:
<<: *kernel-4-14
args: >-
nopat
console=ttyS0,115200n8
tg3.short_preamble=1
tg3.bcm5718s_reset=1
##network:
## interfaces:
## ma1:
## name: ~
## syspath: pci0000:00/0000:00:1c.0/0000:0a:00.0

View File

@@ -0,0 +1,246 @@
from onl.platform.base import *
from onl.platform.accton import *
class OnlPlatform_x86_64_accton_as7926_80xk_r0(OnlPlatformAccton,
OnlPlatformPortConfig_80x100):
PLATFORM='x86-64-accton-as7926-80xk-r0'
MODEL="AS7926-80xk"
SYS_OBJECT_ID=".7926.80"
def baseconfig(self):
self.insmod('optoe')
self.insmod('ym2651y')
self.insmod('accton_i2c_cpld')
for m in [ 'fan', 'cpld', 'psu', 'leds']:
self.insmod("x86-64-accton-as7926-80xk-%s.ko" % m)
########### initialize I2C bus 0 ###########
self.new_i2c_devices([
# initialize multiplexer (PCA9548)
('pca9548', 0x77, 0),
# initiate leaf multiplexer (PCA9548) of bottom board
('pca9548', 0x76, 1),
('pca9548', 0x72, 2),
('pca9548', 0x73, 9),
# initiate PSU-1
('as7926_80xk_psu1', 0x53, 18),
('ym2651', 0x5b, 18),
# initiate PSU-2
('as7926_80xk_psu2', 0x51, 18),
('ym2651', 0x59, 18),
# initiate PSU-3
('as7926_80xk_psu3', 0x52, 18),
('ym2651', 0x5a, 18),
# initiate PSU-4
('as7926_80xk_psu4', 0x50, 18),
('ym2651', 0x58, 18),
# initiate chassis fan
('as7926_80xk_fan', 0x66, 22),
#initiate CPLD
('accton_i2c_cpld', 0x60, 11),
('as7926_80xk_cpld1', 0x62, 12),
('as7926_80xk_cpld2', 0x63, 13),
# initiate leaf multiplexer (PCA9548)
('pca9548', 0x74, 25),
('pca9548', 0x74, 26),
('pca9548', 0x74, 27),
('pca9548', 0x74, 28),
('pca9548', 0x74, 29),
# initialize QSFP port 1-40 of bottom board
('optoe1', 0x50, 33),
('optoe1', 0x50, 34),
('optoe1', 0x50, 35),
('optoe1', 0x50, 36),
('optoe1', 0x50, 37),
('optoe1', 0x50, 38),
('optoe1', 0x50, 39),
('optoe1', 0x50, 40),
('optoe1', 0x50, 41),
('optoe1', 0x50, 42),
('optoe1', 0x50, 43),
('optoe1', 0x50, 44),
('optoe1', 0x50, 45),
('optoe1', 0x50, 46),
('optoe1', 0x50, 47),
('optoe1', 0x50, 48),
('optoe1', 0x50, 49),
('optoe1', 0x50, 50),
('optoe1', 0x50, 51),
('optoe1', 0x50, 52),
('optoe1', 0x50, 53),
('optoe1', 0x50, 54),
('optoe1', 0x50, 55),
('optoe1', 0x50, 56),
('optoe1', 0x50, 57),
('optoe1', 0x50, 58),
('optoe1', 0x50, 59),
('optoe1', 0x50, 60),
('optoe1', 0x50, 61),
('optoe1', 0x50, 62),
('optoe1', 0x50, 63),
('optoe1', 0x50, 64),
('optoe1', 0x50, 65),
('optoe1', 0x50, 66),
('optoe1', 0x50, 67),
('optoe1', 0x50, 68),
('optoe1', 0x50, 69),
('optoe1', 0x50, 70),
('optoe1', 0x50, 71),
('optoe1', 0x50, 72),
('24c02', 0x57, 0),
# initiate leaf multiplexer (PCA9548) of top board
('pca9548', 0x75, 1),
('pca9548', 0x71, 2),
('pca9548', 0x73, 73),
('as7926_80xk_cpld3', 0x62, 76),
('as7926_80xk_cpld4', 0x63, 77),
# initiate leaf multiplexer (PCA9548)
('pca9548', 0x74, 89),
('pca9548', 0x74, 90),
('pca9548', 0x74, 91),
('pca9548', 0x74, 92),
('pca9548', 0x74, 93),
# initialize QSFP port 41-80 of top board
('optoe1', 0x50, 97),
('optoe1', 0x50, 98),
('optoe1', 0x50, 99),
('optoe1', 0x50, 100),
('optoe1', 0x50, 101),
('optoe1', 0x50, 102),
('optoe1', 0x50, 103),
('optoe1', 0x50, 104),
('optoe1', 0x50, 105),
('optoe1', 0x50, 106),
('optoe1', 0x50, 107),
('optoe1', 0x50, 108),
('optoe1', 0x50, 109),
('optoe1', 0x50, 110),
('optoe1', 0x50, 111),
('optoe1', 0x50, 112),
('optoe1', 0x50, 113),
('optoe1', 0x50, 114),
('optoe1', 0x50, 115),
('optoe1', 0x50, 116),
('optoe1', 0x50, 117),
('optoe1', 0x50, 118),
('optoe1', 0x50, 119),
('optoe1', 0x50, 120),
('optoe1', 0x50, 121),
('optoe1', 0x50, 122),
('optoe1', 0x50, 123),
('optoe1', 0x50, 124),
('optoe1', 0x50, 125),
('optoe1', 0x50, 126),
('optoe1', 0x50, 127),
('optoe1', 0x50, 128),
('optoe1', 0x50, 129),
('optoe1', 0x50, 130),
('optoe1', 0x50, 131),
('optoe1', 0x50, 132),
('optoe1', 0x50, 133),
('optoe1', 0x50, 134),
('optoe1', 0x50, 135),
('optoe1', 0x50, 136),
])
subprocess.call('echo port1 > /sys/bus/i2c/devices/33-0050/port_name', shell=True)
subprocess.call('echo port2 > /sys/bus/i2c/devices/34-0050/port_name', shell=True)
subprocess.call('echo port3 > /sys/bus/i2c/devices/35-0050/port_name', shell=True)
subprocess.call('echo port4 > /sys/bus/i2c/devices/36-0050/port_name', shell=True)
subprocess.call('echo port5 > /sys/bus/i2c/devices/37-0050/port_name', shell=True)
subprocess.call('echo port6 > /sys/bus/i2c/devices/38-0050/port_name', shell=True)
subprocess.call('echo port7 > /sys/bus/i2c/devices/39-0050/port_name', shell=True)
subprocess.call('echo port8 > /sys/bus/i2c/devices/40-0050/port_name', shell=True)
subprocess.call('echo port9 > /sys/bus/i2c/devices/41-0050/port_name', shell=True)
subprocess.call('echo port10 > /sys/bus/i2c/devices/42-0050/port_name', shell=True)
subprocess.call('echo port11 > /sys/bus/i2c/devices/43-0050/port_name', shell=True)
subprocess.call('echo port12 > /sys/bus/i2c/devices/44-0050/port_name', shell=True)
subprocess.call('echo port13 > /sys/bus/i2c/devices/45-0050/port_name', shell=True)
subprocess.call('echo port14 > /sys/bus/i2c/devices/46-0050/port_name', shell=True)
subprocess.call('echo port15 > /sys/bus/i2c/devices/47-0050/port_name', shell=True)
subprocess.call('echo port16 > /sys/bus/i2c/devices/48-0050/port_name', shell=True)
subprocess.call('echo port17 > /sys/bus/i2c/devices/49-0050/port_name', shell=True)
subprocess.call('echo port18 > /sys/bus/i2c/devices/50-0050/port_name', shell=True)
subprocess.call('echo port19 > /sys/bus/i2c/devices/51-0050/port_name', shell=True)
subprocess.call('echo port20 > /sys/bus/i2c/devices/52-0050/port_name', shell=True)
subprocess.call('echo port21 > /sys/bus/i2c/devices/53-0050/port_name', shell=True)
subprocess.call('echo port22 > /sys/bus/i2c/devices/54-0050/port_name', shell=True)
subprocess.call('echo port23 > /sys/bus/i2c/devices/55-0050/port_name', shell=True)
subprocess.call('echo port24 > /sys/bus/i2c/devices/56-0050/port_name', shell=True)
subprocess.call('echo port25 > /sys/bus/i2c/devices/57-0050/port_name', shell=True)
subprocess.call('echo port26 > /sys/bus/i2c/devices/58-0050/port_name', shell=True)
subprocess.call('echo port27 > /sys/bus/i2c/devices/59-0050/port_name', shell=True)
subprocess.call('echo port28 > /sys/bus/i2c/devices/60-0050/port_name', shell=True)
subprocess.call('echo port29 > /sys/bus/i2c/devices/61-0050/port_name', shell=True)
subprocess.call('echo port30 > /sys/bus/i2c/devices/62-0050/port_name', shell=True)
subprocess.call('echo port31 > /sys/bus/i2c/devices/63-0050/port_name', shell=True)
subprocess.call('echo port32 > /sys/bus/i2c/devices/64-0050/port_name', shell=True)
subprocess.call('echo port33 > /sys/bus/i2c/devices/65-0050/port_name', shell=True)
subprocess.call('echo port34 > /sys/bus/i2c/devices/66-0050/port_name', shell=True)
subprocess.call('echo port35 > /sys/bus/i2c/devices/67-0050/port_name', shell=True)
subprocess.call('echo port36 > /sys/bus/i2c/devices/68-0050/port_name', shell=True)
subprocess.call('echo port37 > /sys/bus/i2c/devices/69-0050/port_name', shell=True)
subprocess.call('echo port38 > /sys/bus/i2c/devices/70-0050/port_name', shell=True)
subprocess.call('echo port39 > /sys/bus/i2c/devices/71-0050/port_name', shell=True)
subprocess.call('echo port40 > /sys/bus/i2c/devices/72-0050/port_name', shell=True)
subprocess.call('echo port41 > /sys/bus/i2c/devices/97-0050/port_name', shell=True)
subprocess.call('echo port42 > /sys/bus/i2c/devices/98-0050/port_name', shell=True)
subprocess.call('echo port43 > /sys/bus/i2c/devices/99-0050/port_name', shell=True)
subprocess.call('echo port44 > /sys/bus/i2c/devices/100-0050/port_name', shell=True)
subprocess.call('echo port45 > /sys/bus/i2c/devices/101-0050/port_name', shell=True)
subprocess.call('echo port46 > /sys/bus/i2c/devices/102-0050/port_name', shell=True)
subprocess.call('echo port47 > /sys/bus/i2c/devices/103-0050/port_name', shell=True)
subprocess.call('echo port48 > /sys/bus/i2c/devices/104-0050/port_name', shell=True)
subprocess.call('echo port49 > /sys/bus/i2c/devices/105-0050/port_name', shell=True)
subprocess.call('echo port50 > /sys/bus/i2c/devices/106-0050/port_name', shell=True)
subprocess.call('echo port51 > /sys/bus/i2c/devices/107-0050/port_name', shell=True)
subprocess.call('echo port52 > /sys/bus/i2c/devices/108-0050/port_name', shell=True)
subprocess.call('echo port53 > /sys/bus/i2c/devices/109-0050/port_name', shell=True)
subprocess.call('echo port54 > /sys/bus/i2c/devices/110-0050/port_name', shell=True)
subprocess.call('echo port55 > /sys/bus/i2c/devices/111-0050/port_name', shell=True)
subprocess.call('echo port56 > /sys/bus/i2c/devices/112-0050/port_name', shell=True)
subprocess.call('echo port57 > /sys/bus/i2c/devices/113-0050/port_name', shell=True)
subprocess.call('echo port58 > /sys/bus/i2c/devices/114-0050/port_name', shell=True)
subprocess.call('echo port59 > /sys/bus/i2c/devices/115-0050/port_name', shell=True)
subprocess.call('echo port60 > /sys/bus/i2c/devices/116-0050/port_name', shell=True)
subprocess.call('echo port61 > /sys/bus/i2c/devices/117-0050/port_name', shell=True)
subprocess.call('echo port62 > /sys/bus/i2c/devices/118-0050/port_name', shell=True)
subprocess.call('echo port63 > /sys/bus/i2c/devices/119-0050/port_name', shell=True)
subprocess.call('echo port64 > /sys/bus/i2c/devices/120-0050/port_name', shell=True)
subprocess.call('echo port65 > /sys/bus/i2c/devices/121-0050/port_name', shell=True)
subprocess.call('echo port66 > /sys/bus/i2c/devices/122-0050/port_name', shell=True)
subprocess.call('echo port67 > /sys/bus/i2c/devices/123-0050/port_name', shell=True)
subprocess.call('echo port68 > /sys/bus/i2c/devices/124-0050/port_name', shell=True)
subprocess.call('echo port69 > /sys/bus/i2c/devices/125-0050/port_name', shell=True)
subprocess.call('echo port70 > /sys/bus/i2c/devices/126-0050/port_name', shell=True)
subprocess.call('echo port71 > /sys/bus/i2c/devices/127-0050/port_name', shell=True)
subprocess.call('echo port72 > /sys/bus/i2c/devices/128-0050/port_name', shell=True)
subprocess.call('echo port73 > /sys/bus/i2c/devices/129-0050/port_name', shell=True)
subprocess.call('echo port74 > /sys/bus/i2c/devices/130-0050/port_name', shell=True)
subprocess.call('echo port75 > /sys/bus/i2c/devices/131-0050/port_name', shell=True)
subprocess.call('echo port76 > /sys/bus/i2c/devices/132-0050/port_name', shell=True)
subprocess.call('echo port77 > /sys/bus/i2c/devices/133-0050/port_name', shell=True)
subprocess.call('echo port78 > /sys/bus/i2c/devices/134-0050/port_name', shell=True)
subprocess.call('echo port79 > /sys/bus/i2c/devices/135-0050/port_name', shell=True)
subprocess.call('echo port80 > /sys/bus/i2c/devices/136-0050/port_name', shell=True)
return True