mirror of
https://github.com/Telecominfraproject/OpenNetworkLinux.git
synced 2025-12-24 16:57:02 +00:00
Merge pull request #500 from robertxyu/master
Add support for Inventec d7264q28b
This commit is contained in:
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -0,0 +1 @@
|
||||
!include $ONL_TEMPLATES/platform-modules.yml VENDOR=inventec BASENAME=x86-64-inventec-d6556 ARCH=amd64 KERNELS="onl-kernel-3.16-lts-x86-64-all:amd64"
|
||||
1
packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/.gitignore
vendored
Normal file
1
packages/platforms/inventec/x86-64/x86-64-inventec-d6556/modules/builds/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
lib
|
||||
@@ -0,0 +1,6 @@
|
||||
KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64
|
||||
KMODULES := src
|
||||
VENDOR := inventec
|
||||
BASENAME := x86-64-inventec-d6556
|
||||
ARCH := x86_64
|
||||
include $(ONL)/make/kmodule.mk
|
||||
@@ -0,0 +1,8 @@
|
||||
obj-m += i2c-gpio.o
|
||||
obj-m += inv_cpld.o inv_psoc.o
|
||||
obj-m += inv_platform.o
|
||||
obj-m += inv_pthread.o
|
||||
obj-m += swps.o
|
||||
swps-objs := inv_swps.o io_expander.o inv_mux.o transceiver.o
|
||||
obj-m += vpd.o
|
||||
vpd-objs := inv_vpd.o onie_tlvinfo.o
|
||||
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Bitbanging I2C bus driver using the GPIO API
|
||||
*
|
||||
* Copyright (C) 2007 Atmel Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
struct i2c_gpio_private_data {
|
||||
struct i2c_adapter adap;
|
||||
struct i2c_algo_bit_data bit_data;
|
||||
struct i2c_gpio_platform_data pdata;
|
||||
};
|
||||
|
||||
/* Toggle SDA by changing the direction of the pin */
|
||||
static void i2c_gpio_setsda_dir(void *data, int state)
|
||||
{
|
||||
struct i2c_gpio_platform_data *pdata = data;
|
||||
|
||||
if (state)
|
||||
gpio_direction_input(pdata->sda_pin);
|
||||
else
|
||||
gpio_direction_output(pdata->sda_pin, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Toggle SDA by changing the output value of the pin. This is only
|
||||
* valid for pins configured as open drain (i.e. setting the value
|
||||
* high effectively turns off the output driver.)
|
||||
*/
|
||||
static void i2c_gpio_setsda_val(void *data, int state)
|
||||
{
|
||||
struct i2c_gpio_platform_data *pdata = data;
|
||||
|
||||
gpio_set_value(pdata->sda_pin, state);
|
||||
}
|
||||
|
||||
/* Toggle SCL by changing the direction of the pin. */
|
||||
static void i2c_gpio_setscl_dir(void *data, int state)
|
||||
{
|
||||
struct i2c_gpio_platform_data *pdata = data;
|
||||
|
||||
if (state)
|
||||
gpio_direction_input(pdata->scl_pin);
|
||||
else
|
||||
gpio_direction_output(pdata->scl_pin, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Toggle SCL by changing the output value of the pin. This is used
|
||||
* for pins that are configured as open drain and for output-only
|
||||
* pins. The latter case will break the i2c protocol, but it will
|
||||
* often work in practice.
|
||||
*/
|
||||
static void i2c_gpio_setscl_val(void *data, int state)
|
||||
{
|
||||
struct i2c_gpio_platform_data *pdata = data;
|
||||
|
||||
gpio_set_value(pdata->scl_pin, state);
|
||||
}
|
||||
|
||||
static int i2c_gpio_getsda(void *data)
|
||||
{
|
||||
struct i2c_gpio_platform_data *pdata = data;
|
||||
|
||||
return gpio_get_value(pdata->sda_pin);
|
||||
}
|
||||
|
||||
static int i2c_gpio_getscl(void *data)
|
||||
{
|
||||
struct i2c_gpio_platform_data *pdata = data;
|
||||
|
||||
return gpio_get_value(pdata->scl_pin);
|
||||
}
|
||||
|
||||
static int of_i2c_gpio_get_pins(struct device_node *np,
|
||||
unsigned int *sda_pin, unsigned int *scl_pin)
|
||||
{
|
||||
if (of_gpio_count(np) < 2)
|
||||
return -ENODEV;
|
||||
|
||||
*sda_pin = of_get_gpio(np, 0);
|
||||
*scl_pin = of_get_gpio(np, 1);
|
||||
|
||||
if (*sda_pin == -EPROBE_DEFER || *scl_pin == -EPROBE_DEFER)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
if (!gpio_is_valid(*sda_pin) || !gpio_is_valid(*scl_pin)) {
|
||||
pr_err("%s: invalid GPIO pins, sda=%d/scl=%d\n",
|
||||
np->full_name, *sda_pin, *scl_pin);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void of_i2c_gpio_get_props(struct device_node *np,
|
||||
struct i2c_gpio_platform_data *pdata)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
of_property_read_u32(np, "i2c-gpio,delay-us", &pdata->udelay);
|
||||
|
||||
if (!of_property_read_u32(np, "i2c-gpio,timeout-ms", ®))
|
||||
pdata->timeout = msecs_to_jiffies(reg);
|
||||
|
||||
pdata->sda_is_open_drain =
|
||||
of_property_read_bool(np, "i2c-gpio,sda-open-drain");
|
||||
pdata->scl_is_open_drain =
|
||||
of_property_read_bool(np, "i2c-gpio,scl-open-drain");
|
||||
pdata->scl_is_output_only =
|
||||
of_property_read_bool(np, "i2c-gpio,scl-output-only");
|
||||
}
|
||||
|
||||
static int i2c_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct i2c_gpio_private_data *priv;
|
||||
struct i2c_gpio_platform_data *pdata;
|
||||
struct i2c_algo_bit_data *bit_data;
|
||||
struct i2c_adapter *adap;
|
||||
unsigned int sda_pin, scl_pin;
|
||||
int ret;
|
||||
|
||||
/* First get the GPIO pins; if it fails, we'll defer the probe. */
|
||||
if (pdev->dev.of_node) {
|
||||
ret = of_i2c_gpio_get_pins(pdev->dev.of_node,
|
||||
&sda_pin, &scl_pin);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
if (!dev_get_platdata(&pdev->dev))
|
||||
return -ENXIO;
|
||||
pdata = dev_get_platdata(&pdev->dev);
|
||||
sda_pin = pdata->sda_pin;
|
||||
scl_pin = pdata->scl_pin;
|
||||
}
|
||||
|
||||
ret = devm_gpio_request(&pdev->dev, sda_pin, "sda");
|
||||
if (ret) {
|
||||
if (ret == -EINVAL)
|
||||
ret = -EPROBE_DEFER; /* Try again later */
|
||||
return ret;
|
||||
}
|
||||
ret = devm_gpio_request(&pdev->dev, scl_pin, "scl");
|
||||
if (ret) {
|
||||
if (ret == -EINVAL)
|
||||
ret = -EPROBE_DEFER; /* Try again later */
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
adap = &priv->adap;
|
||||
bit_data = &priv->bit_data;
|
||||
pdata = &priv->pdata;
|
||||
|
||||
if (pdev->dev.of_node) {
|
||||
pdata->sda_pin = sda_pin;
|
||||
pdata->scl_pin = scl_pin;
|
||||
of_i2c_gpio_get_props(pdev->dev.of_node, pdata);
|
||||
} else {
|
||||
memcpy(pdata, dev_get_platdata(&pdev->dev), sizeof(*pdata));
|
||||
}
|
||||
|
||||
if (pdata->sda_is_open_drain) {
|
||||
gpio_direction_output(pdata->sda_pin, 1);
|
||||
bit_data->setsda = i2c_gpio_setsda_val;
|
||||
} else {
|
||||
gpio_direction_input(pdata->sda_pin);
|
||||
bit_data->setsda = i2c_gpio_setsda_dir;
|
||||
}
|
||||
|
||||
if (pdata->scl_is_open_drain || pdata->scl_is_output_only) {
|
||||
gpio_direction_output(pdata->scl_pin, 1);
|
||||
bit_data->setscl = i2c_gpio_setscl_val;
|
||||
} else {
|
||||
gpio_direction_input(pdata->scl_pin);
|
||||
bit_data->setscl = i2c_gpio_setscl_dir;
|
||||
}
|
||||
|
||||
if (!pdata->scl_is_output_only)
|
||||
bit_data->getscl = i2c_gpio_getscl;
|
||||
bit_data->getsda = i2c_gpio_getsda;
|
||||
|
||||
if (pdata->udelay)
|
||||
bit_data->udelay = pdata->udelay;
|
||||
else if (pdata->scl_is_output_only)
|
||||
bit_data->udelay = 50; /* 10 kHz */
|
||||
else
|
||||
bit_data->udelay = 5; /* 100 kHz */
|
||||
|
||||
if (pdata->timeout)
|
||||
bit_data->timeout = pdata->timeout;
|
||||
else
|
||||
bit_data->timeout = HZ / 10; /* 100 ms */
|
||||
|
||||
bit_data->data = pdata;
|
||||
|
||||
adap->owner = THIS_MODULE;
|
||||
if (pdev->dev.of_node)
|
||||
strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));
|
||||
else
|
||||
snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
|
||||
|
||||
adap->algo_data = bit_data;
|
||||
adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
adap->dev.parent = &pdev->dev;
|
||||
adap->dev.of_node = pdev->dev.of_node;
|
||||
|
||||
adap->nr = pdev->id;
|
||||
ret = i2c_bit_add_numbered_bus(adap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
platform_set_drvdata(pdev, priv);
|
||||
|
||||
dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n",
|
||||
pdata->sda_pin, pdata->scl_pin,
|
||||
pdata->scl_is_output_only
|
||||
? ", no clock stretching" : "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2c_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct i2c_gpio_private_data *priv;
|
||||
struct i2c_gpio_platform_data *pdata;
|
||||
struct i2c_adapter *adap;
|
||||
|
||||
priv = platform_get_drvdata(pdev);
|
||||
adap = &priv->adap;
|
||||
pdata = &priv->pdata;
|
||||
|
||||
i2c_del_adapter(adap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
static const struct of_device_id i2c_gpio_dt_ids[] = {
|
||||
{ .compatible = "i2c-gpio", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, i2c_gpio_dt_ids);
|
||||
#endif
|
||||
|
||||
static struct platform_driver i2c_gpio_driver = {
|
||||
.driver = {
|
||||
.name = "i2c-gpio",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(i2c_gpio_dt_ids),
|
||||
},
|
||||
.probe = i2c_gpio_probe,
|
||||
.remove = i2c_gpio_remove,
|
||||
};
|
||||
|
||||
static int __init i2c_gpio_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&i2c_gpio_driver);
|
||||
if (ret)
|
||||
printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
subsys_initcall(i2c_gpio_init);
|
||||
|
||||
static void __exit i2c_gpio_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&i2c_gpio_driver);
|
||||
}
|
||||
module_exit(i2c_gpio_exit);
|
||||
|
||||
MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
|
||||
MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:i2c-gpio");
|
||||
@@ -0,0 +1,526 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.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 "I2CHostCommunication.h"
|
||||
|
||||
#define USE_SMBUS 1
|
||||
|
||||
/* definition */
|
||||
#define CPLD_INFO_OFFSET 0x00
|
||||
#define CPLD_PSU_OFFSET 0x08
|
||||
#define CPLD_LED_OFFSET 0x0E
|
||||
#define CPLD_LED_STATU_OFFSET 0x0D
|
||||
#define CPLD_CTL_OFFSET 0x0C
|
||||
#define CPLD_BIOSCS_OFFSET 0x04
|
||||
#define CPLD_PSUFANLED_OFFSET 0x75
|
||||
|
||||
/* Each client has this additional data */
|
||||
struct cpld_data {
|
||||
struct device *hwmon_dev;
|
||||
struct mutex update_lock;
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
static ssize_t cpld_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count)
|
||||
{
|
||||
#if USE_SMBUS
|
||||
int i;
|
||||
|
||||
for(i=0; i<count; i++) {
|
||||
buf[i] = i2c_smbus_read_byte_data(client, offset+i);
|
||||
}
|
||||
return count;
|
||||
#else
|
||||
struct i2c_msg msg[2];
|
||||
char msgbuf[2];
|
||||
int status;
|
||||
|
||||
memset(msg, 0, sizeof(msg));
|
||||
|
||||
msgbuf[0] = offset;
|
||||
|
||||
msg[0].addr = client->addr;
|
||||
msg[0].buf = msgbuf;
|
||||
msg[0].len = 1;
|
||||
|
||||
msg[1].addr = client->addr;
|
||||
msg[1].flags = I2C_M_RD;
|
||||
msg[1].buf = buf;
|
||||
msg[1].len = count;
|
||||
|
||||
status = i2c_transfer(client->adapter, msg, 2);
|
||||
|
||||
if(status == 2)
|
||||
status = count;
|
||||
|
||||
return status;
|
||||
#endif
|
||||
}
|
||||
|
||||
static ssize_t cpld_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count)
|
||||
{
|
||||
#if USE_SMBUS
|
||||
int i;
|
||||
|
||||
for(i=0; i<count; i++) {
|
||||
i2c_smbus_write_byte_data(client, offset+i, buf[i]);
|
||||
}
|
||||
return count;
|
||||
#else
|
||||
struct i2c_msg msg;
|
||||
int status;
|
||||
u8 writebuf[64];
|
||||
|
||||
int i = 0;
|
||||
|
||||
msg.addr = client->addr;
|
||||
msg.flags = 0;
|
||||
|
||||
/* msg.buf is u8 and casts will mask the values */
|
||||
msg.buf = writebuf;
|
||||
|
||||
msg.buf[i++] = offset;
|
||||
memcpy(&msg.buf[i], buf, count);
|
||||
msg.len = i + count;
|
||||
|
||||
status = i2c_transfer(client->adapter, &msg, 1);
|
||||
if (status == 1)
|
||||
status = count;
|
||||
|
||||
return status;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* sysfs attributes for hwmon */
|
||||
|
||||
static ssize_t show_info(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u32 status;
|
||||
//struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
u8 b[4];
|
||||
|
||||
memset(b, 0, 4);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
status = cpld_i2c_read(client, b, CPLD_INFO_OFFSET, 4);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
if(status != 4) return sprintf(buf, "read cpld info fail\n");
|
||||
|
||||
status = sprintf (buf, "The CPLD release date is %02d/%02d/%d.\n", b[2] & 0xf, (b[3] & 0x1f), 2014+(b[2] >> 4)); /* mm/dd/yyyy*/
|
||||
status = sprintf (buf, "%sThe PCB version is %X%X\n", buf, b[0]>>4, b[0]&0xf);
|
||||
status = sprintf (buf, "%sThe CPLD version is %d.%d\n", buf, b[1]>>4, b[1]&0xf);
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t show_ctl(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u32 status;
|
||||
//struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
u8 b[1];
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
status = cpld_i2c_read(client, b, CPLD_CTL_OFFSET, 1);
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
if(status != 1) return sprintf(buf, "read cpld ctl fail\n");
|
||||
|
||||
|
||||
status = sprintf (buf, "0x%X\n", b[0]);
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static ssize_t set_ctl(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
//struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
u8 byte;
|
||||
|
||||
u8 temp = simple_strtol(buf, NULL, 10);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
cpld_i2c_read(client, &byte, CPLD_CTL_OFFSET, 1);
|
||||
if(temp) byte |= (1<<0);
|
||||
else byte &= ~(1<<0);
|
||||
cpld_i2c_write(client, &byte, CPLD_CTL_OFFSET, 1);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_bios_cs(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u32 status;
|
||||
//struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
u8 b[1];
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
status = cpld_i2c_read(client, b, CPLD_BIOSCS_OFFSET, 1);
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
if(status != 1) return sprintf(buf, "read cpld BIOS_CS fail\n");
|
||||
|
||||
|
||||
status = sprintf (buf, "0x%X\n", b[0] & 0x01);
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static ssize_t set_bios_cs(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
//struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
u8 byte;
|
||||
|
||||
u8 temp = simple_strtol(buf, NULL, 10);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
cpld_i2c_read(client, &byte, CPLD_BIOSCS_OFFSET, 1);
|
||||
if(temp) byte |= 0x01;
|
||||
else byte &= ~(0x01);
|
||||
cpld_i2c_write(client, &byte, CPLD_BIOSCS_OFFSET, 1);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static char* led_str[] = {
|
||||
"OFF", //000
|
||||
"0.5 Hz", //001
|
||||
"1 Hz", //010
|
||||
"2 Hz", //011
|
||||
"4 Hz", //100
|
||||
"NA", //101
|
||||
"NA", //110
|
||||
"ON", //111
|
||||
};
|
||||
|
||||
static ssize_t show_led(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u32 status;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
u8 byte;
|
||||
int shift = (attr->index == 0)?3:0;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
status = cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
if(status != 1) return sprintf(buf, "read cpld offset 0x%x\n", CPLD_LED_OFFSET);
|
||||
|
||||
byte = (byte >> shift) & 0x7;
|
||||
|
||||
status = sprintf (buf, "%d: %s\n", byte, led_str[byte]);
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static ssize_t set_led(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
|
||||
u8 temp = simple_strtol(buf, NULL, 16);
|
||||
u8 byte;
|
||||
int shift = (attr->index == 0)?3:0;
|
||||
|
||||
temp &= 0x7;
|
||||
//validate temp value: 0,1,2,3,7, TBD
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1);
|
||||
byte &= ~(0x7<<shift);
|
||||
byte |= (temp<<shift);
|
||||
cpld_i2c_write(client, &byte, CPLD_LED_OFFSET, 1);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
CPLD report the PSU0 status
|
||||
000 = PSU normal operation
|
||||
100 = PSU fault
|
||||
010 = PSU unpowered
|
||||
111 = PSU not installed
|
||||
|
||||
7 6 | 5 4 3 | 2 1 0
|
||||
----------------------
|
||||
| psu0 | psu1
|
||||
*/
|
||||
static char* psu_str[] = {
|
||||
"normal", //000
|
||||
"NA", //001
|
||||
"unpowered", //010
|
||||
"NA", //011
|
||||
"fault", //100
|
||||
"NA", //101
|
||||
"NA", //110
|
||||
"not installed", //111
|
||||
};
|
||||
|
||||
static ssize_t show_psu(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u32 status;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
u8 byte;
|
||||
int shift = (attr->index == 1)?0:3;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
status = cpld_i2c_read(client, &byte, CPLD_PSU_OFFSET, 1);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
byte = (byte >> shift) & 0x7;
|
||||
|
||||
status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]);
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static char* status_psufan_str[] = {
|
||||
"OFF", //00
|
||||
"ON", //01
|
||||
"1 Hz", //10
|
||||
"2 Hz", //11
|
||||
};
|
||||
|
||||
static ssize_t show_psufan_led(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u32 status;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
u8 red_status, grn_status, byte;
|
||||
int shift = (attr->index == 0)?0:2;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
status = cpld_i2c_read(client, &byte, CPLD_PSUFANLED_OFFSET, 1);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
byte = (byte>>shift) & 0x33;
|
||||
grn_status = byte >> 4;
|
||||
red_status = byte & 0x03;
|
||||
|
||||
return sprintf (buf, "0x%02x: Green %s , Red %s\n", byte, status_psufan_str[grn_status],status_psufan_str[red_status]);
|
||||
}
|
||||
|
||||
static ssize_t set_psufan_led(struct device *dev, struct device_attribute *da,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
int shift = (attr->index == 0)?0:2;
|
||||
int mask = (attr->index == 0)?0xcc:0x33;
|
||||
u8 temp = simple_strtol(buf, NULL, 16) & 0x33;
|
||||
u8 byte = 0;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
cpld_i2c_read(client, &byte, CPLD_PSUFANLED_OFFSET, 1);
|
||||
byte &= mask;
|
||||
byte |= (temp<<shift);
|
||||
cpld_i2c_write(client, &byte, CPLD_PSUFANLED_OFFSET, 1);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static SENSOR_DEVICE_ATTR(info, S_IRUGO, show_info, 0, 0);
|
||||
static SENSOR_DEVICE_ATTR(ctl, S_IWUSR|S_IRUGO, show_ctl, set_ctl, 0);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(grn_led, S_IWUSR|S_IRUGO, show_led, set_led, 0);
|
||||
static SENSOR_DEVICE_ATTR(red_led, S_IWUSR|S_IRUGO, show_led, set_led, 1);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu, 0, 0);
|
||||
static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu, 0, 1);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(fan_led, S_IWUSR|S_IRUGO, show_psufan_led, set_psufan_led, 0);
|
||||
static SENSOR_DEVICE_ATTR(psu_led, S_IWUSR|S_IRUGO, show_psufan_led, set_psufan_led, 1);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(bios_cs, S_IWUSR|S_IRUGO, show_bios_cs, set_bios_cs, 0);
|
||||
|
||||
static struct attribute *cpld_attributes[] = {
|
||||
//info
|
||||
&sensor_dev_attr_info.dev_attr.attr,
|
||||
&sensor_dev_attr_ctl.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_grn_led.dev_attr.attr,
|
||||
&sensor_dev_attr_red_led.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_psu0.dev_attr.attr,
|
||||
&sensor_dev_attr_psu1.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_fan_led.dev_attr.attr,
|
||||
&sensor_dev_attr_psu_led.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_bios_cs.dev_attr.attr,
|
||||
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group cpld_group = {
|
||||
.attrs = cpld_attributes,
|
||||
};
|
||||
|
||||
static struct attribute *cpld2_attributes[] = {
|
||||
//info
|
||||
&sensor_dev_attr_info.dev_attr.attr,
|
||||
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group cpld2_group = {
|
||||
.attrs = cpld2_attributes,
|
||||
};
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* device probe and removal */
|
||||
|
||||
static int
|
||||
cpld_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
struct cpld_data *data;
|
||||
int status;
|
||||
|
||||
// printk("+%s \n", __func__);
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
|
||||
return -EIO;
|
||||
|
||||
data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->update_lock);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
if(id->driver_data==1) // CPLD2
|
||||
status = sysfs_create_group(&client->dev.kobj, &cpld2_group);
|
||||
else // default CPLD1
|
||||
status = sysfs_create_group(&client->dev.kobj, &cpld_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: sensor '%s'\n",
|
||||
dev_name(data->hwmon_dev), client->name);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_remove:
|
||||
sysfs_remove_group(&client->dev.kobj, &cpld_group);
|
||||
exit_free:
|
||||
i2c_set_clientdata(client, NULL);
|
||||
kfree(data);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int cpld_remove(struct i2c_client *client)
|
||||
{
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &cpld_group);
|
||||
i2c_set_clientdata(client, NULL);
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id cpld_ids[] = {
|
||||
{ "inv_cpld" , 0, },
|
||||
{ "inv_cpld2", 1, },
|
||||
{ /* LIST END */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cpld_ids);
|
||||
|
||||
static struct i2c_driver cpld_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "inv_cpld",
|
||||
},
|
||||
.probe = cpld_probe,
|
||||
.remove = cpld_remove,
|
||||
.id_table = cpld_ids,
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* module glue */
|
||||
|
||||
static int __init inv_cpld_init(void)
|
||||
{
|
||||
return i2c_add_driver(&cpld_driver);
|
||||
}
|
||||
|
||||
static void __exit inv_cpld_exit(void)
|
||||
{
|
||||
i2c_del_driver(&cpld_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("eddie.lan <eddie.lan@inventec>");
|
||||
MODULE_DESCRIPTION("inv cpld driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(inv_cpld_init);
|
||||
module_exit(inv_cpld_exit);
|
||||
@@ -0,0 +1,275 @@
|
||||
#include <asm/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include "io_expander.h"
|
||||
#include "inv_mux.h"
|
||||
|
||||
static struct mux_obj_s *mux_head_p = NULL;
|
||||
|
||||
|
||||
/* ========== MUX object functions ==========
|
||||
*/
|
||||
int
|
||||
_common_force_pull_gpio(int mem_addr,
|
||||
int input,
|
||||
int bit_offset){
|
||||
|
||||
unsigned int val = 0;
|
||||
unsigned int targ = 0;
|
||||
|
||||
/* Get current value */
|
||||
val = inl(mem_addr);
|
||||
if (val == 0) {
|
||||
SWPS_ERR("%s: inl:%d fail!\n", __func__, val);
|
||||
return -1;
|
||||
}
|
||||
/* Count target value */
|
||||
switch (input) {
|
||||
case 0: /* Pull Low */
|
||||
targ = (val & (~(1 << bit_offset)));
|
||||
break;
|
||||
case 1: /* Pull high */
|
||||
targ = (val | (1 << bit_offset));
|
||||
break;
|
||||
default:
|
||||
SWPS_ERR("%s: input state:%d incorrect!\n",
|
||||
__func__, input);
|
||||
return -1;
|
||||
}
|
||||
/* Setup gpio */
|
||||
outl(targ, mem_addr);
|
||||
if (targ != inl(mem_addr)){
|
||||
SWPS_ERR("%s: outl:%d fail!\n", __func__, targ);
|
||||
return -1;
|
||||
}
|
||||
SWPS_DEBUG("%s: done.\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
rangeley_force_pull_high(struct mux_obj_s *self){
|
||||
SWPS_ERR("%s: not ready!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
rangeley_force_pull_low(struct mux_obj_s *self){
|
||||
SWPS_ERR("%s: not ready!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hedera_force_pull_high(struct mux_obj_s *self){
|
||||
return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 1, 5);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hedera_force_pull_low(struct mux_obj_s *self){
|
||||
return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 0, 5);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
normal_gpio_pull_high(struct mux_obj_s *self){
|
||||
return gpio_direction_output(self->gpio_num, 1);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
normal_gpio_pull_low(struct mux_obj_s *self){
|
||||
return gpio_direction_output(self->gpio_num, 0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
pca9548_reset_mux_all(struct mux_obj_s *self){
|
||||
/* [Note] Power-on reset (PCA9548A-NXP)
|
||||
* When power is applied to VDD, an internal Power-On Reset (POR)
|
||||
* holds the PCA9548A in a reset condition until VDD has reached
|
||||
* VPOR. At this point, the reset condition is released and the
|
||||
* PCA9548A register and I2C-bus state machine are initialized to
|
||||
* their default states (all zeroes) causing all the channels to
|
||||
* be deselected. Thereafter, VDD must be lowered below 0.2 V for
|
||||
* at least 5 us in order to reset the device.
|
||||
*/
|
||||
if (self->_pull_low(self) < 0) {
|
||||
SWPS_ERR("%s: _pull_low fail!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
mdelay(MUX_RST_WAIT_MS);
|
||||
if (self->_pull_high(self) < 0) {
|
||||
SWPS_ERR("%s: _pull_high fail!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
mdelay(MUX_RST_WAIT_MS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
common_reset_mux_all(struct mux_obj_s *self){
|
||||
SWPS_ERR("%s: not ready!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
init_gpio_4_force(struct mux_obj_s *self){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
init_gpio_4_normal(struct mux_obj_s *self){
|
||||
|
||||
int err = 0;
|
||||
|
||||
if (!gpio_is_valid(self->gpio_num)) {
|
||||
SWPS_ERR("%s: GIPO:%d isn't valid\n", __func__, self->gpio_num);
|
||||
return -1;
|
||||
}
|
||||
err = gpio_request(self->gpio_num, MUX_GPIO_LABEL);
|
||||
if (err < 0) {
|
||||
SWPS_ERR("%s: gpio_request fail <err>:%d <gpio>:%d\n",
|
||||
__func__, err, self->gpio_num);
|
||||
return -1;
|
||||
}
|
||||
SWPS_DEBUG("%s: gpio_request:%d ok.\n", __func__, self->gpio_num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_setup_muxctl_cb(struct mux_obj_s *self,
|
||||
unsigned gpio){
|
||||
|
||||
char mod_dsc[32] = "ERR";
|
||||
|
||||
switch (gpio) {
|
||||
case MUX_RST_GPIO_FORCE_RANGELEY:
|
||||
self->gpio_num = gpio;
|
||||
self->_pull_low = rangeley_force_pull_low;
|
||||
self->_pull_high = rangeley_force_pull_high;
|
||||
self->_init = init_gpio_4_force;
|
||||
self->reset = pca9548_reset_mux_all;
|
||||
memset(mod_dsc, 0, 32);
|
||||
snprintf(mod_dsc, 31, "Rangeley force mode");
|
||||
goto ok_setup_muxctl_cb;
|
||||
|
||||
case MUX_RST_GPIO_FORCE_HEDERA:
|
||||
self->gpio_num = gpio;
|
||||
self->_pull_low = hedera_force_pull_low;
|
||||
self->_pull_high = hedera_force_pull_high;
|
||||
self->_init = init_gpio_4_force;
|
||||
self->reset = pca9548_reset_mux_all;
|
||||
memset(mod_dsc, 0, 32);
|
||||
snprintf(mod_dsc, 31, "Hedera force mode");
|
||||
goto ok_setup_muxctl_cb;
|
||||
|
||||
case MUX_RST_GPIO_48_PAC9548:
|
||||
case MUX_RST_GPIO_69_PAC9548:
|
||||
case MUX_RST_GPIO_249_PCA9548:
|
||||
case MUX_RST_GPIO_500_PAC9548:
|
||||
case MUX_RST_GPIO_505_PCA9548:
|
||||
self->gpio_num = gpio;
|
||||
self->_pull_low = normal_gpio_pull_low;
|
||||
self->_pull_high = normal_gpio_pull_high;
|
||||
self->_init = init_gpio_4_normal;
|
||||
self->reset = pca9548_reset_mux_all;
|
||||
memset(mod_dsc, 0, 32);
|
||||
snprintf(mod_dsc, 31, "Normal mode <gpio>:%d", (int)gpio);
|
||||
goto ok_setup_muxctl_cb;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
SWPS_ERR("%s: Unexpected GPIO:%d\n", __func__, gpio);
|
||||
return -1;
|
||||
|
||||
ok_setup_muxctl_cb:
|
||||
SWPS_INFO("muxctl: %s.\n", mod_dsc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ========== MUX public functions ==========
|
||||
*/
|
||||
void
|
||||
clean_mux_gpio(void){
|
||||
|
||||
if (!mux_head_p) {
|
||||
SWPS_DEBUG("%s: mux_head_p is NULL\n", __func__);
|
||||
return;
|
||||
}
|
||||
if (gpio_is_valid(mux_head_p->gpio_num)) {
|
||||
gpio_free(mux_head_p->gpio_num);
|
||||
}
|
||||
kfree(mux_head_p);
|
||||
mux_head_p = NULL;
|
||||
SWPS_DEBUG("%s: done.\n", __func__);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
reset_mux_gpio(void){
|
||||
|
||||
if (!mux_head_p) {
|
||||
SWPS_ERR("%s: MUX ctl object doesn't exist!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
if (mux_head_p->reset(mux_head_p) < 0){
|
||||
SWPS_ERR("%s: reset fail!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
init_mux_gpio(unsigned gpio){
|
||||
|
||||
/* Create MUX control object */
|
||||
if (mux_head_p) {
|
||||
SWPS_DEBUG("%s: mux_head_p is not NULL!\n", __func__);
|
||||
clean_mux_gpio();
|
||||
}
|
||||
/* Currently, it is using single muxctl architecture.
|
||||
* In the future, it may use the multi-muxctl if HW add new features.
|
||||
* (Ex: Port power-status control)
|
||||
*/
|
||||
mux_head_p = kzalloc(sizeof(struct mux_obj_s), GFP_KERNEL);
|
||||
if (!mux_head_p) {
|
||||
SWPS_ERR("%s: kzalloc fail!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
/* Initial MUX controller */
|
||||
if (_setup_muxctl_cb(mux_head_p, gpio) < 0){
|
||||
SWPS_ERR("%s: _setup_muxctl_cb fail!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
if (mux_head_p->_init(mux_head_p) < 0) {
|
||||
SWPS_ERR("%s: init() fail\n", __func__);
|
||||
goto err_init_mux_gpio;
|
||||
}
|
||||
/* Setup default value */
|
||||
if (mux_head_p->_pull_high(mux_head_p) < 0) {
|
||||
SWPS_ERR("%s: setup default fail!\n", __func__);
|
||||
goto err_init_mux_gpio;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_init_mux_gpio:
|
||||
clean_mux_gpio();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef INV_MUX_H
|
||||
#define INV_MUX_H
|
||||
|
||||
|
||||
/* MUX basic information */
|
||||
#define MUX_GPIO_LABEL "SWPS_RST_MUX"
|
||||
|
||||
/* MUX reset GPIO define */
|
||||
#define MUX_RST_GPIO_FORCE (30100)
|
||||
#define MUX_RST_GPIO_FORCE_RANGELEY (30101)
|
||||
#define MUX_RST_GPIO_FORCE_HEDERA (30102)
|
||||
#define MUX_RST_GPIO_48_PAC9548 (48)
|
||||
#define MUX_RST_GPIO_69_PAC9548 (69)
|
||||
#define MUX_RST_GPIO_249_PCA9548 (249)
|
||||
#define MUX_RST_GPIO_500_PAC9548 (500)
|
||||
#define MUX_RST_GPIO_505_PCA9548 (505)
|
||||
|
||||
/* MUX relate value define */
|
||||
#define MUX_RST_WAIT_MS (1)
|
||||
#define MUX_RST_MEM_ADDR_RANGELEY (0) // TBD
|
||||
#define MUX_RST_MEM_ADDR_HEDERA (0x548)
|
||||
|
||||
struct mux_obj_s {
|
||||
unsigned gpio_num;
|
||||
int (*_pull_high)(struct mux_obj_s *self);
|
||||
int (*_pull_low)(struct mux_obj_s *self);
|
||||
int (*_init)(struct mux_obj_s *self);
|
||||
int (*reset)(struct mux_obj_s *self);
|
||||
};
|
||||
|
||||
|
||||
void clean_mux_gpio(void);
|
||||
int reset_mux_gpio(void);
|
||||
int init_mux_gpio(unsigned gpio);
|
||||
|
||||
|
||||
#endif /* INV_MUX_H */
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c/pca954x.h>
|
||||
|
||||
struct inv_i2c_board_info {
|
||||
int ch;
|
||||
int size;
|
||||
struct i2c_board_info *board_info;
|
||||
};
|
||||
|
||||
#define bus_id(id) (id)
|
||||
static struct pca954x_platform_mode mux_modes_0[] = {
|
||||
{.adap_id = bus_id(2),}, {.adap_id = bus_id(3),},
|
||||
{.adap_id = bus_id(4),}, {.adap_id = bus_id(5),},
|
||||
{.adap_id = bus_id(6),}, {.adap_id = bus_id(7),},
|
||||
{.adap_id = bus_id(8),}, {.adap_id = bus_id(9),},
|
||||
};
|
||||
static struct pca954x_platform_mode mux_modes_0_0[] = {
|
||||
{.adap_id = bus_id(10),}, {.adap_id = bus_id(11),},
|
||||
{.adap_id = bus_id(12),}, {.adap_id = bus_id(13),},
|
||||
{.adap_id = bus_id(14),}, {.adap_id = bus_id(15),},
|
||||
{.adap_id = bus_id(16),}, {.adap_id = bus_id(17),},
|
||||
};
|
||||
|
||||
static struct pca954x_platform_mode mux_modes_0_1[] = {
|
||||
{.adap_id = bus_id(18),}, {.adap_id = bus_id(19),},
|
||||
{.adap_id = bus_id(20),}, {.adap_id = bus_id(21),},
|
||||
{.adap_id = bus_id(22),}, {.adap_id = bus_id(23),},
|
||||
{.adap_id = bus_id(24),}, {.adap_id = bus_id(25),},
|
||||
};
|
||||
|
||||
static struct pca954x_platform_mode mux_modes_0_2[] = {
|
||||
{.adap_id = bus_id(26),}, {.adap_id = bus_id(27),},
|
||||
{.adap_id = bus_id(28),}, {.adap_id = bus_id(29),},
|
||||
{.adap_id = bus_id(30),}, {.adap_id = bus_id(31),},
|
||||
{.adap_id = bus_id(32),}, {.adap_id = bus_id(33),},
|
||||
};
|
||||
|
||||
static struct pca954x_platform_mode mux_modes_0_3[] = {
|
||||
{.adap_id = bus_id(34),}, {.adap_id = bus_id(35),},
|
||||
{.adap_id = bus_id(36),}, {.adap_id = bus_id(37),},
|
||||
{.adap_id = bus_id(38),}, {.adap_id = bus_id(39),},
|
||||
{.adap_id = bus_id(40),}, {.adap_id = bus_id(41),},
|
||||
};
|
||||
|
||||
static struct pca954x_platform_mode mux_modes_0_4[] = {
|
||||
{.adap_id = bus_id(42),}, {.adap_id = bus_id(43),},
|
||||
{.adap_id = bus_id(44),}, {.adap_id = bus_id(45),},
|
||||
{.adap_id = bus_id(46),}, {.adap_id = bus_id(47),},
|
||||
{.adap_id = bus_id(48),}, {.adap_id = bus_id(49),},
|
||||
};
|
||||
|
||||
static struct pca954x_platform_mode mux_modes_0_5[] = {
|
||||
{.adap_id = bus_id(50),}, {.adap_id = bus_id(51),},
|
||||
{.adap_id = bus_id(52),}, {.adap_id = bus_id(53),},
|
||||
{.adap_id = bus_id(54),}, {.adap_id = bus_id(55),},
|
||||
{.adap_id = bus_id(56),}, {.adap_id = bus_id(57),},
|
||||
};
|
||||
|
||||
static struct pca954x_platform_mode mux_modes_0_6[] = {
|
||||
{.adap_id = bus_id(58),}, {.adap_id = bus_id(59),},
|
||||
{.adap_id = bus_id(60),}, {.adap_id = bus_id(61),},
|
||||
{.adap_id = bus_id(62),}, {.adap_id = bus_id(63),},
|
||||
{.adap_id = bus_id(64),}, {.adap_id = bus_id(65),},
|
||||
};
|
||||
|
||||
//no i2c device driver attach to mux 7
|
||||
|
||||
|
||||
static struct pca954x_platform_data mux_data_0 = {
|
||||
.modes = mux_modes_0,
|
||||
.num_modes = 8,
|
||||
};
|
||||
static struct pca954x_platform_data mux_data_0_0 = {
|
||||
.modes = mux_modes_0_0,
|
||||
.num_modes = 8,
|
||||
};
|
||||
static struct pca954x_platform_data mux_data_0_1 = {
|
||||
.modes = mux_modes_0_1,
|
||||
.num_modes = 8,
|
||||
};
|
||||
static struct pca954x_platform_data mux_data_0_2 = {
|
||||
.modes = mux_modes_0_2,
|
||||
.num_modes = 8,
|
||||
};
|
||||
static struct pca954x_platform_data mux_data_0_3 = {
|
||||
.modes = mux_modes_0_3,
|
||||
.num_modes = 8,
|
||||
};
|
||||
static struct pca954x_platform_data mux_data_0_4 = {
|
||||
.modes = mux_modes_0_4,
|
||||
.num_modes = 8,
|
||||
};
|
||||
static struct pca954x_platform_data mux_data_0_5 = {
|
||||
.modes = mux_modes_0_5,
|
||||
.num_modes = 8,
|
||||
};
|
||||
static struct pca954x_platform_data mux_data_0_6 = {
|
||||
.modes = mux_modes_0_6,
|
||||
.num_modes = 8,
|
||||
};
|
||||
|
||||
static struct i2c_board_info i2c_device_info0[] __initdata = {
|
||||
// {"inv_psoc", 0, 0x66, 0, 0, 0},//psoc
|
||||
// {"inv_cpld", 0, 0x55, 0, 0, 0},//cpld
|
||||
{"pca9548", 0, 0x70, &mux_data_0, 0, 0},
|
||||
};
|
||||
|
||||
static struct i2c_board_info i2c_device_info2[] __initdata = {
|
||||
{"pca9548", 0, 0x72, &mux_data_0_0, 0, 0},
|
||||
};
|
||||
static struct i2c_board_info i2c_device_info3[] __initdata = {
|
||||
{"pca9548", 0, 0x72, &mux_data_0_1, 0, 0},
|
||||
};
|
||||
static struct i2c_board_info i2c_device_info4[] __initdata = {
|
||||
{"pca9548", 0, 0x72, &mux_data_0_2, 0, 0},
|
||||
};
|
||||
static struct i2c_board_info i2c_device_info5[] __initdata = {
|
||||
{"pca9548", 0, 0x72, &mux_data_0_3, 0, 0},
|
||||
};
|
||||
static struct i2c_board_info i2c_device_info6[] __initdata = {
|
||||
{"pca9548", 0, 0x72, &mux_data_0_4, 0, 0},
|
||||
};
|
||||
static struct i2c_board_info i2c_device_info7[] __initdata = {
|
||||
{"pca9548", 0, 0x72, &mux_data_0_5, 0, 0},
|
||||
};
|
||||
static struct i2c_board_info i2c_device_info8[] __initdata = {
|
||||
{"pca9548", 0, 0x72, &mux_data_0_6, 0, 0},
|
||||
};
|
||||
|
||||
|
||||
static struct inv_i2c_board_info i2cdev_list[] = {
|
||||
{bus_id(1), ARRAY_SIZE(i2c_device_info0), i2c_device_info0 }, //mux root
|
||||
|
||||
{bus_id(2), ARRAY_SIZE(i2c_device_info2), i2c_device_info2 }, //mux 0
|
||||
{bus_id(3), ARRAY_SIZE(i2c_device_info3), i2c_device_info3 }, //mux 1
|
||||
{bus_id(4), ARRAY_SIZE(i2c_device_info4), i2c_device_info4 }, //mux 2
|
||||
{bus_id(5), ARRAY_SIZE(i2c_device_info5), i2c_device_info5 }, //mux 3
|
||||
{bus_id(6), ARRAY_SIZE(i2c_device_info6), i2c_device_info6 }, //mux 4
|
||||
{bus_id(7), ARRAY_SIZE(i2c_device_info7), i2c_device_info7 }, //mux 5
|
||||
{bus_id(8), ARRAY_SIZE(i2c_device_info8), i2c_device_info8 }, //mux 6
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
static struct platform_device *device_i2c_gpio0;
|
||||
static struct i2c_gpio_platform_data i2c_gpio_platdata0 = {
|
||||
.scl_pin = 58, //494,
|
||||
.sda_pin = 75, //511,
|
||||
|
||||
.udelay = 5, //5:100kHz
|
||||
.sda_is_open_drain = 0,
|
||||
.scl_is_open_drain = 0,
|
||||
.scl_is_output_only = 0
|
||||
};
|
||||
|
||||
static int __init inv_platform_init(void)
|
||||
{
|
||||
struct i2c_adapter *adap = NULL;
|
||||
struct i2c_client *e = NULL;
|
||||
int ret = 0;
|
||||
int i,j,k;
|
||||
|
||||
//printk("%s \n", __func__);
|
||||
|
||||
//use i2c-gpio
|
||||
//register i2c gpio
|
||||
//config gpio58,75 to gpio function 58=32+3*8+2 75=32*2+8*1+3 gpio69=32*2+8*0+5
|
||||
outl( inl(0x533) | (1<<2), 0x533); //i2c-gpio sdl (GPIO58)
|
||||
outl( inl(0x541) | (1<<3), 0x541); //i2c-gpio sda (GPIO75)
|
||||
outl( inl(0x540) | (1<<5), 0x540); //RST_I2C_MUX_N (GPIO69)
|
||||
outl( inl(0x500) | (1<<7), 0x500); //SYS_RDY_N (GPIO7)
|
||||
outl( inl(0x501) | (1<<7), 0x501); //BMC_HEART_BEAT (GPIO15)
|
||||
outl( inl(0x503) | (1<<2)|(1<<3), 0x503); //PSOC_HEART_BEAT(26),CPLD_HEART_BEAT(27)
|
||||
|
||||
device_i2c_gpio0 = platform_device_alloc("i2c-gpio", 1);
|
||||
if (!device_i2c_gpio0) {
|
||||
printk(KERN_ERR "i2c-gpio: platform_device_alloc fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
device_i2c_gpio0->name = "i2c-gpio";
|
||||
device_i2c_gpio0->id = 1;
|
||||
device_i2c_gpio0->dev.platform_data = &i2c_gpio_platdata0;
|
||||
|
||||
ret = platform_device_add(device_i2c_gpio0);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "i2c-gpio: platform_device_add fail %d\n", ret);
|
||||
}
|
||||
|
||||
for(i=0; i<ARRAY_SIZE(i2cdev_list); i++) {
|
||||
adap = i2c_get_adapter( i2cdev_list[i].ch );
|
||||
if (adap == NULL) {
|
||||
printk("platform get channel %d adapter fail\n", i);
|
||||
continue;
|
||||
}
|
||||
i2c_put_adapter(adap);
|
||||
for(j=0; j<i2cdev_list[i].size; j++) {
|
||||
for(k=0; k<300; k++) {
|
||||
e = i2c_new_device(adap, &i2cdev_list[i].board_info[j] );
|
||||
if(e == NULL) msleep(10); else break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit inv_platform_exit(void)
|
||||
{
|
||||
device_i2c_gpio0->dev.platform_data = NULL;
|
||||
platform_device_unregister(device_i2c_gpio0);
|
||||
}
|
||||
|
||||
module_init(inv_platform_init);
|
||||
module_exit(inv_platform_exit);
|
||||
|
||||
MODULE_AUTHOR("Inventec");
|
||||
MODULE_DESCRIPTION("Platform devices");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,994 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/fs.h>
|
||||
#include <asm/uaccess.h>
|
||||
#define SWITCH_TEMPERATURE_SOCK "/proc/switch/temp"
|
||||
#define PSOC_POLLING_PERIOD 1000
|
||||
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/ipmi.h>
|
||||
#include <linux/ipmi_smi.h>
|
||||
|
||||
#define IPMI_MAX_INTF (4)
|
||||
#define NETFN_OEM 0x30
|
||||
#define CMD_GETDATA 0x31
|
||||
#define CMD_SETDATA 0x32
|
||||
#define FAN_NUM 4
|
||||
#define PSU_NUM 2
|
||||
|
||||
#define FAN_CLEI_SUPPORT 1
|
||||
#define PSU_CLEI_SUPPORT 0
|
||||
|
||||
#define PSU1 0x5800
|
||||
#define PSU2 0x5900
|
||||
#define BMC_PMBusNumber 3
|
||||
#define PMBus_Vendor 0x99
|
||||
#define PMBus_Serial 0x9E
|
||||
#define PMBus_Temp2 0x8E
|
||||
#define PMBus_Version 0x9B
|
||||
#define MaxLeng_Result 0x40
|
||||
|
||||
#define BMC_FanCLEIBusNumber 9
|
||||
#define DEVICE_CLEI_ADDR 0x52,0x53,0x54,0x55,0x56,0x50,0x51
|
||||
|
||||
#define MAX_IPMI_RECV_LENGTH 0xff
|
||||
static char CLEI_ADDR[]={DEVICE_CLEI_ADDR};
|
||||
struct task_struct *kthread_auto_update;
|
||||
static long pmbus_reg2data_linear(int data, int linear16);
|
||||
struct ipmi_result{
|
||||
char result[MAX_IPMI_RECV_LENGTH];
|
||||
int result_length;
|
||||
};
|
||||
|
||||
DEFINE_MUTEX(ipmi_mutex);
|
||||
DEFINE_MUTEX(ipmi2_mutex);
|
||||
static struct ipmi_result ipmiresult;
|
||||
static struct device *hwmon_dev;
|
||||
static struct kobject *device_kobj;
|
||||
static ipmi_user_t ipmi_mh_user = NULL;
|
||||
static void msg_handler(struct ipmi_recv_msg *msg,void* handler_data);
|
||||
static struct ipmi_user_hndl ipmi_hndlrs = { .ipmi_recv_hndl = msg_handler,};
|
||||
|
||||
static atomic_t dummy_count = ATOMIC_INIT(0);
|
||||
static void dummy_smi_free(struct ipmi_smi_msg *msg)
|
||||
{
|
||||
atomic_dec(&dummy_count);
|
||||
}
|
||||
static void dummy_recv_free(struct ipmi_recv_msg *msg)
|
||||
{
|
||||
atomic_dec(&dummy_count);
|
||||
}
|
||||
static struct ipmi_smi_msg halt_smi_msg = {
|
||||
.done = dummy_smi_free
|
||||
};
|
||||
static struct ipmi_recv_msg halt_recv_msg = {
|
||||
.done = dummy_recv_free
|
||||
};
|
||||
|
||||
struct __attribute__ ((__packed__)) psoc_psu_layout {
|
||||
u16 psu1_iin;
|
||||
u16 psu2_iin;
|
||||
u16 psu1_iout;
|
||||
u16 psu2_iout;
|
||||
|
||||
u16 psu1_pin;
|
||||
u16 psu2_pin;
|
||||
u16 psu1_pout;
|
||||
u16 psu2_pout;
|
||||
|
||||
u16 psu1_vin;
|
||||
u16 psu2_vin;
|
||||
u16 psu1_vout;
|
||||
u16 psu2_vout;
|
||||
};
|
||||
|
||||
struct __attribute__ ((__packed__)) clei {
|
||||
u8 issue_number[3];
|
||||
u8 abbreviation_number[9];
|
||||
u8 fc_number[10];
|
||||
u8 clei_code[10];
|
||||
u8 product_year_and_month[5];
|
||||
u8 label_location_code[2];
|
||||
u8 serial_number[5];
|
||||
u8 pcb_revision[5];
|
||||
u8 vendor_name[10];
|
||||
u8 reserved[5];
|
||||
};
|
||||
|
||||
struct __attribute__ ((__packed__)) psoc_layout {
|
||||
u8 ctl; //offset: 0
|
||||
u16 switch_temp; //offset: 1
|
||||
|
||||
// BYTE[03:20] - voltage
|
||||
u16 voltage[15]; //offset: 0x03-0x20
|
||||
|
||||
// BYTE[21:27] - ExtFan
|
||||
u8 led_ctl2; //offset: 21
|
||||
u8 ext_pwm; //offset: 22
|
||||
u16 ext_rpm[2]; //offset: 23
|
||||
u8 gpi_fan2; //offset: 27
|
||||
|
||||
//gpo
|
||||
u8 led_ctl; //offset: 28
|
||||
|
||||
u8 gpio; //offset: 29
|
||||
|
||||
//pwm duty
|
||||
u8 pwm[4]; //offset: 2a
|
||||
u8 pwm_psu[2]; //offset: 2e
|
||||
|
||||
//fan rpm
|
||||
u16 fan[4*2]; //offset: 30
|
||||
|
||||
u8 reserve1[4]; //offset: 40
|
||||
|
||||
//gpi
|
||||
u8 gpi_fan; //offset: 44
|
||||
|
||||
//psu state
|
||||
u8 psu_state; //offset: 45
|
||||
|
||||
//temperature
|
||||
u16 temp[5]; //offset: 46
|
||||
u16 temp_psu[2]; //offset: 50
|
||||
|
||||
//version
|
||||
u8 version[2]; //offset: 54
|
||||
|
||||
u8 reserve2[4]; //offset: 56
|
||||
struct psoc_psu_layout psu_info; //offset: 5a
|
||||
};
|
||||
|
||||
/* definition */
|
||||
#define PSOC_OFF(m) offsetof(struct psoc_layout, m)
|
||||
#define PSOC_PSU_OFF(m) offsetof(struct psoc_psu_layout, m)
|
||||
|
||||
#define SWITCH_TMP_OFFSET PSOC_OFF(switch_temp)
|
||||
#define PWM_OFFSET PSOC_OFF(pwm)
|
||||
#define THERMAL_OFFSET PSOC_OFF(temp)
|
||||
#define RPM_OFFSET PSOC_OFF(fan)
|
||||
#define DIAG_FLAG_OFFSET PSOC_OFF(ctl)
|
||||
#define FAN_LED_OFFSET PSOC_OFF(led_ctl)
|
||||
#define FAN_GPI_OFFSET PSOC_OFF(gpi_fan)
|
||||
#define PSOC_PSU_OFFSET PSOC_OFF(psu_state)
|
||||
#define VERSION_OFFSET PSOC_OFF(version)
|
||||
#define PSU_INFO_OFFSET PSOC_OFF(psu_info)
|
||||
|
||||
#define PWM2_OFFSET PSOC_OFF(ext_pwm)
|
||||
#define RPM2_OFFSET PSOC_OFF(ext_rpm)
|
||||
#define FAN_LED2_OFFSET PSOC_OFF(led_ctl2)
|
||||
#define FAN_GPI2_OFFSET PSOC_OFF(gpi_fan2)
|
||||
|
||||
#define CLEI_OFF(m) offsetof(struct clei, m)
|
||||
#define FAN1_CLEI_INDEX 0
|
||||
#define FAN2_CLEI_INDEX 1
|
||||
#define FAN3_CLEI_INDEX 2
|
||||
#define FAN4_CLEI_INDEX 3
|
||||
#define FAN5_CLEI_INDEX 4
|
||||
#define PSU1_CLEI_INDEX 5
|
||||
#define PSU2_CLEI_INDEX 6
|
||||
|
||||
static void msg_handler(struct ipmi_recv_msg *recv_msg,void* handler_data)
|
||||
{
|
||||
struct ipmi_result *msg_result = recv_msg->user_msg_data;
|
||||
|
||||
if(recv_msg->msg.data[0]==0 && recv_msg->msg.data_len>0) {
|
||||
msg_result->result_length=recv_msg->msg.data_len-1;
|
||||
memcpy(msg_result->result, &recv_msg->msg.data[1], recv_msg->msg.data_len-1);
|
||||
}
|
||||
ipmi_free_recv_msg(recv_msg);
|
||||
mutex_unlock(&ipmi_mutex);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int start_ipmi_command(char NetFn, char cmd,char *data,int data_length, char* result, int* result_length)
|
||||
{
|
||||
int rv=0,i;
|
||||
int timeout;
|
||||
|
||||
//wait previous command finish at least 50msec
|
||||
timeout=50;
|
||||
while((mutex_is_locked(&ipmi_mutex) == 1 || (mutex_is_locked(&ipmi2_mutex) == 1)) && (--timeout)>0) { usleep_range(1000,1010); }
|
||||
if(timeout==0) { return -1; }
|
||||
mutex_lock(&ipmi_mutex);
|
||||
mutex_lock(&ipmi2_mutex);
|
||||
|
||||
if(ipmi_mh_user == NULL) {
|
||||
for (i=0,rv=1; i<IPMI_MAX_INTF && rv; i++) {
|
||||
rv = ipmi_create_user(i, &ipmi_hndlrs, NULL, &ipmi_mh_user);
|
||||
}
|
||||
}
|
||||
|
||||
if (rv < 0) {
|
||||
mutex_unlock(&ipmi_mutex);
|
||||
mutex_unlock(&ipmi2_mutex);
|
||||
return rv;
|
||||
}
|
||||
else {
|
||||
struct ipmi_system_interface_addr addr;
|
||||
struct kernel_ipmi_msg msg;
|
||||
uint8_t msg_data[data_length];
|
||||
|
||||
memcpy(msg_data,data,data_length);
|
||||
addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
|
||||
addr.channel = IPMI_BMC_CHANNEL;
|
||||
addr.lun = 0;
|
||||
|
||||
msg.netfn = NetFn;
|
||||
msg.cmd = cmd;
|
||||
msg.data = msg_data;
|
||||
msg.data_len = data_length;
|
||||
|
||||
rv = ipmi_request_supply_msgs(ipmi_mh_user, (struct ipmi_addr*)&addr, 0,&msg, &ipmiresult, &halt_smi_msg, &halt_recv_msg, 0);
|
||||
if (rv) {
|
||||
mutex_unlock(&ipmi_mutex);
|
||||
mutex_unlock(&ipmi2_mutex);
|
||||
return -6;
|
||||
}
|
||||
|
||||
//skip command if 1sec no response from remote
|
||||
timeout=1000;
|
||||
while(mutex_is_locked(&ipmi_mutex) == 1 && (--timeout)>0) { usleep_range(1000,1100);}
|
||||
if(timeout==0) {
|
||||
mutex_unlock(&ipmi2_mutex);
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
*result_length=ipmiresult.result_length;
|
||||
memcpy(result,ipmiresult.result,*result_length);
|
||||
mutex_unlock(&ipmi2_mutex);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(start_ipmi_command);
|
||||
|
||||
static ssize_t psoc_ipmi_read(u8 *buf, u8 offset, size_t count)
|
||||
{
|
||||
uint8_t data[2];
|
||||
int result_len=0;
|
||||
int rv;
|
||||
|
||||
data[0] = offset;
|
||||
data[1] = count;
|
||||
|
||||
rv=start_ipmi_command(NETFN_OEM, CMD_GETDATA,data,2, buf, &result_len);
|
||||
|
||||
return result_len;
|
||||
}
|
||||
|
||||
static ssize_t psoc_ipmi_write(char *buf, unsigned offset, size_t count)
|
||||
{
|
||||
uint8_t data[count+1],result[1];
|
||||
int result_len;
|
||||
|
||||
data[0] = offset;
|
||||
memcpy(&data[1],buf,count);
|
||||
|
||||
start_ipmi_command(NETFN_OEM, CMD_SETDATA,data,count+1, result, &result_len);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static u16 psoc_read16(u8 offset)
|
||||
{
|
||||
u16 value = 0;
|
||||
u8 buf[]={0,0};
|
||||
|
||||
if(psoc_ipmi_read(buf, offset, 2) == 2)
|
||||
value = (buf[0]<<8 | buf[1]<<0);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static u8 psoc_read8(u8 offset)
|
||||
{
|
||||
u8 value = 0;
|
||||
u8 buf = 0;
|
||||
|
||||
if(psoc_ipmi_read(&buf, offset, 1) == 1)
|
||||
value = buf;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
CPLD report the PSU0 status
|
||||
000 = PSU normal operation
|
||||
100 = PSU fault
|
||||
010 = PSU unpowered
|
||||
111 = PSU not installed
|
||||
|
||||
7 6 | 5 4 3 | 2 1 0
|
||||
----------------------
|
||||
| psu1 | psu0
|
||||
*/
|
||||
static char* psu_str[] = {
|
||||
"normal", //000
|
||||
"NA", //001
|
||||
"unpowered", //010
|
||||
"NA", //011
|
||||
"fault", //100
|
||||
"NA", //101
|
||||
"NA", //110
|
||||
"not installed", //111
|
||||
};
|
||||
|
||||
static ssize_t show_psu_st(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u32 status=0;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u8 byte=0;
|
||||
int shift = (attr->index == 0)?3:0;
|
||||
|
||||
status = psoc_ipmi_read(&byte, PSOC_PSU_OFFSET, 1);
|
||||
|
||||
byte = (byte >> shift) & 0x7;
|
||||
|
||||
status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]);
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static ssize_t show_ipmi_pmbus(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
uint8_t data[4],result[MaxLeng_Result];
|
||||
int result_len=0;
|
||||
|
||||
data[0] = BMC_PMBusNumber;
|
||||
data[1] = (attr->index & 0xFF00 ) >>7;
|
||||
data[3] = attr->index & 0xff;
|
||||
if(data[3]==PMBus_Temp2)
|
||||
{data[2]=2;}
|
||||
else
|
||||
{data[2]=MaxLeng_Result;}
|
||||
|
||||
if(start_ipmi_command(0x06, 0x52,data,4, result, &result_len)==0)
|
||||
{
|
||||
if(data[3]==PMBus_Temp2)
|
||||
{
|
||||
return sprintf(buf, "%ld \n", pmbus_reg2data_linear(result[0] | (result[1]<<8), 0 ));
|
||||
}
|
||||
result[result[0]+1]='\0';
|
||||
return sprintf(buf, "%s\n",&result[1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t show_clei(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u8 device_index = attr->index & 0xFF;
|
||||
|
||||
uint8_t data[5],result[MaxLeng_Result];
|
||||
int result_len=0;
|
||||
|
||||
data[0] = (device_index<=FAN5_CLEI_INDEX) ? BMC_FanCLEIBusNumber:BMC_PMBusNumber;
|
||||
data[1] = CLEI_ADDR[device_index]<<1;
|
||||
data[2] = sizeof(struct clei);
|
||||
data[3] = (device_index<=FAN5_CLEI_INDEX) ? 0x00 : 0x01; //PSU CLEI will start from 0x0100
|
||||
data[4] = 0;
|
||||
|
||||
if(start_ipmi_command(0x06, 0x52,data,5, result, &result_len)==0)
|
||||
{
|
||||
if(result_len < sizeof(struct clei)) memset(result, 0, sizeof(struct clei));
|
||||
sprintf (buf, "Issue Number: %.3s\n", &result[CLEI_OFF(issue_number)]);
|
||||
sprintf (buf, "%sAbbreviation Number: %.9s\n", buf, &result[CLEI_OFF(abbreviation_number)]);
|
||||
sprintf (buf, "%sFC Number: %.10s\n", buf, &result[CLEI_OFF(fc_number)]);
|
||||
sprintf (buf, "%sCLEI Code: %.10s\n", buf, &result[CLEI_OFF(clei_code)]);
|
||||
sprintf (buf, "%sProduct Year and Month: %.5s\n", buf, &result[CLEI_OFF(product_year_and_month)]);
|
||||
sprintf (buf, "%s2D Label Location Code: %.2s\n", buf, &result[CLEI_OFF(label_location_code)]);
|
||||
sprintf (buf, "%sSerial Number: %.5s\n", buf, &result[CLEI_OFF(serial_number)]);
|
||||
sprintf (buf, "%sPCB Revision: %.5s\n", buf, &result[CLEI_OFF(pcb_revision)]);
|
||||
sprintf (buf, "%sVendor Name: %.10s\n", buf, &result[CLEI_OFF(vendor_name)]);
|
||||
return strlen(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
return sprintf(buf, "NONE\n");
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t show_thermal(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
int status=0;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u8 offset = attr->index * 2 + THERMAL_OFFSET;
|
||||
|
||||
status = psoc_read16(offset);
|
||||
|
||||
return sprintf(buf, "%d\n",
|
||||
(s8)(status>>8) * 1000 );
|
||||
}
|
||||
|
||||
static ssize_t show_pwm(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
int status=0;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u8 offset = attr->index;
|
||||
|
||||
status = psoc_read8(offset);
|
||||
|
||||
return sprintf(buf, "%d\n",
|
||||
status);
|
||||
}
|
||||
|
||||
static ssize_t set_pwm(struct device *dev,
|
||||
struct device_attribute *da,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u8 offset = attr->index;
|
||||
u8 pwm = simple_strtol(buf, NULL, 10);
|
||||
if(pwm > 255) pwm = 255;
|
||||
psoc_ipmi_write(&pwm, offset, 1);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t show_rpm(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
int status=0;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u8 offset = attr->index;
|
||||
status = psoc_read16(offset);
|
||||
|
||||
return sprintf(buf, "%d\n",
|
||||
status);
|
||||
}
|
||||
|
||||
static ssize_t show_switch_tmp(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u16 status=0;
|
||||
u16 temp = 0;
|
||||
|
||||
status = psoc_ipmi_read((u8*)&temp, SWITCH_TMP_OFFSET, 2);
|
||||
|
||||
status = sprintf (buf, "%d\n", (s8)(temp>>8) * 1000 );
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static ssize_t set_switch_tmp(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
long temp = simple_strtol(buf, NULL, 10);
|
||||
u16 temp2 = ( (temp/1000) <<8 ) & 0xFF00 ;
|
||||
|
||||
psoc_ipmi_write((u8*)&temp2, SWITCH_TMP_OFFSET, 2);
|
||||
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_diag(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u16 status=0;
|
||||
u8 diag_flag = 0;
|
||||
|
||||
status = psoc_ipmi_read((u8*)&diag_flag, DIAG_FLAG_OFFSET, 1);
|
||||
|
||||
status = sprintf (buf, "%d\n", ((diag_flag & 0x80)?1:0));
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static ssize_t set_diag(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
u8 value = 0;
|
||||
u8 diag = simple_strtol(buf, NULL, 10);
|
||||
|
||||
diag = diag?1:0;
|
||||
|
||||
psoc_ipmi_read((u8*)&value, DIAG_FLAG_OFFSET, 1);
|
||||
if(diag) value |= (1<<7);
|
||||
else value &= ~(1<<7);
|
||||
psoc_ipmi_write((u8*)&value, DIAG_FLAG_OFFSET, 1);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_version(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u16 status=0;
|
||||
|
||||
status = psoc_read16(VERSION_OFFSET);
|
||||
|
||||
return sprintf(buf, "ver: %x.%x\n", (status & 0xFF00)>>8, (status & 0xFF) );
|
||||
}
|
||||
|
||||
|
||||
static ssize_t show_fan_led(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
int status=0;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u8 bit = attr->index;
|
||||
|
||||
if(bit < 8) { status = psoc_read8(FAN_LED_OFFSET); }
|
||||
#if FAN_NUM>4
|
||||
if(bit >= 8) { status = psoc_read8(FAN_LED2_OFFSET); bit-=8; }
|
||||
#endif
|
||||
|
||||
return sprintf(buf, "%d\n",
|
||||
(status & (1<<bit))?1:0 );
|
||||
}
|
||||
|
||||
static ssize_t set_fan_led(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
u8 bit = attr->index;
|
||||
u8 led_state = 0;
|
||||
|
||||
u8 v = simple_strtol(buf, NULL, 10);
|
||||
|
||||
if(attr->index < 8) { led_state = psoc_read8(FAN_LED_OFFSET ); }
|
||||
#if FAN_NUM>4
|
||||
if(attr->index >= 8) { led_state = psoc_read8(FAN_LED2_OFFSET); bit-=8; }
|
||||
#endif
|
||||
if(v) led_state |= (1<<bit);
|
||||
else led_state &= ~(1<<bit);
|
||||
|
||||
if(attr->index < 8) { psoc_ipmi_write(&led_state, FAN_LED_OFFSET, 1);}
|
||||
#if FAN_NUM>4
|
||||
if(attr->index >= 8) { psoc_ipmi_write(&led_state, FAN_LED2_OFFSET,1);}
|
||||
#endif
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_value8(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
int status=0;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u8 offset = attr->index;
|
||||
|
||||
status = psoc_read8(offset);
|
||||
|
||||
return sprintf(buf, "0x%02X\n", status );
|
||||
}
|
||||
|
||||
static long pmbus_reg2data_linear(int data, int linear16)
|
||||
{
|
||||
s16 exponent;
|
||||
s32 mantissa;
|
||||
long val;
|
||||
|
||||
if (linear16) { /* LINEAR16 */
|
||||
exponent = -9;
|
||||
mantissa = (u16) data;
|
||||
} else { /* LINEAR11 */
|
||||
exponent = ((s16)data) >> 11;
|
||||
exponent = ((s16)( data & 0xF800) ) >> 11;
|
||||
mantissa = ((s32)((data & 0x7ff) << 5)) >> 5;
|
||||
}
|
||||
|
||||
//printk("data=%d, m=%d, e=%d\n", data, exponent, mantissa);
|
||||
val = mantissa;
|
||||
|
||||
/* scale result to micro-units for power sensors */
|
||||
val = val * 1000L;
|
||||
|
||||
if (exponent >= 0)
|
||||
val <<= exponent;
|
||||
else
|
||||
val >>= -exponent;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static ssize_t show_psu_psoc(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u16 status=0;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u8 offset = attr->index + PSU_INFO_OFFSET;
|
||||
|
||||
status = psoc_read16(offset);
|
||||
|
||||
if((strstr(attr->dev_attr.attr.name, "vout")!=NULL)|(strstr(attr->dev_attr.attr.name, "in3")!=NULL)|(strstr(attr->dev_attr.attr.name, "in4")!=NULL)) {
|
||||
offset=1;
|
||||
}
|
||||
else {
|
||||
offset=0;
|
||||
}
|
||||
|
||||
return sprintf(buf, "%ld \n", pmbus_reg2data_linear(status, offset ));
|
||||
}
|
||||
|
||||
static ssize_t show_name(struct device *dev,
|
||||
struct device_attribute *devattr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "inv_psoc\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
|
||||
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_thermal, 0, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_thermal, 0, 1);
|
||||
static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_thermal, 0, 2);
|
||||
static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_thermal, 0, 3);
|
||||
static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_thermal, 0, 4);
|
||||
static SENSOR_DEVICE_ATTR(thermal_psu1, S_IRUGO, show_thermal, 0, 5);
|
||||
static SENSOR_DEVICE_ATTR(thermal_psu2, S_IRUGO, show_thermal, 0, 6);
|
||||
static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_thermal, 0, 5);
|
||||
static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_thermal, 0, 6);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 0 + PWM_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 1 + PWM_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 2 + PWM_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 3 + PWM_OFFSET);
|
||||
#if FAN_NUM > 4
|
||||
static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 0 + PWM2_OFFSET);
|
||||
#endif
|
||||
static SENSOR_DEVICE_ATTR(pwm_psu1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 4 + PWM_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(pwm_psu2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 5 + PWM_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(pwm6, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 4 + PWM_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(pwm7, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 5 + PWM_OFFSET);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu_st, 0, 0);
|
||||
static SENSOR_DEVICE_ATTR(psu2, S_IRUGO, show_psu_st, 0, 1);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, 0, 0*2 + RPM_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_rpm, 0, 1*2 + RPM_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_rpm, 0, 2*2 + RPM_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_rpm, 0, 3*2 + RPM_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_rpm, 0, 4*2 + RPM_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_rpm, 0, 5*2 + RPM_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_rpm, 0, 6*2 + RPM_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_rpm, 0, 7*2 + RPM_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(rpm_psu1, S_IRUGO, show_rpm, 0, 8*2 + RPM_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(rpm_psu2, S_IRUGO, show_rpm, 0, 9*2 + RPM_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(fan11_input, S_IRUGO, show_rpm, 0, 8*2 + RPM_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(fan12_input, S_IRUGO, show_rpm, 0, 9*2 + RPM_OFFSET);
|
||||
|
||||
#if FAN_NUM > 4
|
||||
static SENSOR_DEVICE_ATTR(fan9_input , S_IRUGO, show_rpm, 0,0*2 + RPM2_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(fan10_input, S_IRUGO, show_rpm, 0,1*2 + RPM2_OFFSET);
|
||||
#endif
|
||||
|
||||
static SENSOR_DEVICE_ATTR(switch_tmp, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp6_input, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(diag, S_IWUSR|S_IRUGO, show_diag, set_diag, 0);
|
||||
static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, 0, 0);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(fan_led_grn1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 0);
|
||||
static SENSOR_DEVICE_ATTR(fan_led_grn2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 1);
|
||||
static SENSOR_DEVICE_ATTR(fan_led_grn3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 2);
|
||||
static SENSOR_DEVICE_ATTR(fan_led_grn4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 3);
|
||||
static SENSOR_DEVICE_ATTR(fan_led_red1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 4);
|
||||
static SENSOR_DEVICE_ATTR(fan_led_red2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 5);
|
||||
static SENSOR_DEVICE_ATTR(fan_led_red3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 6);
|
||||
static SENSOR_DEVICE_ATTR(fan_led_red4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 7);
|
||||
|
||||
#if FAN_NUM>4
|
||||
static SENSOR_DEVICE_ATTR(fan_led_grn5, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 8);
|
||||
static SENSOR_DEVICE_ATTR(fan_led_red5, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 12);
|
||||
static SENSOR_DEVICE_ATTR(fan_gpi2, S_IRUGO, show_value8, 0, FAN_GPI2_OFFSET);
|
||||
#endif
|
||||
|
||||
static SENSOR_DEVICE_ATTR(fan_gpi, S_IRUGO, show_value8, 0, FAN_GPI_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vout));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iout));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pout));
|
||||
|
||||
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin));
|
||||
static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin));
|
||||
static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin));
|
||||
static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vout));
|
||||
static SENSOR_DEVICE_ATTR(curr3_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iout));
|
||||
static SENSOR_DEVICE_ATTR(power3_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pout));
|
||||
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vout));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iout));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pout));
|
||||
|
||||
static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin));
|
||||
static SENSOR_DEVICE_ATTR(curr2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin));
|
||||
static SENSOR_DEVICE_ATTR(power2_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin));
|
||||
static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vout));
|
||||
static SENSOR_DEVICE_ATTR(curr4_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iout));
|
||||
static SENSOR_DEVICE_ATTR(power4_input, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pout));
|
||||
|
||||
//IPMI
|
||||
static SENSOR_DEVICE_ATTR(thermal2_psu1, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Temp2);
|
||||
static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Temp2);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_vendor, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Vendor);
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_serial, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Serial);
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_version, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Version);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(thermal2_psu2, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Temp2);
|
||||
static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Temp2);
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_vendor, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Vendor);
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_serial, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Serial);
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_version, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Version);
|
||||
|
||||
//CLEI
|
||||
#if FAN_CLEI_SUPPORT
|
||||
static SENSOR_DEVICE_ATTR(fan1_clei, S_IRUGO, show_clei, 0, FAN1_CLEI_INDEX );
|
||||
static SENSOR_DEVICE_ATTR(fan2_clei, S_IRUGO, show_clei, 0, FAN2_CLEI_INDEX );
|
||||
static SENSOR_DEVICE_ATTR(fan3_clei, S_IRUGO, show_clei, 0, FAN3_CLEI_INDEX );
|
||||
static SENSOR_DEVICE_ATTR(fan4_clei, S_IRUGO, show_clei, 0, FAN4_CLEI_INDEX );
|
||||
#if FAN_NUM > 4
|
||||
static SENSOR_DEVICE_ATTR(fan5_clei, S_IRUGO, show_clei, 0, FAN5_CLEI_INDEX );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PSU_CLEI_SUPPORT
|
||||
static SENSOR_DEVICE_ATTR(psu1_clei, S_IRUGO, show_clei, 0, PSU1_CLEI_INDEX );
|
||||
static SENSOR_DEVICE_ATTR(psu2_clei, S_IRUGO, show_clei, 0, PSU2_CLEI_INDEX );
|
||||
#endif
|
||||
|
||||
static struct attribute *psoc_attributes[] = {
|
||||
//name
|
||||
&dev_attr_name.attr,
|
||||
//thermal
|
||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp4_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp5_input.dev_attr.attr,
|
||||
&sensor_dev_attr_thermal_psu1.dev_attr.attr,
|
||||
&sensor_dev_attr_thermal_psu2.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_temp7_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp8_input.dev_attr.attr,
|
||||
|
||||
//pwm
|
||||
&sensor_dev_attr_pwm1.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm2.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm3.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm4.dev_attr.attr,
|
||||
#if FAN_NUM > 4
|
||||
&sensor_dev_attr_pwm5.dev_attr.attr,
|
||||
#endif
|
||||
&sensor_dev_attr_pwm_psu1.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm_psu2.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm6.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm7.dev_attr.attr,
|
||||
|
||||
//rpm
|
||||
&sensor_dev_attr_fan1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan4_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan5_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan6_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan7_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan8_input.dev_attr.attr,
|
||||
#if FAN_NUM > 4
|
||||
&sensor_dev_attr_fan9_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan10_input.dev_attr.attr,
|
||||
#endif
|
||||
&sensor_dev_attr_rpm_psu1.dev_attr.attr,
|
||||
&sensor_dev_attr_rpm_psu2.dev_attr.attr,
|
||||
&sensor_dev_attr_fan11_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan12_input.dev_attr.attr,
|
||||
//switch temperature
|
||||
&sensor_dev_attr_switch_tmp.dev_attr.attr,
|
||||
&sensor_dev_attr_temp6_input.dev_attr.attr,
|
||||
|
||||
//diag flag
|
||||
&sensor_dev_attr_diag.dev_attr.attr,
|
||||
|
||||
//version
|
||||
&sensor_dev_attr_version.dev_attr.attr,
|
||||
|
||||
//fan led
|
||||
&sensor_dev_attr_fan_led_grn1.dev_attr.attr,
|
||||
&sensor_dev_attr_fan_led_grn2.dev_attr.attr,
|
||||
&sensor_dev_attr_fan_led_grn3.dev_attr.attr,
|
||||
&sensor_dev_attr_fan_led_grn4.dev_attr.attr,
|
||||
&sensor_dev_attr_fan_led_red1.dev_attr.attr,
|
||||
&sensor_dev_attr_fan_led_red2.dev_attr.attr,
|
||||
&sensor_dev_attr_fan_led_red3.dev_attr.attr,
|
||||
&sensor_dev_attr_fan_led_red4.dev_attr.attr,
|
||||
#if FAN_NUM >4
|
||||
&sensor_dev_attr_fan_led_grn5.dev_attr.attr,
|
||||
&sensor_dev_attr_fan_led_red5.dev_attr.attr,
|
||||
&sensor_dev_attr_fan_gpi2.dev_attr.attr,
|
||||
#endif
|
||||
//fan GPI
|
||||
&sensor_dev_attr_fan_gpi.dev_attr.attr,
|
||||
&sensor_dev_attr_psu1.dev_attr.attr,
|
||||
&sensor_dev_attr_psu2.dev_attr.attr,
|
||||
|
||||
|
||||
//psu_psoc
|
||||
&sensor_dev_attr_psoc_psu1_vin.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu1_vout.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu1_iin.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu1_iout.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu1_pin.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu1_pout.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_vin.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_vout.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_iin.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_iout.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_pin.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_pout.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_in1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_curr1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_power1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_curr2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_power2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_curr3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_power3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_in4_input.dev_attr.attr,
|
||||
&sensor_dev_attr_curr4_input.dev_attr.attr,
|
||||
&sensor_dev_attr_power4_input.dev_attr.attr,
|
||||
|
||||
//ipmi_i2c_command
|
||||
&sensor_dev_attr_thermal2_psu1.dev_attr.attr,
|
||||
&sensor_dev_attr_temp9_input.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu1_vendor.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu1_serial.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu1_version.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_thermal2_psu2.dev_attr.attr,
|
||||
&sensor_dev_attr_temp10_input.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_vendor.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_serial.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_version.dev_attr.attr,
|
||||
|
||||
//clei
|
||||
#if FAN_CLEI_SUPPORT
|
||||
&sensor_dev_attr_fan1_clei.dev_attr.attr,
|
||||
&sensor_dev_attr_fan2_clei.dev_attr.attr,
|
||||
&sensor_dev_attr_fan3_clei.dev_attr.attr,
|
||||
&sensor_dev_attr_fan4_clei.dev_attr.attr,
|
||||
#if FAN_NUM > 4
|
||||
&sensor_dev_attr_fan5_clei.dev_attr.attr,
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PSU_CLEI_SUPPORT
|
||||
&sensor_dev_attr_psu1_clei.dev_attr.attr,
|
||||
&sensor_dev_attr_psu2_clei.dev_attr.attr,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group psoc_group = {
|
||||
.attrs = psoc_attributes,
|
||||
};
|
||||
|
||||
//=================================
|
||||
static void check_switch_temp(void)
|
||||
{
|
||||
static struct file *f;
|
||||
mm_segment_t old_fs;
|
||||
|
||||
set_fs(get_ds());
|
||||
f = filp_open(SWITCH_TEMPERATURE_SOCK,O_RDONLY,0644);
|
||||
if(IS_ERR(f)) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
char temp_str[]={0,0,0,0,0,0,0};
|
||||
loff_t pos = 0;
|
||||
u16 temp2 = 0;
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
vfs_read(f, temp_str,6,&pos);
|
||||
temp2 = ((simple_strtoul(temp_str,NULL,10)/1000) <<8 ) & 0xFF00 ;
|
||||
psoc_ipmi_write((u8*)&temp2, SWITCH_TMP_OFFSET, 2);
|
||||
}
|
||||
filp_close(f,NULL);
|
||||
set_fs(old_fs);
|
||||
}
|
||||
|
||||
static int psoc_polling_thread(void *p)
|
||||
{
|
||||
while (!kthread_should_stop())
|
||||
{
|
||||
check_switch_temp();
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if(kthread_should_stop())
|
||||
break;
|
||||
|
||||
schedule_timeout(msecs_to_jiffies(PSOC_POLLING_PERIOD));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init inv_psoc_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
hwmon_dev = hwmon_device_register(NULL);
|
||||
if (IS_ERR(hwmon_dev)) {
|
||||
goto fail_hwmon_device_register;
|
||||
}
|
||||
|
||||
device_kobj = kobject_create_and_add("device", &hwmon_dev->kobj);
|
||||
if(!device_kobj) {
|
||||
goto fail_hwmon_device_register;
|
||||
}
|
||||
|
||||
ret = sysfs_create_group(device_kobj, &psoc_group);
|
||||
if (ret) {
|
||||
goto fail_create_group_hwmon;
|
||||
}
|
||||
|
||||
ret = sysfs_create_group(&hwmon_dev->kobj, &psoc_group);
|
||||
if (ret) {
|
||||
goto fail_create_group_hwmon;
|
||||
}
|
||||
|
||||
kthread_auto_update = kthread_run(psoc_polling_thread,NULL,"BMC_DRIVER");
|
||||
if (IS_ERR(kthread_auto_update)) {
|
||||
goto fail_create_group_hwmon;
|
||||
}
|
||||
return ret;
|
||||
|
||||
fail_create_group_hwmon:
|
||||
hwmon_device_unregister(hwmon_dev);
|
||||
fail_hwmon_device_register:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void __exit inv_psoc_exit(void)
|
||||
{
|
||||
kthread_stop(kthread_auto_update);
|
||||
if(ipmi_mh_user!=NULL) {ipmi_destroy_user(ipmi_mh_user);}
|
||||
sysfs_remove_group(device_kobj, &psoc_group);
|
||||
if(hwmon_dev != NULL) hwmon_device_unregister(hwmon_dev);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Ting.Jack <ting.jack@inventec>");
|
||||
MODULE_DESCRIPTION("inv psoc driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(inv_psoc_init);
|
||||
module_exit(inv_psoc_exit);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,332 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/i2c.h>
|
||||
#include "inv_vpd.h"
|
||||
#include "onie_tlvinfo.h"
|
||||
|
||||
static int vpd_major;
|
||||
static struct class *vpd_class_p = NULL;
|
||||
static char cEeprom[SYS_EEPROM_MAX_SIZE];
|
||||
static DEFINE_MUTEX(vpd_mutex);
|
||||
|
||||
static int
|
||||
__swp_match(struct device *dev, const void *data){
|
||||
|
||||
char *name = (char *)data;
|
||||
if (strcmp(dev_name(dev), name) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int get_vpd_data(struct i2c_client *pi2c_client, int i_offset, char *c_buf)
|
||||
{
|
||||
int iRet;
|
||||
|
||||
read_eeprom( pi2c_client, cEeprom);
|
||||
iRet = tlvinfo_decode_tlv(cEeprom, i_offset,c_buf);
|
||||
return iRet;
|
||||
}
|
||||
|
||||
static
|
||||
int write_vpd_data(struct i2c_client *pi2c_client, int i_offset, const char *c_buf)
|
||||
{
|
||||
int iErr = 0;
|
||||
|
||||
if (read_eeprom(pi2c_client, cEeprom)) {
|
||||
printk(KERN_ERR "write vpd data eror at %d-%s\n", __LINE__, __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tlvinfo_delete_tlv(cEeprom, i_offset) == TRUE) {
|
||||
}
|
||||
if (c_buf) {
|
||||
if(!tlvinfo_add_tlv(cEeprom, i_offset , c_buf)) {
|
||||
printk(KERN_ERR "write vpd data eror at %d-%s\n", __LINE__, __FUNCTION__);
|
||||
iErr = -1;
|
||||
} else {
|
||||
iErr = prog_eeprom(pi2c_client,cEeprom);
|
||||
}
|
||||
}
|
||||
return iErr;
|
||||
}
|
||||
|
||||
static struct device *
|
||||
get_swpdev_by_name(char *name){
|
||||
struct device *dev = class_find_device(vpd_class_p,
|
||||
NULL,
|
||||
name,
|
||||
__swp_match);
|
||||
return dev;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
store_attr_vpd(struct device *dev_p,
|
||||
struct device_attribute *attr_p,
|
||||
const char *buf_p,
|
||||
size_t count){
|
||||
struct i2c_client *pi2c_client = dev_get_drvdata(dev_p);
|
||||
struct vpd_device_attribute *attr = to_vpd_dev_attr(attr_p);
|
||||
int iOffset = attr->index;
|
||||
int iErr , iLen;
|
||||
char *pChar;
|
||||
|
||||
if (!pi2c_client){
|
||||
return -ENODEV;
|
||||
}
|
||||
mutex_lock(&vpd_mutex);
|
||||
|
||||
//-strip 0x0a in the last byte.
|
||||
for (iLen = 0, pChar = (char*)buf_p;
|
||||
iLen < 255 && *pChar != 0;
|
||||
iLen++, pChar++) ;
|
||||
if (iLen !=0 && *pChar == 0 && *(pChar-1) == 0x0a)
|
||||
*(pChar - 1) = 0;
|
||||
//-
|
||||
|
||||
iErr = write_vpd_data( pi2c_client, iOffset, buf_p);
|
||||
|
||||
mutex_unlock(&vpd_mutex);
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
show_attr_vpd(struct device *dev_p,
|
||||
struct device_attribute *attr_p,
|
||||
char *buf_p){
|
||||
|
||||
struct i2c_client *pi2c_client = dev_get_drvdata(dev_p);
|
||||
struct vpd_device_attribute *attr = to_vpd_dev_attr(attr_p);
|
||||
int iOffset = attr->index;
|
||||
int iErr , iLen;
|
||||
|
||||
if (!pi2c_client){
|
||||
return -ENODEV;
|
||||
}
|
||||
mutex_lock(&vpd_mutex);
|
||||
iErr = get_vpd_data( pi2c_client, iOffset, buf_p);
|
||||
mutex_unlock(&vpd_mutex);
|
||||
|
||||
if( iErr <= 0 )
|
||||
iLen = 0;
|
||||
else
|
||||
iLen = snprintf(buf_p, TLV_DECODE_VALUE_MAX_LEN, "%s\n", buf_p);
|
||||
|
||||
return iLen;
|
||||
}
|
||||
|
||||
/* ================= Vpd attribute ========================
|
||||
*/
|
||||
static VPD_DEVICE_ATTR(product_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PRODUCT_NAME );
|
||||
static VPD_DEVICE_ATTR(pn ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PART_NUMBER );
|
||||
static VPD_DEVICE_ATTR(sn ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_SERIAL_NUMBER );
|
||||
static VPD_DEVICE_ATTR(base_mac_addr,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MAC_BASE );
|
||||
static VPD_DEVICE_ATTR(man_date ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_DATE );
|
||||
static VPD_DEVICE_ATTR(dev_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_DEVICE_VERSION );
|
||||
static VPD_DEVICE_ATTR(label_rev ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_LABEL_REVISION );
|
||||
static VPD_DEVICE_ATTR(plat_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PLATFORM_NAME );
|
||||
static VPD_DEVICE_ATTR(ldr_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_ONIE_VERSION );
|
||||
static VPD_DEVICE_ATTR(mac_addr ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MAC_SIZE );
|
||||
static VPD_DEVICE_ATTR(manufacturer ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_NAME );
|
||||
static VPD_DEVICE_ATTR(country_code ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_COUNTRY );
|
||||
static VPD_DEVICE_ATTR(vendor_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_VENDOR_NAME );
|
||||
static VPD_DEVICE_ATTR(diag_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_DIAG_VERSION );
|
||||
static VPD_DEVICE_ATTR(service_tag ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_SERVICE_TAG );
|
||||
static VPD_DEVICE_ATTR(vendor_ext ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_VENDOR_EXT );
|
||||
static VPD_DEVICE_ATTR(crc32 ,S_IRUGO, show_attr_vpd, NULL, TLV_CODE_CRC_32 );
|
||||
|
||||
static void
|
||||
clean_vpd_common(void)
|
||||
{
|
||||
dev_t dev_num;
|
||||
struct device *device_p;
|
||||
|
||||
device_p = get_swpdev_by_name(VPD_DEVICE);
|
||||
if (device_p){
|
||||
dev_num = MKDEV(vpd_major, 1);
|
||||
device_unregister(device_p);
|
||||
device_destroy(vpd_class_p, dev_num);
|
||||
}
|
||||
VPD_DEBUG("%s: done.\n", __func__);
|
||||
}
|
||||
|
||||
|
||||
static struct register_attr VpdRegAttr[VPD_ENTRY_SIZE ] ={
|
||||
{ &vpd_dev_attr_product_name.dev_attr, "vpd_dev_attr_product_name"},
|
||||
{ &vpd_dev_attr_pn.dev_attr, "vpd_dev_attr_pn"},
|
||||
{ &vpd_dev_attr_sn.dev_attr, "vpd_dev_attr_sn"},
|
||||
{ &vpd_dev_attr_base_mac_addr.dev_attr, "vpd_dev_attr_base_mac_addr"},
|
||||
{ &vpd_dev_attr_man_date.dev_attr, "vpd_dev_attr_man_date"},
|
||||
{ &vpd_dev_attr_dev_ver.dev_attr, "vpd_dev_attr_dev_ver"},
|
||||
{ &vpd_dev_attr_label_rev.dev_attr, "vpd_dev_attr_label_rev"},
|
||||
{ &vpd_dev_attr_plat_name.dev_attr, "vpd_dev_attr_plat_name"},
|
||||
{ &vpd_dev_attr_ldr_ver.dev_attr, "vpd_dev_attr_ldr_ver"},
|
||||
{ &vpd_dev_attr_mac_addr.dev_attr, "vpd_dev_attr_mac_addr"},
|
||||
{ &vpd_dev_attr_manufacturer.dev_attr, "vpd_dev_attr_manufacturer"},
|
||||
{ &vpd_dev_attr_country_code.dev_attr, "vpd_dev_attr_country_code"},
|
||||
{ &vpd_dev_attr_vendor_name.dev_attr, "vpd_dev_attr_vendor_name"},
|
||||
{ &vpd_dev_attr_diag_ver.dev_attr, "vpd_dev_attr_diag_ver"},
|
||||
{ &vpd_dev_attr_service_tag.dev_attr, "vpd_dev_attr_service_tag"},
|
||||
{ &vpd_dev_attr_vendor_ext.dev_attr, "vpd_dev_attr_vendor_ext"},
|
||||
{ &vpd_dev_attr_crc32.dev_attr, "vpd_dev_attr_crc32"},
|
||||
};
|
||||
|
||||
static int
|
||||
register_vpd_attr(struct device *device_p){
|
||||
|
||||
char *err_attr = NULL;
|
||||
int i;
|
||||
|
||||
for( i = 0 ; i <VPD_ENTRY_SIZE ;i++ ){
|
||||
if(device_create_file(device_p, VpdRegAttr[ i ].attr) < 0) {
|
||||
err_attr = VpdRegAttr[ i ].errmsg;
|
||||
goto err_register_vpd_attr;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_register_vpd_attr:
|
||||
VPD_ERR("%s: %s\n", __func__, err_attr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
register_vpd_device(void)
|
||||
{
|
||||
struct device *device_p = NULL;
|
||||
int minor_comm = 0; /* Default minor number for common device */
|
||||
dev_t dev_num = MKDEV(vpd_major, minor_comm);
|
||||
char *err_msg = "ERROR";
|
||||
struct i2c_adapter *adap;
|
||||
struct i2c_client *vpd_i2c_client = NULL;
|
||||
|
||||
vpd_i2c_client = kzalloc(sizeof(*vpd_i2c_client), GFP_KERNEL);
|
||||
if (!vpd_i2c_client){
|
||||
printk(KERN_ERR "can not kzalloc client:%d", VPD_I2C_BUS);
|
||||
goto err_register_vpd_device;
|
||||
}
|
||||
|
||||
adap = i2c_get_adapter(VPD_I2C_BUS);
|
||||
vpd_i2c_client->adapter = adap;
|
||||
vpd_i2c_client->addr = VPD_I2C_ADDR;
|
||||
|
||||
device_p = device_create(vpd_class_p, /* struct class *cls */
|
||||
NULL, /* struct device *parent */
|
||||
dev_num, /* dev_t devt */
|
||||
vpd_i2c_client, /* void *private_data */
|
||||
VPD_DEVICE); /* const char *fmt */
|
||||
if (IS_ERR(device_p)){
|
||||
err_msg = "device_create fail";
|
||||
goto err_register_vpd_device_1;
|
||||
}
|
||||
if (register_vpd_attr(device_p) < 0) {
|
||||
err_msg = "register_vpd_attr fail";
|
||||
goto err_register_vpd_device_2;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_register_vpd_device_2:
|
||||
device_unregister(device_p);
|
||||
device_destroy(vpd_class_p, dev_num);
|
||||
err_register_vpd_device_1:
|
||||
kfree(vpd_i2c_client);
|
||||
vpd_i2c_client = NULL;
|
||||
err_register_vpd_device:
|
||||
VPD_ERR("%s: %s\n", __func__, err_msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
register_vpd_module(void)
|
||||
{
|
||||
dev_t vpd_devt = 0;
|
||||
|
||||
if (alloc_chrdev_region(&vpd_devt, 0, 1, VPD_DEVICE) < 0){
|
||||
VPD_WARN("Allocate VPD MAJOR failure! \n");
|
||||
goto err_register_vpd_module;
|
||||
}
|
||||
vpd_major = MAJOR(vpd_devt);
|
||||
|
||||
/* Create class object */
|
||||
vpd_class_p = class_create(THIS_MODULE, EEPROM_CLASS);
|
||||
if (IS_ERR(vpd_class_p)) {
|
||||
VPD_ERR("Create class failure! \n");
|
||||
goto err_register_vpd_module_1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_register_vpd_module_1:
|
||||
unregister_chrdev_region(MKDEV(vpd_major, 0), 1);
|
||||
err_register_vpd_module:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
init_vpd_common(void)
|
||||
{
|
||||
char *err_msg = "ERR";
|
||||
|
||||
if (register_vpd_device() < 0) {
|
||||
err_msg = "register_vpd_device fail";
|
||||
goto err_init_vpd_common;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_init_vpd_common:
|
||||
VPD_ERR("%s: %s\n", __func__, err_msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int __init
|
||||
vpd_module_init(void)
|
||||
{
|
||||
if (register_vpd_module() < 0){
|
||||
goto err_vpd_module_init;
|
||||
}
|
||||
if (init_vpd_common() < 0){
|
||||
goto err_vpd_module_init_1;
|
||||
}
|
||||
VPD_INFO("Inventec vpd module V.%s initial success.\n", VPD_VERSION);
|
||||
return 0;
|
||||
|
||||
err_vpd_module_init_1:
|
||||
class_unregister(vpd_class_p);
|
||||
class_destroy(vpd_class_p);
|
||||
unregister_chrdev_region(MKDEV(vpd_major, 0), 1);
|
||||
err_vpd_module_init:
|
||||
VPD_ERR("Inventec vpd module V.%s initial failure.\n", VPD_VERSION);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void __exit
|
||||
vpd_module_exit(void)
|
||||
{
|
||||
clean_vpd_common();
|
||||
class_unregister(vpd_class_p);
|
||||
class_destroy(vpd_class_p);
|
||||
unregister_chrdev_region(MKDEV(vpd_major, 0), 1);
|
||||
VPD_INFO("Remove Inventec vpd module success.\n");
|
||||
}
|
||||
|
||||
|
||||
/* Module information */
|
||||
MODULE_AUTHOR(VPD_AUTHOR);
|
||||
MODULE_DESCRIPTION(VPD_DESC);
|
||||
MODULE_VERSION(VPD_VERSION);
|
||||
MODULE_LICENSE(VPD_LICENSE);
|
||||
|
||||
module_init(vpd_module_init);
|
||||
module_exit(vpd_module_exit);
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef INV_VPD_H
|
||||
#define INV_VPD_H
|
||||
|
||||
#define EEPROM_CLASS "eeprom"
|
||||
#define VPD_DEVICE "vpd"
|
||||
#define VPD_AUTHOR "Neil <liao.neil@inventec.com>"
|
||||
#define VPD_DESC "Inventec eeprom vpd driver"
|
||||
#define VPD_VERSION "1.0.0"
|
||||
#define VPD_LICENSE "GPL"
|
||||
|
||||
#define VPD_ENTRY_SIZE (17)
|
||||
#define VPD_I2C_BUS (0)
|
||||
#define VPD_I2C_ADDR (0x53)
|
||||
|
||||
struct register_attr {
|
||||
struct device_attribute *attr;
|
||||
char * errmsg;
|
||||
};
|
||||
|
||||
struct vpd_device_attribute{
|
||||
struct device_attribute dev_attr;
|
||||
int index;
|
||||
};
|
||||
|
||||
#define to_vpd_dev_attr(_dev_attr) \
|
||||
container_of(_dev_attr, struct vpd_device_attribute, dev_attr)
|
||||
|
||||
#define VPD_ATTR(_name, _mode, _show, _store, _index) \
|
||||
{ .dev_attr = __ATTR(_name, _mode, _show, _store), \
|
||||
.index = _index }
|
||||
|
||||
#define VPD_DEVICE_ATTR(_name, _mode, _show, _store, _index) \
|
||||
struct vpd_device_attribute vpd_dev_attr_##_name \
|
||||
= VPD_ATTR(_name, _mode, _show, _store, _index)
|
||||
|
||||
#define VPD_INFO(fmt, args...) printk( KERN_INFO "[VPD] " fmt, ##args)
|
||||
#define VPD_WARN(fmt, args...) printk( KERN_WARNING "[VPD] " fmt, ##args)
|
||||
#define VPD_ERR(fmt, args...) printk( KERN_ERR "[VPD] " fmt, ##args)
|
||||
|
||||
#ifdef DEBUG_VPD
|
||||
# define VPD_DEBUG(fmt, args...) printk( KERN_DEBUG "[VPD] " fmt, ##args)
|
||||
#else
|
||||
# define VPD_DEBUG(fmt, args...)
|
||||
#endif
|
||||
|
||||
#endif /* INV_VPD_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,180 @@
|
||||
#ifndef IO_EXPANDER_H
|
||||
#define IO_EXPANDER_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
|
||||
/* IOEXP type define (SFP series) */
|
||||
#define IOEXP_TYPE_MAGINOLIA_NAB (10101)
|
||||
#define IOEXP_TYPE_MAGINOLIA_4AB (10102)
|
||||
#define IOEXP_TYPE_CYPRESS_NABC (10103)
|
||||
#define IOEXP_TYPE_MAPLE_NABC (10104)
|
||||
|
||||
/* IOEXP type define (QSFP series) */
|
||||
#define IOEXP_TYPE_MAGINOLIA_7AB (10201)
|
||||
#define IOEXP_TYPE_REDWOOD_P01P08 (10202)
|
||||
#define IOEXP_TYPE_REDWOOD_P09P16 (10203)
|
||||
#define IOEXP_TYPE_HUDSON32IGA_P01P08 (10204)
|
||||
#define IOEXP_TYPE_HUDSON32IGA_P09P16 (10205)
|
||||
#define IOEXP_TYPE_SPRUCE_7AB (10206)
|
||||
#define IOEXP_TYPE_CYPRESS_7ABC (10207)
|
||||
#define IOEXP_TYPE_TAHOE_5A (10208)
|
||||
#define IOEXP_TYPE_TAHOE_6ABC (10209)
|
||||
#define IOEXP_TYPE_SEQUOIA_NABC (10210)
|
||||
#define IOEXP_TYPE_LAVENDER_P65 (10211)
|
||||
#define IOEXP_TYPE_MAPLE_0ABC (10212)
|
||||
|
||||
/* CPLD type define */
|
||||
#define CPLD_TYPE_COTTONWOOD (10301)
|
||||
|
||||
/* IOEXP mode define */
|
||||
#define IOEXP_MODE_POLLING (19000)
|
||||
#define IOEXP_MODE_DIRECT (19001)
|
||||
|
||||
/* IOEXP state define */
|
||||
#define STATE_IOEXP_NORMAL (0)
|
||||
#define STATE_IOEXP_INIT (-1)
|
||||
#define STATE_IOEXP_ABNORMAL (-2)
|
||||
|
||||
/* IOEXP error code define */
|
||||
#define ERR_IOEXP_NOTSUPPORT (-100)
|
||||
#define ERR_IOEXP_UNINIT (-101)
|
||||
#define ERR_IOEXP_BADCONF (-102)
|
||||
#define ERR_IOEXP_ABNORMAL (-103)
|
||||
#define ERR_IOEXP_NOSTATE (-104)
|
||||
#define ERR_IOEXP_BADINPUT (-105)
|
||||
#define ERR_IOEXP_UNEXCPT (-199)
|
||||
|
||||
#define SWPS_INFO(fmt, args...) printk( KERN_INFO "[SWPS] " fmt, ##args)
|
||||
#define SWPS_WARN(fmt, args...) printk( KERN_WARNING "[SWPS] " fmt, ##args)
|
||||
#define SWPS_ERR(fmt, args...) printk( KERN_ERR "[SWPS] " fmt, ##args)
|
||||
|
||||
#ifdef DEBUG_SWPS
|
||||
# define SWPS_DEBUG(fmt, args...) printk( KERN_DEBUG "[SWPS] " fmt, ##args)
|
||||
#else
|
||||
# define SWPS_DEBUG(fmt, args...)
|
||||
#endif
|
||||
|
||||
|
||||
struct ioexp_addr_s {
|
||||
int chan_id;
|
||||
int chip_addr;
|
||||
int read_offset[8];
|
||||
int write_offset[8];
|
||||
int conf_offset[8];
|
||||
uint8_t data_default[8];
|
||||
uint8_t conf_default[8];
|
||||
};
|
||||
|
||||
struct ioexp_i2c_s {
|
||||
int chip_id;
|
||||
struct i2c_client *i2c_client_p;
|
||||
struct ioexp_i2c_s *next;
|
||||
};
|
||||
|
||||
|
||||
struct ioexp_bitmap_s {
|
||||
int chip_id; /* IOEXP chip id */
|
||||
int ioexp_voffset; /* IOEXP virtual offset */
|
||||
int bit_shift;
|
||||
};
|
||||
|
||||
struct ioexp_map_s {
|
||||
int chip_amount; /* Number of chips that IOEXP object content */
|
||||
int data_width; /* Number of (Read/Write/Config) bytes */
|
||||
struct ioexp_addr_s *map_addr; /* Chip address info */
|
||||
struct ioexp_bitmap_s map_present[10]; /* IOEXP for SFP / QSFP */
|
||||
struct ioexp_bitmap_s map_tx_disable[10]; /* IOEXP for SFP */
|
||||
struct ioexp_bitmap_s map_tx_fault[10]; /* IOEXP for SFP */
|
||||
struct ioexp_bitmap_s map_rxlos[10]; /* IOEXP for SFP */
|
||||
struct ioexp_bitmap_s map_reset[10]; /* IOEXP for QSFP */
|
||||
struct ioexp_bitmap_s map_lpmod[10]; /* IOEXP for QSFP */
|
||||
struct ioexp_bitmap_s map_modsel[10]; /* IOEXP for QSFP */
|
||||
struct ioexp_bitmap_s map_hard_rs0[10]; /* IOEXP for QSFP */
|
||||
struct ioexp_bitmap_s map_hard_rs1[10]; /* IOEXP for QSFP */
|
||||
};
|
||||
|
||||
struct ioexp_data_s {
|
||||
uint8_t data[8];
|
||||
};
|
||||
|
||||
struct ioexp_obj_s {
|
||||
|
||||
/* ============================
|
||||
* Object public property
|
||||
* ============================
|
||||
*/
|
||||
int ioexp_id;
|
||||
int ioexp_type;
|
||||
|
||||
/* ============================
|
||||
* Object private property
|
||||
* ============================
|
||||
*/
|
||||
struct ioexp_data_s chip_data[16]; /* Max: 8-ioexp in one virt-ioexp(ioexp_obj) */
|
||||
struct ioexp_map_s *ioexp_map_p;
|
||||
struct ioexp_obj_s *next;
|
||||
struct ioexp_i2c_s *i2c_head_p;
|
||||
struct mutex lock;
|
||||
int mode;
|
||||
int state;
|
||||
|
||||
/* ===========================================
|
||||
* Object public functions
|
||||
* ===========================================
|
||||
*/
|
||||
int (*get_present)(struct ioexp_obj_s *self, int virt_offset);
|
||||
int (*get_tx_fault)(struct ioexp_obj_s *self, int virt_offset);
|
||||
int (*get_rxlos)(struct ioexp_obj_s *self, int virt_offset);
|
||||
int (*get_tx_disable)(struct ioexp_obj_s *self, int virt_offset);
|
||||
int (*get_reset)(struct ioexp_obj_s *self, int virt_offset);
|
||||
int (*get_lpmod)(struct ioexp_obj_s *self, int virt_offset);
|
||||
int (*get_modsel)(struct ioexp_obj_s *self, int virt_offset);
|
||||
int (*get_hard_rs0)(struct ioexp_obj_s *self, int virt_offset);
|
||||
int (*get_hard_rs1)(struct ioexp_obj_s *self, int virt_offset);
|
||||
int (*set_tx_disable)(struct ioexp_obj_s *self, int virt_offset, int input_val);
|
||||
int (*set_reset)(struct ioexp_obj_s *self, int virt_offset, int input_val);
|
||||
int (*set_lpmod)(struct ioexp_obj_s *self, int virt_offset, int input_val);
|
||||
int (*set_modsel)(struct ioexp_obj_s *self, int virt_offset, int input_val);
|
||||
int (*set_hard_rs0)(struct ioexp_obj_s *self, int virt_offset, int input_val);
|
||||
int (*set_hard_rs1)(struct ioexp_obj_s *self, int virt_offset, int input_val);
|
||||
|
||||
/* ===========================================
|
||||
* Object private functions
|
||||
* ===========================================
|
||||
*/
|
||||
int (*init)(struct ioexp_obj_s *self);
|
||||
int (*check)(struct ioexp_obj_s *self);
|
||||
int (*update_all)(struct ioexp_obj_s *self, int show_err, char *caller_name);
|
||||
int (*fsm_4_direct)(struct ioexp_obj_s* self);
|
||||
int (*fsm_4_polling)(struct ioexp_obj_s* self);
|
||||
};
|
||||
|
||||
|
||||
struct ioexp_obj_s* get_ioexp_obj(int ioexp_id);
|
||||
int create_ioexp_obj(int ioexp_id,
|
||||
int ioexp_type,
|
||||
struct ioexp_addr_s *addr_map_p,
|
||||
int run_mode);
|
||||
int init_ioexp_objs(void);
|
||||
int check_ioexp_objs(void);
|
||||
void clean_ioexp_objs(void);
|
||||
|
||||
void unlock_ioexp_all(void);
|
||||
int lock_ioexp_all(void);
|
||||
|
||||
int check_channel_tier_1(void);
|
||||
int resync_channel_tier_1(void);
|
||||
|
||||
/* Macro for bit control */
|
||||
#define SWP_BIT_SET(byte_val,bit_shift) ((byte_val) |= (1<<(bit_shift)))
|
||||
#define SWP_BIT_CLEAR(byte_val,bit_shift) ((byte_val) &= ~(1<<(bit_shift)))
|
||||
|
||||
|
||||
#endif /* IO_EXPANDER_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,815 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ctype.h>
|
||||
//#include <linux/crc32.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
//#include <linux/slab.h>
|
||||
//#include <linux/platform_device.h>
|
||||
#include "onie_tlvinfo.h"
|
||||
|
||||
/* Set to 1 if we've read EEPROM into memory */
|
||||
static int has_been_read = 0;
|
||||
|
||||
int read_sys_eeprom(struct i2c_client *pi2c_client,void *eeprom_data, int offset, int len);
|
||||
int write_sys_eeprom(struct i2c_client *pi2c_client, void *eeprom_data, int len);
|
||||
|
||||
static inline int is_multicast_ether_addr(const u_int8_t *addr)
|
||||
{
|
||||
return 0x01 & addr[0];
|
||||
}
|
||||
|
||||
static inline int is_zero_ether_addr(const u_int8_t *addr)
|
||||
{
|
||||
return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]);
|
||||
}
|
||||
|
||||
static inline int is_valid_ether_addr(const u_int8_t *addr)
|
||||
{
|
||||
return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static unsigned int crc32(unsigned char const *p, unsigned int len)
|
||||
{
|
||||
int i;
|
||||
unsigned int crc = 0;
|
||||
while (len--) {
|
||||
crc ^= *p++;
|
||||
for (i = 0; i < 8; i++)
|
||||
crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
#else
|
||||
static unsigned long crc32_tab[] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
|
||||
static unsigned long crc32(unsigned char const *buf, unsigned int size)
|
||||
{
|
||||
unsigned char *p = (unsigned char*)buf;
|
||||
unsigned long crc = 0;
|
||||
|
||||
crc = crc ^ ~0U;
|
||||
|
||||
while (size--)
|
||||
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
|
||||
|
||||
return crc ^ ~0U;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int set_bytes(char *buf, const char *string, int * converted_accum)
|
||||
{
|
||||
char *p = (char *) string;
|
||||
int i;
|
||||
uint byte;
|
||||
|
||||
if (!p) {
|
||||
printk("ERROR: NULL string passed in.\n");
|
||||
return -1;
|
||||
}
|
||||
/* Convert string to bytes */
|
||||
for (i = 0, p = (char *)string; (i < TLV_VALUE_MAX_LEN) && (*p != 0);
|
||||
i++) {
|
||||
while ((*p == ' ') || (*p == '\t') || (*p == ',') ||
|
||||
(*p == ';')) {
|
||||
p++;
|
||||
}
|
||||
if (*p != 0) {
|
||||
if (!isdigit(*p)) {
|
||||
printk("ERROR: Non-digit found in byte string: (%s)\n", string);
|
||||
return -1;
|
||||
}
|
||||
byte = strtoul(p, &p, 0);
|
||||
if (byte >= 256) {
|
||||
printk("ERROR: The value specified is greater than 255: (%u) " \
|
||||
"in string: %s\n", byte, string);
|
||||
return -1;
|
||||
}
|
||||
buf[i] = byte & 0xFF;
|
||||
}
|
||||
}
|
||||
if ((i == TLV_VALUE_MAX_LEN) && (*p != 0)) {
|
||||
printk("ERROR: Trying to assign too many bytes "
|
||||
"(max: %d) in string: %s\n", TLV_VALUE_MAX_LEN, string);
|
||||
return -1;
|
||||
}
|
||||
*converted_accum = i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* set_date
|
||||
*
|
||||
* Validates the format of the data string
|
||||
*
|
||||
* This function takes a pointer to a date string (i.e. MM/DD/YYYY hh:mm:ss)
|
||||
* and validates that the format is correct. If so the string is copied
|
||||
* to the supplied buffer.
|
||||
*/
|
||||
static int set_date(char *buf, const char *string)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!string) {
|
||||
printk("ERROR: NULL date string passed in.\n");
|
||||
return -1;
|
||||
}
|
||||
if (strlen(string) != 19) {
|
||||
printk("ERROR: Date strlen() != 19 -- %zd\n", strlen(string));
|
||||
printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n", string);
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; string[i] != 0; i++) {
|
||||
switch (i) {
|
||||
case 2:
|
||||
case 5:
|
||||
if (string[i] != '/') {
|
||||
printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
|
||||
string);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (string[i] != ' ') {
|
||||
printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
|
||||
string);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
case 16:
|
||||
if (string[i] != ':') {
|
||||
printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
|
||||
string);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (!isdigit(string[i])) {
|
||||
printk("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
|
||||
string);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
strcpy(buf, string);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* is_valid_tlv
|
||||
*
|
||||
* Perform basic sanity checks on a TLV field. The TLV is pointed to
|
||||
* by the parameter provided.
|
||||
* 1. The type code is not reserved (0x00 or 0xFF)
|
||||
*/
|
||||
static inline bool is_valid_tlv(tlvinfo_tlv_t *tlv)
|
||||
{
|
||||
return((tlv->type != 0x00) && (tlv->type != 0xFF));
|
||||
}
|
||||
|
||||
/*
|
||||
* set_mac
|
||||
*
|
||||
* Converts a string MAC address into a binary buffer.
|
||||
*
|
||||
* This function takes a pointer to a MAC address string
|
||||
* (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number).
|
||||
* The string format is verified and then converted to binary and
|
||||
* stored in a buffer.
|
||||
*/
|
||||
static int set_mac(char *buf, const char *string)
|
||||
{
|
||||
char *p = (char *) string;
|
||||
int i;
|
||||
int err = 0;
|
||||
char *end;
|
||||
|
||||
if (!p) {
|
||||
printk("ERROR: NULL mac addr string passed in.\n");
|
||||
return -1;
|
||||
}
|
||||
if (strlen(p) != 17) {
|
||||
printk("ERROR: MAC address strlen() != 17 -- %zd\n", strlen(p));
|
||||
printk("ERROR: Bad MAC address format: %s\n", string);
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < 17; i++) {
|
||||
if ((i % 3) == 2) {
|
||||
if (p[i] != ':') {
|
||||
err++;
|
||||
printk("ERROR: mac: p[%i] != :, found: `%c'\n",
|
||||
i, p[i]);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
} else if (!isxdigit(p[i])) {
|
||||
err++;
|
||||
printk("ERROR: mac: p[%i] != hex digit, found: `%c'\n",
|
||||
i, p[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (err != 0) {
|
||||
printk("ERROR: Bad MAC address format: %s\n", string);
|
||||
return -1;
|
||||
}
|
||||
/* Convert string to binary */
|
||||
for (i = 0, p = (char *)string; i < 6; i++) {
|
||||
buf[i] = p ? strtoul(p, &end, 16) : 0;
|
||||
if (p) {
|
||||
p = (*end) ? end + 1 : end;
|
||||
}
|
||||
}
|
||||
if (!is_valid_ether_addr((char *)buf)) {
|
||||
printk("ERROR: MAC address must not be 00:00:00:00:00:00, "
|
||||
"a multicast address or FF:FF:FF:FF:FF:FF.\n");
|
||||
printk("ERROR: Bad MAC address format: %s\n", string);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* is_valid_tlvinfo_header
|
||||
*
|
||||
* Perform sanity checks on the first 11 bytes of the TlvInfo EEPROM
|
||||
* data pointed to by the parameter:
|
||||
* 1. First 8 bytes contain null-terminated ASCII string "TlvInfo"
|
||||
* 2. Version byte is 1
|
||||
* 3. Total length bytes contain value which is less than or equal
|
||||
* to the allowed maximum (2048-11)
|
||||
*
|
||||
*/
|
||||
static inline bool is_valid_tlvinfo_header(tlvinfo_header_t *hdr)
|
||||
{
|
||||
int max_size = TLV_TOTAL_LEN_MAX;
|
||||
return((strcmp(hdr->signature, TLV_INFO_ID_STRING) == 0) &&
|
||||
(hdr->version == TLV_INFO_VERSION) &&
|
||||
(be16_to_cpu(hdr->totallen) <= max_size) );
|
||||
}
|
||||
|
||||
/*
|
||||
* decode_tlv_value
|
||||
*
|
||||
* Decode a single TLV value into a string.
|
||||
|
||||
* The validity of EEPROM contents and the TLV field have been verified
|
||||
* prior to calling this function.
|
||||
*/
|
||||
#define DECODE_NAME_MAX 20
|
||||
|
||||
static void decode_tlv_value(tlvinfo_tlv_t * tlv, char* value)
|
||||
{
|
||||
int i;
|
||||
|
||||
switch (tlv->type) {
|
||||
case TLV_CODE_PRODUCT_NAME:
|
||||
case TLV_CODE_PART_NUMBER:
|
||||
case TLV_CODE_SERIAL_NUMBER:
|
||||
case TLV_CODE_MANUF_DATE:
|
||||
case TLV_CODE_LABEL_REVISION:
|
||||
case TLV_CODE_PLATFORM_NAME:
|
||||
case TLV_CODE_ONIE_VERSION:
|
||||
case TLV_CODE_MANUF_NAME:
|
||||
case TLV_CODE_MANUF_COUNTRY:
|
||||
case TLV_CODE_VENDOR_NAME:
|
||||
case TLV_CODE_DIAG_VERSION:
|
||||
case TLV_CODE_SERVICE_TAG:
|
||||
memcpy(value, tlv->value, tlv->length);
|
||||
value[tlv->length] = 0;
|
||||
break;
|
||||
case TLV_CODE_MAC_BASE:
|
||||
snprintf(value, MAX_STRING_SIZE, "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
tlv->value[0], tlv->value[1], tlv->value[2],
|
||||
tlv->value[3], tlv->value[4], tlv->value[5]);
|
||||
break;
|
||||
case TLV_CODE_DEVICE_VERSION:
|
||||
snprintf(value, MAX_STRING_SIZE, "%u", tlv->value[0]);
|
||||
break;
|
||||
case TLV_CODE_MAC_SIZE:
|
||||
snprintf(value, MAX_STRING_SIZE, "%u", (tlv->value[0] << 8) | tlv->value[1]);
|
||||
break;
|
||||
case TLV_CODE_VENDOR_EXT:
|
||||
value[0] = 0;
|
||||
for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length);
|
||||
i++) {
|
||||
snprintf(value, MAX_STRING_SIZE, "%s 0x%02X", value, tlv->value[i]);
|
||||
}
|
||||
break;
|
||||
case TLV_CODE_CRC_32:
|
||||
snprintf(value, MAX_STRING_SIZE, "0x%02X%02X%02X%02X",
|
||||
tlv->value[0], tlv->value[1], tlv->value[2],
|
||||
tlv->value[3]);
|
||||
break;
|
||||
default:
|
||||
value[0] = 0;
|
||||
for (i = 0; (i < (TLV_DECODE_VALUE_MAX_LEN/5)) && (i < tlv->length);
|
||||
i++) {
|
||||
snprintf(value, MAX_STRING_SIZE, "%s 0x%02X", value, tlv->value[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* is_checksum_valid
|
||||
*
|
||||
* Validate the checksum in the provided TlvInfo EEPROM data. First,
|
||||
* verify that the TlvInfo header is valid, then make sure the last
|
||||
* TLV is a CRC-32 TLV. Then calculate the CRC over the EEPROM data
|
||||
* and compare it to the value stored in the EEPROM CRC-32 TLV.
|
||||
*/
|
||||
static bool is_checksum_valid(u_int8_t *eeprom)
|
||||
{
|
||||
tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom;
|
||||
tlvinfo_tlv_t * eeprom_crc;
|
||||
unsigned int calc_crc;
|
||||
unsigned int stored_crc;
|
||||
|
||||
// Is the eeprom header valid?
|
||||
if (!is_valid_tlvinfo_header(eeprom_hdr)) {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
// Is the last TLV a CRC?
|
||||
eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) +
|
||||
be16_to_cpu(eeprom_hdr->totallen) -
|
||||
(sizeof(tlvinfo_tlv_t) + 4)];
|
||||
if ((eeprom_crc->type != TLV_CODE_CRC_32) || (eeprom_crc->length != 4)) {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
// Calculate the checksum
|
||||
calc_crc = crc32((void *)eeprom, sizeof(tlvinfo_header_t) +
|
||||
be16_to_cpu(eeprom_hdr->totallen) - 4);
|
||||
stored_crc = ((eeprom_crc->value[0] << 24) | (eeprom_crc->value[1] << 16) |
|
||||
(eeprom_crc->value[2] << 8) | eeprom_crc->value[3]);
|
||||
|
||||
//printk(KERN_ERR "[SWPS] cal_crc =0x%x, stored_crc =0x%x\n", calc_crc, stored_crc);
|
||||
//return(calc_crc == stored_crc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* update_crc
|
||||
*
|
||||
* This function updates the CRC-32 TLV. If there is no CRC-32 TLV, then
|
||||
* one is added. This function should be called after each update to the
|
||||
* EEPROM structure, to make sure the CRC is always correct.
|
||||
*/
|
||||
static void update_crc(u_int8_t *eeprom)
|
||||
{
|
||||
tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom;
|
||||
tlvinfo_tlv_t * eeprom_crc;
|
||||
unsigned int calc_crc;
|
||||
|
||||
// Is the eeprom header valid?
|
||||
if (!is_valid_tlvinfo_header(eeprom_hdr)) {
|
||||
return;
|
||||
}
|
||||
// Is the last TLV a CRC?
|
||||
eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) +
|
||||
be16_to_cpu(eeprom_hdr->totallen) -
|
||||
(sizeof(tlvinfo_tlv_t) + 4)];
|
||||
if (eeprom_crc->type != TLV_CODE_CRC_32) {
|
||||
if ((be16_to_cpu(eeprom_hdr->totallen) + sizeof(tlvinfo_tlv_t) + 4) >
|
||||
TLV_TOTAL_LEN_MAX) {
|
||||
return;
|
||||
}
|
||||
eeprom_crc = (tlvinfo_tlv_t *) &eeprom[sizeof(tlvinfo_header_t) +
|
||||
be16_to_cpu(
|
||||
eeprom_hdr->totallen)];
|
||||
eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) +
|
||||
sizeof(tlvinfo_tlv_t) + 4);
|
||||
eeprom_crc->type = TLV_CODE_CRC_32;
|
||||
}
|
||||
eeprom_crc->length = 4;
|
||||
|
||||
// Calculate the checksum
|
||||
calc_crc = crc32((void *)eeprom,
|
||||
sizeof(tlvinfo_header_t) +
|
||||
be16_to_cpu(eeprom_hdr->totallen) - 4);
|
||||
|
||||
eeprom_crc->value[0] = (calc_crc >> 24) & 0xFF;
|
||||
eeprom_crc->value[1] = (calc_crc >> 16) & 0xFF;
|
||||
eeprom_crc->value[2] = (calc_crc >> 8) & 0xFF;
|
||||
eeprom_crc->value[3] = (calc_crc >> 0) & 0xFF;
|
||||
}
|
||||
|
||||
/*
|
||||
* show_eeprom
|
||||
*
|
||||
* Display the contents of the EEPROM
|
||||
*/
|
||||
|
||||
/*
|
||||
* read_eeprom
|
||||
*
|
||||
* Read the EEPROM into memory, if it hasn't already been read.
|
||||
*/
|
||||
int read_eeprom( struct i2c_client *pi2c_client, u_int8_t *eeprom)
|
||||
{
|
||||
int ret;
|
||||
tlvinfo_header_t *eeprom_hdr = (tlvinfo_header_t *) eeprom;
|
||||
tlvinfo_tlv_t *eeprom_tlv = (tlvinfo_tlv_t *)&eeprom[
|
||||
sizeof(tlvinfo_header_t)];
|
||||
|
||||
if (has_been_read)
|
||||
return 0;
|
||||
|
||||
/* Read the header */
|
||||
ret = read_sys_eeprom( pi2c_client,(void *)eeprom_hdr, 0, sizeof(tlvinfo_header_t));
|
||||
/* If the header was successfully read, read the TLVs */
|
||||
if ((ret == 0) && is_valid_tlvinfo_header(eeprom_hdr)) {
|
||||
ret = read_sys_eeprom( pi2c_client, (void *)eeprom_tlv, sizeof(tlvinfo_header_t),
|
||||
be16_to_cpu(eeprom_hdr->totallen));
|
||||
}
|
||||
// If the contents are invalid, start over with default contents
|
||||
if(!is_valid_tlvinfo_header(eeprom_hdr))
|
||||
printk(KERN_ERR
|
||||
"Notice: Invalid TLV header found. Using default contents--1.\n");
|
||||
if(!is_checksum_valid(eeprom))
|
||||
printk(KERN_ERR
|
||||
"Notice: Invalid TLV checksum found. Using default contents--2.\n");
|
||||
if ( !is_valid_tlvinfo_header(eeprom_hdr) || !is_checksum_valid(eeprom) ){
|
||||
strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING);
|
||||
eeprom_hdr->version = TLV_INFO_VERSION;
|
||||
eeprom_hdr->totallen = cpu_to_be16(0);
|
||||
update_crc(eeprom);
|
||||
}
|
||||
has_been_read = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* prog_eeprom
|
||||
* Write the EEPROM data from CPU memory to the hardware.
|
||||
*/
|
||||
int prog_eeprom(struct i2c_client *pi2c_client, u_int8_t * eeprom)
|
||||
{
|
||||
int ret = 0;
|
||||
tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom;
|
||||
int eeprom_len;
|
||||
|
||||
eeprom_len = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen);
|
||||
ret = write_sys_eeprom( pi2c_client, eeprom, eeprom_len);
|
||||
if (ret) {
|
||||
printk("Programming failed.\n");
|
||||
return -1;
|
||||
}
|
||||
has_been_read = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* tlvinfo_find_tlv
|
||||
*
|
||||
* This function finds the TLV with the supplied code in the EERPOM.
|
||||
* An offset from the beginning of the EEPROM is returned in the
|
||||
* eeprom_index parameter if the TLV is found.
|
||||
*/
|
||||
bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode,
|
||||
int *eeprom_index)
|
||||
{
|
||||
tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom;
|
||||
tlvinfo_tlv_t * eeprom_tlv;
|
||||
int eeprom_end;
|
||||
|
||||
// Make sure the EEPROM contents are valid
|
||||
if (!is_valid_tlvinfo_header(eeprom_hdr) || !is_checksum_valid(eeprom)) {
|
||||
return(FALSE);
|
||||
}
|
||||
// Search through the TLVs, looking for the first one which matches the
|
||||
// supplied type code.
|
||||
*eeprom_index = sizeof(tlvinfo_header_t);
|
||||
eeprom_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen);
|
||||
|
||||
while (*eeprom_index < eeprom_end) {
|
||||
eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[*eeprom_index];
|
||||
if (!is_valid_tlv(eeprom_tlv)) {
|
||||
return(FALSE);
|
||||
}
|
||||
if (eeprom_tlv->type == tcode) {
|
||||
return(TRUE);
|
||||
}
|
||||
*eeprom_index += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length;
|
||||
}
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* tlvinfo_decode_tlv
|
||||
*
|
||||
* This function finds the TLV with the supplied code in the EERPOM
|
||||
* and decodes the value into the buffer provided.
|
||||
*/
|
||||
bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, char* value)
|
||||
{
|
||||
int eeprom_index;
|
||||
tlvinfo_tlv_t * eeprom_tlv;
|
||||
|
||||
// Find the TLV and then decode it
|
||||
|
||||
if (tlvinfo_find_tlv(eeprom, tcode, &eeprom_index)) {
|
||||
eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index];
|
||||
decode_tlv_value(eeprom_tlv, value);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* tlvinfo_delete_tlv
|
||||
*
|
||||
* This function deletes the TLV with the specified type code from the
|
||||
* EEPROM.
|
||||
*/
|
||||
bool tlvinfo_delete_tlv(u_int8_t * eeprom, u_int8_t code)
|
||||
{
|
||||
int eeprom_index;
|
||||
int tlength;
|
||||
tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom;
|
||||
tlvinfo_tlv_t * eeprom_tlv;
|
||||
|
||||
// Find the TLV and then move all following TLVs "forward"
|
||||
if (tlvinfo_find_tlv(eeprom, code, &eeprom_index)) {
|
||||
eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index];
|
||||
tlength = sizeof(tlvinfo_tlv_t) + eeprom_tlv->length;
|
||||
memcpy(&eeprom[eeprom_index], &eeprom[eeprom_index+tlength],
|
||||
sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen) -
|
||||
eeprom_index - tlength);
|
||||
eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) -
|
||||
tlength);
|
||||
update_crc(eeprom);
|
||||
return(TRUE);
|
||||
}
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* tlvinfo_add_tlv
|
||||
*
|
||||
* This function adds a TLV to the EEPROM, converting the value (a string) to
|
||||
* the format in which it will be stored in the EEPROM.
|
||||
*/
|
||||
#define MAX_TLV_VALUE_LEN 256
|
||||
bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, const char *strval)
|
||||
{
|
||||
tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom;
|
||||
tlvinfo_tlv_t * eeprom_tlv;
|
||||
int new_tlv_len = 0;
|
||||
u_int32_t value;
|
||||
char data[MAX_TLV_VALUE_LEN];
|
||||
int eeprom_index;
|
||||
int max_size = TLV_TOTAL_LEN_MAX;
|
||||
|
||||
// Encode each TLV type into the format to be stored in the EERPOM
|
||||
switch (tcode) {
|
||||
case TLV_CODE_PRODUCT_NAME:
|
||||
case TLV_CODE_PART_NUMBER:
|
||||
case TLV_CODE_SERIAL_NUMBER:
|
||||
case TLV_CODE_LABEL_REVISION:
|
||||
case TLV_CODE_PLATFORM_NAME:
|
||||
case TLV_CODE_ONIE_VERSION:
|
||||
case TLV_CODE_MANUF_NAME:
|
||||
case TLV_CODE_MANUF_COUNTRY:
|
||||
case TLV_CODE_VENDOR_NAME:
|
||||
case TLV_CODE_DIAG_VERSION:
|
||||
case TLV_CODE_SERVICE_TAG:
|
||||
strncpy(data, strval, MAX_TLV_VALUE_LEN);
|
||||
|
||||
if( strlen(strval) >= MAX_TLV_VALUE_LEN )
|
||||
new_tlv_len = MAX_TLV_VALUE_LEN;
|
||||
else
|
||||
new_tlv_len = strlen(strval);
|
||||
|
||||
break;
|
||||
case TLV_CODE_DEVICE_VERSION:
|
||||
value = strtoul(strval, NULL, 0);
|
||||
if (value >= 256) {
|
||||
printk("ERROR: Device version must be 255 or less. Value " \
|
||||
"supplied: %u", value);
|
||||
return(FALSE);
|
||||
}
|
||||
data[0] = value & 0xFF;
|
||||
new_tlv_len = 1;
|
||||
break;
|
||||
case TLV_CODE_MAC_SIZE:
|
||||
value = strtoul(strval, NULL, 0);
|
||||
if (value >= 65536) {
|
||||
printk("ERROR: MAC Size must be 65535 or less. Value " \
|
||||
"supplied: %u", value);
|
||||
return(FALSE);
|
||||
}
|
||||
data[0] = (value >> 8) & 0xFF;
|
||||
data[1] = value & 0xFF;
|
||||
new_tlv_len = 2;
|
||||
break;
|
||||
case TLV_CODE_MANUF_DATE:
|
||||
if (set_date(data, strval) != 0) {
|
||||
return(FALSE);
|
||||
}
|
||||
new_tlv_len = 19;
|
||||
break;
|
||||
case TLV_CODE_MAC_BASE:
|
||||
if (set_mac(data, strval) != 0) {
|
||||
return(FALSE);
|
||||
}
|
||||
new_tlv_len = 6;
|
||||
break;
|
||||
case TLV_CODE_CRC_32:
|
||||
printk("WARNING: The CRC TLV is set automatically and cannot be set " \
|
||||
"manually.\n");
|
||||
return(FALSE);
|
||||
case TLV_CODE_VENDOR_EXT:
|
||||
default:
|
||||
if (set_bytes(data, strval, &new_tlv_len) != 0 ) {
|
||||
return(FALSE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Is there room for this TLV?
|
||||
if ((be16_to_cpu(eeprom_hdr->totallen) + sizeof(tlvinfo_tlv_t) +
|
||||
new_tlv_len) > max_size) {
|
||||
printk("ERROR: There is not enough room in the EERPOM to save data.\n");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
// Add TLV at the end, overwriting CRC TLV if it exists
|
||||
if (tlvinfo_find_tlv(eeprom, TLV_CODE_CRC_32, &eeprom_index)) {
|
||||
eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen)
|
||||
- sizeof(tlvinfo_tlv_t) - 4);
|
||||
} else {
|
||||
eeprom_index = sizeof(tlvinfo_header_t) +
|
||||
be16_to_cpu(eeprom_hdr->totallen);
|
||||
}
|
||||
eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[eeprom_index];
|
||||
eeprom_tlv->type = tcode;
|
||||
eeprom_tlv->length = new_tlv_len;
|
||||
memcpy(eeprom_tlv->value, data, new_tlv_len);
|
||||
|
||||
// Update the total length and calculate (add) a new CRC-32 TLV
|
||||
eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) +
|
||||
sizeof(tlvinfo_tlv_t) + new_tlv_len);
|
||||
update_crc(eeprom);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* read_sys_eeprom - read the hwinfo from i2c EEPROM
|
||||
*/
|
||||
int read_sys_eeprom(struct i2c_client *pi2c_client,void *eeprom_data, int offset, int len)
|
||||
{
|
||||
int iRet = 0;
|
||||
int i = 0;
|
||||
unsigned char ucBuf[2];
|
||||
u_int8_t *c;
|
||||
unsigned short usAddr = SYS_EEPROM_OFFSET + offset;
|
||||
|
||||
c = eeprom_data;
|
||||
for (i = 0; i < len; i++) {
|
||||
ucBuf[0] = (usAddr & 0xFF00) >> 8;
|
||||
ucBuf[1] = (usAddr & 0x00FF);
|
||||
|
||||
iRet = i2c_smbus_write_byte_data(pi2c_client, ucBuf[0], ucBuf[1]);
|
||||
if( iRet < 0 ){
|
||||
printk(KERN_ERR"Error!! VPD data read error\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*c = i2c_smbus_read_byte(pi2c_client);
|
||||
c++; usAddr++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* write_sys_eeprom - write the hwinfo to i2c EEPROM
|
||||
*/
|
||||
int write_sys_eeprom(struct i2c_client *pi2c_client, void *eeprom_data, int len)
|
||||
{
|
||||
int iRet = 0;
|
||||
int i = 0;
|
||||
u_int8_t *c;
|
||||
unsigned short usAddr = SYS_EEPROM_OFFSET;
|
||||
unsigned char ucBuf[3];
|
||||
|
||||
c = eeprom_data;
|
||||
for (i = 0; i < len; i++) {
|
||||
ucBuf[ 0 ] = (usAddr & 0xFF00) >>8 ;
|
||||
ucBuf[ 1 ] = (usAddr & 0x00FF);
|
||||
ucBuf[ 2 ] = *c;
|
||||
|
||||
iRet = i2c_smbus_write_word_data( pi2c_client, ucBuf[0], (ucBuf[2] << 8 | ucBuf[1]));
|
||||
if (iRet < 0 ){
|
||||
printk(KERN_ERR"Error!! VPD data write error . \n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
c++; usAddr++;
|
||||
msleep_interruptible(10);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void update_eeprom_header(u_int8_t *eeprom)
|
||||
{
|
||||
tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom;
|
||||
|
||||
strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING);
|
||||
eeprom_hdr->version = TLV_INFO_VERSION;
|
||||
eeprom_hdr->totallen = cpu_to_be16(0);
|
||||
update_crc(eeprom);
|
||||
}
|
||||
#if 0
|
||||
int find_vpd_data(u_int8_t *eeprom, int i_offset, char *c_buf)
|
||||
{
|
||||
int tlv_end;
|
||||
int curr_tlv;
|
||||
tlvinfo_header_t * eeprom_hdr = (tlvinfo_header_t *) eeprom;
|
||||
tlvinfo_tlv_t * eeprom_tlv;
|
||||
int iFind = 0;
|
||||
|
||||
if( !is_valid_tlvinfo_header(eeprom_hdr) ) {
|
||||
printk(KERN_ERR"EEPROM does not contain data in a valid TlvInfo format.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
curr_tlv = sizeof(tlvinfo_header_t);
|
||||
tlv_end = sizeof(tlvinfo_header_t) + be16_to_cpu(eeprom_hdr->totallen);
|
||||
while(curr_tlv < tlv_end){
|
||||
eeprom_tlv = (tlvinfo_tlv_t *) &eeprom[curr_tlv];
|
||||
if (!is_valid_tlv(eeprom_tlv)) {
|
||||
printk(KERN_ERR"Invalid TLV field starting at EEPROM offset %d\n",
|
||||
curr_tlv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
decode_tlv_value(eeprom_tlv, c_buf);
|
||||
if( eeprom_tlv->type == i_offset){
|
||||
iFind = 1;
|
||||
break;
|
||||
}
|
||||
curr_tlv += sizeof(tlvinfo_tlv_t) + eeprom_tlv->length;
|
||||
}
|
||||
|
||||
if( iFind == 0 )
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* The Definition of the TlvInfo EEPROM format can be found at onie.org or
|
||||
* github.com/onie
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#define strtoul simple_strtoul
|
||||
|
||||
#define FALSE 0
|
||||
#define TRUE (!FALSE)
|
||||
#define MAX_STRING_SIZE 128
|
||||
/*
|
||||
* Tlvinf header: Layout of the header for the TlvInfo format
|
||||
*
|
||||
* See the end of this file for details of this eeprom format
|
||||
*/
|
||||
struct __attribute__ ((__packed__)) tlvinfo_header_s {
|
||||
char signature[8]; /* 0x00 - 0x07 EEPROM Tag "TlvInfo" */
|
||||
u_int8_t version; /* 0x08 Structure version */
|
||||
u_int16_t totallen; /* 0x09 - 0x0A Length of all data which follows */
|
||||
};
|
||||
typedef struct tlvinfo_header_s tlvinfo_header_t;
|
||||
|
||||
// Header Field Constants
|
||||
#define TLV_INFO_ID_STRING "TlvInfo"
|
||||
#define TLV_INFO_VERSION 0x01
|
||||
#define TLV_TOTAL_LEN_MAX (SYS_EEPROM_SIZE - sizeof(tlvinfo_header_t))
|
||||
|
||||
/*
|
||||
* TlvInfo TLV: Layout of a TLV field
|
||||
*/
|
||||
struct __attribute__ ((__packed__)) tlvinfo_tlv_s {
|
||||
u_int8_t type;
|
||||
u_int8_t length;
|
||||
u_int8_t value[0];
|
||||
};
|
||||
typedef struct tlvinfo_tlv_s tlvinfo_tlv_t;
|
||||
|
||||
/* Maximum length of a TLV value in bytes */
|
||||
#define TLV_VALUE_MAX_LEN 255
|
||||
|
||||
/**
|
||||
* The TLV Types.
|
||||
*
|
||||
* Keep these in sync with tlv_code_list in cmd_sys_eeprom.c
|
||||
*/
|
||||
#define TLV_CODE_PRODUCT_NAME 0x21
|
||||
#define TLV_CODE_PART_NUMBER 0x22
|
||||
#define TLV_CODE_SERIAL_NUMBER 0x23
|
||||
#define TLV_CODE_MAC_BASE 0x24
|
||||
#define TLV_CODE_MANUF_DATE 0x25
|
||||
#define TLV_CODE_DEVICE_VERSION 0x26
|
||||
#define TLV_CODE_LABEL_REVISION 0x27
|
||||
#define TLV_CODE_PLATFORM_NAME 0x28
|
||||
#define TLV_CODE_ONIE_VERSION 0x29
|
||||
#define TLV_CODE_MAC_SIZE 0x2A
|
||||
#define TLV_CODE_MANUF_NAME 0x2B
|
||||
#define TLV_CODE_MANUF_COUNTRY 0x2C
|
||||
#define TLV_CODE_VENDOR_NAME 0x2D
|
||||
#define TLV_CODE_DIAG_VERSION 0x2E
|
||||
#define TLV_CODE_SERVICE_TAG 0x2F
|
||||
#define TLV_CODE_VENDOR_EXT 0xFD
|
||||
#define TLV_CODE_CRC_32 0xFE
|
||||
|
||||
/*
|
||||
* Struct for displaying the TLV codes and names.
|
||||
*/
|
||||
struct tlv_code_desc {
|
||||
u_int8_t m_code;
|
||||
char* m_name;
|
||||
};
|
||||
|
||||
/*
|
||||
* List of TLV codes and names.
|
||||
*/
|
||||
static const struct tlv_code_desc tlv_code_list[] = {
|
||||
{ TLV_CODE_PRODUCT_NAME , "Product Name"},
|
||||
{ TLV_CODE_PART_NUMBER , "Part Number"},
|
||||
{ TLV_CODE_SERIAL_NUMBER , "Serial Number"},
|
||||
{ TLV_CODE_MAC_BASE , "Base MAC Address"},
|
||||
{ TLV_CODE_MANUF_DATE , "Manufacture Date"},
|
||||
{ TLV_CODE_DEVICE_VERSION , "Device Version"},
|
||||
{ TLV_CODE_LABEL_REVISION , "Label Revision"},
|
||||
{ TLV_CODE_PLATFORM_NAME , "Platform Name"},
|
||||
{ TLV_CODE_ONIE_VERSION , "Loader Version"},
|
||||
{ TLV_CODE_MAC_SIZE , "MAC Addresses"},
|
||||
{ TLV_CODE_MANUF_NAME , "Manufacturer"},
|
||||
{ TLV_CODE_MANUF_COUNTRY , "Country Code"},
|
||||
{ TLV_CODE_VENDOR_NAME , "Vendor Name"},
|
||||
{ TLV_CODE_DIAG_VERSION , "Diag Version"},
|
||||
{ TLV_CODE_SERVICE_TAG , "Service Tag"},
|
||||
{ TLV_CODE_VENDOR_EXT , "Vendor Extension"},
|
||||
{ TLV_CODE_CRC_32 , "CRC-32"},
|
||||
};
|
||||
|
||||
static inline const char* tlv_type2name(u_int8_t type)
|
||||
{
|
||||
char* name = "Unknown";
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(tlv_code_list)/sizeof(tlv_code_list[0]); i++) {
|
||||
if (tlv_code_list[i].m_code == type) {
|
||||
name = tlv_code_list[i].m_name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/*
|
||||
* The max decode value is currently for the 'raw' type or the 'vendor
|
||||
* extension' type, both of which have the same decode format. The
|
||||
* max decode string size is computed as follows:
|
||||
*
|
||||
* strlen(" 0xFF") * TLV_VALUE_MAX_LEN + 1
|
||||
*
|
||||
*/
|
||||
#define TLV_DECODE_VALUE_MAX_LEN ((5 * TLV_VALUE_MAX_LEN) + 1)
|
||||
|
||||
|
||||
/*
|
||||
* Each platform must define the following platform-specific macros
|
||||
* in sys_eeprom_platform.h:
|
||||
* SYS_EEPROM_SIZE: size of usable eeprom
|
||||
* SYS_EEPROM_I2C_DEVICE: i2c-bus
|
||||
* SYS_EEPROM_I2C_ADDR: address on the bus
|
||||
* The following may also be defined in sys_eeprom_platform.h, else
|
||||
* the defaults with take over:
|
||||
* SYS_EEPROM_MAX_SIZE: Total size of the eeprom
|
||||
* SYS_EEPROM_OFFSET: offset from where the ONIE header starts
|
||||
*/
|
||||
#define SYS_EEPROM_MAX_SIZE 2048
|
||||
#define SYS_EEPROM_OFFSET 0
|
||||
#define SYS_EEPROM_SIZE SYS_EEPROM_MAX_SIZE
|
||||
#define SYS_EEPROM_I2C_DEVICE "/dev/i2c-0"
|
||||
#define SYS_EEPROM_I2C_ADDR 0x53
|
||||
|
||||
#if (SYS_EEPROM_SIZE + SYS_EEPROM_OFFSET > SYS_EEPROM_MAX_SIZE)
|
||||
#error SYS_EEPROM_SIZE + SYS_EEPROM_OFFSET is greater than SYS_EEPROM_MAX_SIZE
|
||||
#endif
|
||||
|
||||
// Access functions to onie_tlvinfo
|
||||
void show_eeprom(u_int8_t *eeprom);
|
||||
int read_eeprom(struct i2c_client *pi2c_client, u_int8_t *eeprom);
|
||||
int prog_eeprom(struct i2c_client *pi2c_client,u_int8_t * eeprom);
|
||||
void update_eeprom_header(u_int8_t *eeprom);
|
||||
bool tlvinfo_find_tlv(u_int8_t *eeprom, u_int8_t tcode, int *eeprom_index);
|
||||
bool tlvinfo_delete_tlv(u_int8_t * eeprom, u_int8_t code);
|
||||
bool tlvinfo_add_tlv(u_int8_t * eeprom, int tcode, const char *strval);
|
||||
bool tlvinfo_decode_tlv(u_int8_t *eeprom, u_int8_t tcode, char* value);
|
||||
//int find_vpd_data(u_int8_t *eeprom, int i_offset, char *c_buf);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,808 @@
|
||||
#ifndef TRANSCEIVER_H
|
||||
#define TRANSCEIVER_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* advanced features control */
|
||||
#define TRANSVR_INFO_DUMP_ENABLE (1)
|
||||
#define TRANSVR_INFO_CACHE_ENABLE (1)
|
||||
#define TRANSVR_UEVENT_ENABLE (1)
|
||||
|
||||
/* Transceiver type define */
|
||||
#define TRANSVR_TYPE_UNKNOW_1 (0x00)
|
||||
#define TRANSVR_TYPE_UNKNOW_2 (0xff)
|
||||
#define TRANSVR_TYPE_SFP (0x03) /* Define for SFP, SFP+, SFP28 */
|
||||
#define TRANSVR_TYPE_QSFP (0x0c)
|
||||
#define TRANSVR_TYPE_QSFP_PLUS (0x0d)
|
||||
#define TRANSVR_TYPE_QSFP_28 (0x11)
|
||||
#define TRANSVR_TYPE_UNPLUGGED (0xfa) /* Define for ERROR handle */
|
||||
#define TRANSVR_TYPE_FAKE (0xfc) /* Define for ERROR handle */
|
||||
#define TRANSVR_TYPE_INCONSISTENT (0xfd) /* Define for ERROR handle */
|
||||
#define TRANSVR_TYPE_ERROR (0xfe) /* Define for ERROR handle */
|
||||
|
||||
/* Transceiver class for base info */
|
||||
#define TRANSVR_CLASS_UNSPECIFIED (0)
|
||||
#define TRANSVR_CLASS_ERROR (-26001)
|
||||
#define TRANSVR_CLASS_1G (26001)
|
||||
#define TRANSVR_CLASS_10G (26011)
|
||||
#define TRANSVR_CLASS_25G (26021)
|
||||
#define TRANSVR_CLASS_40G (26041)
|
||||
#define TRANSVR_CLASS_100G (26101)
|
||||
#define TRANSVR_CLASS_NO_SPERARABLE (26901)
|
||||
#define TRANSVR_CLASS_EXTEND_COMP (26902)
|
||||
/* Transceiver class for Optical 1G */
|
||||
#define TRANSVR_CLASS_OPTICAL (27000)
|
||||
#define TRANSVR_CLASS_OPTICAL_100 (27001)
|
||||
#define TRANSVR_CLASS_OPTICAL_1G (27002)
|
||||
#define TRANSVR_CLASS_OPTICAL_1G_AOC (27003)
|
||||
#define TRANSVR_CLASS_OPTICAL_1G_SX (27004)
|
||||
#define TRANSVR_CLASS_OPTICAL_1G_LX (27005)
|
||||
#define TRANSVR_CLASS_OPTICAL_1G_EX (27006)
|
||||
/* Transceiver class for Optical 10G */
|
||||
#define TRANSVR_CLASS_OPTICAL_10G (27010)
|
||||
#define TRANSVR_CLASS_OPTICAL_10G_S_AOC (27011)
|
||||
#define TRANSVR_CLASS_OPTICAL_10G_S_SR (27012)
|
||||
#define TRANSVR_CLASS_OPTICAL_10G_S_LR (27013)
|
||||
#define TRANSVR_CLASS_OPTICAL_10G_S_ER (27014)
|
||||
#define TRANSVR_CLASS_OPTICAL_10G_Q_AOC (27015)
|
||||
#define TRANSVR_CLASS_OPTICAL_10G_Q_SR (27016)
|
||||
#define TRANSVR_CLASS_OPTICAL_10G_Q_LR (27017)
|
||||
#define TRANSVR_CLASS_OPTICAL_10G_Q_ER (27018)
|
||||
/* Transceiver class for Optical 25G */
|
||||
#define TRANSVR_CLASS_OPTICAL_25G (27020)
|
||||
#define TRANSVR_CLASS_OPTICAL_25G_AOC (27021)
|
||||
#define TRANSVR_CLASS_OPTICAL_25G_SR (27022)
|
||||
#define TRANSVR_CLASS_OPTICAL_25G_LR (27023)
|
||||
#define TRANSVR_CLASS_OPTICAL_25G_ER (27024)
|
||||
/* Transceiver class for Optical 40G */
|
||||
#define TRANSVR_CLASS_OPTICAL_40G (27040)
|
||||
#define TRANSVR_CLASS_OPTICAL_40G_AOC (27041)
|
||||
#define TRANSVR_CLASS_OPTICAL_40G_SR4 (27042)
|
||||
#define TRANSVR_CLASS_OPTICAL_40G_LR4 (27043)
|
||||
#define TRANSVR_CLASS_OPTICAL_40G_ER4 (27044)
|
||||
/* Transceiver class for Optical 100G */
|
||||
#define TRANSVR_CLASS_OPTICAL_100G (27100)
|
||||
#define TRANSVR_CLASS_OPTICAL_100G_AOC (27101)
|
||||
#define TRANSVR_CLASS_OPTICAL_100G_SR4 (27102)
|
||||
#define TRANSVR_CLASS_OPTICAL_100G_LR4 (27103)
|
||||
#define TRANSVR_CLASS_OPTICAL_100G_ER4 (27104)
|
||||
#define TRANSVR_CLASS_OPTICAL_100G_PSM4 (27105)
|
||||
/* Transceiver class for Copper */
|
||||
#define TRANSVR_CLASS_COPPER (28000)
|
||||
#define TRANSVR_CLASS_COPPER_L1_1G (28001)
|
||||
#define TRANSVR_CLASS_COPPER_L1_10G (28011)
|
||||
#define TRANSVR_CLASS_COPPER_L4_10G (28012)
|
||||
#define TRANSVR_CLASS_COPPER_L1_25G (28021)
|
||||
#define TRANSVR_CLASS_COPPER_L4_40G (28041)
|
||||
#define TRANSVR_CLASS_COPPER_L4_100G (28101)
|
||||
/* Transceiver class for Base-T */
|
||||
#define TRANSVR_CLASS_BASE_T_1000 (29001)
|
||||
#define TRANSVR_CLASS_BASE_T_1000_up (29002)
|
||||
/* For uevent message */
|
||||
#define TRANSVR_UEVENT_KEY_IF "IF_TYPE"
|
||||
#define TRANSVR_UEVENT_KEY_SP "IF_SPEED"
|
||||
#define TRANSVR_UEVENT_KEY_LANE "IF_LANE"
|
||||
#define TRANSVR_UEVENT_UNKNOW "UNKNOW"
|
||||
#define TRANSVR_IF_KR "KR"
|
||||
#define TRANSVR_IF_KR4 "KR4"
|
||||
#define TRANSVR_IF_SR "SR"
|
||||
#define TRANSVR_IF_SR4 "SR4"
|
||||
#define TRANSVR_IF_SFI "SFI"
|
||||
#define TRANSVR_IF_IF_GMII "GMII"
|
||||
#define TRANSVR_IF_IF_XGMII "XGMII"
|
||||
#define TRANSVR_IF_SP_100 "100"
|
||||
#define TRANSVR_IF_SP_1G "1000"
|
||||
#define TRANSVR_IF_SP_10G "10000"
|
||||
#define TRANSVR_IF_SP_25G "25000"
|
||||
#define TRANSVR_IF_SP_40G "40000"
|
||||
#define TRANSVR_IF_SP_100G "100000"
|
||||
|
||||
/* Transceiver mode define */
|
||||
#define TRANSVR_MODE_DIRECT (21000)
|
||||
#define TRANSVR_MODE_POLLING (21001)
|
||||
|
||||
/* Transceiver state define
|
||||
* [Note]
|
||||
* 1. State is used to represent the state of "Transceiver" and "Object".
|
||||
* 2. State for different target has different means. The description as following:
|
||||
*/
|
||||
#define STATE_TRANSVR_CONNECTED (0) /* [Transvr]:Be plugged in. [Obj]:Link up, and work normally. */
|
||||
#define STATE_TRANSVR_NEW (-100) /* [Transvr]:(Not used) [Obj]:Create */
|
||||
#define STATE_TRANSVR_INIT (-101) /* [Transvr]:Be plugged in. [Obj]:Link up, and in initial process. */
|
||||
#define STATE_TRANSVR_ISOLATED (-102) /* [Transvr]:Be plugged in. [Obj]:Isolate, and not provide service. */
|
||||
#define STATE_TRANSVR_SWAPPED (-200) /* [Transvr]:Be plugged in. [Obj]:(Not used) */
|
||||
#define STATE_TRANSVR_DISCONNECTED (-300) /* [Transvr]:Un-plugged. [Obj]:Link down, and not provide service. */
|
||||
#define STATE_TRANSVR_UNEXCEPTED (-901) /* [Transvr]:Any [Obj]:Any, and not in expect case. */
|
||||
|
||||
/* Task state define */
|
||||
#define STATE_T_TASK_WAIT (110)
|
||||
#define STATE_T_TASK_DONE (0)
|
||||
#define STATE_T_TASK_INIT (-110)
|
||||
#define STATE_T_TASK_FAIL (-410)
|
||||
|
||||
|
||||
/* Event for task handling */
|
||||
#define EVENT_TRANSVR_TASK_WAIT (2101)
|
||||
#define EVENT_TRANSVR_TASK_DONE (0)
|
||||
#define EVENT_TRANSVR_TASK_FAIL (-2101)
|
||||
/* Event for initial handling */
|
||||
#define EVENT_TRANSVR_INIT_UP (2201)
|
||||
#define EVENT_TRANSVR_INIT_DOWN (1)
|
||||
#define EVENT_TRANSVR_INIT_REINIT (-2201)
|
||||
#define EVENT_TRANSVR_INIT_FAIL (-2202)
|
||||
/* Event for others */
|
||||
#define EVENT_TRANSVR_RELOAD_FAIL (-2301)
|
||||
#define EVENT_TRANSVR_EXCEP_INIT (-2401)
|
||||
#define EVENT_TRANSVR_EXCEP_UP (-2402)
|
||||
#define EVENT_TRANSVR_EXCEP_DOWN (-2403)
|
||||
#define EVENT_TRANSVR_EXCEP_SWAP (-2404)
|
||||
#define EVENT_TRANSVR_EXCEP_EXCEP (-2405)
|
||||
#define EVENT_TRANSVR_EXCEP_ISOLATED (-2406)
|
||||
#define EVENT_TRANSVR_I2C_CRASH (-2501)
|
||||
|
||||
/* Transceiver error code define */
|
||||
#define ERR_TRANSVR_UNINIT (-201)
|
||||
#define ERR_TRANSVR_UNPLUGGED (-202)
|
||||
#define ERR_TRANSVR_ABNORMAL (-203)
|
||||
#define ERR_TRANSVR_NOSTATE (-204)
|
||||
#define ERR_TRANSVR_NOTSUPPORT (-205)
|
||||
#define ERR_TRANSVR_BADINPUT (-206)
|
||||
#define ERR_TRANSVR_UPDATE_FAIL (-207)
|
||||
#define ERR_TRANSVR_RELOAD_FAIL (-208)
|
||||
#define ERR_TRANSVR_INIT_FAIL (-209)
|
||||
#define ERR_TRANSVR_UNDEFINED (-210)
|
||||
#define ERR_TRANSVR_TASK_FAIL (-211)
|
||||
#define ERR_TRANSVR_TASK_BUSY (-212)
|
||||
#define ERR_TRANSVR_UEVENT_FAIL (-213)
|
||||
#define ERR_TRANSVR_FUNC_DISABLE (-214)
|
||||
#define ERR_TRANSVR_I2C_CRASH (-297)
|
||||
#define ERR_TRNASVR_BE_ISOLATED (-298)
|
||||
#define ERR_TRANSVR_UNEXCPT (-299)
|
||||
|
||||
/* For debug */
|
||||
#define DEBUG_TRANSVR_INT_VAL (-99)
|
||||
#define DEBUG_TRANSVR_HEX_VAL (0xfe)
|
||||
#define DEBUG_TRANSVR_STR_VAL "ERROR"
|
||||
|
||||
/* For system internal */
|
||||
#define VAL_TRANSVR_COMID_ARREESS (0x50)
|
||||
#define VAL_TRANSVR_COMID_OFFSET (0x00)
|
||||
#define VAL_TRANSVR_EXTPHY_ADDR_56 (0x56)
|
||||
#define VAL_TRANSVR_8472_READY_ADDR (0x51)
|
||||
#define VAL_TRANSVR_8472_READY_PAGE (-1)
|
||||
#define VAL_TRANSVR_8472_READY_OFFSET (110)
|
||||
#define VAL_TRANSVR_8472_READY_BIT (0)
|
||||
#define VAL_TRANSVR_8472_READY_VALUE (0)
|
||||
#define VAL_TRANSVR_8472_READY_ABNORMAL (0xff)
|
||||
#define VAL_TRANSVR_8436_READY_ADDR (0x50)
|
||||
#define VAL_TRANSVR_8436_READY_PAGE (-1)
|
||||
#define VAL_TRANSVR_8436_READY_OFFSET (2)
|
||||
#define VAL_TRANSVR_8436_READY_BIT (0)
|
||||
#define VAL_TRANSVR_8436_READY_VALUE (0)
|
||||
#define VAL_TRANSVR_8436_READY_ABNORMAL (0xff)
|
||||
#define VAL_TRANSVR_8436_PWD_ADDR (0x50)
|
||||
#define VAL_TRANSVR_8436_PWD_PAGE (-1)
|
||||
#define VAL_TRANSVR_8436_PWD_OFFSET (123)
|
||||
#define VAL_TRANSVR_PAGE_FREE (-99)
|
||||
#define VAL_TRANSVR_PAGE_SELECT_OFFSET (127)
|
||||
#define VAL_TRANSVR_PAGE_SELECT_DELAY (5)
|
||||
#define VAL_TRANSVR_TASK_RETRY_FOREVER (-999)
|
||||
#define VAL_TRANSVR_FUNCTION_DISABLE (-1)
|
||||
#define STR_TRANSVR_SFP "SFP"
|
||||
#define STR_TRANSVR_QSFP "QSFP"
|
||||
#define STR_TRANSVR_QSFP_PLUS "QSFP+"
|
||||
#define STR_TRANSVR_QSFP28 "QSFP28"
|
||||
|
||||
/* For transvr buf len */
|
||||
#define LEN_TRANSVR_S_STR (16)
|
||||
#define LEN_TRANSVR_M_STR (32)
|
||||
#define LEN_TRANSVR_L_STR (64)
|
||||
|
||||
/* Optical wavelength */
|
||||
#define VAL_OPTICAL_WAVELENGTH_SR (850)
|
||||
#define VAL_OPTICAL_WAVELENGTH_LR (1310)
|
||||
#define VAL_OPTICAL_WAVELENGTH_ER (1550)
|
||||
|
||||
/* BCM chip type define */
|
||||
#define BCM_CHIP_TYPE_TRIDENT_2 (31001) /* Magnolia, Hudson32i, Spruce */
|
||||
#define BCM_CHIP_TYPE_TOMAHAWK (31002) /* Redwood, Cypress, Sequoia */
|
||||
#define BCM_CHIP_TYPE_TRIDENT_3 (31003) /* Maple */
|
||||
|
||||
#define BF_CHIP_TYPE_TOFINO (31011) /* Lavender */
|
||||
|
||||
/* Info from transceiver EEPROM */
|
||||
struct eeprom_map_s {
|
||||
int addr_br; int page_br; int offset_br; int length_br;
|
||||
int addr_cdr; int page_cdr; int offset_cdr; int length_cdr;
|
||||
int addr_comp_rev; int page_comp_rev; int offset_comp_rev; int length_comp_rev;
|
||||
int addr_connector; int page_connector; int offset_connector; int length_connector;
|
||||
int addr_diag_type; int page_diag_type; int offset_diag_type; int length_diag_type;
|
||||
int addr_extbr; int page_extbr; int offset_extbr; int length_extbr;
|
||||
int addr_ext_id; int page_ext_id; int offset_ext_id; int length_ext_id;
|
||||
int addr_id; int page_id; int offset_id; int length_id;
|
||||
int addr_len_sm; int page_len_sm; int offset_len_sm; int length_len_sm;
|
||||
int addr_len_smf; int page_len_smf; int offset_len_smf; int length_len_smf;
|
||||
int addr_len_om1; int page_len_om1; int offset_len_om1; int length_len_om1;
|
||||
int addr_len_om2; int page_len_om2; int offset_len_om2; int length_len_om2;
|
||||
int addr_len_om3; int page_len_om3; int offset_len_om3; int length_len_om3;
|
||||
int addr_len_om4; int page_len_om4; int offset_len_om4; int length_len_om4;
|
||||
int addr_option; int page_option; int offset_option; int length_option;
|
||||
int addr_rate_id; int page_rate_id; int offset_rate_id; int length_rate_id;
|
||||
int addr_rx_am; int page_rx_am; int offset_rx_am; int length_rx_am;
|
||||
int addr_rx_em; int page_rx_em; int offset_rx_em; int length_rx_em;
|
||||
int addr_rx_los; int page_rx_los; int offset_rx_los; int length_rx_los;
|
||||
int addr_rx_power; int page_rx_power; int offset_rx_power; int length_rx_power;
|
||||
int addr_soft_rs0; int page_soft_rs0; int offset_soft_rs0; int length_soft_rs0;
|
||||
int addr_soft_rs1; int page_soft_rs1; int offset_soft_rs1; int length_soft_rs1;
|
||||
int addr_temp; int page_temp; int offset_temp; int length_temp;
|
||||
int addr_trancomp; int page_trancomp; int offset_trancomp; int length_trancomp;
|
||||
int addr_trancomp_ext; int page_trancomp_ext; int offset_trancomp_ext; int length_trancomp_ext;
|
||||
int addr_tx_bias; int page_tx_bias; int offset_tx_bias; int length_tx_bias;
|
||||
int addr_tx_disable; int page_tx_disable; int offset_tx_disable; int length_tx_disable;
|
||||
int addr_tx_eq; int page_tx_eq; int offset_tx_eq; int length_tx_eq;
|
||||
int addr_tx_fault; int page_tx_fault; int offset_tx_fault; int length_tx_fault;
|
||||
int addr_tx_power; int page_tx_power; int offset_tx_power; int length_tx_power;
|
||||
int addr_vendor_name; int page_vendor_name; int offset_vendor_name; int length_vendor_name;
|
||||
int addr_vendor_pn; int page_vendor_pn; int offset_vendor_pn; int length_vendor_pn;
|
||||
int addr_vendor_rev; int page_vendor_rev; int offset_vendor_rev; int length_vendor_rev;
|
||||
int addr_vendor_sn; int page_vendor_sn; int offset_vendor_sn; int length_vendor_sn;
|
||||
int addr_voltage; int page_voltage; int offset_voltage; int length_voltage;
|
||||
int addr_wavelength; int page_wavelength; int offset_wavelength; int length_wavelength;
|
||||
};
|
||||
|
||||
|
||||
struct transvr_worker_s;
|
||||
|
||||
/* Class of transceiver object */
|
||||
struct transvr_obj_s {
|
||||
|
||||
/* ========== Object private property ==========
|
||||
* [Prop]: id
|
||||
* [Desc]: Type of serial transceiver.
|
||||
* [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh /QSFP28:11h
|
||||
*/
|
||||
uint8_t id;
|
||||
|
||||
/* [Prop]: connector
|
||||
* [Desc]: Connector type.
|
||||
* [Note]: SFP : A0h / 2
|
||||
* QSFP: 00h / 130
|
||||
*/
|
||||
uint8_t connector;
|
||||
|
||||
/* [Prop]: transvr_comp
|
||||
* [Desc]: Transceiver compliance code.
|
||||
* [Note]: SFP: SFF-8472
|
||||
* - Normal : A0h / offset 3-10
|
||||
* - Extended: A0h / offset 36
|
||||
* QSFP: SFF-8436 & SFF-8636
|
||||
* - Normal : 00h / offset 131-138
|
||||
* - Extended: 00h / offset 192
|
||||
*/
|
||||
uint8_t transvr_comp[8];
|
||||
uint8_t transvr_comp_ext;
|
||||
|
||||
/* [Prop]: vendor_name
|
||||
* [Desc]: SFP vendor name (ASCII 16 byte char).
|
||||
* [Note]: ex:FINISAR CORP.
|
||||
*/
|
||||
char *vendor_name;
|
||||
|
||||
/* [Prop]: vendor_pn
|
||||
* [Desc]: Part number provided by SFP vendor (ASCII 16 byte char).
|
||||
* [Note]:
|
||||
*/
|
||||
char *vendor_pn;
|
||||
|
||||
/* [Prop]: vendor_rev
|
||||
* [Desc]: Revision level for part number provided by vendor (ASCII 4 byte char).
|
||||
* [Note]:
|
||||
*/
|
||||
char *vendor_rev;
|
||||
|
||||
/* [Prop]: vendor_sn
|
||||
* [Desc]: Serial number provided by vendor (ASCII 16 byte char).
|
||||
* [Note]:
|
||||
*/
|
||||
char *vendor_sn;
|
||||
|
||||
/* [Prop]: Extended identifier
|
||||
* [Desc]: SFP:
|
||||
* => None
|
||||
*
|
||||
* QSFP:
|
||||
* => This byte contained two information:
|
||||
* (1) Power consumption class
|
||||
* (2) CDR function present
|
||||
* [Note]: Bit description as below:
|
||||
* [SFP]
|
||||
* None
|
||||
*
|
||||
* [QSFP]
|
||||
* (1) Power consumption class:
|
||||
* Class 1: 1.5W (Bit6-7 = 00:)
|
||||
* Class 2: 2.0W (Bit6-7 = 01:)
|
||||
* Class 3: 2.5W (Bit6-7 = 10:)
|
||||
* Class 4: 3.5W (Bit6-7 = 11:)
|
||||
* Class 5: 4.0W (Bit0-1 = 01:)
|
||||
* Class 6: 4.5W (Bit0-1 = 10:)
|
||||
* Class 7: 5.0W (Bit0-1 = 11:)
|
||||
* (2) CDR function present:
|
||||
* Bit2: 0 = No CDR in RX
|
||||
* 1 = CDR present in RX
|
||||
* Bit3: 0 = No CDR in TX
|
||||
* 1 = CDR present in TX
|
||||
*/
|
||||
uint8_t ext_id;
|
||||
|
||||
/* [Prop]: br
|
||||
* [Desc]: Nominal bit rate, units of 100 MBits/sec.
|
||||
* [Note]: SFP:03h / QSFP:0Ch / QSPF+:0Dh
|
||||
* has val: 0x67
|
||||
* no val :
|
||||
*/
|
||||
uint8_t br;
|
||||
|
||||
/* [Prop]: extbr
|
||||
* [Desc]: Extended br (00h/222)
|
||||
* [Desc]: Nominal bit rate per channel, units of 250 Mbps.
|
||||
* Complements. Byte 140. See Table 32A.
|
||||
*/
|
||||
uint8_t extbr;
|
||||
|
||||
/* [Prop]: len_sm
|
||||
* [Desc]: Length (single mode)-(100's)m
|
||||
* [Note]: This value specifies the link length that is supported by the transceiver
|
||||
* while operating in compliance with the applicable standards using single mode
|
||||
* fiber. The value is in units of 100 meters. A value of 255 means that the
|
||||
* transceiver supports a link length greater than 25.4 km. A value of zero means
|
||||
* that the transceiver does not support single mode fiber or that the length
|
||||
* information must be determined from the transceiver technology.
|
||||
*/
|
||||
int len_sm;
|
||||
|
||||
/* [Prop]: len_smf
|
||||
* [Desc]: Length (single mode)-km
|
||||
* [Note]: Addition to EEPROM data from original GBIC definition. This value specifies
|
||||
* the link length that is supported by the transceiver while operating in
|
||||
* compliance with the applicable standards using single mode fiber. The value
|
||||
* is in units of kilometers. A value of 255 means that the transceiver supports
|
||||
* a link length greater than 254 km. A value of zero means that the transceiver
|
||||
* does not support single mode fiber or that the length information must be
|
||||
* determined from the transceiver technology.
|
||||
*/
|
||||
int len_smf;
|
||||
|
||||
/* [Prop]: len_om1
|
||||
* [Desc]: Link length supported for 62.5 um OM1 fiber, units of 10 m
|
||||
* [Note]: The value is in units of 10 meters. A value of 255 means that the
|
||||
* transceiver supports a link length greater than 2.54 km. A value of
|
||||
* zero means that the transceiver does not support 50 micron multi-mode
|
||||
* fiber or that the length information must be determined from the transceiver
|
||||
* technology.
|
||||
*/
|
||||
int len_om1;
|
||||
|
||||
/* [Prop]: len_om2
|
||||
* [Desc]: Link length supported for 50 um OM2 fiber, units of 10 m
|
||||
* [Note]: The value is in units of 10 meters. A value of 255 means that the
|
||||
* transceiver supports a link length greater than 2.54 km. A value of
|
||||
* zero means that the transceiver does not support 50 micron multi-mode
|
||||
* fiber or that the length information must be determined from the transceiver
|
||||
* technology.
|
||||
*/
|
||||
int len_om2;
|
||||
|
||||
/* [Prop]: len_om3
|
||||
* [Desc]: Length (50um, OM3)
|
||||
* [Note]: This value specifies link length that is supported by the transceiver while
|
||||
* operating in compliance with applicable standards using 50 micron multimode
|
||||
* OM3 [2000 MHz*km] fiber. The value is in units of 10 meters. A value of 255
|
||||
* means that the transceiver supports a link length greater than 2.54 km. A value
|
||||
* of zero means that the transceiver does not support 50 micron multimode fiber
|
||||
* or that the length information must be determined from the transceiver technology.
|
||||
*/
|
||||
int len_om3;
|
||||
|
||||
/* [Prop]: len_om4
|
||||
* [Desc]: Length (50um, OM4) and Length (Active Cable or Copper)
|
||||
* [Note]: For optical links, this value specifies link length that is supported by the
|
||||
* transceiver while operating in compliance with applicable standards using 50 micron
|
||||
* multimode OM4 [4700 MHz*km] fiber. The value is in units of 10 meters. A value of
|
||||
* 255 means that the transceiver supports a link length greater than 2.54 km. A value
|
||||
* of zero means that the transceiver does not support 50 micron multimode fiber or that
|
||||
* the length information must be determined from the transceiver codes specified in Table 5-3.
|
||||
*
|
||||
* For copper links, this value specifies minimum link length supported by the transceiver
|
||||
* while operating in compliance with applicable standards using copper cable. For active
|
||||
* cable, this value represents actual length. The value is in units of 1 meter. A value of 255
|
||||
* means the transceiver supports a link length greater than 254 meters. A value of zero means
|
||||
* the transceiver does not support copper or active cables or the length information must be
|
||||
* determined from transceiver technology. Further information about cable design, equalization,
|
||||
* and connectors is usually required to guarantee meeting a particular length requirement.
|
||||
*/
|
||||
int len_om4;
|
||||
|
||||
/* [Prop]: comp_rev
|
||||
* [Desc]: SFF spec revision compliance
|
||||
* [Note]: Indicates which revision of SFF SFF-8472 (SFP) / SFF-8636 (QSFP) the transceiver
|
||||
* complies with. (unsigned integer)
|
||||
*/
|
||||
uint8_t comp_rev;
|
||||
|
||||
/* [Prop]: CDR
|
||||
* [Desc]: For transceivers with CDR capability, setting the CDR to ON engages the internal
|
||||
* retiming function. Setting the CDR to OFF enables an internal bypassing mode ,which
|
||||
* directs traffic around the internal CDR. (Reference: SFF-8636)
|
||||
* [Note]: value=0xff: ON.
|
||||
* value=0x00: OFF.
|
||||
*/
|
||||
uint8_t cdr;
|
||||
|
||||
/* [Prop]: rate_id
|
||||
* [Desc]: Soft Rate Select 0(RX).
|
||||
* [Note]: 1. Addr: A0h / Offset: 13
|
||||
* 2. Value description:
|
||||
* 00h Unspecified
|
||||
* 01h SFF-8079 (4/2/1G Rate_Select & AS0/AS1)
|
||||
* 02h SFF-8431 (8/4/2G Rx Rate_Select only)
|
||||
* 03h Unspecified *
|
||||
* 04h SFF-8431 (8/4/2G Tx Rate_Select only)
|
||||
* 05h Unspecified *
|
||||
* 06h SFF-8431 (8/4/2G Independent Rx & Tx Rate_select)
|
||||
* 07h Unspecified *
|
||||
* 08h FC-PI-5 (16/8/4G Rx Rate_select only) High=16G only, Low=8G/4G
|
||||
* 09h Unspecified *
|
||||
* 0Ah FC-PI-5 (16/8/4G Independent Rx, Tx Rate_select) High=16G only,
|
||||
* Low=8G/4G
|
||||
* 0Bh Unspecified *
|
||||
* 0Ch FC-PI-6 (32/16/8G Independent Rx, Tx Rate_Select)
|
||||
* High=32G only, Low = 16G/8G
|
||||
* 0Dh Unspecified *
|
||||
* 0Eh 10/8G Rx and Tx Rate_Select controlling the operation or locking
|
||||
* modes of the internal signal conditioner, retimer or CDR, according
|
||||
* to the logic table defined in Table 10-2, High Bit Rate
|
||||
* (10G) =9.95-11.3 Gb/s; Low Bit Rate (8G) = 8.5 Gb/s. In this mode,
|
||||
* the default value of bit 110.3 (Soft Rate Select RS(0), Table 9-11)
|
||||
* and of bit 118.3 (Soft Rate Select RS(1), Table 10-1) is 1.
|
||||
* 0Fh Unspecified *
|
||||
* 10h-FFh Unallocated
|
||||
*/
|
||||
int rate_id;
|
||||
|
||||
/* [Prop]: soft_rs0
|
||||
* [Desc]: Soft Rate Select 0(RX).
|
||||
* [Note]: 1. Writing '1' selects full bandwidth operation.
|
||||
* 2. This bit is "OR'd with the hard Rate_Select, AS(0) or RS(0) pin value.
|
||||
* 3. Default at power up is logic zero/low
|
||||
* 4. Addr: A2h / Offset: 110 / Bit: 3
|
||||
*/
|
||||
uint8_t soft_rs0;
|
||||
|
||||
/* [Prop]: soft_rs1
|
||||
* [Desc]: Soft Rate Select 1(TX).
|
||||
* [Note]: 1. Writing '1' selects full bandwidth TX operation.
|
||||
* 2. This bit is "OR'd with the hard Rate_Select, AS(1) or RS(1) pin value.
|
||||
* 3. Default at power up is logic zero/low
|
||||
* 4. Addr: A2h / Offset: 118 / Bit: 3
|
||||
*/
|
||||
uint8_t soft_rs1;
|
||||
|
||||
/* [Prop]: diag_type
|
||||
* [Desc]: DIAGNOSTIC MONITORING TYPE (A0h/92)
|
||||
* [Note]: Description in SFF-8472 as below:
|
||||
* Bit7: Reserved for legacy diagnostic implementations. Must be '0' for compliance
|
||||
* with this document.
|
||||
* Bit6: Digital diagnostic monitoring implemented (described in this document).
|
||||
* Must be '1' for compliance with this document.
|
||||
* Bit5 Internally calibrated
|
||||
* Bit4 Externally calibrated
|
||||
* Bit3 Received power measurement type.0 = OMA, 1 = average power
|
||||
* Bit2 Address change required see section above, "addressing modes"
|
||||
* Bit1-0 Unallocated
|
||||
*/
|
||||
uint8_t diag_type;
|
||||
|
||||
/* [Prop]: curr_temp
|
||||
* [Desc]: Transceiver Current Temperature (A2h/96-97)
|
||||
* [Note]: 1. Dependent on diag_type.
|
||||
* 2. 96: High byte
|
||||
* 3. 97: Low byte
|
||||
* 4. This feature only for SFP
|
||||
*/
|
||||
uint8_t curr_temp[2];
|
||||
|
||||
/* [Prop]: curr_vol
|
||||
* [Desc]: Transceiver Current Voltage (SFP:A2h/108-109; QSFP:00h/22-23)
|
||||
* [Note]: 1. Dependent on diag_type.
|
||||
* 2. 98: High byte
|
||||
* 3. 99: Low byte
|
||||
* 4. This feature only for SFP
|
||||
* 5. Internally measured transceiver supply voltage. Represented
|
||||
* as a 16 bit unsigned integer with the voltage defined as the
|
||||
* full 16 bit value (0-65535) with LSB equal to 100 uVolt,
|
||||
* yielding a total range of 0 to +6.55 Volts
|
||||
*/
|
||||
uint8_t curr_voltage[2];
|
||||
|
||||
/* [Prop]: curr_tx_bias
|
||||
* [Desc]: Transceiver TX Bias Current (SFP:A2h/100-101; QSFP:00h/26-27)
|
||||
* [Note]: 1. Dependent on diag_type.
|
||||
* 2. 100: High byte
|
||||
* 3. 101: Low byte
|
||||
* 4. This feature only for SFP
|
||||
* 5. Measured TX bias current in uA. Represented as a 16 bit unsigned
|
||||
* integer with the current defined as the full 16 bit value (0-65535)
|
||||
* with LSB equal to 2 uA, yielding a total range of 0 to 131 mA.
|
||||
* Accuracy is vendor specific but must be better than 10% of the
|
||||
* manufacturer's nominal value over specified operating temperature
|
||||
* and voltage.
|
||||
*/
|
||||
uint8_t curr_tx_bias[8];
|
||||
|
||||
/* [Prop]: curr_tx_power
|
||||
* [Desc]: Transceiver TX Output Power (A2h/102-103)
|
||||
* [Note]: 1. Dependent on diag_type.
|
||||
* 2. 102: High byte
|
||||
* 3. 103: Low byte
|
||||
* 4. This feature only for SFP
|
||||
* 5. Measured TX output power in mW. Represented as a 16 bit unsigned
|
||||
* integer with the power defined as the full 16 bit value (0-65535)
|
||||
* with LSB equal to 0.1 uW, yielding a total range of 0 to 6.5535 mW
|
||||
* (~ -40 to +8.2 dBm). Data is assumed to be based on measurement of
|
||||
* laser monitor photodiode current. It is factory calibrated to absolute
|
||||
* units using the most representative fiber output type. Accuracy is
|
||||
* vendor specific but must be better than 3dB over specified temperature
|
||||
* and voltage. Data is not valid when the transmitter is disabled.
|
||||
*/
|
||||
uint8_t curr_tx_power[8];
|
||||
|
||||
/* [Prop]: curr_tx_power
|
||||
* [Desc]: Transceiver TX Output Power (A2h/102-103)
|
||||
* [Note]: 1. Dependent on diag_type.
|
||||
* 2. 102: High byte
|
||||
* 3. 103: Low byte
|
||||
* 4. This feature only for SFP
|
||||
* 5. Measured RX received optical power in mW. Value can represent either
|
||||
* average received power or OMA depending upon how bit 3 of byte 92 (A0h)
|
||||
* is set. Represented as a 16 bit unsigned integer with the power defined
|
||||
* as the full 16 bit value (0-65535) with LSB equal to 0.1 uW, yielding a
|
||||
* total range of 0 to 6.5535 mW (~ -40 to +8.2 dBm). Absolute accuracy is
|
||||
* dependent upon the exact optical wavelength. For the vendor specified
|
||||
* wavelength, accuracy shall be better than 3dB over specified temperature
|
||||
* and voltage.
|
||||
*/
|
||||
uint8_t curr_rx_power[8];
|
||||
|
||||
/* [Prop]: wavelength
|
||||
* [Desc]: Wavelength or Copper Cable Attenuation
|
||||
* [Note]: (Following is info from SFF-8636)
|
||||
* For optical free side devices, this parameter identifies the nominal
|
||||
* transmitter output wavelength at room temperature. This parameter is a
|
||||
* 16-bit hex value with Byte 186 as high order byte and Byte 187 as low
|
||||
* order byte. The laser wavelength is equal to the 16-bit integer value
|
||||
* divided by 20 in nm (units of 0.05 nm). This resolution should be adequate
|
||||
* to cover all relevant wavelengths yet provide enough resolution for all
|
||||
* expected DWDM applications. For accurate representation of controlled
|
||||
* wavelength applications, this value should represent the center of the
|
||||
* guaranteed wavelength range. If the free side device is identified as
|
||||
* copper cable these registers will be used to define the cable attenuation.
|
||||
* An indication of 0 dB attenuation refers to the case where the attenuation
|
||||
* is not known or is unavailable.
|
||||
* Byte 186 (00-FFh) is the copper cable attenuation at 2.5 GHz in units of 1 dB.
|
||||
* Byte 187 (00-FFh) is the copper cable attenuation at 5.0 GHz in units of 1 dB.
|
||||
*/
|
||||
uint8_t wavelength[2];
|
||||
|
||||
/* [Prop]: Amplitude control
|
||||
* [Desc]: Amplitude control
|
||||
* [Note]: QSFP28 => SFF-8636 03H Byte-238/239
|
||||
*/
|
||||
uint8_t rx_am[2];
|
||||
|
||||
/* [Prop]: Emphasis control
|
||||
* [Desc]: Emphasis control
|
||||
* [Note]: SFP+/28 => SFF-8472 A2H Byte-115
|
||||
* QSFP28 => SFF-8636 03H Byte-236/237
|
||||
*/
|
||||
uint8_t rx_em[2];
|
||||
|
||||
/* [Prop]: Soft Rx LOS
|
||||
* [Desc]: Soft Rx LOS which provide by transceiver
|
||||
* [Note]: (Following is info from SFF-8636)
|
||||
* Byte 3:
|
||||
* - Bit 0: L-Rx1 LOS
|
||||
* - Bit 1: L-Rx2 LOS
|
||||
* - Bit 2: L-Rx3 LOS
|
||||
* - Bit 3: L-Rx4 LOS
|
||||
*/
|
||||
uint8_t rx_los;
|
||||
|
||||
/* [Prop]: Soft Tx Disable
|
||||
* [Desc]: Soft Tx Disable which provide by transceiver
|
||||
* [Note]: (Following is info from SFF-8636)
|
||||
* Byte 86:
|
||||
* - Bit 0: Tx1 Disable
|
||||
* - Bit 1: Tx2 Disable
|
||||
* - Bit 2: Tx3 Disable
|
||||
* - Bit 3: Tx4 Disable
|
||||
*/
|
||||
uint8_t tx_disable;
|
||||
|
||||
/* [Prop]: Soft Tx Fault
|
||||
* [Desc]: Soft Tx Fault which provide by transceiver
|
||||
* [Note]: (Following is info from SFF-8636)
|
||||
* Byte 86:
|
||||
* - Bit 0: Tx1 Fault
|
||||
* - Bit 1: Tx2 Fault
|
||||
* - Bit 2: Tx3 Fault
|
||||
* - Bit 3: Tx4 Fault
|
||||
*/
|
||||
uint8_t tx_fault;
|
||||
|
||||
/* [Prop]: Transceiver EQUALIZATION
|
||||
* [Desc]: Transceiver EQUALIZATION
|
||||
* [Note]: SFP+/28 => SFF-8472 A2H Byte-114
|
||||
* QSFP28 => SFF-8636 03H Byte-234/235
|
||||
*/
|
||||
uint8_t tx_eq[2];
|
||||
|
||||
/* [Prop]: OPTION VALUES
|
||||
* [Desc]: The bits in the option field shall specify the options implemented in the transceiver.
|
||||
* [Note]: SFP+/28 => SFF-8472 A0H Byte-64/65
|
||||
* QSFP+/28 => SFF-8636 00H Byte-193/195
|
||||
*/
|
||||
uint8_t option[3];
|
||||
|
||||
/* [Prop]: External PHY offset
|
||||
* [Desc]: It needs to be setup first if you want to access transceiver external phy.
|
||||
* [Note]: This feature dependent on transceiver.
|
||||
* Currently, only 1G-RJ45 transceiver supported it.
|
||||
*/
|
||||
uint8_t extphy_offset;
|
||||
|
||||
/* ========== Object private property ==========
|
||||
*/
|
||||
struct device *transvr_dev_p;
|
||||
struct eeprom_map_s *eeprom_map_p;
|
||||
struct i2c_client *i2c_client_p;
|
||||
struct ioexp_obj_s *ioexp_obj_p;
|
||||
struct transvr_worker_s *worker_p;
|
||||
struct mutex lock;
|
||||
char swp_name[32];
|
||||
int auto_config;
|
||||
int auto_tx_disable;
|
||||
int chan_id;
|
||||
int chipset_type;
|
||||
int curr_page;
|
||||
int info;
|
||||
int ioexp_virt_offset;
|
||||
int lane_id[8];
|
||||
int layout;
|
||||
int mode;
|
||||
int retry;
|
||||
int state;
|
||||
int temp;
|
||||
int type;
|
||||
|
||||
/* ========== Object public functions ==========
|
||||
*/
|
||||
int (*get_id)(struct transvr_obj_s *self);
|
||||
int (*get_ext_id)(struct transvr_obj_s *self);
|
||||
int (*get_connector)(struct transvr_obj_s *self);
|
||||
int (*get_vendor_name)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_vendor_pn)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_vendor_rev)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_vendor_sn)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_power_cls)(struct transvr_obj_s *self);
|
||||
int (*get_br)(struct transvr_obj_s *self);
|
||||
int (*get_len_sm)(struct transvr_obj_s *self);
|
||||
int (*get_len_smf)(struct transvr_obj_s *self);
|
||||
int (*get_len_om1)(struct transvr_obj_s *self);
|
||||
int (*get_len_om2)(struct transvr_obj_s *self);
|
||||
int (*get_len_om3)(struct transvr_obj_s *self);
|
||||
int (*get_len_om4)(struct transvr_obj_s *self);
|
||||
int (*get_comp_rev)(struct transvr_obj_s *self);
|
||||
int (*get_comp_eth_1)(struct transvr_obj_s *self);
|
||||
int (*get_comp_eth_10)(struct transvr_obj_s *self);
|
||||
int (*get_comp_eth_10_40)(struct transvr_obj_s *self);
|
||||
int (*get_comp_extend)(struct transvr_obj_s *self);
|
||||
int (*get_cdr)(struct transvr_obj_s *self);
|
||||
int (*get_rate_id)(struct transvr_obj_s *self);
|
||||
int (*get_soft_rs0)(struct transvr_obj_s *self);
|
||||
int (*get_soft_rs1)(struct transvr_obj_s *self);
|
||||
int (*get_info)(struct transvr_obj_s *self);
|
||||
int (*get_if_type)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_if_speed)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_if_lane)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_curr_temp)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_curr_vol)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_soft_rx_los)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_soft_tx_disable)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_soft_tx_fault)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_auto_tx_disable)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_tx_bias)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_tx_power)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_rx_power)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_tx_eq)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_rx_am)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_rx_em)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_wavelength)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_extphy_offset)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*get_extphy_reg)(struct transvr_obj_s *self, char *buf_p);
|
||||
int (*set_cdr)(struct transvr_obj_s *self, int input_val);
|
||||
int (*set_soft_rs0)(struct transvr_obj_s *self, int input_val);
|
||||
int (*set_soft_rs1)(struct transvr_obj_s *self, int input_val);
|
||||
int (*set_soft_tx_disable)(struct transvr_obj_s *self, int input_val);
|
||||
int (*set_auto_tx_disable)(struct transvr_obj_s *self, int input_val);
|
||||
int (*set_tx_eq)(struct transvr_obj_s *self, int input_val);
|
||||
int (*set_rx_am)(struct transvr_obj_s *self, int input_val);
|
||||
int (*set_rx_em)(struct transvr_obj_s *self, int input_val);
|
||||
int (*set_extphy_offset)(struct transvr_obj_s *self, int input_val);
|
||||
int (*set_extphy_reg)(struct transvr_obj_s *self, int input_val);
|
||||
|
||||
/* ========== Object private functions ==========
|
||||
*/
|
||||
int (*init)(struct transvr_obj_s *self);
|
||||
int (*clean)(struct transvr_obj_s *self);
|
||||
int (*check)(struct transvr_obj_s *self);
|
||||
int (*update_all)(struct transvr_obj_s *self, int show_err);
|
||||
int (*fsm_4_direct)(struct transvr_obj_s* self, char *caller_name);
|
||||
int (*fsm_4_polling)(struct transvr_obj_s* self, char *caller_name);
|
||||
int (*send_uevent)(struct transvr_obj_s* self, enum kobject_action u_action);
|
||||
int (*dump_all)(struct transvr_obj_s* self);
|
||||
};
|
||||
|
||||
|
||||
/* For AVL Mapping */
|
||||
struct transvr_avl_s {
|
||||
char vendor_name[32];
|
||||
char vendor_pn[32];
|
||||
int (*init)(struct transvr_obj_s *self);
|
||||
};
|
||||
|
||||
|
||||
/* Worker for long term task of transceiver */
|
||||
struct transvr_worker_s {
|
||||
/* Task Parameter */
|
||||
struct transvr_obj_s *transvr_p;
|
||||
struct transvr_worker_s *next_p;
|
||||
struct transvr_worker_s *pre_p;
|
||||
unsigned long trigger_time;
|
||||
char func_name[64];
|
||||
int retry;
|
||||
int state;
|
||||
|
||||
/* Task private data */
|
||||
void *p_data;
|
||||
|
||||
/* Call back function */
|
||||
int (*main_task)(struct transvr_worker_s *task);
|
||||
int (*post_task)(struct transvr_worker_s *task);
|
||||
};
|
||||
|
||||
|
||||
struct transvr_obj_s *
|
||||
create_transvr_obj(char *swp_name,
|
||||
int chan_id,
|
||||
struct ioexp_obj_s *ioexp_obj_p,
|
||||
int ioexp_virt_offset,
|
||||
int transvr_type,
|
||||
int chipset_type,
|
||||
int run_mode);
|
||||
|
||||
void lock_transvr_obj(struct transvr_obj_s *self);
|
||||
void unlock_transvr_obj(struct transvr_obj_s *self);
|
||||
int isolate_transvr_obj(struct transvr_obj_s *self);
|
||||
|
||||
int resync_channel_tier_2(struct transvr_obj_s *self);
|
||||
|
||||
void alarm_msg_2_user(struct transvr_obj_s *self, char *emsg);
|
||||
|
||||
#endif /* TRANSCEIVER_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -0,0 +1 @@
|
||||
!include $ONL_TEMPLATES/onlp-platform-any.yml PLATFORM=x86-64-inventec-d6556 ARCH=amd64 TOOLCHAIN=x86_64-linux-gnu
|
||||
@@ -0,0 +1,2 @@
|
||||
FILTER=src
|
||||
include $(ONL)/make/subdirs.mk
|
||||
@@ -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-inventec-d6556
|
||||
include $(BUILDER)/standardinit.mk
|
||||
|
||||
DEPENDMODULES := AIM IOF x86_64_inventec_d6556 onlplib
|
||||
DEPENDMODULE_HEADERS := sff
|
||||
|
||||
include $(BUILDER)/dependmodules.mk
|
||||
|
||||
SHAREDLIB := libonlp-x86-64-inventec-d6556.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
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Inclusive Makefile for the libonlp-x86-64-inventec-d6556 module.
|
||||
#
|
||||
# Autogenerated 2018-11-30 07:22:16.900798
|
||||
#
|
||||
###############################################################################
|
||||
libonlp-x86-64-inventec-d6556_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
@@ -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_inventec_d6556 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
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Inclusive Makefile for the onlpdump module.
|
||||
#
|
||||
# Autogenerated 2018-11-30 07:22:10.961262
|
||||
#
|
||||
###############################################################################
|
||||
onlpdump_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
name: x86_64_inventec_d6556
|
||||
@@ -0,0 +1,9 @@
|
||||
###############################################################################
|
||||
#
|
||||
#
|
||||
#
|
||||
###############################################################################
|
||||
include ../../init.mk
|
||||
MODULE := x86_64_inventec_d6556
|
||||
AUTOMODULE := x86_64_inventec_d6556
|
||||
include $(BUILDER)/definemodule.mk
|
||||
@@ -0,0 +1,9 @@
|
||||
###############################################################################
|
||||
#
|
||||
# x86_64_inventec_d6556 Autogeneration
|
||||
#
|
||||
###############################################################################
|
||||
x86_64_inventec_d6556_AUTO_DEFS := module/auto/x86_64_inventec_d6556.yml
|
||||
x86_64_inventec_d6556_AUTO_DIRS := module/inc/x86_64_inventec_d6556 module/src
|
||||
include $(BUILDER)/auto.mk
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
###############################################################################
|
||||
#
|
||||
# x86_64_inventec_d6556 Autogeneration Definitions.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
cdefs: &cdefs
|
||||
- x86_64_inventec_d6556_CONFIG_INCLUDE_LOGGING:
|
||||
doc: "Include or exclude logging."
|
||||
default: 1
|
||||
- x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT:
|
||||
doc: "Default enabled log options."
|
||||
default: AIM_LOG_OPTIONS_DEFAULT
|
||||
- x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT:
|
||||
doc: "Default enabled log bits."
|
||||
default: AIM_LOG_BITS_DEFAULT
|
||||
- x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT:
|
||||
doc: "Default enabled custom log bits."
|
||||
default: 0
|
||||
- x86_64_inventec_d6556_CONFIG_PORTING_STDLIB:
|
||||
doc: "Default all porting macros to use the C standard libraries."
|
||||
default: 1
|
||||
- x86_64_inventec_d6556_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS:
|
||||
doc: "Include standard library headers for stdlib porting macros."
|
||||
default: x86_64_inventec_d6556_CONFIG_PORTING_STDLIB
|
||||
- x86_64_inventec_d6556_CONFIG_INCLUDE_UCLI:
|
||||
doc: "Include generic uCli support."
|
||||
default: 0
|
||||
- x86_64_inventec_d6556_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION:
|
||||
doc: "Assume chassis fan direction is the same as the PSU fan direction."
|
||||
default: 0
|
||||
|
||||
|
||||
definitions:
|
||||
cdefs:
|
||||
x86_64_inventec_d6556_CONFIG_HEADER:
|
||||
defs: *cdefs
|
||||
basename: x86_64_inventec_d6556_config
|
||||
|
||||
portingmacro:
|
||||
x86_64_inventec_d6556:
|
||||
macros:
|
||||
- malloc
|
||||
- free
|
||||
- memset
|
||||
- memcpy
|
||||
- strncpy
|
||||
- vsnprintf
|
||||
- snprintf
|
||||
- strlen
|
||||
@@ -0,0 +1,14 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_inventec_d6556/x86_64_inventec_d6556_config.h>
|
||||
|
||||
/* <--auto.start.xmacro(ALL).define> */
|
||||
/* <auto.end.xmacro(ALL).define> */
|
||||
|
||||
/* <--auto.start.xenum(ALL).define> */
|
||||
/* <auto.end.xenum(ALL).define> */
|
||||
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
* @file
|
||||
* @brief x86_64_inventec_d6556 Configuration Header
|
||||
*
|
||||
* @addtogroup x86_64_inventec_d6556-config
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef __x86_64_inventec_d6556_CONFIG_H__
|
||||
#define __x86_64_inventec_d6556_CONFIG_H__
|
||||
|
||||
#ifdef GLOBAL_INCLUDE_CUSTOM_CONFIG
|
||||
#include <global_custom_config.h>
|
||||
#endif
|
||||
#ifdef x86_64_inventec_d6556_INCLUDE_CUSTOM_CONFIG
|
||||
#include <x86_64_inventec_d6556_custom_config.h>
|
||||
#endif
|
||||
|
||||
/* <auto.start.cdefs(x86_64_inventec_d6556_CONFIG_HEADER).header> */
|
||||
#include <AIM/aim.h>
|
||||
/**
|
||||
* x86_64_inventec_d6556_CONFIG_INCLUDE_LOGGING
|
||||
*
|
||||
* Include or exclude logging. */
|
||||
|
||||
|
||||
#ifndef x86_64_inventec_d6556_CONFIG_INCLUDE_LOGGING
|
||||
#define x86_64_inventec_d6556_CONFIG_INCLUDE_LOGGING 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT
|
||||
*
|
||||
* Default enabled log options. */
|
||||
|
||||
|
||||
#ifndef x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT
|
||||
#define x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT AIM_LOG_OPTIONS_DEFAULT
|
||||
#endif
|
||||
|
||||
/**
|
||||
* x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT
|
||||
*
|
||||
* Default enabled log bits. */
|
||||
|
||||
|
||||
#ifndef x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT
|
||||
#define x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT AIM_LOG_BITS_DEFAULT
|
||||
#endif
|
||||
|
||||
/**
|
||||
* x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT
|
||||
*
|
||||
* Default enabled custom log bits. */
|
||||
|
||||
|
||||
#ifndef x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT
|
||||
#define x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* x86_64_inventec_d6556_CONFIG_PORTING_STDLIB
|
||||
*
|
||||
* Default all porting macros to use the C standard libraries. */
|
||||
|
||||
|
||||
#ifndef x86_64_inventec_d6556_CONFIG_PORTING_STDLIB
|
||||
#define x86_64_inventec_d6556_CONFIG_PORTING_STDLIB 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* x86_64_inventec_d6556_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS
|
||||
*
|
||||
* Include standard library headers for stdlib porting macros. */
|
||||
|
||||
|
||||
#ifndef x86_64_inventec_d6556_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS
|
||||
#define x86_64_inventec_d6556_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS x86_64_inventec_d6556_CONFIG_PORTING_STDLIB
|
||||
#endif
|
||||
|
||||
/**
|
||||
* x86_64_inventec_d6556_CONFIG_INCLUDE_UCLI
|
||||
*
|
||||
* Include generic uCli support. */
|
||||
|
||||
|
||||
#ifndef x86_64_inventec_d6556_CONFIG_INCLUDE_UCLI
|
||||
#define x86_64_inventec_d6556_CONFIG_INCLUDE_UCLI 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* x86_64_inventec_d6556_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION
|
||||
*
|
||||
* Assume chassis fan direction is the same as the PSU fan direction. */
|
||||
|
||||
|
||||
#ifndef x86_64_inventec_d6556_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION
|
||||
#define x86_64_inventec_d6556_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION 0
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* All compile time options can be queried or displayed
|
||||
*/
|
||||
|
||||
/** Configuration settings structure. */
|
||||
typedef struct x86_64_inventec_d6556_config_settings_s {
|
||||
/** name */
|
||||
const char* name;
|
||||
/** value */
|
||||
const char* value;
|
||||
} x86_64_inventec_d6556_config_settings_t;
|
||||
|
||||
/** Configuration settings table. */
|
||||
/** x86_64_inventec_d6556_config_settings table. */
|
||||
extern x86_64_inventec_d6556_config_settings_t x86_64_inventec_d6556_config_settings[];
|
||||
|
||||
/**
|
||||
* @brief Lookup a configuration setting.
|
||||
* @param setting The name of the configuration option to lookup.
|
||||
*/
|
||||
const char* x86_64_inventec_d6556_config_lookup(const char* setting);
|
||||
|
||||
/**
|
||||
* @brief Show the compile-time configuration.
|
||||
* @param pvs The output stream.
|
||||
*/
|
||||
int x86_64_inventec_d6556_config_show(struct aim_pvs_s* pvs);
|
||||
|
||||
/* <auto.end.cdefs(x86_64_inventec_d6556_CONFIG_HEADER).header> */
|
||||
|
||||
#include "x86_64_inventec_d6556_porting.h"
|
||||
|
||||
#endif /* __x86_64_inventec_d6556_CONFIG_H__ */
|
||||
/* @} */
|
||||
@@ -0,0 +1,26 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
* x86_64_inventec_d6556 Doxygen Header
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef __x86_64_inventec_d6556_DOX_H__
|
||||
#define __x86_64_inventec_d6556_DOX_H__
|
||||
|
||||
/**
|
||||
* @defgroup x86_64_inventec_d6556 x86_64_inventec_d6556 - x86_64_inventec_d6556 Description
|
||||
*
|
||||
|
||||
The documentation overview for this module should go here.
|
||||
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @defgroup x86_64_inventec_d6556-x86_64_inventec_d6556 Public Interface
|
||||
* @defgroup x86_64_inventec_d6556-config Compile Time Configuration
|
||||
* @defgroup x86_64_inventec_d6556-porting Porting Macros
|
||||
*
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#endif /* __x86_64_inventec_d6556_DOX_H__ */
|
||||
@@ -0,0 +1,107 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
* @file
|
||||
* @brief x86_64_inventec_d6556 Porting Macros.
|
||||
*
|
||||
* @addtogroup x86_64_inventec_d6556-porting
|
||||
* @{
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef __x86_64_inventec_d6556_PORTING_H__
|
||||
#define __x86_64_inventec_d6556_PORTING_H__
|
||||
|
||||
|
||||
/* <auto.start.portingmacro(ALL).define> */
|
||||
#if x86_64_inventec_d6556_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_inventec_d6556_MALLOC
|
||||
#if defined(GLOBAL_MALLOC)
|
||||
#define x86_64_inventec_d6556_MALLOC GLOBAL_MALLOC
|
||||
#elif x86_64_inventec_d6556_CONFIG_PORTING_STDLIB == 1
|
||||
#define x86_64_inventec_d6556_MALLOC malloc
|
||||
#else
|
||||
#error The macro x86_64_inventec_d6556_MALLOC is required but cannot be defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef x86_64_inventec_d6556_FREE
|
||||
#if defined(GLOBAL_FREE)
|
||||
#define x86_64_inventec_d6556_FREE GLOBAL_FREE
|
||||
#elif x86_64_inventec_d6556_CONFIG_PORTING_STDLIB == 1
|
||||
#define x86_64_inventec_d6556_FREE free
|
||||
#else
|
||||
#error The macro x86_64_inventec_d6556_FREE is required but cannot be defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef x86_64_inventec_d6556_MEMSET
|
||||
#if defined(GLOBAL_MEMSET)
|
||||
#define x86_64_inventec_d6556_MEMSET GLOBAL_MEMSET
|
||||
#elif x86_64_inventec_d6556_CONFIG_PORTING_STDLIB == 1
|
||||
#define x86_64_inventec_d6556_MEMSET memset
|
||||
#else
|
||||
#error The macro x86_64_inventec_d6556_MEMSET is required but cannot be defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef x86_64_inventec_d6556_MEMCPY
|
||||
#if defined(GLOBAL_MEMCPY)
|
||||
#define x86_64_inventec_d6556_MEMCPY GLOBAL_MEMCPY
|
||||
#elif x86_64_inventec_d6556_CONFIG_PORTING_STDLIB == 1
|
||||
#define x86_64_inventec_d6556_MEMCPY memcpy
|
||||
#else
|
||||
#error The macro x86_64_inventec_d6556_MEMCPY is required but cannot be defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef x86_64_inventec_d6556_STRNCPY
|
||||
#if defined(GLOBAL_STRNCPY)
|
||||
#define x86_64_inventec_d6556_STRNCPY GLOBAL_STRNCPY
|
||||
#elif x86_64_inventec_d6556_CONFIG_PORTING_STDLIB == 1
|
||||
#define x86_64_inventec_d6556_STRNCPY strncpy
|
||||
#else
|
||||
#error The macro x86_64_inventec_d6556_STRNCPY is required but cannot be defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef x86_64_inventec_d6556_VSNPRINTF
|
||||
#if defined(GLOBAL_VSNPRINTF)
|
||||
#define x86_64_inventec_d6556_VSNPRINTF GLOBAL_VSNPRINTF
|
||||
#elif x86_64_inventec_d6556_CONFIG_PORTING_STDLIB == 1
|
||||
#define x86_64_inventec_d6556_VSNPRINTF vsnprintf
|
||||
#else
|
||||
#error The macro x86_64_inventec_d6556_VSNPRINTF is required but cannot be defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef x86_64_inventec_d6556_SNPRINTF
|
||||
#if defined(GLOBAL_SNPRINTF)
|
||||
#define x86_64_inventec_d6556_SNPRINTF GLOBAL_SNPRINTF
|
||||
#elif x86_64_inventec_d6556_CONFIG_PORTING_STDLIB == 1
|
||||
#define x86_64_inventec_d6556_SNPRINTF snprintf
|
||||
#else
|
||||
#error The macro x86_64_inventec_d6556_SNPRINTF is required but cannot be defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef x86_64_inventec_d6556_STRLEN
|
||||
#if defined(GLOBAL_STRLEN)
|
||||
#define x86_64_inventec_d6556_STRLEN GLOBAL_STRLEN
|
||||
#elif x86_64_inventec_d6556_CONFIG_PORTING_STDLIB == 1
|
||||
#define x86_64_inventec_d6556_STRLEN strlen
|
||||
#else
|
||||
#error The macro x86_64_inventec_d6556_STRLEN is required but cannot be defined.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* <auto.end.portingmacro(ALL).define> */
|
||||
|
||||
|
||||
#endif /* __x86_64_inventec_d6556_PORTING_H__ */
|
||||
/* @} */
|
||||
@@ -0,0 +1,10 @@
|
||||
###############################################################################
|
||||
#
|
||||
#
|
||||
#
|
||||
###############################################################################
|
||||
THIS_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
x86_64_inventec_d6556_INCLUDES := -I $(THIS_DIR)inc
|
||||
x86_64_inventec_d6556_INTERNAL_INCLUDES := -I $(THIS_DIR)src
|
||||
x86_64_inventec_d6556_DEPENDMODULE_ENTRIES := init:x86_64_inventec_d6556 ucli:x86_64_inventec_d6556
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
###############################################################################
|
||||
#
|
||||
# Local source generation targets.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
ucli:
|
||||
@../../../../tools/uclihandlers.py x86_64_inventec_d6556_ucli.c
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "x86_64_inventec_d6556_int.h"
|
||||
|
||||
#if x86_64_inventec_d6556_CONFIG_INCLUDE_DEBUG == 1
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
static char help__[] =
|
||||
"Usage: debug [options]\n"
|
||||
" -c CPLD Versions\n"
|
||||
" -h Help\n"
|
||||
;
|
||||
|
||||
int
|
||||
x86_64_inventec_d6556_debug_main(int argc, char* argv[])
|
||||
{
|
||||
int c = 0;
|
||||
int help = 0;
|
||||
int rv = 0;
|
||||
|
||||
while( (c = getopt(argc, argv, "ch")) != -1) {
|
||||
switch(c)
|
||||
{
|
||||
case 'c': c = 1; break;
|
||||
case 'h': help = 1; rv = 0; break;
|
||||
default: help = 1; rv = 1; break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(help || argc == 1) {
|
||||
printf("%s", help__);
|
||||
return rv;
|
||||
}
|
||||
|
||||
if(c) {
|
||||
printf("Not implemented.\n");
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
/************************************************************
|
||||
* fani.c
|
||||
*
|
||||
* Copyright 2018 Inventec Technology Corporation.
|
||||
*
|
||||
************************************************************
|
||||
*
|
||||
* Fan Platform Implementation Defaults.
|
||||
*
|
||||
***********************************************************/
|
||||
#include <stdlib.h>
|
||||
#include <onlplib/file.h>
|
||||
#include <onlp/platformi/fani.h>
|
||||
#include <onlplib/mmap.h>
|
||||
#include <fcntl.h>
|
||||
#include "platform_lib.h"
|
||||
|
||||
#define FAN_GPI_ON_MAIN_BOARD INV_PSOC_PREFIX"/fan_gpi"
|
||||
|
||||
#define MAX_FAN_SPEED 18000
|
||||
#define MAX_PSU_FAN_SPEED 25500
|
||||
|
||||
#define PROJECT_NAME
|
||||
#define LEN_FILE_NAME 80
|
||||
|
||||
static char* devfiles__[FAN_MAX] = /* must map with onlp_thermal_id */
|
||||
{
|
||||
"reserved",
|
||||
INV_PSOC_PREFIX"/fan1_input",
|
||||
INV_PSOC_PREFIX"/fan2_input",
|
||||
INV_PSOC_PREFIX"/fan3_input",
|
||||
INV_PSOC_PREFIX"/fan4_input",
|
||||
INV_PSOC_PREFIX"/fan5_input",
|
||||
INV_PSOC_PREFIX"/fan6_input",
|
||||
INV_PSOC_PREFIX"/fan7_input",
|
||||
INV_PSOC_PREFIX"/fan8_input",
|
||||
INV_PSOC_PREFIX"/rpm_psu1",
|
||||
INV_PSOC_PREFIX"/rpm_psu2",
|
||||
};
|
||||
|
||||
#define MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(id) \
|
||||
{ \
|
||||
{ ONLP_FAN_ID_CREATE(FAN_##id##_ON_MAIN_BOARD), "Chassis Fan "#id, 0 }, \
|
||||
0x0, \
|
||||
(ONLP_FAN_CAPS_F2B | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \
|
||||
0, \
|
||||
0, \
|
||||
ONLP_FAN_MODE_INVALID, \
|
||||
}
|
||||
|
||||
#define MAKE_FAN_INFO_NODE_ON_PSU(psu_id, fan_id) \
|
||||
{ \
|
||||
{ ONLP_FAN_ID_CREATE(FAN_##fan_id##_ON_PSU##psu_id), "Chassis PSU-"#psu_id " Fan "#fan_id, 0 }, \
|
||||
0x0, \
|
||||
(ONLP_FAN_CAPS_F2B | ONLP_FAN_CAPS_GET_RPM | ONLP_FAN_CAPS_GET_PERCENTAGE), \
|
||||
0, \
|
||||
0, \
|
||||
ONLP_FAN_MODE_INVALID, \
|
||||
}
|
||||
|
||||
/* Static fan information */
|
||||
onlp_fan_info_t linfo[FAN_MAX] = {
|
||||
{ }, /* Not used */
|
||||
MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(1),
|
||||
MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(2),
|
||||
MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(3),
|
||||
MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(4),
|
||||
MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(5),
|
||||
MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(6),
|
||||
MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(7),
|
||||
MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(8),
|
||||
MAKE_FAN_INFO_NODE_ON_PSU(1,1),
|
||||
MAKE_FAN_INFO_NODE_ON_PSU(2,1),
|
||||
};
|
||||
|
||||
#define VALIDATE(_id) \
|
||||
do { \
|
||||
if(!ONLP_OID_IS_FAN(_id)) { \
|
||||
return ONLP_STATUS_E_INVALID; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static int
|
||||
_onlp_fani_info_get_fan(int fid, onlp_fan_info_t* info)
|
||||
{
|
||||
int value, ret;
|
||||
char vstr[32], *vstrp = vstr, **vp = &vstrp;
|
||||
|
||||
memset(vstr, 0, 32);
|
||||
/* get fan present status */
|
||||
ret = onlp_file_read_str(vp, FAN_GPI_ON_MAIN_BOARD);
|
||||
if (ret < 0) {
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
sscanf(*vp, "%x", &value);
|
||||
if (value & (1 << (fid-1))) {
|
||||
info->status |= ONLP_FAN_STATUS_FAILED;
|
||||
}
|
||||
else {
|
||||
info->status |= ONLP_FAN_STATUS_PRESENT;
|
||||
info->status |= ONLP_FAN_STATUS_F2B;
|
||||
}
|
||||
|
||||
/* get front fan speed */
|
||||
memset(vstr, 0, 32);
|
||||
ret = onlp_file_read_str(vp, devfiles__[fid]);
|
||||
if (ret < 0) {
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
sscanf(*vp, "%d", &value);
|
||||
info->rpm = value;
|
||||
info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED;
|
||||
|
||||
snprintf(info->model, ONLP_CONFIG_INFO_STR_MAX, "NA");
|
||||
snprintf(info->serial, ONLP_CONFIG_INFO_STR_MAX, "NA");
|
||||
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
_onlp_get_fan_direction_on_psu(void)
|
||||
{
|
||||
/* Try to read direction from PSU1.
|
||||
* If PSU1 is not valid, read from PSU2
|
||||
*/
|
||||
int i = 0;
|
||||
|
||||
for (i = PSU1_ID; i <= PSU2_ID; i++) {
|
||||
psu_type_t psu_type;
|
||||
psu_type = get_psu_type(i, NULL, 0);
|
||||
|
||||
if (psu_type == PSU_TYPE_UNKNOWN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (PSU_TYPE_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 fid, onlp_fan_info_t* info)
|
||||
{
|
||||
int value, ret, index;
|
||||
char vstr[32], *vstrp = vstr, **vp = &vstrp;
|
||||
|
||||
info->status |= ONLP_FAN_STATUS_PRESENT;
|
||||
info->status |= ONLP_FAN_STATUS_F2B;
|
||||
|
||||
/* get fan direction */
|
||||
info->status |= _onlp_get_fan_direction_on_psu();
|
||||
|
||||
if (info->status & ONLP_FAN_STATUS_FAILED) {
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
index = ONLP_OID_ID_GET(info->hdr.id);
|
||||
info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT);
|
||||
/* get front fan speed */
|
||||
memset(vstr, 0, 32);
|
||||
ret = onlp_file_read_str(vp, devfiles__[fid]);
|
||||
if (ret < 0) {
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
sscanf(*vp, "%d", &value);
|
||||
info->rpm = value;
|
||||
info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED;
|
||||
info->status |= (value == 0) ? ONLP_FAN_STATUS_FAILED : 0;
|
||||
|
||||
snprintf(info->model, ONLP_CONFIG_INFO_STR_MAX, "NA");
|
||||
snprintf(info->serial, ONLP_CONFIG_INFO_STR_MAX, "NA");
|
||||
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function will be called prior to all of onlp_fani_* functions.
|
||||
*/
|
||||
int
|
||||
onlp_fani_init(void)
|
||||
{
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
int
|
||||
onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info)
|
||||
{
|
||||
int rc = 0;
|
||||
int local_id;
|
||||
VALIDATE(id);
|
||||
|
||||
local_id = ONLP_OID_ID_GET(id);
|
||||
*info = linfo[local_id];
|
||||
switch (local_id)
|
||||
{
|
||||
case FAN_1_ON_PSU1:
|
||||
case FAN_1_ON_PSU2:
|
||||
rc = _onlp_fani_info_get_fan_on_psu(local_id, info);
|
||||
break;
|
||||
case FAN_1_ON_MAIN_BOARD:
|
||||
case FAN_2_ON_MAIN_BOARD:
|
||||
case FAN_3_ON_MAIN_BOARD:
|
||||
case FAN_4_ON_MAIN_BOARD:
|
||||
case FAN_5_ON_MAIN_BOARD:
|
||||
case FAN_6_ON_MAIN_BOARD:
|
||||
case FAN_7_ON_MAIN_BOARD:
|
||||
case FAN_8_ON_MAIN_BOARD:
|
||||
rc = _onlp_fani_info_get_fan(local_id, info);
|
||||
break;
|
||||
default:
|
||||
rc = ONLP_STATUS_E_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function sets the fan speed of the given OID as a percentage.
|
||||
*
|
||||
* This will only be called if the OID has the PERCENTAGE_SET
|
||||
* capability.
|
||||
*
|
||||
* It is optional if you have no fans at all with this feature.
|
||||
*/
|
||||
int
|
||||
onlp_fani_percentage_set(onlp_oid_t id, int p)
|
||||
{
|
||||
int fid;
|
||||
char *path = NULL;
|
||||
|
||||
VALIDATE(id);
|
||||
|
||||
fid = ONLP_OID_ID_GET(id);
|
||||
|
||||
/* reject p=0 (p=0, stop fan) */
|
||||
if (p == 0){
|
||||
return ONLP_STATUS_E_INVALID;
|
||||
}
|
||||
|
||||
switch (fid)
|
||||
{
|
||||
case FAN_1_ON_PSU1:
|
||||
return psu_pmbus_info_set(PSU1_ID, "rpm_psu1", p);
|
||||
case FAN_1_ON_PSU2:
|
||||
return psu_pmbus_info_set(PSU2_ID, "rpm_psu2", p);
|
||||
case FAN_1_ON_MAIN_BOARD:
|
||||
case FAN_2_ON_MAIN_BOARD:
|
||||
case FAN_3_ON_MAIN_BOARD:
|
||||
case FAN_4_ON_MAIN_BOARD:
|
||||
case FAN_5_ON_MAIN_BOARD:
|
||||
case FAN_6_ON_MAIN_BOARD:
|
||||
case FAN_7_ON_MAIN_BOARD:
|
||||
case FAN_8_ON_MAIN_BOARD:
|
||||
path = FAN_NODE(fan_duty_cycle_percentage);
|
||||
break;
|
||||
default:
|
||||
return ONLP_STATUS_E_INVALID;
|
||||
}
|
||||
|
||||
if (onlp_file_write_int(p, path, NULL) != 0) {
|
||||
AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
/************************************************************
|
||||
* ledi.c
|
||||
*
|
||||
* Copyright 2018 Inventec Technology Corporation.
|
||||
*
|
||||
************************************************************
|
||||
*
|
||||
***********************************************************/
|
||||
#include <onlp/platformi/ledi.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <onlplib/mmap.h>
|
||||
#include <onlplib/file.h>
|
||||
#include "platform_lib.h"
|
||||
|
||||
#define filename "brightness"
|
||||
|
||||
#define VALIDATE(_id) \
|
||||
do { \
|
||||
if(!ONLP_OID_IS_LED(_id)) { \
|
||||
return ONLP_STATUS_E_INVALID; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static char* devfiles__[LED_MAX] = /* must map with onlp_thermal_id */
|
||||
{
|
||||
"reserved",
|
||||
INV_CPLD_PREFIX"/%s_led",
|
||||
INV_PSOC_PREFIX"/fan_led_%s1",
|
||||
INV_PSOC_PREFIX"/fan_led_%s2",
|
||||
INV_PSOC_PREFIX"/fan_led_%s3",
|
||||
INV_PSOC_PREFIX"/fan_led_%s4",
|
||||
};
|
||||
|
||||
enum led_light_mode {
|
||||
LED_MODE_OFF = 0,
|
||||
LED_MODE_GREEN,
|
||||
LED_MODE_AMBER,
|
||||
LED_MODE_RED,
|
||||
LED_MODE_BLUE,
|
||||
LED_MODE_GREEN_BLINK,
|
||||
LED_MODE_AMBER_BLINK,
|
||||
LED_MODE_RED_BLINK,
|
||||
LED_MODE_BLUE_BLINK,
|
||||
LED_MODE_AUTO,
|
||||
LED_MODE_UNKNOWN
|
||||
};
|
||||
|
||||
typedef struct led_light_mode_map {
|
||||
enum onlp_led_id id;
|
||||
enum led_light_mode driver_led_mode;
|
||||
enum onlp_led_mode_e onlp_led_mode;
|
||||
} led_light_mode_map_t;
|
||||
|
||||
led_light_mode_map_t led_map[] = {
|
||||
{LED_SYS, LED_MODE_OFF, ONLP_LED_MODE_OFF},
|
||||
{LED_SYS, LED_MODE_GREEN, ONLP_LED_MODE_GREEN},
|
||||
{LED_SYS, LED_MODE_AMBER, ONLP_LED_MODE_ORANGE},
|
||||
{LED_SYS, LED_MODE_RED, ONLP_LED_MODE_RED},
|
||||
{LED_FAN1,LED_MODE_AUTO, ONLP_LED_MODE_AUTO},
|
||||
{LED_FAN2,LED_MODE_AUTO, ONLP_LED_MODE_AUTO},
|
||||
{LED_FAN3,LED_MODE_AUTO, ONLP_LED_MODE_AUTO},
|
||||
{LED_FAN4,LED_MODE_AUTO, ONLP_LED_MODE_AUTO},
|
||||
};
|
||||
|
||||
static char last_path[][10] = /* must map with onlp_led_id */
|
||||
{
|
||||
"reserved",
|
||||
"diag",
|
||||
"loc",
|
||||
"fan",
|
||||
"psu1",
|
||||
"psu2"
|
||||
};
|
||||
|
||||
/*
|
||||
* Get the information for the given LED OID.
|
||||
*/
|
||||
static onlp_led_info_t linfo[LED_MAX] =
|
||||
{
|
||||
{ }, /* Not used */
|
||||
{
|
||||
{ ONLP_LED_ID_CREATE(LED_SYS), "Chassis LED (SYSTEM LED)", 0 },
|
||||
ONLP_LED_STATUS_PRESENT,
|
||||
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED | ONLP_LED_CAPS_ORANGE,
|
||||
ONLP_LED_MODE_ON, '0',
|
||||
},
|
||||
{
|
||||
{ ONLP_LED_ID_CREATE(LED_FAN1), "Fan LED 1 (FAN1 LED)", 0 },
|
||||
ONLP_LED_STATUS_PRESENT,
|
||||
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED,
|
||||
ONLP_LED_MODE_ON, '0',
|
||||
},
|
||||
{
|
||||
{ ONLP_LED_ID_CREATE(LED_FAN2), "Fan LED 2 (FAN2 LED)", 0 },
|
||||
ONLP_LED_STATUS_PRESENT,
|
||||
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED,
|
||||
ONLP_LED_MODE_ON, '0',
|
||||
},
|
||||
{
|
||||
{ ONLP_LED_ID_CREATE(LED_FAN3), "Fan LED 3 (FAN3 LED)", 0 },
|
||||
ONLP_LED_STATUS_PRESENT,
|
||||
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED,
|
||||
ONLP_LED_MODE_ON, '0',
|
||||
},
|
||||
{
|
||||
{ ONLP_LED_ID_CREATE(LED_FAN4), "Fan LED 4 (FAN4 LED)", 0 },
|
||||
ONLP_LED_STATUS_PRESENT,
|
||||
ONLP_LED_CAPS_ON_OFF | ONLP_LED_CAPS_GREEN | ONLP_LED_CAPS_RED,
|
||||
ONLP_LED_MODE_ON, '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)
|
||||
{
|
||||
/*
|
||||
* Diag LED Off
|
||||
*/
|
||||
onlp_ledi_mode_set(ONLP_LED_ID_CREATE(LED_SYS), ONLP_LED_MODE_OFF);
|
||||
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
int onlp_chassis_led_read(char *pathp, char *buf, size_t len)
|
||||
{
|
||||
FILE * fp;
|
||||
|
||||
fp = fopen (pathp, "r");
|
||||
if(fp == NULL) {
|
||||
perror("Error opening file");
|
||||
return(-1);
|
||||
}
|
||||
if( fgets (buf, len, fp) == NULL ) {
|
||||
perror("Error fgets operation");
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
onlp_ledi_info_get(onlp_oid_t id, onlp_led_info_t* info)
|
||||
{
|
||||
int local_id, gret = 0, rret = 0;
|
||||
char fullpath_grn[50] = {0};
|
||||
char fullpath_red[50] = {0};
|
||||
int gvalue = 0, rvalue = 0;
|
||||
char buf[32] = {0};
|
||||
|
||||
VALIDATE(id);
|
||||
|
||||
local_id = ONLP_OID_ID_GET(id);
|
||||
|
||||
/* get fullpath */
|
||||
switch (local_id) {
|
||||
case LED_SYS:
|
||||
sprintf(fullpath_grn, devfiles__[local_id], "grn");
|
||||
sprintf(fullpath_red, devfiles__[local_id], "red");
|
||||
|
||||
/* Set LED mode */
|
||||
gret = onlp_chassis_led_read(fullpath_grn, buf, 32);
|
||||
if (buf[0] == '1' || buf[0] == '2' || buf[0] == '3' || buf[0] == '7') {
|
||||
gvalue = 1;
|
||||
}
|
||||
|
||||
rret = onlp_chassis_led_read(fullpath_red, buf, 32);
|
||||
if (buf[0] == '1' || buf[0] == '2' || buf[0] == '3' || buf[0] == '7') {
|
||||
rvalue = 1;
|
||||
}
|
||||
if (gret < 0 && rret < 0) {
|
||||
DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__);
|
||||
gvalue = -1;
|
||||
rvalue = -1;
|
||||
}
|
||||
break;
|
||||
case LED_FAN1:
|
||||
case LED_FAN2:
|
||||
case LED_FAN3:
|
||||
case LED_FAN4:
|
||||
sprintf(fullpath_grn, devfiles__[local_id], "grn");
|
||||
sprintf(fullpath_red, devfiles__[local_id], "red");
|
||||
|
||||
/* Set LED mode */
|
||||
if (onlp_file_read_int(&gvalue, fullpath_grn) != 0) {
|
||||
DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__);
|
||||
gvalue = 0;
|
||||
}
|
||||
if (onlp_file_read_int(&rvalue, fullpath_red) != 0) {
|
||||
DEBUG_PRINT("%s(%d)\r\n", __FUNCTION__, __LINE__);
|
||||
rvalue = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEBUG_PRINT("%s(%d) Invalid led id %d\r\n", __FUNCTION__, __LINE__, local_id);
|
||||
gvalue = -1;
|
||||
rvalue = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set the onlp_oid_hdr_t and capabilities */
|
||||
*info = linfo[ONLP_OID_ID_GET(id)];
|
||||
|
||||
if (gvalue == 1 && rvalue == 0) {
|
||||
info->mode = ONLP_LED_MODE_GREEN;
|
||||
info->status |= ONLP_LED_STATUS_ON;
|
||||
}
|
||||
else
|
||||
if (gvalue == 0 && rvalue == 1) {
|
||||
info->mode = ONLP_LED_MODE_RED;
|
||||
info->status |= ONLP_LED_STATUS_ON;
|
||||
}
|
||||
else
|
||||
if (gvalue == 1 && rvalue == 1) {
|
||||
info->mode = ONLP_LED_MODE_ORANGE;
|
||||
info->status |= ONLP_LED_STATUS_ON;
|
||||
}
|
||||
else
|
||||
if (gvalue == 0 && rvalue == 0) {
|
||||
info->mode = ONLP_LED_MODE_OFF;
|
||||
info->status |= ONLP_LED_STATUS_ON;
|
||||
}
|
||||
else {
|
||||
info->mode = ONLP_LED_MODE_OFF;
|
||||
info->status |= ONLP_LED_STATUS_FAILED;
|
||||
}
|
||||
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 local_id;
|
||||
char fullpath[50] = {0};
|
||||
|
||||
VALIDATE(id);
|
||||
|
||||
local_id = ONLP_OID_ID_GET(id);
|
||||
switch (local_id) {
|
||||
case LED_SYS:
|
||||
sprintf(fullpath, "%s%s/%s", INV_CPLD_PREFIX, last_path[local_id], filename);
|
||||
break;
|
||||
case LED_FAN1:
|
||||
case LED_FAN2:
|
||||
case LED_FAN3:
|
||||
case LED_FAN4:
|
||||
sprintf(fullpath, "%s%s/%s", INV_PSOC_PREFIX, last_path[local_id], filename);
|
||||
break;
|
||||
default:
|
||||
DEBUG_PRINT("%s(%d) Invalid led id %d\r\n", __FUNCTION__, __LINE__, local_id);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
|
||||
if (onlp_file_write_int(onlp_to_driver_led_mode(local_id, mode), fullpath, NULL) != 0)
|
||||
{
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
###############################################################################
|
||||
#
|
||||
#
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
LIBRARY := x86_64_inventec_d6556
|
||||
$(LIBRARY)_SUBDIR := $(dir $(lastword $(MAKEFILE_LIST)))
|
||||
include $(BUILDER)/lib.mk
|
||||
@@ -0,0 +1,184 @@
|
||||
/************************************************************
|
||||
* platform_lib.c
|
||||
*
|
||||
* Copyright 2018 Inventec Corporation.
|
||||
*
|
||||
************************************************************
|
||||
*
|
||||
***********************************************************/
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <AIM/aim.h>
|
||||
#include <onlplib/file.h>
|
||||
#include <onlp/onlp.h>
|
||||
#include "platform_lib.h"
|
||||
|
||||
#define PSU_NODE_MAX_PATH_LEN 64
|
||||
|
||||
int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len)
|
||||
{
|
||||
if ((buffer == NULL) || (buf_size < 0)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return onlp_file_read((uint8_t*)buffer, buf_size, &data_len, "%s", filename);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#define I2C_PSU_MODEL_NAME_LEN 32
|
||||
#define I2C_PSU_FAN_DIR_LEN 8
|
||||
#include <ctype.h>
|
||||
psu_type_t get_psu_type(int id, char* modelname, int modelname_len)
|
||||
{
|
||||
char *node = NULL;
|
||||
char model_name[I2C_PSU_MODEL_NAME_LEN + 1] = {0};
|
||||
char fan_dir[I2C_PSU_FAN_DIR_LEN + 1] = {0};
|
||||
|
||||
/* Check AC model name */
|
||||
node = (id == PSU1_ID) ? PSU1_AC_HWMON_NODE(psu_model_name) : PSU2_AC_HWMON_NODE(psu_model_name);
|
||||
|
||||
if (onlp_file_read_string(node, model_name, sizeof(model_name), 0) != 0) {
|
||||
return PSU_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
if(isspace(model_name[strlen(model_name)-1])) {
|
||||
model_name[strlen(model_name)] = 0;
|
||||
}
|
||||
|
||||
if (strncmp(model_name, "YM-2651Y", 8) == 0) {
|
||||
if (modelname) {
|
||||
strncpy(modelname, model_name, 8);
|
||||
}
|
||||
|
||||
node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_fan_dir) : PSU2_AC_PMBUS_NODE(psu_fan_dir);
|
||||
if (onlp_file_read_string(node, fan_dir, sizeof(fan_dir), 0) != 0) {
|
||||
return PSU_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) {
|
||||
return PSU_TYPE_AC_F2B;
|
||||
}
|
||||
|
||||
if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) {
|
||||
return PSU_TYPE_AC_B2F;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(model_name, "YM-2651V", 8) == 0) {
|
||||
if (modelname) {
|
||||
strncpy(modelname, model_name, 8);
|
||||
}
|
||||
|
||||
node = (id == PSU1_ID) ? PSU1_AC_PMBUS_NODE(psu_fan_dir) : PSU2_AC_PMBUS_NODE(psu_fan_dir);
|
||||
if (onlp_file_read_string(node, fan_dir, sizeof(fan_dir), 0) != 0) {
|
||||
return PSU_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
if (strncmp(fan_dir, "F2B", strlen("F2B")) == 0) {
|
||||
return PSU_TYPE_DC_48V_F2B;
|
||||
}
|
||||
|
||||
if (strncmp(fan_dir, "B2F", strlen("B2F")) == 0) {
|
||||
return PSU_TYPE_DC_48V_B2F;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(model_name, "PSU-12V-750", 11) == 0) {
|
||||
if (modelname) {
|
||||
strncpy(modelname, model_name, 11);
|
||||
}
|
||||
|
||||
node = (id == PSU1_ID) ? PSU1_AC_HWMON_NODE(psu_fan_dir) : PSU2_AC_HWMON_NODE(psu_fan_dir);
|
||||
if (onlp_file_read_string(node, fan_dir, sizeof(fan_dir), 0) != 0) {
|
||||
return PSU_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
if (strncmp(fan_dir, "F2B", 3) == 0) {
|
||||
return PSU_TYPE_DC_12V_F2B;
|
||||
}
|
||||
|
||||
if (strncmp(fan_dir, "B2F", 3) == 0) {
|
||||
return PSU_TYPE_DC_12V_B2F;
|
||||
}
|
||||
|
||||
if (strncmp(fan_dir, "NON", 3) == 0) {
|
||||
return PSU_TYPE_DC_12V_FANLESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(model_name, "DPS-150AB-10", 12) == 0) {
|
||||
if (modelname) {
|
||||
strncpy(modelname, model_name, 12);
|
||||
}
|
||||
|
||||
return PSU_TYPE_DC_12V_F2B;
|
||||
}
|
||||
|
||||
return PSU_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
int psu_pmbus_info_get(int id, char *node, int *value)
|
||||
{
|
||||
int ret = 0;
|
||||
*value = 0;
|
||||
|
||||
if (PSU1_ID == id) {
|
||||
ret = onlp_file_read_int(value, "%s%s%d", PSU1_AC_PMBUS_PREFIX, node, PSU1_ID);
|
||||
}
|
||||
else
|
||||
if (PSU2_ID == id) {
|
||||
ret = onlp_file_read_int(value, "%s%s%d", PSU2_AC_PMBUS_PREFIX, node, PSU2_ID);
|
||||
}
|
||||
else {
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int psu_pmbus_info_set(int id, char *node, int value)
|
||||
{
|
||||
char path[PSU_NODE_MAX_PATH_LEN] = {0};
|
||||
|
||||
switch (id) {
|
||||
case PSU1_ID:
|
||||
sprintf(path, "%s%s%d", PSU1_AC_PMBUS_PREFIX, node, PSU1_ID);
|
||||
break;
|
||||
case PSU2_ID:
|
||||
sprintf(path, "%s%s%d", PSU2_AC_PMBUS_PREFIX, node, PSU2_ID);
|
||||
break;
|
||||
default:
|
||||
return ONLP_STATUS_E_UNSUPPORTED;
|
||||
};
|
||||
|
||||
if (onlp_file_write_int(value, path, NULL) != 0) {
|
||||
AIM_LOG_ERROR("Unable to write data to file (%s)\r\n", path);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/************************************************************
|
||||
* platform_lib.h
|
||||
*
|
||||
* Copyright 2018 Inventec Technology Corporation.
|
||||
*
|
||||
************************************************************
|
||||
*
|
||||
***********************************************************/
|
||||
#ifndef __PLATFORM_LIB_H__
|
||||
#define __PLATFORM_LIB_H__
|
||||
|
||||
#include "x86_64_inventec_d6556_log.h"
|
||||
|
||||
#define ONLP_NODE_MAX_INT_LEN (8)
|
||||
#define ONLP_NODE_MAX_PATH_LEN (64)
|
||||
|
||||
#define INV_CPLD_COUNT (2)
|
||||
#define INV_CPLD_PREFIX "/sys/bus/i2c/devices/0-0055/"
|
||||
#define INV_CPLD2_PREFIX "/sys/bus/i2c/devices/0-0077/"
|
||||
#define INV_PSOC_PREFIX "/sys/devices/virtual/hwmon/hwmon1/"
|
||||
#define INV_EPRM_PREFIX "/sys/bus/i2c/devices/0-0053/"
|
||||
#define INV_CTMP_PREFIX "/sys/devices/platform/coretemp.0/hwmon/hwmon0/"
|
||||
|
||||
#define CHASSIS_SFP_COUNT (56)
|
||||
|
||||
/*
|
||||
* Definitions of Chassis EEPROM
|
||||
*/
|
||||
#define EEPROM_NODE(node) INV_EPRM_PREFIX#node
|
||||
|
||||
|
||||
/*
|
||||
* Definitions of D7264Q28B device
|
||||
*/
|
||||
enum onlp_thermal_id {
|
||||
THERMAL_RESERVED = 0,
|
||||
THERMAL_CPU_CORE_FIRST,
|
||||
THERMAL_CPU_CORE_2,
|
||||
THERMAL_CPU_CORE_3,
|
||||
THERMAL_CPU_CORE_4,
|
||||
THERMAL_CPU_CORE_LAST,
|
||||
THERMAL_1_ON_MAIN_BROAD,
|
||||
THERMAL_2_ON_MAIN_BROAD,
|
||||
THERMAL_3_ON_MAIN_BROAD,
|
||||
THERMAL_4_ON_MAIN_BROAD,
|
||||
THERMAL_5_ON_MAIN_BROAD,
|
||||
THERMAL_1_ON_PSU1,
|
||||
THERMAL_2_ON_PSU1,
|
||||
THERMAL_1_ON_PSU2,
|
||||
THERMAL_2_ON_PSU2,
|
||||
THERMAL_MAX
|
||||
};
|
||||
#define CHASSIS_THERMAL_COUNT (10)
|
||||
|
||||
enum onlp_fan_id {
|
||||
FAN_RESERVED = 0,
|
||||
FAN_1_ON_MAIN_BOARD,
|
||||
FAN_2_ON_MAIN_BOARD,
|
||||
FAN_3_ON_MAIN_BOARD,
|
||||
FAN_4_ON_MAIN_BOARD,
|
||||
FAN_5_ON_MAIN_BOARD,
|
||||
FAN_6_ON_MAIN_BOARD,
|
||||
FAN_7_ON_MAIN_BOARD,
|
||||
FAN_8_ON_MAIN_BOARD,
|
||||
FAN_1_ON_PSU1,
|
||||
FAN_1_ON_PSU2,
|
||||
FAN_MAX
|
||||
};
|
||||
#define CHASSIS_FAN_COUNT (8)
|
||||
|
||||
enum onlp_led_id
|
||||
{
|
||||
LED_RESERVED = 0,
|
||||
LED_SYS,
|
||||
LED_FAN1,
|
||||
LED_FAN2,
|
||||
LED_FAN3,
|
||||
LED_FAN4,
|
||||
LED_MAX
|
||||
};
|
||||
#define CHASSIS_LED_COUNT (1)
|
||||
|
||||
enum onlp_psu_id
|
||||
{
|
||||
PSU_RESERVED = 0,
|
||||
PSU1_ID,
|
||||
PSU2_ID,
|
||||
PSU_MAX
|
||||
};
|
||||
#define CHASSIS_PSU_COUNT (2)
|
||||
|
||||
|
||||
#define PSU1_AC_PMBUS_PREFIX INV_PSOC_PREFIX
|
||||
#define PSU2_AC_PMBUS_PREFIX INV_PSOC_PREFIX
|
||||
|
||||
#define PSU1_AC_PMBUS_NODE(node) PSU1_AC_PMBUS_PREFIX#node
|
||||
#define PSU2_AC_PMBUS_NODE(node) PSU2_AC_PMBUS_PREFIX#node
|
||||
|
||||
#define PSU1_AC_HWMON_PREFIX INV_CPLD_PREFIX
|
||||
#define PSU2_AC_HWMON_PREFIX INV_CPLD_PREFIX
|
||||
|
||||
typedef enum psu_type {
|
||||
PSU_TYPE_UNKNOWN,
|
||||
PSU_TYPE_AC_F2B,
|
||||
PSU_TYPE_AC_B2F,
|
||||
PSU_TYPE_DC_48V_F2B,
|
||||
PSU_TYPE_DC_48V_B2F,
|
||||
PSU_TYPE_DC_12V_FANLESS,
|
||||
PSU_TYPE_DC_12V_F2B,
|
||||
PSU_TYPE_DC_12V_B2F
|
||||
} psu_type_t;
|
||||
|
||||
psu_type_t get_psu_type(int id, char* modelname, int modelname_len);
|
||||
|
||||
#define PSU1_AC_HWMON_NODE(node) PSU1_AC_HWMON_PREFIX#node
|
||||
#define PSU2_AC_HWMON_NODE(node) PSU2_AC_HWMON_PREFIX#node
|
||||
|
||||
/*
|
||||
* Definitions of FAN device
|
||||
*/
|
||||
#define FAN_BOARD_PATH INV_PSOC_PREFIX
|
||||
#define FAN_NODE(node) FAN_BOARD_PATH#node
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
int onlp_file_read_binary(char *filename, char *buffer, int buf_size, int data_len);
|
||||
int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_len);
|
||||
|
||||
int psu_pmbus_info_get(int id, char *node, int *value);
|
||||
int psu_pmbus_info_set(int id, char *node, int value);
|
||||
|
||||
#define DEBUG_MODE 0
|
||||
|
||||
#if (DEBUG_MODE == 1)
|
||||
#define DEBUG_PRINT(format, ...) printf(format, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_PRINT(format, ...)
|
||||
#endif
|
||||
|
||||
#endif /* __PLATFORM_LIB_H__ */
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
/************************************************************
|
||||
* psui.c
|
||||
*
|
||||
* Copyright 2018 Inventec Technology Corporation.
|
||||
*
|
||||
************************************************************
|
||||
*
|
||||
***********************************************************/
|
||||
#include <onlp/platformi/psui.h>
|
||||
#include <onlplib/mmap.h>
|
||||
#include <onlplib/file.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "platform_lib.h"
|
||||
|
||||
#define PSU_STATUS_PRESENT (0)
|
||||
#define PSU_STATUS_POWER_GOOD (1)
|
||||
#define PSU_STATUS_UNPOWERED (2)
|
||||
#define PSU_STATUS_FAULT (4)
|
||||
#define PSU_STATUS_UNINSTALLED (7)
|
||||
|
||||
#define VALIDATE(_id) \
|
||||
do { \
|
||||
if(!ONLP_OID_IS_PSU(_id)) { \
|
||||
return ONLP_STATUS_E_INVALID; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static char* status_devfiles__[PSU_MAX] = /* must map with onlp_psu_id */
|
||||
{
|
||||
"reserved",
|
||||
INV_CPLD_PREFIX"/psu0",
|
||||
INV_CPLD_PREFIX"/psu1",
|
||||
};
|
||||
|
||||
static char* module_devfiles__[PSU_MAX] = /* must map with onlp_psu_id */
|
||||
{
|
||||
"reserved",
|
||||
INV_PSOC_PREFIX"/psoc_psu1_%s",
|
||||
INV_PSOC_PREFIX"/psoc_psu2_%s",
|
||||
};
|
||||
|
||||
static int
|
||||
psu_status_info_get(int id, char *node, int *value)
|
||||
{
|
||||
int ret = 0;
|
||||
char node_path[ONLP_NODE_MAX_PATH_LEN] = {0};
|
||||
char vstr[32], *vstrp = vstr, **vp = &vstrp;
|
||||
|
||||
*value = 0;
|
||||
|
||||
if (PSU1_ID == id) {
|
||||
sprintf(node_path, status_devfiles__[id]);
|
||||
}
|
||||
else if (PSU2_ID == id) {
|
||||
sprintf(node_path, status_devfiles__[id]);
|
||||
}
|
||||
|
||||
ret = onlp_file_read_str(vp, node_path);
|
||||
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
|
||||
if (!isdigit(*vstrp)) {
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
*value = *vstrp - '0';
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
onlp_psui_init(void)
|
||||
{
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
psu_module_info_get(int id, onlp_psu_info_t* info)
|
||||
{
|
||||
int ret = 0;
|
||||
char node_path[ONLP_NODE_MAX_PATH_LEN] = {0};
|
||||
char vstr[32], *vstrp = vstr, **vp = &vstrp;
|
||||
int value = 0;
|
||||
|
||||
info->caps |= ONLP_PSU_CAPS_DC12;
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "vout");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read vout from file(%s)\r\n", node_path);
|
||||
}
|
||||
else {
|
||||
info->mvout = value;
|
||||
info->caps |= ONLP_PSU_CAPS_VOUT;
|
||||
}
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "iout");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read iout from file(%s)\r\n", node_path);
|
||||
}
|
||||
else {
|
||||
info->miout = value;
|
||||
info->caps |= ONLP_PSU_CAPS_IOUT;
|
||||
}
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "pout");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read pout from file(%s)\r\n", node_path);
|
||||
}
|
||||
else {
|
||||
info->mpout = value;
|
||||
info->caps |= ONLP_PSU_CAPS_POUT;
|
||||
}
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "vin");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read vin from file(%s)\r\n", node_path);
|
||||
}
|
||||
else {
|
||||
info->mvin = value;
|
||||
info->caps |= ONLP_PSU_CAPS_VIN;
|
||||
}
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "iin");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read iin from file(%s)\r\n", node_path);
|
||||
}
|
||||
else {
|
||||
info->miin = value;
|
||||
info->caps |= ONLP_PSU_CAPS_IIN;
|
||||
}
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "pin");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read pin from file(%s)\r\n", node_path);
|
||||
}
|
||||
else {
|
||||
info->mpin = value;
|
||||
info->caps |= ONLP_PSU_CAPS_PIN;
|
||||
}
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "model");
|
||||
ret = onlp_file_read_str(vp, node_path);
|
||||
if (ret > 0) {
|
||||
strncpy(info->model, *vp, ret-1);
|
||||
}
|
||||
else {
|
||||
//AIM_LOG_ERROR("Unable to read model name from file(%s)\r\n", node_path);
|
||||
strncpy(info->model, "N/A", 3);
|
||||
}
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "serial");
|
||||
ret = onlp_file_read_str(vp, node_path);
|
||||
if (ret > 0) {
|
||||
strncpy(info->serial, *vp, ret-1);
|
||||
}
|
||||
else {
|
||||
AIM_LOG_ERROR("Unable to read model name from file(%s)\r\n", node_path);
|
||||
strncpy(info->serial, "N/A", 3);
|
||||
}
|
||||
|
||||
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_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1),
|
||||
ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU1),
|
||||
ONLP_FAN_ID_CREATE(FAN_1_ON_PSU1)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
{
|
||||
ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0,
|
||||
{
|
||||
ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2),
|
||||
ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU2),
|
||||
ONLP_FAN_ID_CREATE(FAN_1_ON_PSU2)
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
VALIDATE(id);
|
||||
|
||||
memset(info, 0, sizeof(onlp_psu_info_t));
|
||||
*info = pinfo[index]; /* Set the onlp_oid_hdr_t */
|
||||
|
||||
/* Get the present state */
|
||||
if ((ret = psu_status_info_get(index, "psu", &val)) == ONLP_STATUS_E_INTERNAL) {
|
||||
printf("Unable to read PSU(%d) node(psu)\r\n", index);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (val == 0) {
|
||||
info->status = ONLP_PSU_STATUS_PRESENT;
|
||||
}
|
||||
else
|
||||
if (val == 1) {
|
||||
info->status = ONLP_PSU_STATUS_UNPLUGGED;
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
info->status = ONLP_PSU_STATUS_FAILED;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = psu_module_info_get(index, info)) != ONLP_STATUS_OK) {
|
||||
printf("Unable to read PSU(%d) module information\r\n", index);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
/************************************************************
|
||||
* sfpi.c
|
||||
*
|
||||
* Copyright 2018 Inventec Technology Corporation.
|
||||
*
|
||||
************************************************************
|
||||
*
|
||||
***********************************************************/
|
||||
#include <onlp/platformi/sfpi.h>
|
||||
|
||||
#include <fcntl.h> /* For O_RDWR && open */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <onlplib/i2c.h>
|
||||
#include <onlplib/file.h>
|
||||
#include "platform_lib.h"
|
||||
|
||||
static char sfp_node_path[ONLP_NODE_MAX_PATH_LEN] = {0};
|
||||
|
||||
#define NUM_OF_SFP_PORT (CHASSIS_SFP_COUNT)
|
||||
static const int sfp_mux_index[NUM_OF_SFP_PORT] = {
|
||||
18, 19, 20, 21, 22, 23, 24, 25,
|
||||
26, 27, 28, 29, 30, 31, 32, 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,
|
||||
10, 11, 12, 13, 14, 15, 16, 17
|
||||
};
|
||||
|
||||
#define FRONT_PORT_TO_MUX_INDEX(port) (sfp_mux_index[port])
|
||||
|
||||
static int
|
||||
sfp_node_read_int(char *node_path, int *value, int data_len)
|
||||
{
|
||||
int ret = 0;
|
||||
*value = 0;
|
||||
|
||||
ret = onlp_file_read_int(value, node_path);
|
||||
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char*
|
||||
sfp_get_port_path(int port, char *node_name)
|
||||
{
|
||||
sprintf(sfp_node_path, "/sys/class/swps/port%d/%s", port, node_name);
|
||||
|
||||
return sfp_node_path;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
*
|
||||
* 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, 64}
|
||||
*/
|
||||
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;
|
||||
char* path = sfp_get_port_path(port, "present");
|
||||
if (sfp_node_read_int(path, &present, 0) != 0) {
|
||||
AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
if (present == 0) {
|
||||
present = 1;
|
||||
}
|
||||
else
|
||||
if (present == 1) {
|
||||
present = 0;
|
||||
}
|
||||
else {
|
||||
AIM_LOG_ERROR("Unvalid present status %d from port(%d)\r\n",present,port);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
return present;
|
||||
}
|
||||
|
||||
int
|
||||
onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
|
||||
{
|
||||
uint32_t presence_all[2] = {0};
|
||||
int port, ret, index;
|
||||
|
||||
for (port = 0, index = 0; port < NUM_OF_SFP_PORT; port++) {
|
||||
if (port == 32) {
|
||||
index = 1;
|
||||
}
|
||||
|
||||
ret = onlp_sfpi_is_present(port);
|
||||
if (ret == 1) {
|
||||
presence_all[index] |= (1<<port);
|
||||
}
|
||||
else
|
||||
if (ret == 0) {
|
||||
presence_all[index] &= ~(1<<port);
|
||||
}
|
||||
else {
|
||||
AIM_LOG_ERROR("Unable to read present status of port(%d).", port);
|
||||
}
|
||||
}
|
||||
/* Populate bitmap */
|
||||
for(port = 0, index = 0; port < NUM_OF_SFP_PORT; port++) {
|
||||
if (port == 32) {
|
||||
index = 1;
|
||||
}
|
||||
|
||||
AIM_BITMAP_MOD(dst, port, (presence_all[index] & 1));
|
||||
presence_all[index] >>= 1;
|
||||
}
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
int
|
||||
onlp_sfpi_eeprom_read(int port, uint8_t data[256])
|
||||
{
|
||||
#if 1
|
||||
int bus = FRONT_PORT_TO_MUX_INDEX(port);
|
||||
|
||||
memset(data, 0, 256);
|
||||
/* Read eeprom information into data[] */
|
||||
if (onlp_i2c_read(bus, 0x50, 0x00, 256, data, 0) != 0)
|
||||
{
|
||||
AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
#else
|
||||
char* path;
|
||||
int len = 0;
|
||||
/*
|
||||
* Read the SFP eeprom into data[]
|
||||
*
|
||||
* Return MISSING if SFP is missing.
|
||||
* Return OK if eeprom is read
|
||||
*/
|
||||
memset(data, 0, 256);
|
||||
path = sfp_get_port_path(port, "eeprom");
|
||||
if (onlp_file_read(&data[0], 256, &len, path) < 0) {
|
||||
AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
#endif
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
int
|
||||
onlp_sfpi_dom_read(int port, uint8_t data[256])
|
||||
{
|
||||
return onlp_sfpi_eeprom_read( port, data);
|
||||
}
|
||||
|
||||
int
|
||||
onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr)
|
||||
{
|
||||
int bus = FRONT_PORT_TO_MUX_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 = FRONT_PORT_TO_MUX_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 = FRONT_PORT_TO_MUX_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 = FRONT_PORT_TO_MUX_INDEX(port);
|
||||
return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE);
|
||||
}
|
||||
|
||||
int
|
||||
onlp_sfpi_denit(void)
|
||||
{
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/************************************************************
|
||||
* sysi.c
|
||||
*
|
||||
* Copyright 2018 Inventec Technology Corporation.
|
||||
*
|
||||
************************************************************
|
||||
*
|
||||
***********************************************************/
|
||||
#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 "x86_64_inventec_d6556_int.h"
|
||||
#include "x86_64_inventec_d6556_log.h"
|
||||
|
||||
#include "platform_lib.h"
|
||||
|
||||
#define NUM_OF_CPLD INV_CPLD_COUNT
|
||||
|
||||
#define NUM_OF_THERMAL_ON_MAIN_BROAD (CHASSIS_THERMAL_COUNT)
|
||||
#define NUM_OF_FAN_ON_MAIN_BROAD (CHASSIS_FAN_COUNT)
|
||||
#define NUM_OF_PSU_ON_MAIN_BROAD (CHASSIS_PSU_COUNT)
|
||||
#define NUM_OF_LED_ON_MAIN_BROAD (CHASSIS_LED_COUNT)
|
||||
|
||||
const char*
|
||||
onlp_sysi_platform_get(void)
|
||||
{
|
||||
return "x86-64-inventec-d6556-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, EEPROM_NODE(eeprom)) == 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));
|
||||
|
||||
/* 4 Thermal sensors on the chassis */
|
||||
for (i = 1; i <= NUM_OF_THERMAL_ON_MAIN_BROAD; i++)
|
||||
{
|
||||
*e++ = ONLP_THERMAL_ID_CREATE(i);
|
||||
}
|
||||
|
||||
/* 5 LEDs on the chassis */
|
||||
for (i = 1; i <= NUM_OF_LED_ON_MAIN_BROAD; i++)
|
||||
{
|
||||
*e++ = ONLP_LED_ID_CREATE(i);
|
||||
}
|
||||
|
||||
/* 2 PSUs on the chassis */
|
||||
for (i = 1; i <= NUM_OF_PSU_ON_MAIN_BROAD; i++)
|
||||
{
|
||||
*e++ = ONLP_PSU_ID_CREATE(i);
|
||||
}
|
||||
|
||||
/* 4 Fans on the chassis */
|
||||
for (i = 1; i <= NUM_OF_FAN_ON_MAIN_BROAD; i++)
|
||||
{
|
||||
*e++ = ONLP_FAN_ID_CREATE(i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *arr_cplddev_version[NUM_OF_CPLD] =
|
||||
{
|
||||
INV_CPLD_PREFIX"/version",
|
||||
INV_CPLD2_PREFIX"/version",
|
||||
};
|
||||
|
||||
int
|
||||
onlp_sysi_platform_info_get(onlp_platform_info_t* pi)
|
||||
{
|
||||
int i, v[NUM_OF_CPLD]={0};
|
||||
for (i=0; i < NUM_OF_CPLD; i++) {
|
||||
v[i] = 0;
|
||||
if(onlp_file_read_int(v+i, arr_cplddev_version[i]) < 0) {
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
}
|
||||
pi->cpld_versions = aim_fstrdup("%d.%d", v[0], v[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
onlp_sysi_platform_info_free(onlp_platform_info_t* pi)
|
||||
{
|
||||
aim_free(pi->cpld_versions);
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/************************************************************
|
||||
* thermali.c
|
||||
*
|
||||
* Copyright 2018 Inventec Technology Corporation.
|
||||
*
|
||||
************************************************************
|
||||
*
|
||||
* Thermal Sensor Platform Implementation.
|
||||
*
|
||||
***********************************************************/
|
||||
#include <unistd.h>
|
||||
#include <onlplib/mmap.h>
|
||||
#include <onlplib/file.h>
|
||||
#include <onlp/platformi/thermali.h>
|
||||
#include <fcntl.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__[THERMAL_MAX] = /* must map with onlp_thermal_id */
|
||||
{
|
||||
"reserved",
|
||||
INV_CTMP_PREFIX"/temp1_%s",
|
||||
INV_CTMP_PREFIX"/temp2_%s",
|
||||
INV_CTMP_PREFIX"/temp3_%s",
|
||||
INV_CTMP_PREFIX"/temp4_%s",
|
||||
INV_CTMP_PREFIX"/temp5_%s",
|
||||
INV_PSOC_PREFIX"/temp1_input",
|
||||
INV_PSOC_PREFIX"/temp2_input",
|
||||
INV_PSOC_PREFIX"/temp3_input",
|
||||
INV_PSOC_PREFIX"/temp4_input",
|
||||
INV_PSOC_PREFIX"/temp5_input",
|
||||
INV_PSOC_PREFIX"/thermal_psu1",
|
||||
INV_PSOC_PREFIX"/thermal2_psu1",
|
||||
INV_PSOC_PREFIX"/thermal_psu2",
|
||||
INV_PSOC_PREFIX"/thermal2_psu2",
|
||||
};
|
||||
|
||||
/* Static values */
|
||||
static onlp_thermal_info_t linfo[THERMAL_MAX] = {
|
||||
{ }, /* Not used */
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_FIRST), "Physical id 0", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_2), "CPU Core 0", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_3), "CPU Core 1", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_4), "CPU Core 2", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_LAST), "CPU Core 3", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_MAIN_BROAD), "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_BROAD), "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_BROAD), "Chassis Thermal Sensor 3", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "Chassis Thermal Sensor 4", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_3_ON_MAIN_BROAD), "Chassis Thermal Sensor 5", 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_2_ON_PSU1), "PSU-1 Thermal Sensor 2", 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_2_ON_PSU2), "PSU-2 Thermal Sensor 2", ONLP_PSU_ID_CREATE(PSU2_ID)},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* This will be called to intiialize the thermali subsystem.
|
||||
*/
|
||||
int
|
||||
onlp_thermali_init(void)
|
||||
{
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve the information structure for the given thermal OID.
|
||||
*
|
||||
* If the OID is invalid, return ONLP_E_STATUS_INVALID.
|
||||
* If an unexpected error occurs, return ONLP_E_STATUS_INTERNAL.
|
||||
* Otherwise, return ONLP_STATUS_OK with the OID's information.
|
||||
*
|
||||
* Note -- it is expected that you fill out the information
|
||||
* structure even if the sensor described by the OID is not present.
|
||||
*/
|
||||
int
|
||||
onlp_thermali_info_get(onlp_oid_t id, onlp_thermal_info_t* info)
|
||||
{
|
||||
int local_id;
|
||||
VALIDATE(id);
|
||||
|
||||
local_id = ONLP_OID_ID_GET(id);
|
||||
|
||||
/* Set the onlp_oid_hdr_t and capabilities */
|
||||
*info = linfo[local_id];
|
||||
|
||||
if(local_id >= THERMAL_CPU_CORE_FIRST && local_id <= THERMAL_CPU_CORE_LAST) {
|
||||
char desc[32], *dp = &desc[0];
|
||||
int rv = onlp_file_read_str(&dp, devfiles__[local_id], "label");
|
||||
if (rv > 0) {
|
||||
memset (info->hdr.description, 0, ONLP_OID_DESC_SIZE);
|
||||
strncpy(info->hdr.description, dp, rv);
|
||||
}
|
||||
|
||||
/* Set the onlp_oid_hdr_t and capabilities */
|
||||
return onlp_file_read_int(&info->mcelsius, devfiles__[local_id], "input");
|
||||
}
|
||||
return onlp_file_read_int(&info->mcelsius, devfiles__[local_id]);
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_inventec_d6556/x86_64_inventec_d6556_config.h>
|
||||
|
||||
/* <auto.start.cdefs(x86_64_inventec_d6556_CONFIG_HEADER).source> */
|
||||
#define __x86_64_inventec_d6556_config_STRINGIFY_NAME(_x) #_x
|
||||
#define __x86_64_inventec_d6556_config_STRINGIFY_VALUE(_x) __x86_64_inventec_d6556_config_STRINGIFY_NAME(_x)
|
||||
x86_64_inventec_d6556_config_settings_t x86_64_inventec_d6556_config_settings[] =
|
||||
{
|
||||
#ifdef x86_64_inventec_d6556_CONFIG_INCLUDE_LOGGING
|
||||
{ __x86_64_inventec_d6556_config_STRINGIFY_NAME(x86_64_inventec_d6556_CONFIG_INCLUDE_LOGGING), __x86_64_inventec_d6556_config_STRINGIFY_VALUE(x86_64_inventec_d6556_CONFIG_INCLUDE_LOGGING) },
|
||||
#else
|
||||
{ x86_64_inventec_d6556_CONFIG_INCLUDE_LOGGING(__x86_64_inventec_d6556_config_STRINGIFY_NAME), "__undefined__" },
|
||||
#endif
|
||||
#ifdef x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT
|
||||
{ __x86_64_inventec_d6556_config_STRINGIFY_NAME(x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT), __x86_64_inventec_d6556_config_STRINGIFY_VALUE(x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT) },
|
||||
#else
|
||||
{ x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT(__x86_64_inventec_d6556_config_STRINGIFY_NAME), "__undefined__" },
|
||||
#endif
|
||||
#ifdef x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT
|
||||
{ __x86_64_inventec_d6556_config_STRINGIFY_NAME(x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT), __x86_64_inventec_d6556_config_STRINGIFY_VALUE(x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT) },
|
||||
#else
|
||||
{ x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT(__x86_64_inventec_d6556_config_STRINGIFY_NAME), "__undefined__" },
|
||||
#endif
|
||||
#ifdef x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT
|
||||
{ __x86_64_inventec_d6556_config_STRINGIFY_NAME(x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT), __x86_64_inventec_d6556_config_STRINGIFY_VALUE(x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT) },
|
||||
#else
|
||||
{ x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT(__x86_64_inventec_d6556_config_STRINGIFY_NAME), "__undefined__" },
|
||||
#endif
|
||||
#ifdef x86_64_inventec_d6556_CONFIG_PORTING_STDLIB
|
||||
{ __x86_64_inventec_d6556_config_STRINGIFY_NAME(x86_64_inventec_d6556_CONFIG_PORTING_STDLIB), __x86_64_inventec_d6556_config_STRINGIFY_VALUE(x86_64_inventec_d6556_CONFIG_PORTING_STDLIB) },
|
||||
#else
|
||||
{ x86_64_inventec_d6556_CONFIG_PORTING_STDLIB(__x86_64_inventec_d6556_config_STRINGIFY_NAME), "__undefined__" },
|
||||
#endif
|
||||
#ifdef x86_64_inventec_d6556_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS
|
||||
{ __x86_64_inventec_d6556_config_STRINGIFY_NAME(x86_64_inventec_d6556_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS), __x86_64_inventec_d6556_config_STRINGIFY_VALUE(x86_64_inventec_d6556_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS) },
|
||||
#else
|
||||
{ x86_64_inventec_d6556_CONFIG_PORTING_INCLUDE_STDLIB_HEADERS(__x86_64_inventec_d6556_config_STRINGIFY_NAME), "__undefined__" },
|
||||
#endif
|
||||
#ifdef x86_64_inventec_d6556_CONFIG_INCLUDE_UCLI
|
||||
{ __x86_64_inventec_d6556_config_STRINGIFY_NAME(x86_64_inventec_d6556_CONFIG_INCLUDE_UCLI), __x86_64_inventec_d6556_config_STRINGIFY_VALUE(x86_64_inventec_d6556_CONFIG_INCLUDE_UCLI) },
|
||||
#else
|
||||
{ x86_64_inventec_d6556_CONFIG_INCLUDE_UCLI(__x86_64_inventec_d6556_config_STRINGIFY_NAME), "__undefined__" },
|
||||
#endif
|
||||
#ifdef x86_64_inventec_d6556_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION
|
||||
{ __x86_64_inventec_d6556_config_STRINGIFY_NAME(x86_64_inventec_d6556_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION), __x86_64_inventec_d6556_config_STRINGIFY_VALUE(x86_64_inventec_d6556_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION) },
|
||||
#else
|
||||
{ x86_64_inventec_d6556_CONFIG_INCLUDE_DEFAULT_FAN_DIRECTION(__x86_64_inventec_d6556_config_STRINGIFY_NAME), "__undefined__" },
|
||||
#endif
|
||||
{ NULL, NULL }
|
||||
};
|
||||
#undef __x86_64_inventec_d6556_config_STRINGIFY_VALUE
|
||||
#undef __x86_64_inventec_d6556_config_STRINGIFY_NAME
|
||||
|
||||
const char*
|
||||
x86_64_inventec_d6556_config_lookup(const char* setting)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; x86_64_inventec_d6556_config_settings[i].name; i++) {
|
||||
if(strcmp(x86_64_inventec_d6556_config_settings[i].name, setting)) {
|
||||
return x86_64_inventec_d6556_config_settings[i].value;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
x86_64_inventec_d6556_config_show(struct aim_pvs_s* pvs)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; x86_64_inventec_d6556_config_settings[i].name; i++) {
|
||||
aim_printf(pvs, "%s = %s\n", x86_64_inventec_d6556_config_settings[i].name, x86_64_inventec_d6556_config_settings[i].value);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/* <auto.end.cdefs(x86_64_inventec_d6556_CONFIG_HEADER).source> */
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_inventec_d6556/x86_64_inventec_d6556_config.h>
|
||||
|
||||
/* <--auto.start.enum(ALL).source> */
|
||||
/* <auto.end.enum(ALL).source> */
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
* x86_64_inventec_d6556 Internal Header
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef __x86_64_inventec_d6556_INT_H__
|
||||
#define __x86_64_inventec_d6556_INT_H__
|
||||
|
||||
#include <x86_64_inventec_d6556/x86_64_inventec_d6556_config.h>
|
||||
|
||||
|
||||
#endif /* __x86_64_inventec_d6556_INT_H__ */
|
||||
@@ -0,0 +1,18 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_inventec_d6556/x86_64_inventec_d6556_config.h>
|
||||
|
||||
#include "x86_64_inventec_d6556_log.h"
|
||||
/*
|
||||
* x86_64_inventec_d6556 log struct.
|
||||
*/
|
||||
AIM_LOG_STRUCT_DEFINE(
|
||||
x86_64_inventec_d6556_CONFIG_LOG_OPTIONS_DEFAULT,
|
||||
x86_64_inventec_d6556_CONFIG_LOG_BITS_DEFAULT,
|
||||
NULL, /* Custom log map */
|
||||
x86_64_inventec_d6556_CONFIG_LOG_CUSTOM_BITS_DEFAULT
|
||||
);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef __x86_64_inventec_d6556_LOG_H__
|
||||
#define __x86_64_inventec_d6556_LOG_H__
|
||||
|
||||
#define AIM_LOG_MODULE_NAME x86_64_inventec_d6556
|
||||
#include <AIM/aim_log.h>
|
||||
|
||||
#endif /* __x86_64_inventec_d6556_LOG_H__ */
|
||||
@@ -0,0 +1,24 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_inventec_d6556/x86_64_inventec_d6556_config.h>
|
||||
|
||||
#include "x86_64_inventec_d6556_log.h"
|
||||
|
||||
static int
|
||||
datatypes_init__(void)
|
||||
{
|
||||
#define x86_64_inventec_d6556_ENUMERATION_ENTRY(_enum_name, _desc) AIM_DATATYPE_MAP_REGISTER(_enum_name, _enum_name##_map, _desc, AIM_LOG_INTERNAL);
|
||||
#include <x86_64_inventec_d6556/x86_64_inventec_d6556.x>
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __x86_64_inventec_d6556_module_init__(void)
|
||||
{
|
||||
AIM_LOG_STRUCT_REGISTER();
|
||||
datatypes_init__();
|
||||
}
|
||||
|
||||
int __onlp_platform_version__ = 1;
|
||||
@@ -0,0 +1,50 @@
|
||||
/**************************************************************************//**
|
||||
*
|
||||
*
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <x86_64_inventec_d6556/x86_64_inventec_d6556_config.h>
|
||||
|
||||
#if x86_64_inventec_d6556_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_inventec_d6556_ucli_ucli__config__(ucli_context_t* uc)
|
||||
{
|
||||
UCLI_HANDLER_MACRO_MODULE_CONFIG(x86_64_inventec_d6556)
|
||||
}
|
||||
|
||||
/* <auto.ucli.handlers.start> */
|
||||
/* <auto.ucli.handlers.end> */
|
||||
|
||||
static ucli_module_t
|
||||
x86_64_inventec_d6556_ucli_module__ =
|
||||
{
|
||||
"x86_64_inventec_d6556_ucli",
|
||||
NULL,
|
||||
x86_64_inventec_d6556_ucli_ucli_handlers__,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
ucli_node_t*
|
||||
x86_64_inventec_d6556_ucli_node_create(void)
|
||||
{
|
||||
ucli_node_t* n;
|
||||
ucli_module_init(&x86_64_inventec_d6556_ucli_module__);
|
||||
n = ucli_node_create("x86_64_inventec_d6556", NULL, &x86_64_inventec_d6556_ucli_module__);
|
||||
ucli_node_subnode_add(n, ucli_module_log_node_create("x86_64_inventec_d6556"));
|
||||
return n;
|
||||
}
|
||||
|
||||
#else
|
||||
void*
|
||||
x86_64_inventec_d6556_ucli_node_create(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Inclusive Makefile for the x86_64_inventec_d6556 module.
|
||||
#
|
||||
# Autogenerated 2018-11-30 07:22:11.055018
|
||||
#
|
||||
###############################################################################
|
||||
x86_64_inventec_d6556_BASEDIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
include $(x86_64_inventec_d6556_BASEDIR)module/make.mk
|
||||
include $(x86_64_inventec_d6556_BASEDIR)module/src/make.mk
|
||||
include $(x86_64_inventec_d6556_BASEDIR)module/auto/make.mk
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -0,0 +1 @@
|
||||
!include $ONL_TEMPLATES/platform-config-platform.yml ARCH=amd64 VENDOR=inventec BASENAME=x86-64-inventec-d6556 REVISION=r0
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
|
||||
######################################################################
|
||||
#
|
||||
# platform-config for d6556
|
||||
#
|
||||
######################################################################
|
||||
|
||||
x86-64-inventec-d6556-r0:
|
||||
|
||||
grub:
|
||||
|
||||
serial: >-
|
||||
--port=0x3f8
|
||||
--speed=115200
|
||||
--word=8
|
||||
--parity=no
|
||||
--stop=1
|
||||
|
||||
kernel:
|
||||
<<: *kernel-3-16
|
||||
|
||||
args: >-
|
||||
nopat
|
||||
console=ttyS0,115200n8
|
||||
|
||||
##network
|
||||
## interfaces:
|
||||
## ma1:
|
||||
## name: ~
|
||||
## syspath: pci0000:00/0000:00:14.0
|
||||
@@ -0,0 +1,22 @@
|
||||
from onl.platform.base import *
|
||||
from onl.platform.inventec import *
|
||||
|
||||
class OnlPlatform_x86_64_inventec_d6556_r0(OnlPlatformInventec,
|
||||
OnlPlatformPortConfig_48x25_8x100):
|
||||
PLATFORM='x86-64-inventec-d6556-r0'
|
||||
MODEL="D6556"
|
||||
SYS_OBJECT_ID=".6556.1"
|
||||
|
||||
def baseconfig(self):
|
||||
os.system("insmod /lib/modules/`uname -r`/kernel/drivers/gpio/gpio-ich.ko gpiobase=0")
|
||||
self.insmod('i2c-gpio')
|
||||
self.insmod('inv_platform')
|
||||
self.insmod('inv_psoc')
|
||||
self.new_i2c_device('inv_cpld', 0x55, 0)
|
||||
self.insmod('inv_cpld')
|
||||
self.new_i2c_device('inv_eeprom', 0x53, 0)
|
||||
self.insmod('inv_eeprom')
|
||||
self.insmod('swps')
|
||||
self.insmod('vpd')
|
||||
self.insmod('inv_pthread')
|
||||
return True
|
||||
@@ -1,4 +1,3 @@
|
||||
#obj-m += gpio-ich.o
|
||||
obj-m += inv_platform.o
|
||||
obj-m += inv_cpld.o
|
||||
obj-m += inv_psoc.o
|
||||
|
||||
@@ -1733,14 +1733,6 @@ common_get_eeprom(struct transvr_obj_s *self, char *buf){
|
||||
|
||||
int err = DEBUG_TRANSVR_INT_VAL;
|
||||
|
||||
if (self->state == STATE_TRANSVR_CONNECTED &&
|
||||
self->mode == TRANSVR_MODE_POLLING &&
|
||||
TRANSVR_INFO_CACHE_ENABLE) {
|
||||
memset(buf, 0, self->eeprom_map_p->length_eeprom+1);
|
||||
memcpy(buf, self->eeprom, self->eeprom_map_p->length_eeprom);
|
||||
*(buf+self->eeprom_map_p->length_eeprom) = '\n';
|
||||
return self->eeprom_map_p->length_eeprom+1;
|
||||
}
|
||||
err = _check_by_mode(self, &_common_update_attr_eeprom,
|
||||
"common_get_eeprom");
|
||||
if (err < 0){
|
||||
|
||||
@@ -23,21 +23,7 @@
|
||||
#define PROJECT_NAME
|
||||
#define LEN_FILE_NAME 80
|
||||
|
||||
enum fan_id {
|
||||
FAN_RESERVED,
|
||||
FAN_1_ON_MAIN_BOARD,
|
||||
FAN_2_ON_MAIN_BOARD,
|
||||
FAN_3_ON_MAIN_BOARD,
|
||||
FAN_4_ON_MAIN_BOARD,
|
||||
FAN_5_ON_MAIN_BOARD,
|
||||
FAN_6_ON_MAIN_BOARD,
|
||||
FAN_7_ON_MAIN_BOARD,
|
||||
FAN_8_ON_MAIN_BOARD,
|
||||
FAN_1_ON_PSU1,
|
||||
FAN_1_ON_PSU2,
|
||||
};
|
||||
|
||||
static char* devfiles__[CHASSIS_FAN_COUNT+1] = /* must map with onlp_thermal_id */
|
||||
static char* devfiles__[FAN_MAX] = /* must map with onlp_thermal_id */
|
||||
{
|
||||
"reserved",
|
||||
INV_PSOC_PREFIX"/fan1_input",
|
||||
@@ -73,7 +59,7 @@ static char* devfiles__[CHASSIS_FAN_COUNT+1] = /* must map with onlp_thermal_id
|
||||
}
|
||||
|
||||
/* Static fan information */
|
||||
onlp_fan_info_t linfo[] = {
|
||||
onlp_fan_info_t linfo[FAN_MAX] = {
|
||||
{ }, /* Not used */
|
||||
MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(1),
|
||||
MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(2),
|
||||
@@ -163,7 +149,7 @@ _onlp_get_fan_direction_on_psu(void)
|
||||
static int
|
||||
_onlp_fani_info_get_fan_on_psu(int fid, onlp_fan_info_t* info)
|
||||
{
|
||||
int value, ret;
|
||||
int value, ret, index;
|
||||
char vstr[32], *vstrp = vstr, **vp = &vstrp;
|
||||
|
||||
info->status |= ONLP_FAN_STATUS_PRESENT;
|
||||
@@ -172,6 +158,13 @@ _onlp_fani_info_get_fan_on_psu(int fid, onlp_fan_info_t* info)
|
||||
/* get fan direction */
|
||||
info->status |= _onlp_get_fan_direction_on_psu();
|
||||
|
||||
if (info->status & ONLP_FAN_STATUS_FAILED) {
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
index = ONLP_OID_ID_GET(info->hdr.id);
|
||||
info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT);
|
||||
|
||||
/* get front fan speed */
|
||||
memset(vstr, 0, 32);
|
||||
ret = onlp_file_read_str(vp, devfiles__[fid]);
|
||||
@@ -182,6 +175,10 @@ _onlp_fani_info_get_fan_on_psu(int fid, onlp_fan_info_t* info)
|
||||
info->rpm = value;
|
||||
info->percentage = (info->rpm * 100) / MAX_PSU_FAN_SPEED;
|
||||
info->status |= (value == 0) ? ONLP_FAN_STATUS_FAILED : 0;
|
||||
|
||||
snprintf(info->model, ONLP_CONFIG_INFO_STR_MAX, "NA");
|
||||
snprintf(info->serial, ONLP_CONFIG_INFO_STR_MAX, "NA");
|
||||
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
@@ -255,9 +252,9 @@ onlp_fani_percentage_set(onlp_oid_t id, int p)
|
||||
switch (fid)
|
||||
{
|
||||
case FAN_1_ON_PSU1:
|
||||
return psu_pmbus_info_set(PSU1_ID, "rpm_psu", p);
|
||||
return psu_pmbus_info_set(PSU1_ID, "rpm_psu1", p);
|
||||
case FAN_1_ON_PSU2:
|
||||
return psu_pmbus_info_set(PSU2_ID, "rpm_psu", p);
|
||||
return psu_pmbus_info_set(PSU2_ID, "rpm_psu2", p);
|
||||
case FAN_1_ON_MAIN_BOARD:
|
||||
case FAN_2_ON_MAIN_BOARD:
|
||||
case FAN_3_ON_MAIN_BOARD:
|
||||
|
||||
@@ -25,18 +25,7 @@
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* LED related data */
|
||||
enum onlp_led_id
|
||||
{
|
||||
LED_RESERVED = 0,
|
||||
LED_SYS,
|
||||
LED_FAN1,
|
||||
LED_FAN2,
|
||||
LED_FAN3,
|
||||
LED_FAN4
|
||||
};
|
||||
|
||||
static char* devfiles__[CHASSIS_LED_COUNT+1] = /* must map with onlp_thermal_id */
|
||||
static char* devfiles__[LED_MAX] = /* must map with onlp_thermal_id */
|
||||
{
|
||||
"reserved",
|
||||
INV_CPLD_PREFIX"/%s_led",
|
||||
@@ -90,7 +79,7 @@ static char last_path[][10] = /* must map with onlp_led_id */
|
||||
/*
|
||||
* Get the information for the given LED OID.
|
||||
*/
|
||||
static onlp_led_info_t linfo[] =
|
||||
static onlp_led_info_t linfo[LED_MAX] =
|
||||
{
|
||||
{ }, /* Not used */
|
||||
{
|
||||
|
||||
@@ -14,18 +14,14 @@
|
||||
#define ONLP_NODE_MAX_INT_LEN (8)
|
||||
#define ONLP_NODE_MAX_PATH_LEN (64)
|
||||
|
||||
#define CHASSIS_PSU_COUNT (2)
|
||||
#define CHASSIS_LED_COUNT (5)
|
||||
#define CHASSIS_FAN_COUNT (10)
|
||||
#define CHASSIS_SFP_COUNT (32)
|
||||
#define CHASSIS_THERMAL_COUNT (11)
|
||||
|
||||
#define INV_CPLD_COUNT (1)
|
||||
#define INV_CPLD_PREFIX "/sys/bus/i2c/devices/0-0055/"
|
||||
#define INV_PSOC_PREFIX "/sys/bus/i2c/devices/0-0066/"
|
||||
#define INV_EPRM_PREFIX "/sys/bus/i2c/devices/0-0053/"
|
||||
#define INV_CTMP_PREFIX "/sys/devices/platform/coretemp.0/hwmon/hwmon0/"
|
||||
|
||||
#define CHASSIS_SFP_COUNT (32)
|
||||
|
||||
/*
|
||||
* Definitions of Chassis EEPROM
|
||||
*/
|
||||
@@ -34,12 +30,60 @@
|
||||
/*
|
||||
* Definitions of PSU device
|
||||
*/
|
||||
enum onlp_thermal_id
|
||||
{
|
||||
THERMAL_RESERVED = 0,
|
||||
THERMAL_CPU_CORE_FIRST,
|
||||
THERMAL_CPU_CORE_3,
|
||||
THERMAL_CPU_CORE_4,
|
||||
THERMAL_CPU_CORE_LAST,
|
||||
THERMAL_1_ON_MAIN_BROAD,
|
||||
THERMAL_2_ON_MAIN_BROAD,
|
||||
THERMAL_3_ON_MAIN_BROAD,
|
||||
THERMAL_4_ON_MAIN_BROAD,
|
||||
THERMAL_5_ON_MAIN_BROAD,
|
||||
THERMAL_1_ON_PSU1,
|
||||
THERMAL_1_ON_PSU2,
|
||||
THERMAL_MAX
|
||||
};
|
||||
#define CHASSIS_THERMAL_COUNT (9)
|
||||
|
||||
enum fan_id {
|
||||
FAN_RESERVED = 0,
|
||||
FAN_1_ON_MAIN_BOARD,
|
||||
FAN_2_ON_MAIN_BOARD,
|
||||
FAN_3_ON_MAIN_BOARD,
|
||||
FAN_4_ON_MAIN_BOARD,
|
||||
FAN_5_ON_MAIN_BOARD,
|
||||
FAN_6_ON_MAIN_BOARD,
|
||||
FAN_7_ON_MAIN_BOARD,
|
||||
FAN_8_ON_MAIN_BOARD,
|
||||
FAN_1_ON_PSU1,
|
||||
FAN_1_ON_PSU2,
|
||||
FAN_MAX
|
||||
};
|
||||
#define CHASSIS_FAN_COUNT (8)
|
||||
|
||||
enum onlp_led_id
|
||||
{
|
||||
LED_RESERVED = 0,
|
||||
LED_SYS,
|
||||
LED_FAN1,
|
||||
LED_FAN2,
|
||||
LED_FAN3,
|
||||
LED_FAN4,
|
||||
LED_MAX
|
||||
};
|
||||
#define CHASSIS_LED_COUNT (1)
|
||||
|
||||
enum onlp_psu_id
|
||||
{
|
||||
PSU_RESERVED = 0,
|
||||
PSU1_ID,
|
||||
PSU2_ID
|
||||
PSU2_ID,
|
||||
PSU_MAX
|
||||
};
|
||||
#define CHASSIS_PSU_COUNT (2)
|
||||
|
||||
#define PSU1_AC_PMBUS_PREFIX INV_PSOC_PREFIX
|
||||
#define PSU2_AC_PMBUS_PREFIX INV_PSOC_PREFIX
|
||||
|
||||
@@ -27,14 +27,21 @@
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static char* status_devfiles__[CHASSIS_PSU_COUNT+1] = /* must map with onlp_psu_id */
|
||||
static char* status_devfiles__[PSU_MAX] = /* must map with onlp_psu_id */
|
||||
{
|
||||
"reserved",
|
||||
INV_CPLD_PREFIX"/psu0",
|
||||
INV_CPLD_PREFIX"/psu1",
|
||||
};
|
||||
|
||||
static char* module_devfiles__[CHASSIS_PSU_COUNT+1] = /* must map with onlp_psu_id */
|
||||
static char* module_devfiles__[PSU_MAX] = /* must map with onlp_psu_id */
|
||||
{
|
||||
"reserved",
|
||||
INV_PSOC_PREFIX"/psu1_%s",
|
||||
INV_PSOC_PREFIX"/psu2_%s",
|
||||
};
|
||||
|
||||
static char* module2_devfiles__[PSU_MAX] = /* must map with onlp_psu_id */
|
||||
{
|
||||
"reserved",
|
||||
INV_PSOC_PREFIX"/psoc_psu1_%s",
|
||||
@@ -83,69 +90,97 @@ psu_module_info_get(int id, onlp_psu_info_t* info)
|
||||
{
|
||||
int ret = 0;
|
||||
char node_path[ONLP_NODE_MAX_PATH_LEN] = {0};
|
||||
char vstr[32], *vstrp = vstr, **vp = &vstrp;
|
||||
int value = 0;
|
||||
|
||||
info->caps |= ONLP_PSU_CAPS_DC12;
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "vout");
|
||||
sprintf(node_path, module2_devfiles__[id], "vout");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path);
|
||||
AIM_LOG_ERROR("Unable to read vout from file(%s)\r\n", node_path);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
info->mvout = value;
|
||||
info->caps |= ONLP_PSU_CAPS_VOUT;
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "iout");
|
||||
sprintf(node_path, module2_devfiles__[id], "iout");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
AIM_LOG_ERROR("Unable to read iout from file(%s)\r\n", node_path);
|
||||
}
|
||||
else {
|
||||
info->miout = value;
|
||||
info->caps |= ONLP_PSU_CAPS_IOUT;
|
||||
}
|
||||
info->miout = value;
|
||||
info->caps |= ONLP_PSU_CAPS_IOUT;
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "pout");
|
||||
sprintf(node_path, module2_devfiles__[id], "pout");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
AIM_LOG_ERROR("Unable to read pout from file(%s)\r\n", node_path);
|
||||
}
|
||||
else {
|
||||
info->mpout = value;
|
||||
info->caps |= ONLP_PSU_CAPS_POUT;
|
||||
}
|
||||
info->mpout = value;
|
||||
info->caps |= ONLP_PSU_CAPS_POUT;
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "vin");
|
||||
sprintf(node_path, module2_devfiles__[id], "vin");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
AIM_LOG_ERROR("Unable to read vin from file(%s)\r\n", node_path);
|
||||
}
|
||||
else {
|
||||
info->mvin = value;
|
||||
info->caps |= ONLP_PSU_CAPS_VIN;
|
||||
}
|
||||
info->mvin = value;
|
||||
info->caps |= ONLP_PSU_CAPS_VIN;
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "iin");
|
||||
sprintf(node_path, module2_devfiles__[id], "iin");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
AIM_LOG_ERROR("Unable to read iin from file(%s)\r\n", node_path);
|
||||
}
|
||||
else {
|
||||
info->miin = value;
|
||||
info->caps |= ONLP_PSU_CAPS_IIN;
|
||||
}
|
||||
info->miin = value;
|
||||
info->caps |= ONLP_PSU_CAPS_IIN;
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "pin");
|
||||
sprintf(node_path, module2_devfiles__[id], "pin");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
AIM_LOG_ERROR("Unable to read pin from file(%s)\r\n", node_path);
|
||||
}
|
||||
else {
|
||||
info->mpin = value;
|
||||
info->caps |= ONLP_PSU_CAPS_PIN;
|
||||
}
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "model");
|
||||
ret = onlp_file_read_str(vp, node_path);
|
||||
if (ret > 0) {
|
||||
strncpy(info->model, *vp, ret-1);
|
||||
}
|
||||
else {
|
||||
AIM_LOG_ERROR("Unable to read model name from file(%s)\r\n", node_path);
|
||||
strncpy(info->model, "N/A", 3);
|
||||
}
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "sn");
|
||||
ret = onlp_file_read_str(vp, node_path);
|
||||
if (ret > 0) {
|
||||
strncpy(info->serial, *vp, ret-1);
|
||||
}
|
||||
else {
|
||||
AIM_LOG_ERROR("Unable to read model name from file(%s)\r\n", node_path);
|
||||
strncpy(info->serial, "N/A", 3);
|
||||
}
|
||||
info->mpin = value;
|
||||
info->caps |= ONLP_PSU_CAPS_PIN;
|
||||
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
@@ -157,10 +192,22 @@ static onlp_psu_info_t pinfo[] =
|
||||
{
|
||||
{ }, /* Not used */
|
||||
{
|
||||
{ ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0 },
|
||||
{
|
||||
ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0,
|
||||
{
|
||||
ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1),
|
||||
ONLP_FAN_ID_CREATE(FAN_1_ON_PSU1)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
{ ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0 },
|
||||
{
|
||||
ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0,
|
||||
{
|
||||
ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2),
|
||||
ONLP_FAN_ID_CREATE(FAN_1_ON_PSU2)
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@@ -178,7 +225,7 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info)
|
||||
|
||||
/* Get the present state */
|
||||
if ((ret = psu_status_info_get(index, "psu", &val)) == ONLP_STATUS_E_INTERNAL) {
|
||||
printf("Unable to read PSU(%d) node(psu_present)\r\n", index);
|
||||
printf("Unable to read PSU(%d) node(psu)\r\n", index);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -140,6 +140,17 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
|
||||
int
|
||||
onlp_sfpi_eeprom_read(int port, uint8_t data[256])
|
||||
{
|
||||
#if 1
|
||||
int bus = FRONT_PORT_TO_MUX_INDEX(port);
|
||||
|
||||
memset(data, 0, 256);
|
||||
/* Read eeprom information into data[] */
|
||||
if (onlp_i2c_read(bus, 0x50, 0x00, 256, data, 0) != 0)
|
||||
{
|
||||
AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
#else
|
||||
char* path;
|
||||
int len = 0;
|
||||
/*
|
||||
@@ -154,6 +165,7 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256])
|
||||
AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
#endif
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,23 +22,7 @@
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
enum onlp_thermal_id
|
||||
{
|
||||
THERMAL_RESERVED = 0,
|
||||
THERMAL_CPU_CORE_FIRST,
|
||||
THERMAL_CPU_CORE_3,
|
||||
THERMAL_CPU_CORE_4,
|
||||
THERMAL_CPU_CORE_LAST,
|
||||
THERMAL_1_ON_MAIN_BROAD,
|
||||
THERMAL_2_ON_MAIN_BROAD,
|
||||
THERMAL_3_ON_MAIN_BROAD,
|
||||
THERMAL_4_ON_MAIN_BROAD,
|
||||
THERMAL_5_ON_MAIN_BROAD,
|
||||
THERMAL_1_ON_PSU1,
|
||||
THERMAL_1_ON_PSU2,
|
||||
};
|
||||
|
||||
static char* devfiles__[CHASSIS_THERMAL_COUNT+1] = /* must map with onlp_thermal_id */
|
||||
static char* devfiles__[THERMAL_MAX] = /* must map with onlp_thermal_id */
|
||||
{
|
||||
"reserved",
|
||||
INV_CTMP_PREFIX"/temp2_%s",
|
||||
@@ -55,7 +39,7 @@ static char* devfiles__[CHASSIS_THERMAL_COUNT+1] = /* must map with onlp_therma
|
||||
};
|
||||
|
||||
/* Static values */
|
||||
static onlp_thermal_info_t linfo[CHASSIS_THERMAL_COUNT+1] = {
|
||||
static onlp_thermal_info_t linfo[THERMAL_MAX] = {
|
||||
{ }, /* Not used */
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_FIRST), "CPU Core 0", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
|
||||
@@ -5,7 +5,7 @@ class OnlPlatform_x86_64_inventec_d7032q28b_r0(OnlPlatformInventec,
|
||||
OnlPlatformPortConfig_32x100):
|
||||
PLATFORM='x86-64-inventec-d7032q28b-r0'
|
||||
MODEL="X86-D7032Q28B"
|
||||
SYS_OBJECT_ID="7032.28"
|
||||
SYS_OBJECT_ID=".7032.1"
|
||||
|
||||
def baseconfig(self):
|
||||
os.system("insmod /lib/modules/`uname -r`/kernel/drivers/gpio/gpio-ich.ko gpiobase=0")
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#obj-m += gpio-ich.o
|
||||
obj-m += inv_platform.o
|
||||
obj-m += inv_cpld.o
|
||||
obj-m += inv_psoc.o
|
||||
|
||||
@@ -1731,14 +1731,6 @@ common_get_eeprom(struct transvr_obj_s *self, char *buf){
|
||||
|
||||
int err = DEBUG_TRANSVR_INT_VAL;
|
||||
|
||||
if (self->state == STATE_TRANSVR_CONNECTED &&
|
||||
self->mode == TRANSVR_MODE_POLLING &&
|
||||
TRANSVR_INFO_CACHE_ENABLE) {
|
||||
memset(buf, 0, self->eeprom_map_p->length_eeprom+1);
|
||||
memcpy(buf, self->eeprom, self->eeprom_map_p->length_eeprom);
|
||||
*(buf+self->eeprom_map_p->length_eeprom) = '\n';
|
||||
return self->eeprom_map_p->length_eeprom+1;
|
||||
}
|
||||
err = _check_by_mode(self, &_common_update_attr_eeprom,
|
||||
"common_get_eeprom");
|
||||
if (err < 0){
|
||||
|
||||
@@ -23,21 +23,7 @@
|
||||
#define PROJECT_NAME
|
||||
#define LEN_FILE_NAME 80
|
||||
|
||||
enum fan_id {
|
||||
FAN_RESERVED,
|
||||
FAN_1_ON_MAIN_BOARD,
|
||||
FAN_2_ON_MAIN_BOARD,
|
||||
FAN_3_ON_MAIN_BOARD,
|
||||
FAN_4_ON_MAIN_BOARD,
|
||||
FAN_5_ON_MAIN_BOARD,
|
||||
FAN_6_ON_MAIN_BOARD,
|
||||
FAN_7_ON_MAIN_BOARD,
|
||||
FAN_8_ON_MAIN_BOARD,
|
||||
FAN_1_ON_PSU1,
|
||||
FAN_1_ON_PSU2,
|
||||
};
|
||||
|
||||
static char* devfiles__[CHASSIS_FAN_COUNT+1] = /* must map with onlp_thermal_id */
|
||||
static char* devfiles__[FAN_MAX] = /* must map with onlp_thermal_id */
|
||||
{
|
||||
"reserved",
|
||||
INV_PSOC_PREFIX"/fan1_input",
|
||||
@@ -73,7 +59,7 @@ static char* devfiles__[CHASSIS_FAN_COUNT+1] = /* must map with onlp_thermal_id
|
||||
}
|
||||
|
||||
/* Static fan information */
|
||||
onlp_fan_info_t linfo[] = {
|
||||
onlp_fan_info_t linfo[FAN_MAX] = {
|
||||
{ }, /* Not used */
|
||||
MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(1),
|
||||
MAKE_FAN_INFO_NODE_ON_MAIN_BOARD(2),
|
||||
@@ -163,7 +149,7 @@ _onlp_get_fan_direction_on_psu(void)
|
||||
static int
|
||||
_onlp_fani_info_get_fan_on_psu(int fid, onlp_fan_info_t* info)
|
||||
{
|
||||
int value, ret;
|
||||
int value, ret, index;
|
||||
char vstr[32], *vstrp = vstr, **vp = &vstrp;
|
||||
|
||||
info->status |= ONLP_FAN_STATUS_PRESENT;
|
||||
@@ -172,6 +158,12 @@ _onlp_fani_info_get_fan_on_psu(int fid, onlp_fan_info_t* info)
|
||||
/* get fan direction */
|
||||
info->status |= _onlp_get_fan_direction_on_psu();
|
||||
|
||||
if (info->status & ONLP_FAN_STATUS_FAILED) {
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
index = ONLP_OID_ID_GET(info->hdr.id);
|
||||
info->hdr.coids[0] = ONLP_FAN_ID_CREATE(index + CHASSIS_FAN_COUNT);
|
||||
/* get front fan speed */
|
||||
memset(vstr, 0, 32);
|
||||
ret = onlp_file_read_str(vp, devfiles__[fid]);
|
||||
@@ -189,7 +181,6 @@ _onlp_fani_info_get_fan_on_psu(int fid, onlp_fan_info_t* info)
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function will be called prior to all of onlp_fani_* functions.
|
||||
*/
|
||||
@@ -208,7 +199,6 @@ onlp_fani_info_get(onlp_oid_t id, onlp_fan_info_t* info)
|
||||
|
||||
local_id = ONLP_OID_ID_GET(id);
|
||||
*info = linfo[local_id];
|
||||
|
||||
switch (local_id)
|
||||
{
|
||||
case FAN_1_ON_PSU1:
|
||||
@@ -259,9 +249,9 @@ onlp_fani_percentage_set(onlp_oid_t id, int p)
|
||||
switch (fid)
|
||||
{
|
||||
case FAN_1_ON_PSU1:
|
||||
return psu_pmbus_info_set(PSU1_ID, "rpm_psu", p);
|
||||
return psu_pmbus_info_set(PSU1_ID, "rpm_psu1", p);
|
||||
case FAN_1_ON_PSU2:
|
||||
return psu_pmbus_info_set(PSU2_ID, "rpm_psu", p);
|
||||
return psu_pmbus_info_set(PSU2_ID, "rpm_psu2", p);
|
||||
case FAN_1_ON_MAIN_BOARD:
|
||||
case FAN_2_ON_MAIN_BOARD:
|
||||
case FAN_3_ON_MAIN_BOARD:
|
||||
|
||||
@@ -25,18 +25,7 @@
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* LED related data */
|
||||
enum onlp_led_id
|
||||
{
|
||||
LED_RESERVED = 0,
|
||||
LED_SYS,
|
||||
LED_FAN1,
|
||||
LED_FAN2,
|
||||
LED_FAN3,
|
||||
LED_FAN4
|
||||
};
|
||||
|
||||
static char* devfiles__[CHASSIS_LED_COUNT+1] = /* must map with onlp_thermal_id */
|
||||
static char* devfiles__[LED_MAX] = /* must map with onlp_thermal_id */
|
||||
{
|
||||
"reserved",
|
||||
INV_CPLD_PREFIX"/%s_led",
|
||||
@@ -90,7 +79,7 @@ static char last_path[][10] = /* must map with onlp_led_id */
|
||||
/*
|
||||
* Get the information for the given LED OID.
|
||||
*/
|
||||
static onlp_led_info_t linfo[] =
|
||||
static onlp_led_info_t linfo[LED_MAX] =
|
||||
{
|
||||
{ }, /* Not used */
|
||||
{
|
||||
|
||||
@@ -45,8 +45,8 @@ int onlp_file_read_string(char *filename, char *buffer, int buf_size, int data_l
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define I2C_PSU_MODEL_NAME_LEN 11
|
||||
#define I2C_PSU_FAN_DIR_LEN 3
|
||||
#define I2C_PSU_MODEL_NAME_LEN 32
|
||||
#define I2C_PSU_FAN_DIR_LEN 8
|
||||
#include <ctype.h>
|
||||
psu_type_t get_psu_type(int id, char* modelname, int modelname_len)
|
||||
{
|
||||
@@ -62,7 +62,7 @@ psu_type_t get_psu_type(int id, char* modelname, int modelname_len)
|
||||
}
|
||||
|
||||
if(isspace(model_name[strlen(model_name)-1])) {
|
||||
model_name[strlen(model_name)-1] = 0;
|
||||
model_name[strlen(model_name)] = 0;
|
||||
}
|
||||
|
||||
if (strncmp(model_name, "YM-2651Y", 8) == 0) {
|
||||
@@ -126,6 +126,14 @@ psu_type_t get_psu_type(int id, char* modelname, int modelname_len)
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp(model_name, "DPS-150AB-10", 12) == 0) {
|
||||
if (modelname) {
|
||||
strncpy(modelname, model_name, 12);
|
||||
}
|
||||
|
||||
return PSU_TYPE_DC_12V_F2B;
|
||||
}
|
||||
|
||||
return PSU_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,18 +16,14 @@
|
||||
#define ONLP_NODE_MAX_INT_LEN (8)
|
||||
#define ONLP_NODE_MAX_PATH_LEN (64)
|
||||
|
||||
#define CHASSIS_PSU_COUNT (2)
|
||||
#define CHASSIS_LED_COUNT (5)
|
||||
#define CHASSIS_FAN_COUNT (10)
|
||||
#define CHASSIS_SFP_COUNT (54)
|
||||
#define CHASSIS_THERMAL_COUNT (14)
|
||||
|
||||
#define INV_CPLD_COUNT (1)
|
||||
#define INV_CPLD_PREFIX "/sys/bus/i2c/devices/0-0055/"
|
||||
#define INV_PSOC_PREFIX "/sys/bus/i2c/devices/0-0066/"
|
||||
#define INV_EPRM_PREFIX "/sys/bus/i2c/devices/0-0053/"
|
||||
#define INV_CTMP_PREFIX "/sys/devices/platform/coretemp.0/hwmon/hwmon0/"
|
||||
|
||||
#define CHASSIS_SFP_COUNT (54)
|
||||
|
||||
/*
|
||||
* Definitions of Chassis EEPROM
|
||||
*/
|
||||
@@ -35,14 +31,66 @@
|
||||
|
||||
|
||||
/*
|
||||
* Definitions of PSU device
|
||||
* Definitions of D7054Q28B device
|
||||
*/
|
||||
enum onlp_thermal_id
|
||||
{
|
||||
THERMAL_RESERVED = 0,
|
||||
THERMAL_CPU_CORE_FIRST,
|
||||
THERMAL_CPU_CORE_2,
|
||||
THERMAL_CPU_CORE_3,
|
||||
THERMAL_CPU_CORE_4,
|
||||
THERMAL_CPU_CORE_LAST,
|
||||
THERMAL_1_ON_MAIN_BROAD,
|
||||
THERMAL_2_ON_MAIN_BROAD,
|
||||
THERMAL_3_ON_MAIN_BROAD,
|
||||
THERMAL_4_ON_MAIN_BROAD,
|
||||
THERMAL_5_ON_MAIN_BROAD,
|
||||
THERMAL_1_ON_PSU1,
|
||||
THERMAL_2_ON_PSU1,
|
||||
THERMAL_1_ON_PSU2,
|
||||
THERMAL_2_ON_PSU2,
|
||||
THERMAL_MAX
|
||||
};
|
||||
#define CHASSIS_THERMAL_COUNT (10)
|
||||
|
||||
enum onlp_fan_id {
|
||||
FAN_RESERVED = 0,
|
||||
FAN_1_ON_MAIN_BOARD,
|
||||
FAN_2_ON_MAIN_BOARD,
|
||||
FAN_3_ON_MAIN_BOARD,
|
||||
FAN_4_ON_MAIN_BOARD,
|
||||
FAN_5_ON_MAIN_BOARD,
|
||||
FAN_6_ON_MAIN_BOARD,
|
||||
FAN_7_ON_MAIN_BOARD,
|
||||
FAN_8_ON_MAIN_BOARD,
|
||||
FAN_1_ON_PSU1,
|
||||
FAN_1_ON_PSU2,
|
||||
FAN_MAX
|
||||
};
|
||||
#define CHASSIS_FAN_COUNT (8)
|
||||
|
||||
enum onlp_led_id
|
||||
{
|
||||
LED_RESERVED = 0,
|
||||
LED_SYS,
|
||||
LED_FAN1,
|
||||
LED_FAN2,
|
||||
LED_FAN3,
|
||||
LED_FAN4,
|
||||
LED_MAX
|
||||
};
|
||||
#define CHASSIS_LED_COUNT (1)
|
||||
|
||||
|
||||
enum onlp_psu_id
|
||||
{
|
||||
PSU_RESERVED = 0,
|
||||
PSU1_ID,
|
||||
PSU2_ID
|
||||
PSU2_ID,
|
||||
PSU_MAX
|
||||
};
|
||||
#define CHASSIS_PSU_COUNT (2)
|
||||
|
||||
#define PSU1_AC_PMBUS_PREFIX INV_PSOC_PREFIX
|
||||
#define PSU2_AC_PMBUS_PREFIX INV_PSOC_PREFIX
|
||||
|
||||
@@ -27,14 +27,14 @@
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static char* status_devfiles__[CHASSIS_PSU_COUNT+1] = /* must map with onlp_psu_id */
|
||||
static char* status_devfiles__[PSU_MAX] = /* must map with onlp_psu_id */
|
||||
{
|
||||
"reserved",
|
||||
INV_CPLD_PREFIX"/psu0",
|
||||
INV_CPLD_PREFIX"/psu1",
|
||||
};
|
||||
|
||||
static char* module_devfiles__[CHASSIS_PSU_COUNT+1] = /* must map with onlp_psu_id */
|
||||
static char* module_devfiles__[PSU_MAX] = /* must map with onlp_psu_id */
|
||||
{
|
||||
"reserved",
|
||||
INV_PSOC_PREFIX"/psoc_psu1_%s",
|
||||
@@ -83,6 +83,7 @@ psu_module_info_get(int id, onlp_psu_info_t* info)
|
||||
{
|
||||
int ret = 0;
|
||||
char node_path[ONLP_NODE_MAX_PATH_LEN] = {0};
|
||||
char vstr[32], *vstrp = vstr, **vp = &vstrp;
|
||||
int value = 0;
|
||||
|
||||
info->caps |= ONLP_PSU_CAPS_DC12;
|
||||
@@ -91,61 +92,89 @@ psu_module_info_get(int id, onlp_psu_info_t* info)
|
||||
sprintf(node_path, module_devfiles__[id], "vout");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
AIM_LOG_ERROR("Unable to read vout from file(%s)\r\n", node_path);
|
||||
}
|
||||
else {
|
||||
info->mvout = value;
|
||||
info->caps |= ONLP_PSU_CAPS_VOUT;
|
||||
}
|
||||
info->mvout = value;
|
||||
info->caps |= ONLP_PSU_CAPS_VOUT;
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "iout");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
AIM_LOG_ERROR("Unable to read iout from file(%s)\r\n", node_path);
|
||||
}
|
||||
else {
|
||||
info->miout = value;
|
||||
info->caps |= ONLP_PSU_CAPS_IOUT;
|
||||
}
|
||||
info->miout = value;
|
||||
info->caps |= ONLP_PSU_CAPS_IOUT;
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "pout");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
AIM_LOG_ERROR("Unable to read pout from file(%s)\r\n", node_path);
|
||||
}
|
||||
else {
|
||||
info->mpout = value;
|
||||
info->caps |= ONLP_PSU_CAPS_POUT;
|
||||
}
|
||||
info->mpout = value;
|
||||
info->caps |= ONLP_PSU_CAPS_POUT;
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "vin");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
AIM_LOG_ERROR("Unable to read vin from file(%s)\r\n", node_path);
|
||||
}
|
||||
else {
|
||||
info->mvin = value;
|
||||
info->caps |= ONLP_PSU_CAPS_VIN;
|
||||
}
|
||||
info->mvin = value;
|
||||
info->caps |= ONLP_PSU_CAPS_VIN;
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "iin");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
AIM_LOG_ERROR("Unable to read iin from file(%s)\r\n", node_path);
|
||||
}
|
||||
else {
|
||||
info->miin = value;
|
||||
info->caps |= ONLP_PSU_CAPS_IIN;
|
||||
}
|
||||
info->miin = value;
|
||||
info->caps |= ONLP_PSU_CAPS_IIN;
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "pin");
|
||||
ret = onlp_file_read_int(&value, node_path);
|
||||
if (ret < 0) {
|
||||
AIM_LOG_ERROR("Unable to read status from file(%s)\r\n", node_path);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
AIM_LOG_ERROR("Unable to read pin from file(%s)\r\n", node_path);
|
||||
}
|
||||
else {
|
||||
info->mpin = value;
|
||||
info->caps |= ONLP_PSU_CAPS_PIN;
|
||||
}
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "model");
|
||||
ret = onlp_file_read_str(vp, node_path);
|
||||
if (ret > 0) {
|
||||
strncpy(info->model, *vp, ret-1);
|
||||
}
|
||||
else {
|
||||
//AIM_LOG_ERROR("Unable to read model name from file(%s)\r\n", node_path);
|
||||
strncpy(info->model, "N/A", 3);
|
||||
}
|
||||
|
||||
memset(node_path, 0, ONLP_NODE_MAX_PATH_LEN);
|
||||
sprintf(node_path, module_devfiles__[id], "serial");
|
||||
ret = onlp_file_read_str(vp, node_path);
|
||||
if (ret > 0) {
|
||||
strncpy(info->serial, *vp, ret-1);
|
||||
}
|
||||
else {
|
||||
AIM_LOG_ERROR("Unable to read model name from file(%s)\r\n", node_path);
|
||||
strncpy(info->serial, "N/A", 3);
|
||||
}
|
||||
info->mpin = value;
|
||||
info->caps |= ONLP_PSU_CAPS_PIN;
|
||||
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
@@ -157,10 +186,24 @@ static onlp_psu_info_t pinfo[] =
|
||||
{
|
||||
{ }, /* Not used */
|
||||
{
|
||||
{ ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0 },
|
||||
{
|
||||
ONLP_PSU_ID_CREATE(PSU1_ID), "PSU-1", 0,
|
||||
{
|
||||
ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU1),
|
||||
ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU1),
|
||||
ONLP_FAN_ID_CREATE(FAN_1_ON_PSU1)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
{ ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0 },
|
||||
{
|
||||
ONLP_PSU_ID_CREATE(PSU2_ID), "PSU-2", 0,
|
||||
{
|
||||
ONLP_THERMAL_ID_CREATE(THERMAL_1_ON_PSU2),
|
||||
ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU2),
|
||||
ONLP_FAN_ID_CREATE(FAN_1_ON_PSU2)
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@@ -178,7 +221,7 @@ onlp_psui_info_get(onlp_oid_t id, onlp_psu_info_t* info)
|
||||
|
||||
/* Get the present state */
|
||||
if ((ret = psu_status_info_get(index, "psu", &val)) == ONLP_STATUS_E_INTERNAL) {
|
||||
printf("Unable to read PSU(%d) node(psu_present)\r\n", index);
|
||||
printf("Unable to read PSU(%d) node(psu)\r\n", index);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -170,6 +170,17 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
|
||||
int
|
||||
onlp_sfpi_eeprom_read(int port, uint8_t data[256])
|
||||
{
|
||||
#if 1
|
||||
int bus = FRONT_PORT_TO_MUX_INDEX(port);
|
||||
|
||||
memset(data, 0, 256);
|
||||
/* Read eeprom information into data[] */
|
||||
if (onlp_i2c_read(bus, 0x50, 0x00, 256, data, 0) != 0)
|
||||
{
|
||||
AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
#else
|
||||
char* path;
|
||||
int len = 0;
|
||||
/*
|
||||
@@ -184,6 +195,7 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256])
|
||||
AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
#endif
|
||||
return ONLP_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,26 +22,7 @@
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
enum onlp_thermal_id
|
||||
{
|
||||
THERMAL_RESERVED = 0,
|
||||
THERMAL_CPU_CORE_FIRST,
|
||||
THERMAL_CPU_CORE_2,
|
||||
THERMAL_CPU_CORE_3,
|
||||
THERMAL_CPU_CORE_4,
|
||||
THERMAL_CPU_CORE_LAST,
|
||||
THERMAL_1_ON_MAIN_BROAD,
|
||||
THERMAL_2_ON_MAIN_BROAD,
|
||||
THERMAL_3_ON_MAIN_BROAD,
|
||||
THERMAL_4_ON_MAIN_BROAD,
|
||||
THERMAL_5_ON_MAIN_BROAD,
|
||||
THERMAL_1_ON_PSU1,
|
||||
THERMAL_1_ON_PSU2,
|
||||
THERMAL_2_ON_PSU1,
|
||||
THERMAL_2_ON_PSU2,
|
||||
};
|
||||
|
||||
static char* devfiles__[CHASSIS_THERMAL_COUNT+1] = /* must map with onlp_thermal_id */
|
||||
static char* devfiles__[THERMAL_MAX] = /* must map with onlp_thermal_id */
|
||||
{
|
||||
"reserved",
|
||||
INV_CTMP_PREFIX"/temp1_%s",
|
||||
@@ -55,13 +36,13 @@ static char* devfiles__[CHASSIS_THERMAL_COUNT+1] = /* must map with onlp_therma
|
||||
INV_PSOC_PREFIX"/temp4_input",
|
||||
INV_PSOC_PREFIX"/temp5_input",
|
||||
INV_PSOC_PREFIX"/thermal_psu1",
|
||||
INV_PSOC_PREFIX"/thermal_psu2",
|
||||
INV_PSOC_PREFIX"/thermal2_psu1",
|
||||
INV_PSOC_PREFIX"/thermal_psu2",
|
||||
INV_PSOC_PREFIX"/thermal2_psu2",
|
||||
};
|
||||
|
||||
/* Static values */
|
||||
static onlp_thermal_info_t linfo[CHASSIS_THERMAL_COUNT+1] = {
|
||||
static onlp_thermal_info_t linfo[THERMAL_MAX] = {
|
||||
{ }, /* Not used */
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_CPU_CORE_FIRST), "Physical id 0", 0},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
@@ -107,11 +88,11 @@ static onlp_thermal_info_t linfo[CHASSIS_THERMAL_COUNT+1] = {
|
||||
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_ID_CREATE(THERMAL_2_ON_PSU1), "PSU-1 Thermal Sensor 2", ONLP_PSU_ID_CREATE(PSU1_ID)},
|
||||
ONLP_THERMAL_STATUS_PRESENT,
|
||||
ONLP_THERMAL_CAPS_ALL, 0, ONLP_THERMAL_THRESHOLD_INIT_DEFAULTS
|
||||
},
|
||||
{ { ONLP_THERMAL_ID_CREATE(THERMAL_2_ON_PSU1), "PSU-1 Thermal Sensor 2", ONLP_PSU_ID_CREATE(PSU1_ID)},
|
||||
{ { 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
|
||||
},
|
||||
|
||||
@@ -5,7 +5,7 @@ class OnlPlatform_x86_64_inventec_d7054q28b_r0(OnlPlatformInventec,
|
||||
OnlPlatformPortConfig_48x25_6x100):
|
||||
PLATFORM='x86-64-inventec-d7054q28b-r0'
|
||||
MODEL="X86-D7054Q28B"
|
||||
SYS_OBJECT_ID="7054.28"
|
||||
SYS_OBJECT_ID=".7054.1"
|
||||
|
||||
def baseconfig(self):
|
||||
os.system("insmod /lib/modules/`uname -r`/kernel/drivers/gpio/gpio-ich.ko")
|
||||
@@ -16,5 +16,5 @@ class OnlPlatform_x86_64_inventec_d7054q28b_r0(OnlPlatformInventec,
|
||||
self.insmod('inv_eeprom')
|
||||
self.insmod('swps')
|
||||
self.insmod('vpd')
|
||||
self.insmod('inv_pthread')
|
||||
# self.insmod('inv_pthread')
|
||||
return True
|
||||
|
||||
2
packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/.gitignore
vendored
Normal file
2
packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*x86*64*inventec*d7264q28b*.mk
|
||||
onlpdump.mk
|
||||
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -0,0 +1 @@
|
||||
include $(ONL)/make/pkg.mk
|
||||
@@ -0,0 +1 @@
|
||||
!include $ONL_TEMPLATES/platform-modules.yml VENDOR=inventec BASENAME=x86-64-inventec-d7264q28b ARCH=amd64 KERNELS="onl-kernel-3.16-lts-x86-64-all:amd64"
|
||||
1
packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/.gitignore
vendored
Normal file
1
packages/platforms/inventec/x86-64/x86-64-inventec-d7264q28b/modules/builds/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
lib
|
||||
@@ -0,0 +1,6 @@
|
||||
KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64
|
||||
KMODULES := src
|
||||
VENDOR := inventec
|
||||
BASENAME := x86-64-inventec-d7264q28b
|
||||
ARCH := x86_64
|
||||
include $(ONL)/make/kmodule.mk
|
||||
@@ -0,0 +1,8 @@
|
||||
#obj-m += gpio-ich.o
|
||||
obj-m += inv_cpld.o inv_psoc.o
|
||||
obj-m += inv_platform.o
|
||||
obj-m += swps.o
|
||||
swps-objs := inv_swps.o io_expander.o inv_mux.o transceiver.o
|
||||
obj-m += vpd.o
|
||||
vpd-objs := inv_vpd.o onie_tlvinfo.o
|
||||
obj-m += inv_pthread.o
|
||||
@@ -0,0 +1,548 @@
|
||||
/*
|
||||
* Intel ICH6-10, Series 5 and 6, Atom C2000 (Avoton/Rangeley) GPIO driver
|
||||
*
|
||||
* Copyright (C) 2010 Extreme Engineering Solutions.
|
||||
*
|
||||
* 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/lpc_ich.h>
|
||||
|
||||
#define DRV_NAME "gpio_ich"
|
||||
|
||||
/*
|
||||
* GPIO register offsets in GPIO I/O space.
|
||||
* Each chunk of 32 GPIOs is manipulated via its own USE_SELx, IO_SELx, and
|
||||
* LVLx registers. Logic in the read/write functions takes a register and
|
||||
* an absolute bit number and determines the proper register offset and bit
|
||||
* number in that register. For example, to read the value of GPIO bit 50
|
||||
* the code would access offset ichx_regs[2(=GPIO_LVL)][1(=50/32)],
|
||||
* bit 18 (50%32).
|
||||
*/
|
||||
enum GPIO_REG {
|
||||
GPIO_USE_SEL = 0,
|
||||
GPIO_IO_SEL,
|
||||
GPIO_LVL,
|
||||
GPO_BLINK
|
||||
};
|
||||
|
||||
static const u8 ichx_regs[4][3] = {
|
||||
{0x00, 0x30, 0x40}, /* USE_SEL[1-3] offsets */
|
||||
{0x04, 0x34, 0x44}, /* IO_SEL[1-3] offsets */
|
||||
{0x0c, 0x38, 0x48}, /* LVL[1-3] offsets */
|
||||
{0x18, 0x18, 0x18}, /* BLINK offset */
|
||||
};
|
||||
|
||||
static const u8 ichx_reglen[3] = {
|
||||
0x30, 0x10, 0x10,
|
||||
};
|
||||
|
||||
static const u8 avoton_regs[4][3] = {
|
||||
{0x00, 0x80, 0x00},
|
||||
{0x04, 0x84, 0x00},
|
||||
{0x08, 0x88, 0x00},
|
||||
};
|
||||
|
||||
static const u8 avoton_reglen[3] = {
|
||||
0x10, 0x10, 0x00,
|
||||
};
|
||||
|
||||
#define ICHX_WRITE(val, reg, base_res) outl(val, (reg) + (base_res)->start)
|
||||
#define ICHX_READ(reg, base_res) inl((reg) + (base_res)->start)
|
||||
|
||||
struct ichx_desc {
|
||||
/* Max GPIO pins the chipset can have */
|
||||
uint ngpio;
|
||||
|
||||
/* chipset registers */
|
||||
const u8 (*regs)[3];
|
||||
const u8 *reglen;
|
||||
|
||||
/* GPO_BLINK is available on this chipset */
|
||||
bool have_blink;
|
||||
|
||||
/* Whether the chipset has GPIO in GPE0_STS in the PM IO region */
|
||||
bool uses_gpe0;
|
||||
|
||||
/* USE_SEL is bogus on some chipsets, eg 3100 */
|
||||
u32 use_sel_ignore[3];
|
||||
|
||||
/* Some chipsets have quirks, let these use their own request/get */
|
||||
int (*request)(struct gpio_chip *chip, unsigned offset);
|
||||
int (*get)(struct gpio_chip *chip, unsigned offset);
|
||||
|
||||
/*
|
||||
* Some chipsets don't let reading output values on GPIO_LVL register
|
||||
* this option allows driver caching written output values
|
||||
*/
|
||||
bool use_outlvl_cache;
|
||||
};
|
||||
|
||||
static struct {
|
||||
spinlock_t lock;
|
||||
struct platform_device *dev;
|
||||
struct gpio_chip chip;
|
||||
struct resource *gpio_base; /* GPIO IO base */
|
||||
struct resource *pm_base; /* Power Mangagment IO base */
|
||||
struct ichx_desc *desc; /* Pointer to chipset-specific description */
|
||||
u32 orig_gpio_ctrl; /* Orig CTRL value, used to restore on exit */
|
||||
u8 use_gpio; /* Which GPIO groups are usable */
|
||||
int outlvl_cache[3]; /* cached output values */
|
||||
} ichx_priv;
|
||||
|
||||
static int modparam_gpiobase = -1; /* dynamic */
|
||||
module_param_named(gpiobase, modparam_gpiobase, int, 0444);
|
||||
MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, "
|
||||
"which is the default.");
|
||||
|
||||
static int ichx_write_bit(int reg, unsigned nr, int val, int verify)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 data, tmp;
|
||||
int reg_nr = nr / 32;
|
||||
int bit = nr & 0x1f;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&ichx_priv.lock, flags);
|
||||
|
||||
if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache)
|
||||
data = ichx_priv.outlvl_cache[reg_nr];
|
||||
else
|
||||
data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr],
|
||||
ichx_priv.gpio_base);
|
||||
|
||||
if (val)
|
||||
data |= 1 << bit;
|
||||
else
|
||||
data &= ~(1 << bit);
|
||||
ICHX_WRITE(data, ichx_priv.desc->regs[reg][reg_nr],
|
||||
ichx_priv.gpio_base);
|
||||
if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache)
|
||||
ichx_priv.outlvl_cache[reg_nr] = data;
|
||||
|
||||
tmp = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr],
|
||||
ichx_priv.gpio_base);
|
||||
if (verify && data != tmp)
|
||||
ret = -EPERM;
|
||||
|
||||
spin_unlock_irqrestore(&ichx_priv.lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ichx_read_bit(int reg, unsigned nr)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 data;
|
||||
int reg_nr = nr / 32;
|
||||
int bit = nr & 0x1f;
|
||||
|
||||
spin_lock_irqsave(&ichx_priv.lock, flags);
|
||||
|
||||
data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr],
|
||||
ichx_priv.gpio_base);
|
||||
|
||||
if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache)
|
||||
data = ichx_priv.outlvl_cache[reg_nr] | data;
|
||||
|
||||
spin_unlock_irqrestore(&ichx_priv.lock, flags);
|
||||
|
||||
return data & (1 << bit) ? 1 : 0;
|
||||
}
|
||||
|
||||
static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr)
|
||||
{
|
||||
return !!(ichx_priv.use_gpio & (1 << (nr / 32)));
|
||||
}
|
||||
|
||||
static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
|
||||
{
|
||||
/*
|
||||
* Try setting pin as an input and verify it worked since many pins
|
||||
* are output-only.
|
||||
*/
|
||||
if (ichx_write_bit(GPIO_IO_SEL, nr, 1, 1))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
|
||||
int val)
|
||||
{
|
||||
/* Disable blink hardware which is available for GPIOs from 0 to 31. */
|
||||
if (nr < 32 && ichx_priv.desc->have_blink)
|
||||
ichx_write_bit(GPO_BLINK, nr, 0, 0);
|
||||
|
||||
/* Set GPIO output value. */
|
||||
ichx_write_bit(GPIO_LVL, nr, val, 0);
|
||||
|
||||
/*
|
||||
* Try setting pin as an output and verify it worked since many pins
|
||||
* are input-only.
|
||||
*/
|
||||
if (ichx_write_bit(GPIO_IO_SEL, nr, 0, 1))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ichx_gpio_get(struct gpio_chip *chip, unsigned nr)
|
||||
{
|
||||
return ichx_read_bit(GPIO_LVL, nr);
|
||||
}
|
||||
|
||||
static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 data;
|
||||
|
||||
/*
|
||||
* GPI 0 - 15 need to be read from the power management registers on
|
||||
* a ICH6/3100 bridge.
|
||||
*/
|
||||
if (nr < 16) {
|
||||
if (!ichx_priv.pm_base)
|
||||
return -ENXIO;
|
||||
|
||||
spin_lock_irqsave(&ichx_priv.lock, flags);
|
||||
|
||||
/* GPI 0 - 15 are latched, write 1 to clear*/
|
||||
ICHX_WRITE(1 << (16 + nr), 0, ichx_priv.pm_base);
|
||||
data = ICHX_READ(0, ichx_priv.pm_base);
|
||||
|
||||
spin_unlock_irqrestore(&ichx_priv.lock, flags);
|
||||
|
||||
return (data >> 16) & (1 << nr) ? 1 : 0;
|
||||
} else {
|
||||
return ichx_gpio_get(chip, nr);
|
||||
}
|
||||
}
|
||||
|
||||
static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr)
|
||||
{
|
||||
if (!ichx_gpio_check_available(chip, nr))
|
||||
return -ENXIO;
|
||||
|
||||
/*
|
||||
* Note we assume the BIOS properly set a bridge's USE value. Some
|
||||
* chips (eg Intel 3100) have bogus USE values though, so first see if
|
||||
* the chipset's USE value can be trusted for this specific bit.
|
||||
* If it can't be trusted, assume that the pin can be used as a GPIO.
|
||||
*/
|
||||
if (ichx_priv.desc->use_sel_ignore[nr / 32] & (1 << (nr & 0x1f)))
|
||||
return 0;
|
||||
|
||||
return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV;
|
||||
}
|
||||
|
||||
static int ich6_gpio_request(struct gpio_chip *chip, unsigned nr)
|
||||
{
|
||||
/*
|
||||
* Fixups for bits 16 and 17 are necessary on the Intel ICH6/3100
|
||||
* bridge as they are controlled by USE register bits 0 and 1. See
|
||||
* "Table 704 GPIO_USE_SEL1 register" in the i3100 datasheet for
|
||||
* additional info.
|
||||
*/
|
||||
if (nr == 16 || nr == 17)
|
||||
nr -= 16;
|
||||
|
||||
return ichx_gpio_request(chip, nr);
|
||||
}
|
||||
|
||||
static void ichx_gpio_set(struct gpio_chip *chip, unsigned nr, int val)
|
||||
{
|
||||
ichx_write_bit(GPIO_LVL, nr, val, 0);
|
||||
}
|
||||
|
||||
static void ichx_gpiolib_setup(struct gpio_chip *chip)
|
||||
{
|
||||
chip->owner = THIS_MODULE;
|
||||
chip->label = DRV_NAME;
|
||||
chip->dev = &ichx_priv.dev->dev;
|
||||
|
||||
/* Allow chip-specific overrides of request()/get() */
|
||||
chip->request = ichx_priv.desc->request ?
|
||||
ichx_priv.desc->request : ichx_gpio_request;
|
||||
chip->get = ichx_priv.desc->get ?
|
||||
ichx_priv.desc->get : ichx_gpio_get;
|
||||
|
||||
chip->set = ichx_gpio_set;
|
||||
chip->direction_input = ichx_gpio_direction_input;
|
||||
chip->direction_output = ichx_gpio_direction_output;
|
||||
chip->base = modparam_gpiobase;
|
||||
chip->ngpio = ichx_priv.desc->ngpio;
|
||||
chip->can_sleep = false;
|
||||
chip->dbg_show = NULL;
|
||||
}
|
||||
|
||||
/* ICH6-based, 631xesb-based */
|
||||
static struct ichx_desc ich6_desc = {
|
||||
/* Bridges using the ICH6 controller need fixups for GPIO 0 - 17 */
|
||||
.request = ich6_gpio_request,
|
||||
.get = ich6_gpio_get,
|
||||
|
||||
/* GPIO 0-15 are read in the GPE0_STS PM register */
|
||||
.uses_gpe0 = true,
|
||||
|
||||
.ngpio = 50,
|
||||
.have_blink = true,
|
||||
.regs = ichx_regs,
|
||||
.reglen = ichx_reglen,
|
||||
};
|
||||
|
||||
/* Intel 3100 */
|
||||
static struct ichx_desc i3100_desc = {
|
||||
/*
|
||||
* Bits 16,17, 20 of USE_SEL and bit 16 of USE_SEL2 always read 0 on
|
||||
* the Intel 3100. See "Table 712. GPIO Summary Table" of 3100
|
||||
* Datasheet for more info.
|
||||
*/
|
||||
.use_sel_ignore = {0x00130000, 0x00010000, 0x0},
|
||||
|
||||
/* The 3100 needs fixups for GPIO 0 - 17 */
|
||||
.request = ich6_gpio_request,
|
||||
.get = ich6_gpio_get,
|
||||
|
||||
/* GPIO 0-15 are read in the GPE0_STS PM register */
|
||||
.uses_gpe0 = true,
|
||||
|
||||
.ngpio = 50,
|
||||
.regs = ichx_regs,
|
||||
.reglen = ichx_reglen,
|
||||
};
|
||||
|
||||
/* ICH7 and ICH8-based */
|
||||
static struct ichx_desc ich7_desc = {
|
||||
.ngpio = 50,
|
||||
.have_blink = true,
|
||||
.regs = ichx_regs,
|
||||
.reglen = ichx_reglen,
|
||||
};
|
||||
|
||||
/* ICH9-based */
|
||||
static struct ichx_desc ich9_desc = {
|
||||
.ngpio = 61,
|
||||
.have_blink = true,
|
||||
.regs = ichx_regs,
|
||||
.reglen = ichx_reglen,
|
||||
};
|
||||
|
||||
/* ICH10-based - Consumer/corporate versions have different amount of GPIO */
|
||||
static struct ichx_desc ich10_cons_desc = {
|
||||
.ngpio = 61,
|
||||
.have_blink = true,
|
||||
.regs = ichx_regs,
|
||||
.reglen = ichx_reglen,
|
||||
};
|
||||
static struct ichx_desc ich10_corp_desc = {
|
||||
.ngpio = 72,
|
||||
.have_blink = true,
|
||||
.regs = ichx_regs,
|
||||
.reglen = ichx_reglen,
|
||||
};
|
||||
|
||||
/* Intel 5 series, 6 series, 3400 series, and C200 series */
|
||||
static struct ichx_desc intel5_desc = {
|
||||
.ngpio = 76,
|
||||
.regs = ichx_regs,
|
||||
.reglen = ichx_reglen,
|
||||
};
|
||||
|
||||
/* Avoton */
|
||||
static struct ichx_desc avoton_desc = {
|
||||
/* Avoton has only 59 GPIOs, but we assume the first set of register
|
||||
* (Core) has 32 instead of 31 to keep gpio-ich compliance
|
||||
*/
|
||||
.ngpio = 60,
|
||||
.regs = avoton_regs,
|
||||
.reglen = avoton_reglen,
|
||||
.use_outlvl_cache = true,
|
||||
};
|
||||
|
||||
static int ichx_gpio_request_regions(struct resource *res_base,
|
||||
const char *name, u8 use_gpio)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!res_base || !res_base->start || !res_base->end)
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) {
|
||||
if (!(use_gpio & (1 << i)))
|
||||
continue;
|
||||
if (!request_region(
|
||||
res_base->start + ichx_priv.desc->regs[0][i],
|
||||
ichx_priv.desc->reglen[i], name))
|
||||
goto request_err;
|
||||
}
|
||||
return 0;
|
||||
|
||||
request_err:
|
||||
/* Clean up: release already requested regions, if any */
|
||||
for (i--; i >= 0; i--) {
|
||||
if (!(use_gpio & (1 << i)))
|
||||
continue;
|
||||
release_region(res_base->start + ichx_priv.desc->regs[0][i],
|
||||
ichx_priv.desc->reglen[i]);
|
||||
}
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
static void ichx_gpio_release_regions(struct resource *res_base, u8 use_gpio)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) {
|
||||
if (!(use_gpio & (1 << i)))
|
||||
continue;
|
||||
release_region(res_base->start + ichx_priv.desc->regs[0][i],
|
||||
ichx_priv.desc->reglen[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static int ichx_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res_base, *res_pm;
|
||||
int err;
|
||||
struct lpc_ich_info *ich_info = dev_get_platdata(&pdev->dev);
|
||||
|
||||
if (!ich_info)
|
||||
return -ENODEV;
|
||||
|
||||
ichx_priv.dev = pdev;
|
||||
|
||||
switch (ich_info->gpio_version) {
|
||||
case ICH_I3100_GPIO:
|
||||
ichx_priv.desc = &i3100_desc;
|
||||
break;
|
||||
case ICH_V5_GPIO:
|
||||
ichx_priv.desc = &intel5_desc;
|
||||
break;
|
||||
case ICH_V6_GPIO:
|
||||
ichx_priv.desc = &ich6_desc;
|
||||
break;
|
||||
case ICH_V7_GPIO:
|
||||
ichx_priv.desc = &ich7_desc;
|
||||
break;
|
||||
case ICH_V9_GPIO:
|
||||
ichx_priv.desc = &ich9_desc;
|
||||
break;
|
||||
case ICH_V10CORP_GPIO:
|
||||
ichx_priv.desc = &ich10_corp_desc;
|
||||
break;
|
||||
case ICH_V10CONS_GPIO:
|
||||
ichx_priv.desc = &ich10_cons_desc;
|
||||
break;
|
||||
case AVOTON_GPIO:
|
||||
ichx_priv.desc = &avoton_desc;
|
||||
break;
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
spin_lock_init(&ichx_priv.lock);
|
||||
res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO);
|
||||
ichx_priv.use_gpio = ich_info->use_gpio;
|
||||
err = ichx_gpio_request_regions(res_base, pdev->name,
|
||||
ichx_priv.use_gpio);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
ichx_priv.gpio_base = res_base;
|
||||
|
||||
/*
|
||||
* If necessary, determine the I/O address of ACPI/power management
|
||||
* registers which are needed to read the the GPE0 register for GPI pins
|
||||
* 0 - 15 on some chipsets.
|
||||
*/
|
||||
if (!ichx_priv.desc->uses_gpe0)
|
||||
goto init;
|
||||
|
||||
res_pm = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPE0);
|
||||
if (!res_pm) {
|
||||
pr_warn("ACPI BAR is unavailable, GPI 0 - 15 unavailable\n");
|
||||
goto init;
|
||||
}
|
||||
|
||||
if (!request_region(res_pm->start, resource_size(res_pm),
|
||||
pdev->name)) {
|
||||
pr_warn("ACPI BAR is busy, GPI 0 - 15 unavailable\n");
|
||||
goto init;
|
||||
}
|
||||
|
||||
ichx_priv.pm_base = res_pm;
|
||||
|
||||
init:
|
||||
ichx_gpiolib_setup(&ichx_priv.chip);
|
||||
err = gpiochip_add(&ichx_priv.chip);
|
||||
if (err) {
|
||||
pr_err("Failed to register GPIOs\n");
|
||||
goto add_err;
|
||||
}
|
||||
|
||||
pr_info("GPIO from %d to %d on %s\n", ichx_priv.chip.base,
|
||||
ichx_priv.chip.base + ichx_priv.chip.ngpio - 1, DRV_NAME);
|
||||
|
||||
return 0;
|
||||
|
||||
add_err:
|
||||
ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio);
|
||||
if (ichx_priv.pm_base)
|
||||
release_region(ichx_priv.pm_base->start,
|
||||
resource_size(ichx_priv.pm_base));
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ichx_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = gpiochip_remove(&ichx_priv.chip);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "%s failed, %d\n",
|
||||
"gpiochip_remove()", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
ichx_gpio_release_regions(ichx_priv.gpio_base, ichx_priv.use_gpio);
|
||||
if (ichx_priv.pm_base)
|
||||
release_region(ichx_priv.pm_base->start,
|
||||
resource_size(ichx_priv.pm_base));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ichx_gpio_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = DRV_NAME,
|
||||
},
|
||||
.probe = ichx_gpio_probe,
|
||||
.remove = ichx_gpio_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(ichx_gpio_driver);
|
||||
|
||||
MODULE_AUTHOR("Peter Tyser <ptyser@xes-inc.com>");
|
||||
MODULE_DESCRIPTION("GPIO interface for Intel ICH series");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:"DRV_NAME);
|
||||
@@ -0,0 +1,470 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.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 "I2CHostCommunication.h"
|
||||
|
||||
#define USE_SMBUS 1
|
||||
|
||||
/* definition */
|
||||
#define CPLD_INFO_OFFSET 0x00
|
||||
#define CPLD_PSU_OFFSET 0x08
|
||||
#define CPLD_LED_OFFSET 0x0E
|
||||
#define CPLD_LED_STATU_OFFSET 0x0D
|
||||
#define CPLD_CTL_OFFSET 0x0C
|
||||
#define CPLD_BIOSCS_OFFSET 0x04
|
||||
|
||||
|
||||
/* Each client has this additional data */
|
||||
struct cpld_data {
|
||||
struct device *hwmon_dev;
|
||||
struct mutex update_lock;
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
static ssize_t cpld_i2c_read(struct i2c_client *client, u8 *buf, u8 offset, size_t count)
|
||||
{
|
||||
#if USE_SMBUS
|
||||
int i;
|
||||
|
||||
for(i=0; i<count; i++) {
|
||||
buf[i] = i2c_smbus_read_byte_data(client, offset+i);
|
||||
}
|
||||
return count;
|
||||
#else
|
||||
struct i2c_msg msg[2];
|
||||
char msgbuf[2];
|
||||
int status;
|
||||
|
||||
memset(msg, 0, sizeof(msg));
|
||||
|
||||
msgbuf[0] = offset;
|
||||
|
||||
msg[0].addr = client->addr;
|
||||
msg[0].buf = msgbuf;
|
||||
msg[0].len = 1;
|
||||
|
||||
msg[1].addr = client->addr;
|
||||
msg[1].flags = I2C_M_RD;
|
||||
msg[1].buf = buf;
|
||||
msg[1].len = count;
|
||||
|
||||
status = i2c_transfer(client->adapter, msg, 2);
|
||||
|
||||
if(status == 2)
|
||||
status = count;
|
||||
|
||||
return status;
|
||||
#endif
|
||||
}
|
||||
|
||||
static ssize_t cpld_i2c_write(struct i2c_client *client, char *buf, unsigned offset, size_t count)
|
||||
{
|
||||
#if USE_SMBUS
|
||||
int i;
|
||||
|
||||
for(i=0; i<count; i++) {
|
||||
i2c_smbus_write_byte_data(client, offset+i, buf[i]);
|
||||
}
|
||||
return count;
|
||||
#else
|
||||
struct i2c_msg msg;
|
||||
int status;
|
||||
u8 writebuf[64];
|
||||
|
||||
int i = 0;
|
||||
|
||||
msg.addr = client->addr;
|
||||
msg.flags = 0;
|
||||
|
||||
/* msg.buf is u8 and casts will mask the values */
|
||||
msg.buf = writebuf;
|
||||
|
||||
msg.buf[i++] = offset;
|
||||
memcpy(&msg.buf[i], buf, count);
|
||||
msg.len = i + count;
|
||||
|
||||
status = i2c_transfer(client->adapter, &msg, 1);
|
||||
if (status == 1)
|
||||
status = count;
|
||||
|
||||
return status;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* sysfs attributes for hwmon */
|
||||
|
||||
static ssize_t show_info(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u32 status;
|
||||
//struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
u8 b[4];
|
||||
|
||||
memset(b, 0, 4);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
status = cpld_i2c_read(client, b, CPLD_INFO_OFFSET, 4);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
if(status != 4) return sprintf(buf, "read cpld info fail\n");
|
||||
|
||||
status = sprintf (buf, "The CPLD release date is %02d/%02d/%d.\n", b[2] & 0xf, (b[3] & 0x1f), 2014+(b[2] >> 4)); /* mm/dd/yyyy*/
|
||||
status = sprintf (buf, "%sThe PCB version is %X%X\n", buf, b[0]>>4, b[0]&0xf);
|
||||
status = sprintf (buf, "%sThe CPLD version is %d.%d\n", buf, b[1]>>4, b[1]&0xf);
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t show_ctl(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u32 status;
|
||||
//struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
u8 b[1];
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
status = cpld_i2c_read(client, b, CPLD_CTL_OFFSET, 1);
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
if(status != 1) return sprintf(buf, "read cpld ctl fail\n");
|
||||
|
||||
|
||||
status = sprintf (buf, "0x%X\n", b[0]);
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static ssize_t set_ctl(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
//struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
u8 byte;
|
||||
|
||||
u8 temp = simple_strtol(buf, NULL, 10);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
cpld_i2c_read(client, &byte, CPLD_CTL_OFFSET, 1);
|
||||
if(temp) byte |= (1<<0);
|
||||
else byte &= ~(1<<0);
|
||||
cpld_i2c_write(client, &byte, CPLD_CTL_OFFSET, 1);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_bios_cs(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u32 status;
|
||||
//struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
u8 b[1];
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
status = cpld_i2c_read(client, b, CPLD_BIOSCS_OFFSET, 1);
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
if(status != 1) return sprintf(buf, "read cpld BIOS_CS fail\n");
|
||||
|
||||
|
||||
status = sprintf (buf, "0x%X\n", b[0] & 0x01);
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static ssize_t set_bios_cs(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
//struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
u8 byte;
|
||||
|
||||
u8 temp = simple_strtol(buf, NULL, 10);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
cpld_i2c_read(client, &byte, CPLD_BIOSCS_OFFSET, 1);
|
||||
if(temp) byte |= 0x01;
|
||||
else byte &= ~(0x01);
|
||||
cpld_i2c_write(client, &byte, CPLD_BIOSCS_OFFSET, 1);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static char* led_str[] = {
|
||||
"OFF", //000
|
||||
"0.5 Hz", //001
|
||||
"1 Hz", //010
|
||||
"2 Hz", //011
|
||||
"4 Hz", //100
|
||||
"NA", //101
|
||||
"NA", //110
|
||||
"ON", //111
|
||||
};
|
||||
|
||||
static ssize_t show_led(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u32 status;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
u8 byte;
|
||||
int shift = (attr->index == 0)?3:0;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
status = cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
if(status != 1) return sprintf(buf, "read cpld offset 0x%x\n", CPLD_LED_OFFSET);
|
||||
|
||||
byte = (byte >> shift) & 0x7;
|
||||
|
||||
status = sprintf (buf, "%d: %s\n", byte, led_str[byte]);
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static ssize_t set_led(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
|
||||
u8 temp = simple_strtol(buf, NULL, 16);
|
||||
u8 byte;
|
||||
int shift = (attr->index == 0)?3:0;
|
||||
|
||||
temp &= 0x7;
|
||||
//validate temp value: 0,1,2,3,7, TBD
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
cpld_i2c_read(client, &byte, CPLD_LED_OFFSET, 1);
|
||||
byte &= ~(0x7<<shift);
|
||||
byte |= (temp<<shift);
|
||||
cpld_i2c_write(client, &byte, CPLD_LED_OFFSET, 1);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
CPLD report the PSU0 status
|
||||
000 = PSU normal operation
|
||||
100 = PSU fault
|
||||
010 = PSU unpowered
|
||||
111 = PSU not installed
|
||||
|
||||
7 6 | 5 4 3 | 2 1 0
|
||||
----------------------
|
||||
| psu0 | psu1
|
||||
*/
|
||||
static char* psu_str[] = {
|
||||
"normal", //000
|
||||
"NA", //001
|
||||
"unpowered", //010
|
||||
"NA", //011
|
||||
"fault", //100
|
||||
"NA", //101
|
||||
"NA", //110
|
||||
"not installed", //111
|
||||
};
|
||||
|
||||
static ssize_t show_psu(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u32 status;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
u8 byte;
|
||||
int shift = (attr->index == 1)?0:3;
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
status = cpld_i2c_read(client, &byte, CPLD_PSU_OFFSET, 1);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
byte = (byte >> shift) & 0x7;
|
||||
|
||||
status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]);
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
|
||||
static SENSOR_DEVICE_ATTR(info, S_IRUGO, show_info, 0, 0);
|
||||
static SENSOR_DEVICE_ATTR(ctl, S_IWUSR|S_IRUGO, show_ctl, set_ctl, 0);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(grn_led, S_IWUSR|S_IRUGO, show_led, set_led, 0);
|
||||
static SENSOR_DEVICE_ATTR(red_led, S_IWUSR|S_IRUGO, show_led, set_led, 1);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu, 0, 0);
|
||||
static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu, 0, 1);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(bios_cs, S_IWUSR|S_IRUGO, show_bios_cs, set_bios_cs, 0);
|
||||
|
||||
static struct attribute *cpld_attributes[] = {
|
||||
//info
|
||||
&sensor_dev_attr_info.dev_attr.attr,
|
||||
&sensor_dev_attr_ctl.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_grn_led.dev_attr.attr,
|
||||
&sensor_dev_attr_red_led.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_psu0.dev_attr.attr,
|
||||
&sensor_dev_attr_psu1.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_bios_cs.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group cpld_group = {
|
||||
.attrs = cpld_attributes,
|
||||
};
|
||||
|
||||
static struct attribute *cpld2_attributes[] = {
|
||||
//info
|
||||
&sensor_dev_attr_info.dev_attr.attr,
|
||||
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group cpld2_group = {
|
||||
.attrs = cpld2_attributes,
|
||||
};
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* device probe and removal */
|
||||
|
||||
static int
|
||||
cpld_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
struct cpld_data *data;
|
||||
int status;
|
||||
|
||||
// printk("+%s \n", __func__);
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
|
||||
return -EIO;
|
||||
|
||||
data = kzalloc(sizeof(struct cpld_data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->update_lock);
|
||||
|
||||
/* Register sysfs hooks */
|
||||
if(id->driver_data==1) // CPLD2
|
||||
status = sysfs_create_group(&client->dev.kobj, &cpld2_group);
|
||||
else // default CPLD1
|
||||
status = sysfs_create_group(&client->dev.kobj, &cpld_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: sensor '%s'\n",
|
||||
dev_name(data->hwmon_dev), client->name);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_remove:
|
||||
sysfs_remove_group(&client->dev.kobj, &cpld_group);
|
||||
exit_free:
|
||||
i2c_set_clientdata(client, NULL);
|
||||
kfree(data);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int cpld_remove(struct i2c_client *client)
|
||||
{
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &cpld_group);
|
||||
i2c_set_clientdata(client, NULL);
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id cpld_ids[] = {
|
||||
{ "inv_cpld" , 0, },
|
||||
{ "inv_cpld2", 1, },
|
||||
{ /* LIST END */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cpld_ids);
|
||||
|
||||
static struct i2c_driver cpld_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "inv_cpld",
|
||||
},
|
||||
.probe = cpld_probe,
|
||||
.remove = cpld_remove,
|
||||
.id_table = cpld_ids,
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/* module glue */
|
||||
|
||||
static int __init inv_cpld_init(void)
|
||||
{
|
||||
return i2c_add_driver(&cpld_driver);
|
||||
}
|
||||
|
||||
static void __exit inv_cpld_exit(void)
|
||||
{
|
||||
i2c_del_driver(&cpld_driver);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("eddie.lan <eddie.lan@inventec>");
|
||||
MODULE_DESCRIPTION("inv cpld driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(inv_cpld_init);
|
||||
module_exit(inv_cpld_exit);
|
||||
@@ -0,0 +1,272 @@
|
||||
#include <asm/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include "io_expander.h"
|
||||
#include "inv_mux.h"
|
||||
|
||||
static struct mux_obj_s *mux_head_p = NULL;
|
||||
|
||||
|
||||
/* ========== MUX object functions ==========
|
||||
*/
|
||||
int
|
||||
_common_force_pull_gpio(int mem_addr,
|
||||
int input,
|
||||
int bit_offset){
|
||||
|
||||
unsigned int val = 0;
|
||||
unsigned int targ = 0;
|
||||
|
||||
/* Get current value */
|
||||
val = inl(mem_addr);
|
||||
if (val == 0) {
|
||||
SWPS_ERR("%s: inl:%d fail!\n", __func__, val);
|
||||
return -1;
|
||||
}
|
||||
/* Count target value */
|
||||
switch (input) {
|
||||
case 0: /* Pull Low */
|
||||
targ = (val & (~(1 << bit_offset)));
|
||||
break;
|
||||
case 1: /* Pull high */
|
||||
targ = (val | (1 << bit_offset));
|
||||
break;
|
||||
default:
|
||||
SWPS_ERR("%s: input state:%d incorrect!\n",
|
||||
__func__, input);
|
||||
return -1;
|
||||
}
|
||||
/* Setup gpio */
|
||||
outl(targ, mem_addr);
|
||||
if (targ != inl(mem_addr)){
|
||||
SWPS_ERR("%s: outl:%d fail!\n", __func__, targ);
|
||||
return -1;
|
||||
}
|
||||
SWPS_DEBUG("%s: done.\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
rangeley_force_pull_high(struct mux_obj_s *self){
|
||||
SWPS_ERR("%s: not ready!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
rangeley_force_pull_low(struct mux_obj_s *self){
|
||||
SWPS_ERR("%s: not ready!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hedera_force_pull_high(struct mux_obj_s *self){
|
||||
return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 1, 5);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hedera_force_pull_low(struct mux_obj_s *self){
|
||||
return _common_force_pull_gpio(MUX_RST_MEM_ADDR_HEDERA, 0, 5);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
normal_gpio_pull_high(struct mux_obj_s *self){
|
||||
return gpio_direction_output(self->gpio_num, 1);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
normal_gpio_pull_low(struct mux_obj_s *self){
|
||||
return gpio_direction_output(self->gpio_num, 0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
pca9548_reset_mux_all(struct mux_obj_s *self){
|
||||
/* [Note] Power-on reset (PCA9548A-NXP)
|
||||
* When power is applied to VDD, an internal Power-On Reset (POR)
|
||||
* holds the PCA9548A in a reset condition until VDD has reached
|
||||
* VPOR. At this point, the reset condition is released and the
|
||||
* PCA9548A register and I2C-bus state machine are initialized to
|
||||
* their default states (all zeroes) causing all the channels to
|
||||
* be deselected. Thereafter, VDD must be lowered below 0.2 V for
|
||||
* at least 5 us in order to reset the device.
|
||||
*/
|
||||
if (self->_pull_low(self) < 0) {
|
||||
SWPS_ERR("%s: _pull_low fail!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
mdelay(MUX_RST_WAIT_MS);
|
||||
if (self->_pull_high(self) < 0) {
|
||||
SWPS_ERR("%s: _pull_high fail!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
mdelay(MUX_RST_WAIT_MS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
common_reset_mux_all(struct mux_obj_s *self){
|
||||
SWPS_ERR("%s: not ready!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
init_gpio_4_force(struct mux_obj_s *self){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
init_gpio_4_normal(struct mux_obj_s *self){
|
||||
|
||||
int err = 0;
|
||||
|
||||
if (!gpio_is_valid(self->gpio_num)) {
|
||||
SWPS_ERR("%s: GIPO:%d isn't valid\n", __func__, self->gpio_num);
|
||||
return -1;
|
||||
}
|
||||
err = gpio_request(self->gpio_num, MUX_GPIO_LABEL);
|
||||
if (err < 0) {
|
||||
SWPS_ERR("%s: gpio_request fail <err>:%d <gpio>:%d\n",
|
||||
__func__, err, self->gpio_num);
|
||||
return -1;
|
||||
}
|
||||
SWPS_DEBUG("%s: gpio_request:%d ok.\n", __func__, self->gpio_num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
_setup_muxctl_cb(struct mux_obj_s *self,
|
||||
unsigned gpio){
|
||||
|
||||
char mod_dsc[32] = "ERR";
|
||||
|
||||
switch (gpio) {
|
||||
case MUX_RST_GPIO_FORCE_RANGELEY:
|
||||
self->gpio_num = gpio;
|
||||
self->_pull_low = rangeley_force_pull_low;
|
||||
self->_pull_high = rangeley_force_pull_high;
|
||||
self->_init = init_gpio_4_force;
|
||||
self->reset = pca9548_reset_mux_all;
|
||||
memset(mod_dsc, 0, 32);
|
||||
snprintf(mod_dsc, 31, "Rangeley force mode");
|
||||
goto ok_setup_muxctl_cb;
|
||||
|
||||
case MUX_RST_GPIO_FORCE_HEDERA:
|
||||
self->gpio_num = gpio;
|
||||
self->_pull_low = hedera_force_pull_low;
|
||||
self->_pull_high = hedera_force_pull_high;
|
||||
self->_init = init_gpio_4_force;
|
||||
self->reset = pca9548_reset_mux_all;
|
||||
memset(mod_dsc, 0, 32);
|
||||
snprintf(mod_dsc, 31, "Hedera force mode");
|
||||
goto ok_setup_muxctl_cb;
|
||||
|
||||
case MUX_RST_GPIO_48_PAC9548:
|
||||
case MUX_RST_GPIO_69_PAC9548:
|
||||
case MUX_RST_GPIO_249_PCA9548:
|
||||
self->gpio_num = gpio;
|
||||
self->_pull_low = normal_gpio_pull_low;
|
||||
self->_pull_high = normal_gpio_pull_high;
|
||||
self->_init = init_gpio_4_normal;
|
||||
self->reset = pca9548_reset_mux_all;
|
||||
memset(mod_dsc, 0, 32);
|
||||
snprintf(mod_dsc, 31, "Normal mode <gpio>:%d", (int)gpio);
|
||||
goto ok_setup_muxctl_cb;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
SWPS_ERR("%s: Unexpected GPIO:%d\n", __func__, gpio);
|
||||
return -1;
|
||||
|
||||
ok_setup_muxctl_cb:
|
||||
SWPS_INFO("muxctl: %s.\n", mod_dsc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ========== MUX public functions ==========
|
||||
*/
|
||||
void
|
||||
clean_mux_gpio(void){
|
||||
|
||||
if (!mux_head_p) {
|
||||
SWPS_DEBUG("%s: mux_head_p is NULL\n", __func__);
|
||||
return;
|
||||
}
|
||||
if (gpio_is_valid(mux_head_p->gpio_num)) {
|
||||
gpio_free(mux_head_p->gpio_num);
|
||||
}
|
||||
kfree(mux_head_p);
|
||||
mux_head_p = NULL;
|
||||
SWPS_DEBUG("%s: done.\n", __func__);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
reset_mux_gpio(void){
|
||||
|
||||
if (!mux_head_p) {
|
||||
SWPS_ERR("%s: MUX ctl object doesn't exist!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
if (mux_head_p->reset(mux_head_p) < 0){
|
||||
SWPS_ERR("%s: reset fail!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
init_mux_gpio(unsigned gpio){
|
||||
|
||||
/* Create MUX control object */
|
||||
if (mux_head_p) {
|
||||
SWPS_DEBUG("%s: mux_head_p is not NULL!\n", __func__);
|
||||
clean_mux_gpio();
|
||||
}
|
||||
/* Currently, it is using single muxctl architecture.
|
||||
* In the future, it may use the multi-muxctl if HW add new features.
|
||||
* (Ex: Port power-status control)
|
||||
*/
|
||||
mux_head_p = kzalloc(sizeof(struct mux_obj_s), GFP_KERNEL);
|
||||
if (!mux_head_p) {
|
||||
SWPS_ERR("%s: kzalloc fail!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
/* Initial MUX controller */
|
||||
if (_setup_muxctl_cb(mux_head_p, gpio) < 0){
|
||||
SWPS_ERR("%s: _setup_muxctl_cb fail!\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
if (mux_head_p->_init(mux_head_p) < 0) {
|
||||
SWPS_ERR("%s: init() fail\n", __func__);
|
||||
goto err_init_mux_gpio;
|
||||
}
|
||||
/* Setup default value */
|
||||
if (mux_head_p->_pull_high(mux_head_p) < 0) {
|
||||
SWPS_ERR("%s: setup default fail!\n", __func__);
|
||||
goto err_init_mux_gpio;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_init_mux_gpio:
|
||||
clean_mux_gpio();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
#ifndef INV_MUX_H
|
||||
#define INV_MUX_H
|
||||
|
||||
|
||||
/* MUX basic information */
|
||||
#define MUX_GPIO_LABEL "SWPS_RST_MUX"
|
||||
|
||||
/* MUX reset GPIO define */
|
||||
#define MUX_RST_GPIO_FORCE (30100)
|
||||
#define MUX_RST_GPIO_FORCE_RANGELEY (30101)
|
||||
#define MUX_RST_GPIO_FORCE_HEDERA (30102)
|
||||
#define MUX_RST_GPIO_48_PAC9548 (48)
|
||||
#define MUX_RST_GPIO_69_PAC9548 (69)
|
||||
#define MUX_RST_GPIO_249_PCA9548 (249)
|
||||
|
||||
/* MUX relate value define */
|
||||
#define MUX_RST_WAIT_MS (1)
|
||||
#define MUX_RST_MEM_ADDR_RANGELEY (0) // TBD
|
||||
#define MUX_RST_MEM_ADDR_HEDERA (0x548)
|
||||
|
||||
struct mux_obj_s {
|
||||
unsigned gpio_num;
|
||||
int (*_pull_high)(struct mux_obj_s *self);
|
||||
int (*_pull_low)(struct mux_obj_s *self);
|
||||
int (*_init)(struct mux_obj_s *self);
|
||||
int (*reset)(struct mux_obj_s *self);
|
||||
};
|
||||
|
||||
|
||||
void clean_mux_gpio(void);
|
||||
int reset_mux_gpio(void);
|
||||
int init_mux_gpio(unsigned gpio);
|
||||
|
||||
|
||||
#endif /* INV_MUX_H */
|
||||
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
#include <linux/i2c.h>
|
||||
//#include <linux/i2c-algo-bit.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c/pca954x.h>
|
||||
//#include <linux/i2c/pca953x.h>
|
||||
//#include <linux/i2c/at24.h>
|
||||
|
||||
//#include <asm/gpio.h>
|
||||
//#define IO_EXPAND_BASE 64
|
||||
//#define IO_EXPAND_NGPIO 16
|
||||
|
||||
struct inv_i2c_board_info {
|
||||
int ch;
|
||||
int size;
|
||||
struct i2c_board_info *board_info;
|
||||
};
|
||||
|
||||
#define bus_id(id) (id)
|
||||
static struct pca954x_platform_mode mux_modes_0[] = {
|
||||
{.adap_id = bus_id(2),}, {.adap_id = bus_id(3),},
|
||||
{.adap_id = bus_id(4),}, {.adap_id = bus_id(5),},
|
||||
{.adap_id = bus_id(6),}, {.adap_id = bus_id(7),},
|
||||
{.adap_id = bus_id(8),}, {.adap_id = bus_id(9),},
|
||||
};
|
||||
static struct pca954x_platform_mode mux_modes_0_0[] = {
|
||||
{.adap_id = bus_id(10),}, {.adap_id = bus_id(11),},
|
||||
{.adap_id = bus_id(12),}, {.adap_id = bus_id(13),},
|
||||
{.adap_id = bus_id(14),}, {.adap_id = bus_id(15),},
|
||||
{.adap_id = bus_id(16),}, {.adap_id = bus_id(17),},
|
||||
};
|
||||
|
||||
static struct pca954x_platform_mode mux_modes_0_1[] = {
|
||||
{.adap_id = bus_id(18),}, {.adap_id = bus_id(19),},
|
||||
{.adap_id = bus_id(20),}, {.adap_id = bus_id(21),},
|
||||
{.adap_id = bus_id(22),}, {.adap_id = bus_id(23),},
|
||||
{.adap_id = bus_id(24),}, {.adap_id = bus_id(25),},
|
||||
};
|
||||
|
||||
static struct pca954x_platform_mode mux_modes_0_2[] = {
|
||||
{.adap_id = bus_id(26),}, {.adap_id = bus_id(27),},
|
||||
{.adap_id = bus_id(28),}, {.adap_id = bus_id(29),},
|
||||
{.adap_id = bus_id(30),}, {.adap_id = bus_id(31),},
|
||||
{.adap_id = bus_id(32),}, {.adap_id = bus_id(33),},
|
||||
};
|
||||
|
||||
static struct pca954x_platform_mode mux_modes_0_3[] = {
|
||||
{.adap_id = bus_id(34),}, {.adap_id = bus_id(35),},
|
||||
{.adap_id = bus_id(36),}, {.adap_id = bus_id(37),},
|
||||
{.adap_id = bus_id(38),}, {.adap_id = bus_id(39),},
|
||||
{.adap_id = bus_id(40),}, {.adap_id = bus_id(41),},
|
||||
};
|
||||
|
||||
static struct pca954x_platform_mode mux_modes_0_4[] = {
|
||||
{.adap_id = bus_id(42),}, {.adap_id = bus_id(43),},
|
||||
{.adap_id = bus_id(44),}, {.adap_id = bus_id(45),},
|
||||
{.adap_id = bus_id(46),}, {.adap_id = bus_id(47),},
|
||||
{.adap_id = bus_id(48),}, {.adap_id = bus_id(49),},
|
||||
};
|
||||
|
||||
static struct pca954x_platform_mode mux_modes_0_5[] = {
|
||||
{.adap_id = bus_id(50),}, {.adap_id = bus_id(51),},
|
||||
{.adap_id = bus_id(52),}, {.adap_id = bus_id(53),},
|
||||
{.adap_id = bus_id(54),}, {.adap_id = bus_id(55),},
|
||||
{.adap_id = bus_id(56),}, {.adap_id = bus_id(57),},
|
||||
};
|
||||
|
||||
static struct pca954x_platform_mode mux_modes_0_6[] = {
|
||||
{.adap_id = bus_id(58),}, {.adap_id = bus_id(59),},
|
||||
{.adap_id = bus_id(60),}, {.adap_id = bus_id(61),},
|
||||
{.adap_id = bus_id(62),}, {.adap_id = bus_id(63),},
|
||||
{.adap_id = bus_id(64),}, {.adap_id = bus_id(65),},
|
||||
};
|
||||
|
||||
static struct pca954x_platform_mode mux_modes_0_7[] = {
|
||||
{.adap_id = bus_id(66),}, {.adap_id = bus_id(67),},
|
||||
{.adap_id = bus_id(68),}, {.adap_id = bus_id(69),},
|
||||
{.adap_id = bus_id(70),}, {.adap_id = bus_id(71),},
|
||||
{.adap_id = bus_id(72),}, {.adap_id = bus_id(73),},
|
||||
};
|
||||
|
||||
//no i2c device driver attach to mux 7
|
||||
|
||||
|
||||
static struct pca954x_platform_data mux_data_0 = {
|
||||
.modes = mux_modes_0,
|
||||
.num_modes = 8,
|
||||
};
|
||||
static struct pca954x_platform_data mux_data_0_0 = {
|
||||
.modes = mux_modes_0_0,
|
||||
.num_modes = 8,
|
||||
};
|
||||
static struct pca954x_platform_data mux_data_0_1 = {
|
||||
.modes = mux_modes_0_1,
|
||||
.num_modes = 8,
|
||||
};
|
||||
static struct pca954x_platform_data mux_data_0_2 = {
|
||||
.modes = mux_modes_0_2,
|
||||
.num_modes = 8,
|
||||
};
|
||||
static struct pca954x_platform_data mux_data_0_3 = {
|
||||
.modes = mux_modes_0_3,
|
||||
.num_modes = 8,
|
||||
};
|
||||
static struct pca954x_platform_data mux_data_0_4 = {
|
||||
.modes = mux_modes_0_4,
|
||||
.num_modes = 8,
|
||||
};
|
||||
static struct pca954x_platform_data mux_data_0_5 = {
|
||||
.modes = mux_modes_0_5,
|
||||
.num_modes = 8,
|
||||
};
|
||||
static struct pca954x_platform_data mux_data_0_6 = {
|
||||
.modes = mux_modes_0_6,
|
||||
.num_modes = 8,
|
||||
};
|
||||
static struct pca954x_platform_data mux_data_0_7 = {
|
||||
.modes = mux_modes_0_7,
|
||||
.num_modes = 8,
|
||||
};
|
||||
|
||||
static struct i2c_board_info i2c_device_info0[] __initdata = {
|
||||
// {"inv_psoc", 0, 0x66, 0, 0, 0},//psoc
|
||||
{"inv_cpld", 0, 0x55, 0, 0, 0},//cpld
|
||||
{"inv_cpld2", 0, 0x77, 0, 0, 0},//cpld2
|
||||
{"pca9548", 0, 0x70, &mux_data_0, 0, 0},
|
||||
};
|
||||
|
||||
static struct i2c_board_info i2c_device_info2[] __initdata = {
|
||||
{"pca9548", 0, 0x72, &mux_data_0_0, 0, 0},
|
||||
};
|
||||
static struct i2c_board_info i2c_device_info3[] __initdata = {
|
||||
{"pca9548", 0, 0x72, &mux_data_0_1, 0, 0},
|
||||
};
|
||||
static struct i2c_board_info i2c_device_info4[] __initdata = {
|
||||
{"pca9548", 0, 0x72, &mux_data_0_2, 0, 0},
|
||||
};
|
||||
static struct i2c_board_info i2c_device_info5[] __initdata = {
|
||||
{"pca9548", 0, 0x72, &mux_data_0_3, 0, 0},
|
||||
};
|
||||
static struct i2c_board_info i2c_device_info6[] __initdata = {
|
||||
{"pca9548", 0, 0x72, &mux_data_0_4, 0, 0},
|
||||
};
|
||||
static struct i2c_board_info i2c_device_info7[] __initdata = {
|
||||
{"pca9548", 0, 0x72, &mux_data_0_5, 0, 0},
|
||||
};
|
||||
static struct i2c_board_info i2c_device_info8[] __initdata = {
|
||||
{"pca9548", 0, 0x72, &mux_data_0_6, 0, 0},
|
||||
};
|
||||
static struct i2c_board_info i2c_device_info9[] __initdata = {
|
||||
{"pca9548", 0, 0x72, &mux_data_0_7, 0, 0},
|
||||
};
|
||||
|
||||
|
||||
static struct inv_i2c_board_info i2cdev_list[] = {
|
||||
{0, ARRAY_SIZE(i2c_device_info0), i2c_device_info0 }, //smbus 0
|
||||
|
||||
{bus_id(2), ARRAY_SIZE(i2c_device_info2), i2c_device_info2 }, //mux 0
|
||||
{bus_id(3), ARRAY_SIZE(i2c_device_info3), i2c_device_info3 }, //mux 1
|
||||
{bus_id(4), ARRAY_SIZE(i2c_device_info4), i2c_device_info4 }, //mux 2
|
||||
{bus_id(5), ARRAY_SIZE(i2c_device_info5), i2c_device_info5 }, //mux 3
|
||||
{bus_id(6), ARRAY_SIZE(i2c_device_info6), i2c_device_info6 }, //mux 4
|
||||
{bus_id(7), ARRAY_SIZE(i2c_device_info7), i2c_device_info7 }, //mux 5
|
||||
{bus_id(8), ARRAY_SIZE(i2c_device_info8), i2c_device_info8 }, //mux 6
|
||||
{bus_id(9), ARRAY_SIZE(i2c_device_info9), i2c_device_info9 }, //mux 7
|
||||
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
#if 0
|
||||
static struct i2c_gpio_platform_data i2c_gpio_platdata0 = {
|
||||
.scl_pin = 58,
|
||||
.sda_pin = 75,
|
||||
|
||||
.udelay = 5, //5:100kHz
|
||||
.sda_is_open_drain = 0,
|
||||
.scl_is_open_drain = 0,
|
||||
.scl_is_output_only = 0
|
||||
};
|
||||
|
||||
static struct platform_device device_i2c_gpio0 = {
|
||||
.name = "i2c-gpio",
|
||||
.id = 1, // adapter number
|
||||
.dev.platform_data = &i2c_gpio_platdata0,
|
||||
};
|
||||
#endif
|
||||
static int __init inv_platform_init(void)
|
||||
{
|
||||
struct i2c_adapter *adap = NULL;
|
||||
struct i2c_client *e = NULL;
|
||||
int ret = 0;
|
||||
int i,j,k;
|
||||
|
||||
printk("%s \n", __func__);
|
||||
|
||||
#if 0
|
||||
//use i2c-gpio
|
||||
//register i2c gpio
|
||||
//config gpio58,75 to gpio function 58=32+3*8+2 75=32*2+8*1+3 gpio69=32*2+8*0+5
|
||||
outl( inl(0x533) | (1<<2), 0x533);
|
||||
outl( inl(0x541) | (1<<3), 0x541);
|
||||
outl( inl(0x540) | (1<<5), 0x540); //RST_I2C_MUX_N (GPIO69)
|
||||
outl( inl(0x500) | (1<<7), 0x500); //SYS_RDY_N (GPIO7)
|
||||
outl( inl(0x501) | (1<<7), 0x501); //BMC_HEART_BEAT (GPIO15)
|
||||
outl( inl(0x503) | (1<<2)|(1<<3), 0x503); //PSOC_HEART_BEAT(26),CPLD_HEART_BEAT(27)
|
||||
|
||||
ret = platform_device_register(&device_i2c_gpio0);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "i2c-gpio: device_i2c_gpio0 register fail %d\n", ret);
|
||||
}
|
||||
#endif
|
||||
for(i=0; i<ARRAY_SIZE(i2cdev_list); i++) {
|
||||
adap = i2c_get_adapter( i2cdev_list[i].ch );
|
||||
if (adap == NULL) {
|
||||
printk("sequoia get channel %d adapter fail\n", i);
|
||||
continue;
|
||||
}
|
||||
i2c_put_adapter(adap);
|
||||
for(j=0; j<i2cdev_list[i].size; j++) {
|
||||
for(k=0; k<300; k++) {
|
||||
e = i2c_new_device(adap, &i2cdev_list[i].board_info[j] );
|
||||
if(e == NULL) msleep(10); else break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
module_init(inv_platform_init);
|
||||
//arch_initcall(inv_platform_init);
|
||||
|
||||
MODULE_AUTHOR("Inventec");
|
||||
MODULE_DESCRIPTION("Sequoia Platform devices");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -0,0 +1,762 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kthread.h>
|
||||
|
||||
//=================================
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/ipmi.h>
|
||||
#include <linux/ipmi_smi.h>
|
||||
|
||||
#define IPMI_MAX_INTF (4)
|
||||
#define NETFN_OEM 0x30
|
||||
#define CMD_GETDATA 0x31
|
||||
#define CMD_SETDATA 0x32
|
||||
#define FAN_NUM 4
|
||||
#define PSU_NUM 2
|
||||
|
||||
#define PSU1 0x5800
|
||||
#define PSU2 0x5900
|
||||
#define BMC_PMBusNumber 3
|
||||
#define PMBus_Vender 0x99
|
||||
#define PMBus_Serial 0x9E
|
||||
#define PMBus_Temp2 0x8E
|
||||
#define PMBus_Version 0x9B
|
||||
#define MaxLeng_Result 0x20
|
||||
|
||||
#define MAX_IPMI_RECV_LENGTH 0xff
|
||||
|
||||
static long pmbus_reg2data_linear(int data, int linear16);
|
||||
struct ipmi_result{
|
||||
char result[MAX_IPMI_RECV_LENGTH];
|
||||
int result_length;
|
||||
};
|
||||
|
||||
DEFINE_MUTEX(ipmi_mutex);
|
||||
DEFINE_MUTEX(ipmi2_mutex);
|
||||
static struct ipmi_result ipmiresult;
|
||||
static struct device *hwmon_dev;
|
||||
static ipmi_user_t ipmi_mh_user = NULL;
|
||||
static void msg_handler(struct ipmi_recv_msg *msg,void* handler_data);
|
||||
static struct ipmi_user_hndl ipmi_hndlrs = { .ipmi_recv_hndl = msg_handler,};
|
||||
|
||||
static atomic_t dummy_count = ATOMIC_INIT(0);
|
||||
static void dummy_smi_free(struct ipmi_smi_msg *msg)
|
||||
{
|
||||
atomic_dec(&dummy_count);
|
||||
}
|
||||
static void dummy_recv_free(struct ipmi_recv_msg *msg)
|
||||
{
|
||||
atomic_dec(&dummy_count);
|
||||
}
|
||||
static struct ipmi_smi_msg halt_smi_msg = {
|
||||
.done = dummy_smi_free
|
||||
};
|
||||
static struct ipmi_recv_msg halt_recv_msg = {
|
||||
.done = dummy_recv_free
|
||||
};
|
||||
|
||||
struct __attribute__ ((__packed__)) psoc_psu_layout {
|
||||
u16 psu1_iin;
|
||||
u16 psu2_iin;
|
||||
u16 psu1_iout;
|
||||
u16 psu2_iout;
|
||||
|
||||
u16 psu1_pin;
|
||||
u16 psu2_pin;
|
||||
u16 psu1_pout;
|
||||
u16 psu2_pout;
|
||||
|
||||
u16 psu1_vin;
|
||||
u16 psu2_vin;
|
||||
u16 psu1_vout;
|
||||
u16 psu2_vout;
|
||||
};
|
||||
|
||||
struct __attribute__ ((__packed__)) psoc_layout {
|
||||
u8 ctl; //offset: 0
|
||||
u16 switch_temp; //offset: 1
|
||||
u8 reserve0; //offset: 3
|
||||
|
||||
u8 fw_upgrade; //offset: 4
|
||||
|
||||
//i2c bridge
|
||||
u8 i2c_st; //offset: 5
|
||||
u8 i2c_ctl; //offset: 6
|
||||
u8 i2c_addr; //offset: 7
|
||||
u8 i2c_data[0x20]; //offset: 8
|
||||
|
||||
//gpo
|
||||
u8 led_ctl; //offset: 28
|
||||
|
||||
u8 gpio; //offset: 29
|
||||
|
||||
//pwm duty
|
||||
u8 pwm[FAN_NUM]; //offset: 2a
|
||||
u8 pwm_psu[PSU_NUM]; //offset: 2e
|
||||
|
||||
//fan rpm
|
||||
u16 fan[FAN_NUM*2]; //offset: 30
|
||||
|
||||
u8 reserve1[4]; //offset: 40
|
||||
|
||||
//gpi
|
||||
u8 gpi_fan; //offset: 44
|
||||
|
||||
//psu state
|
||||
u8 psu_state; //offset: 45
|
||||
|
||||
//temperature
|
||||
u16 temp[5]; //offset: 46
|
||||
u16 temp_psu[PSU_NUM]; //offset: 50
|
||||
|
||||
//version
|
||||
u8 version[2]; //offset: 54
|
||||
|
||||
u8 reserve2[4]; //offset: 56
|
||||
struct psoc_psu_layout psu_info; //offset: 5a
|
||||
};
|
||||
|
||||
/* definition */
|
||||
/* definition */
|
||||
#define PSOC_OFF(m) offsetof(struct psoc_layout, m)
|
||||
#define PSOC_PSU_OFF(m) offsetof(struct psoc_psu_layout, m)
|
||||
|
||||
#define SWITCH_TMP_OFFSET PSOC_OFF(switch_temp)
|
||||
#define PWM_OFFSET PSOC_OFF(pwm)
|
||||
#define THERMAL_OFFSET PSOC_OFF(temp)
|
||||
#define RPM_OFFSET PSOC_OFF(fan)
|
||||
#define DIAG_FLAG_OFFSET PSOC_OFF(ctl)
|
||||
#define FAN_LED_OFFSET PSOC_OFF(led_ctl)
|
||||
#define FAN_GPI_OFFSET PSOC_OFF(gpi_fan)
|
||||
#define PSOC_PSU_OFFSET PSOC_OFF(psu_state)
|
||||
#define VERSION_OFFSET PSOC_OFF(version)
|
||||
#define PSU_INFO_OFFSET PSOC_OFF(psu_info)
|
||||
|
||||
|
||||
static void msg_handler(struct ipmi_recv_msg *recv_msg,void* handler_data)
|
||||
{
|
||||
struct ipmi_result *msg_result = recv_msg->user_msg_data;
|
||||
|
||||
if(recv_msg->msg.data[0]==0 && recv_msg->msg.data_len>0) {
|
||||
msg_result->result_length=recv_msg->msg.data_len-1;
|
||||
memcpy(msg_result->result, &recv_msg->msg.data[1], recv_msg->msg.data_len-1);
|
||||
}
|
||||
ipmi_free_recv_msg(recv_msg);
|
||||
mutex_unlock(&ipmi_mutex);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int start_ipmi_command(char NetFn, char cmd,char *data,int data_length, char* result, int* result_length)
|
||||
{
|
||||
int rv=0,i;
|
||||
int timeout;
|
||||
|
||||
//wait previous command finish at least 50msec
|
||||
timeout=50;
|
||||
while((mutex_is_locked(&ipmi_mutex) == 1 || (mutex_is_locked(&ipmi2_mutex) == 1)) && (--timeout)>0) { usleep_range(1000,1010); }
|
||||
if(timeout==0) { return -1; }
|
||||
mutex_lock(&ipmi_mutex);
|
||||
mutex_lock(&ipmi2_mutex);
|
||||
|
||||
if(ipmi_mh_user == NULL) {
|
||||
for (i=0,rv=1; i<IPMI_MAX_INTF && rv; i++) {
|
||||
rv = ipmi_create_user(i, &ipmi_hndlrs, NULL, &ipmi_mh_user);
|
||||
}
|
||||
}
|
||||
|
||||
if (rv < 0) {
|
||||
mutex_unlock(&ipmi_mutex);
|
||||
mutex_unlock(&ipmi2_mutex);
|
||||
return rv;
|
||||
}
|
||||
else {
|
||||
struct ipmi_system_interface_addr addr;
|
||||
struct kernel_ipmi_msg msg;
|
||||
uint8_t msg_data[data_length];
|
||||
|
||||
memcpy(msg_data,data,data_length);
|
||||
addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
|
||||
addr.channel = IPMI_BMC_CHANNEL;
|
||||
addr.lun = 0;
|
||||
|
||||
msg.netfn = NetFn;
|
||||
msg.cmd = cmd;
|
||||
msg.data = msg_data;
|
||||
msg.data_len = data_length;
|
||||
|
||||
rv = ipmi_request_supply_msgs(ipmi_mh_user, (struct ipmi_addr*)&addr, 0,&msg, &ipmiresult, &halt_smi_msg, &halt_recv_msg, 0);
|
||||
if (rv) {
|
||||
mutex_unlock(&ipmi_mutex);
|
||||
mutex_unlock(&ipmi2_mutex);
|
||||
return -6;
|
||||
}
|
||||
|
||||
//skip command if 1sec no response from remote
|
||||
timeout=1000;
|
||||
while(mutex_is_locked(&ipmi_mutex) == 1 && (--timeout)>0) { usleep_range(1000,1100);}
|
||||
if(timeout==0) {
|
||||
mutex_unlock(&ipmi2_mutex);
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
*result_length=ipmiresult.result_length;
|
||||
memcpy(result,ipmiresult.result,*result_length);
|
||||
mutex_unlock(&ipmi2_mutex);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(start_ipmi_command);
|
||||
|
||||
static ssize_t psoc_ipmi_read(u8 *buf, u8 offset, size_t count)
|
||||
{
|
||||
uint8_t data[2];
|
||||
int result_len=0;
|
||||
int rv;
|
||||
|
||||
data[0] = offset;
|
||||
data[1] = count;
|
||||
|
||||
rv=start_ipmi_command(NETFN_OEM, CMD_GETDATA,data,2, buf, &result_len);
|
||||
|
||||
return result_len;
|
||||
}
|
||||
|
||||
static ssize_t psoc_ipmi_write(char *buf, unsigned offset, size_t count)
|
||||
{
|
||||
uint8_t data[count+1],result[1];
|
||||
int result_len;
|
||||
|
||||
data[0] = offset;
|
||||
memcpy(&data[1],buf,count);
|
||||
|
||||
start_ipmi_command(NETFN_OEM, CMD_SETDATA,data,count+1, result, &result_len);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static u16 psoc_read16(u8 offset)
|
||||
{
|
||||
u16 value = 0;
|
||||
u8 buf[]={0,0};
|
||||
|
||||
if(psoc_ipmi_read(buf, offset, 2) == 2)
|
||||
value = (buf[0]<<8 | buf[1]<<0);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static u8 psoc_read8(u8 offset)
|
||||
{
|
||||
u8 value = 0;
|
||||
u8 buf = 0;
|
||||
|
||||
if(psoc_ipmi_read(&buf, offset, 1) == 1)
|
||||
value = buf;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
CPLD report the PSU0 status
|
||||
000 = PSU normal operation
|
||||
100 = PSU fault
|
||||
010 = PSU unpowered
|
||||
111 = PSU not installed
|
||||
|
||||
7 6 | 5 4 3 | 2 1 0
|
||||
----------------------
|
||||
| psu1 | psu0
|
||||
*/
|
||||
static char* psu_str[] = {
|
||||
"normal", //000
|
||||
"NA", //001
|
||||
"unpowered", //010
|
||||
"NA", //011
|
||||
"fault", //100
|
||||
"NA", //101
|
||||
"NA", //110
|
||||
"not installed", //111
|
||||
};
|
||||
|
||||
static ssize_t show_psu_st(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u32 status=0;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u8 byte=0;
|
||||
int shift = (attr->index == 0)?3:0;
|
||||
|
||||
status = psoc_ipmi_read(&byte, PSOC_PSU_OFFSET, 1);
|
||||
|
||||
byte = (byte >> shift) & 0x7;
|
||||
|
||||
status = sprintf (buf, "%d : %s\n", byte, psu_str[byte]);
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static ssize_t show_ipmi_pmbus(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
uint8_t data[4],result[MaxLeng_Result];
|
||||
int result_len=0;
|
||||
|
||||
data[0] = BMC_PMBusNumber;
|
||||
data[1] = (attr->index & 0xFF00 ) >>7;
|
||||
data[3] = attr->index & 0xff;
|
||||
if(data[3]==PMBus_Temp2)
|
||||
{data[2]=2;}
|
||||
else
|
||||
{data[2]=MaxLeng_Result;}
|
||||
|
||||
if(start_ipmi_command(0x06, 0x52,data,4, result, &result_len)==0)
|
||||
{
|
||||
if(data[3]==PMBus_Temp2)
|
||||
{
|
||||
return sprintf(buf, "%ld \n", pmbus_reg2data_linear(result[0] | (result[1]<<8), 0 ));
|
||||
}
|
||||
result[result[0]+1]='\0';
|
||||
return sprintf(buf, "%s\n",&result[1] );
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t show_thermal(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
int status=0;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u8 offset = attr->index * 2 + THERMAL_OFFSET;
|
||||
|
||||
status = psoc_read16(offset);
|
||||
|
||||
return sprintf(buf, "%d\n",
|
||||
(s8)(status>>8) * 1000 );
|
||||
}
|
||||
|
||||
static ssize_t show_pwm(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
int status=0;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u8 offset = attr->index + PWM_OFFSET;
|
||||
|
||||
status = psoc_read8(offset);
|
||||
|
||||
return sprintf(buf, "%d\n",
|
||||
status);
|
||||
}
|
||||
|
||||
static ssize_t set_pwm(struct device *dev,
|
||||
struct device_attribute *da,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u8 offset = attr->index + PWM_OFFSET;
|
||||
|
||||
u8 pwm = simple_strtol(buf, NULL, 10);
|
||||
if(pwm > 255) pwm = 255;
|
||||
|
||||
psoc_ipmi_write(&pwm, offset, 1);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t show_rpm(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
int status=0;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u8 offset = attr->index*2 + RPM_OFFSET;
|
||||
|
||||
status = psoc_read16(offset);
|
||||
|
||||
return sprintf(buf, "%d\n",
|
||||
status);
|
||||
}
|
||||
|
||||
static ssize_t show_switch_tmp(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u16 status=0;
|
||||
u16 temp = 0;
|
||||
|
||||
status = psoc_ipmi_read((u8*)&temp, SWITCH_TMP_OFFSET, 2);
|
||||
|
||||
status = sprintf (buf, "%d\n", (s32)(temp) );
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static ssize_t set_switch_tmp(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
long temp = simple_strtol(buf, NULL, 10);
|
||||
|
||||
u16 temp2 = (u16)temp;
|
||||
|
||||
psoc_ipmi_write((u8*)&temp2, SWITCH_TMP_OFFSET, 2);
|
||||
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_diag(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u16 status=0;
|
||||
u8 diag_flag = 0;
|
||||
|
||||
status = psoc_ipmi_read((u8*)&diag_flag, DIAG_FLAG_OFFSET, 1);
|
||||
|
||||
status = sprintf (buf, "%d\n", ((diag_flag & 0x80)?1:0));
|
||||
|
||||
return strlen(buf);
|
||||
}
|
||||
|
||||
static ssize_t set_diag(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
u8 value = 0;
|
||||
u8 diag = simple_strtol(buf, NULL, 10);
|
||||
|
||||
diag = diag?1:0;
|
||||
|
||||
psoc_ipmi_read((u8*)&value, DIAG_FLAG_OFFSET, 1);
|
||||
if(diag) value |= (1<<7);
|
||||
else value &= ~(1<<7);
|
||||
psoc_ipmi_write((u8*)&value, DIAG_FLAG_OFFSET, 1);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_version(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u16 status=0;
|
||||
|
||||
status = psoc_read16(VERSION_OFFSET);
|
||||
|
||||
return sprintf(buf, "ver: %x.%x\n", (status & 0xFF00)>>8, (status & 0xFF) );
|
||||
}
|
||||
|
||||
static ssize_t show_name(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
return sprintf (buf, "inv_psoc\n");
|
||||
}
|
||||
|
||||
|
||||
static ssize_t show_fan_led(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
int status=0;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u8 bit = attr->index;
|
||||
|
||||
status = psoc_read8(FAN_LED_OFFSET);
|
||||
|
||||
return sprintf(buf, "%d\n",
|
||||
(status & (1<<bit))?1:0 );
|
||||
}
|
||||
|
||||
static ssize_t set_fan_led(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
u8 bit = attr->index;
|
||||
u8 led_state = 0;
|
||||
|
||||
u8 v = simple_strtol(buf, NULL, 10);
|
||||
|
||||
led_state = psoc_read8(FAN_LED_OFFSET);
|
||||
if(v) led_state |= (1<<bit);
|
||||
else led_state &= ~(1<<bit);
|
||||
psoc_ipmi_write(&led_state, FAN_LED_OFFSET, 1);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_value8(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
int status=0;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u8 offset = attr->index;
|
||||
|
||||
status = psoc_read8(offset);
|
||||
|
||||
return sprintf(buf, "0x%02X\n", status );
|
||||
}
|
||||
|
||||
static long pmbus_reg2data_linear(int data, int linear16)
|
||||
{
|
||||
s16 exponent;
|
||||
s32 mantissa;
|
||||
long val;
|
||||
|
||||
if (linear16) { /* LINEAR16 */
|
||||
exponent = -9;
|
||||
mantissa = (u16) data;
|
||||
} else { /* LINEAR11 */
|
||||
exponent = ((s16)data) >> 11;
|
||||
exponent = ((s16)( data & 0xF800) ) >> 11;
|
||||
mantissa = ((s32)((data & 0x7ff) << 5)) >> 5;
|
||||
}
|
||||
|
||||
//printk("data=%d, m=%d, e=%d\n", data, exponent, mantissa);
|
||||
val = mantissa;
|
||||
|
||||
/* scale result to micro-units for power sensors */
|
||||
val = val * 1000L;
|
||||
|
||||
if (exponent >= 0)
|
||||
val <<= exponent;
|
||||
else
|
||||
val >>= -exponent;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static ssize_t show_psu_psoc(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u16 status=0;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
u8 offset = attr->index + PSU_INFO_OFFSET;
|
||||
|
||||
status = psoc_read16(offset);
|
||||
|
||||
return sprintf(buf, "%ld \n", pmbus_reg2data_linear(status, strstr(attr->dev_attr.attr.name, "vout")? 1:0 ));
|
||||
}
|
||||
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_thermal, 0, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_thermal, 0, 1);
|
||||
static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_thermal, 0, 2);
|
||||
static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_thermal, 0, 3);
|
||||
static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_thermal, 0, 4);
|
||||
static SENSOR_DEVICE_ATTR(thermal_psu1, S_IRUGO, show_thermal, 0, 5);
|
||||
static SENSOR_DEVICE_ATTR(thermal_psu2, S_IRUGO, show_thermal, 0, 6);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 0);
|
||||
static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 1);
|
||||
static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 2);
|
||||
static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 3);
|
||||
static SENSOR_DEVICE_ATTR(pwm_psu1, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 4);
|
||||
static SENSOR_DEVICE_ATTR(pwm_psu2, S_IWUSR|S_IRUGO, show_pwm, set_pwm, 5);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(psu0, S_IRUGO, show_psu_st, 0, 0);
|
||||
static SENSOR_DEVICE_ATTR(psu1, S_IRUGO, show_psu_st, 0, 1);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, 0, 0);
|
||||
static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_rpm, 0, 1);
|
||||
static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_rpm, 0, 2);
|
||||
static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_rpm, 0, 3);
|
||||
static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_rpm, 0, 4);
|
||||
static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_rpm, 0, 5);
|
||||
static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_rpm, 0, 6);
|
||||
static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_rpm, 0, 7);
|
||||
static SENSOR_DEVICE_ATTR(rpm_psu1, S_IRUGO, show_rpm, 0, 8);
|
||||
static SENSOR_DEVICE_ATTR(rpm_psu2, S_IRUGO, show_rpm, 0, 9);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(switch_tmp, S_IWUSR|S_IRUGO, show_switch_tmp, set_switch_tmp, 0);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(diag, S_IWUSR|S_IRUGO, show_diag, set_diag, 0);
|
||||
static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, 0, 0);
|
||||
static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(fan_led_grn1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 0);
|
||||
static SENSOR_DEVICE_ATTR(fan_led_grn2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 1);
|
||||
static SENSOR_DEVICE_ATTR(fan_led_grn3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 2);
|
||||
static SENSOR_DEVICE_ATTR(fan_led_grn4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 3);
|
||||
static SENSOR_DEVICE_ATTR(fan_led_red1, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 4);
|
||||
static SENSOR_DEVICE_ATTR(fan_led_red2, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 5);
|
||||
static SENSOR_DEVICE_ATTR(fan_led_red3, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 6);
|
||||
static SENSOR_DEVICE_ATTR(fan_led_red4, S_IWUSR|S_IRUGO, show_fan_led, set_fan_led, 7);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(fan_gpi, S_IRUGO, show_value8, 0, FAN_GPI_OFFSET);
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vin));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_vout));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iin));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_iout));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pin));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu1_pout));
|
||||
|
||||
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_vin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vin));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_vout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_vout));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_iin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iin));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_iout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_iout));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_pin, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pin));
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_pout, S_IRUGO, show_psu_psoc, 0, PSOC_PSU_OFF(psu2_pout));
|
||||
|
||||
//IPMI
|
||||
static SENSOR_DEVICE_ATTR(thermal2_psu1, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Temp2);
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_vender, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Vender);
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_serial, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Serial);
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu1_version, S_IRUGO, show_ipmi_pmbus, 0, PSU1 | PMBus_Version);
|
||||
|
||||
static SENSOR_DEVICE_ATTR(thermal2_psu2, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Temp2);
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_vender, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Vender);
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_serial, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Serial);
|
||||
static SENSOR_DEVICE_ATTR(psoc_psu2_version, S_IRUGO, show_ipmi_pmbus, 0, PSU2 | PMBus_Version);
|
||||
|
||||
|
||||
static struct attribute *psoc_attributes[] = {
|
||||
//thermal
|
||||
&sensor_dev_attr_temp1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp4_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp5_input.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_thermal_psu1.dev_attr.attr,
|
||||
&sensor_dev_attr_thermal_psu2.dev_attr.attr,
|
||||
|
||||
|
||||
//pwm
|
||||
&sensor_dev_attr_pwm1.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm2.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm3.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm4.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm_psu1.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm_psu2.dev_attr.attr,
|
||||
|
||||
//rpm
|
||||
&sensor_dev_attr_fan1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan4_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan5_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan6_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan7_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan8_input.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_rpm_psu1.dev_attr.attr,
|
||||
&sensor_dev_attr_rpm_psu2.dev_attr.attr,
|
||||
|
||||
//switch temperature
|
||||
&sensor_dev_attr_switch_tmp.dev_attr.attr,
|
||||
|
||||
//diag flag
|
||||
&sensor_dev_attr_diag.dev_attr.attr,
|
||||
|
||||
//version
|
||||
&sensor_dev_attr_version.dev_attr.attr,
|
||||
|
||||
//fan led
|
||||
&sensor_dev_attr_fan_led_grn1.dev_attr.attr,
|
||||
&sensor_dev_attr_fan_led_grn2.dev_attr.attr,
|
||||
&sensor_dev_attr_fan_led_grn3.dev_attr.attr,
|
||||
&sensor_dev_attr_fan_led_grn4.dev_attr.attr,
|
||||
&sensor_dev_attr_fan_led_red1.dev_attr.attr,
|
||||
&sensor_dev_attr_fan_led_red2.dev_attr.attr,
|
||||
&sensor_dev_attr_fan_led_red3.dev_attr.attr,
|
||||
&sensor_dev_attr_fan_led_red4.dev_attr.attr,
|
||||
|
||||
//fan GPI
|
||||
&sensor_dev_attr_fan_gpi.dev_attr.attr,
|
||||
&sensor_dev_attr_psu0.dev_attr.attr,
|
||||
&sensor_dev_attr_psu1.dev_attr.attr,
|
||||
|
||||
|
||||
//psu_psoc
|
||||
&sensor_dev_attr_psoc_psu1_vin.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu1_vout.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu1_iin.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu1_iout.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu1_pin.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu1_pout.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_vin.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_vout.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_iin.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_iout.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_pin.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_pout.dev_attr.attr,
|
||||
|
||||
//ipmi_i2c_command
|
||||
&sensor_dev_attr_thermal2_psu1.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu1_vender.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu1_serial.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu1_version.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_thermal2_psu2.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_vender.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_serial.dev_attr.attr,
|
||||
&sensor_dev_attr_psoc_psu2_version.dev_attr.attr,
|
||||
|
||||
&sensor_dev_attr_name.dev_attr.attr,
|
||||
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group psoc_group = {
|
||||
.attrs = psoc_attributes,
|
||||
};
|
||||
|
||||
static int __init inv_psoc_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
printk("+%s\n", __func__);
|
||||
|
||||
hwmon_dev = hwmon_device_register(NULL);
|
||||
if (IS_ERR(hwmon_dev)) {
|
||||
goto fail_hwmon_device_register;
|
||||
}
|
||||
|
||||
ret = sysfs_create_group(&hwmon_dev->kobj, &psoc_group);
|
||||
if (ret) {
|
||||
goto fail_create_group_hwmon;
|
||||
}
|
||||
|
||||
printk(" Enable IPMI PSoC protocol.\n");
|
||||
return ret;
|
||||
|
||||
fail_create_group_hwmon:
|
||||
hwmon_device_unregister(hwmon_dev);
|
||||
fail_hwmon_device_register:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void __exit inv_psoc_exit(void)
|
||||
{
|
||||
if(ipmi_mh_user!=NULL) {ipmi_destroy_user(ipmi_mh_user);}
|
||||
if(hwmon_dev != NULL) hwmon_device_unregister(hwmon_dev);
|
||||
sysfs_remove_group(&hwmon_dev->kobj, &psoc_group);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Ting.Jack <ting.jack@inventec>");
|
||||
MODULE_DESCRIPTION("inv psoc driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(inv_psoc_init);
|
||||
module_exit(inv_psoc_exit);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,896 @@
|
||||
#ifndef INV_SWPS_H
|
||||
#define INV_SWPS_H
|
||||
|
||||
#include "transceiver.h"
|
||||
#include "io_expander.h"
|
||||
#include "inv_mux.h"
|
||||
|
||||
/* Module settings */
|
||||
#define SWP_CLS_NAME "swps"
|
||||
#define SWP_DEV_PORT "port"
|
||||
#define SWP_DEV_MODCTL "module"
|
||||
#define SWP_RESET_PWD "inventec"
|
||||
#define SWP_POLLING_PERIOD (300) /* msec */
|
||||
#define SWP_POLLING_ENABLE (1)
|
||||
#define SWP_AUTOCONFIG_ENABLE (1)
|
||||
|
||||
/* Module information */
|
||||
#define SWP_AUTHOR "Neil <liao.neil@inventec.com>"
|
||||
#define SWP_DESC "Inventec port and transceiver driver"
|
||||
#define SWP_VERSION "4.2.5"
|
||||
#define SWP_LICENSE "GPL"
|
||||
|
||||
#define SWPS_KERN_VER_AF_3_10 (1)
|
||||
|
||||
/* Module status define */
|
||||
#define SWP_STATE_NORMAL (0)
|
||||
#define SWP_STATE_I2C_DIE (-91)
|
||||
|
||||
/* [Note]:
|
||||
* Functions and mechanism for auto-detect platform type is ready,
|
||||
* But HW and BIOS not ready! We need to wait them.
|
||||
* So, please do not use PLATFORM_TYPE_AUTO until they are ready.
|
||||
* (2016.06.13)
|
||||
*/
|
||||
#define PLATFORM_TYPE_AUTO (100)
|
||||
#define PLATFORM_TYPE_MAGNOLIA (111)
|
||||
#define PLATFORM_TYPE_MAGNOLIA_FNC (112)
|
||||
#define PLATFORM_TYPE_REDWOOD (121)
|
||||
#define PLATFORM_TYPE_REDWOOD_FSL (122)
|
||||
#define PLATFORM_TYPE_HUDSON32I_GA (131)
|
||||
#define PLATFORM_TYPE_SPRUCE (141)
|
||||
#define PLATFORM_TYPE_CYPRESS_GA1 (151) /* Up -> Down */
|
||||
#define PLATFORM_TYPE_CYPRESS_GA2 (152) /* Down -> Up */
|
||||
#define PLATFORM_TYPE_CYPRESS_BAI (153) /* Down -> Up */
|
||||
#define PLATFORM_TYPE_TAHOE (161)
|
||||
#define PLATFORM_TYPE_SEQUOIA_GA (171)
|
||||
/* Current running platfrom */
|
||||
#define PLATFORM_SETTINGS PLATFORM_TYPE_SEQUOIA_GA
|
||||
|
||||
/* Define platform flag and kernel version */
|
||||
#if (PLATFORM_SETTINGS == PLATFORM_TYPE_MAGNOLIA)
|
||||
#define SWPS_MAGNOLIA (1)
|
||||
#define SWPS_KERN_VER_BF_3_8 (1)
|
||||
#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_MAGNOLIA_FNC)
|
||||
#define SWPS_MAGNOLIA (1)
|
||||
#define SWPS_KERN_VER_AF_3_10 (1)
|
||||
#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD)
|
||||
#define SWPS_REDWOOD (1)
|
||||
#define SWPS_KERN_VER_BF_3_8 (1)
|
||||
#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_REDWOOD_FSL)
|
||||
#define SWPS_REDWOOD_FSL (1)
|
||||
#define SWPS_KERN_VER_BF_3_8 (1)
|
||||
#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_HUDSON32I_GA)
|
||||
#define SWPS_HUDSON32I_GA (1)
|
||||
#define SWPS_KERN_VER_BF_3_8 (1)
|
||||
#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_SPRUCE)
|
||||
#define SWPS_SPRUCE (1)
|
||||
#define SWPS_KERN_VER_BF_3_8 (1)
|
||||
#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA1)
|
||||
#define SWPS_CYPRESS_GA1 (1)
|
||||
#define SWPS_KERN_VER_BF_3_8 (1)
|
||||
#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_GA2)
|
||||
#define SWPS_CYPRESS_GA2 (1)
|
||||
#define SWPS_KERN_VER_BF_3_8 (1)
|
||||
#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_CYPRESS_BAI)
|
||||
#define SWPS_CYPRESS_BAI (1)
|
||||
#define SWPS_KERN_VER_AF_3_10 (1)
|
||||
#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_TAHOE)
|
||||
#define SWPS_TAHOE (1)
|
||||
#define SWPS_KERN_VER_AF_3_10 (1)
|
||||
#elif (PLATFORM_SETTINGS == PLATFORM_TYPE_SEQUOIA_GA)
|
||||
#define SWPS_SEQUOIA (1)
|
||||
#define SWPS_KERN_VER_BF_3_8 (1)
|
||||
#endif
|
||||
|
||||
|
||||
struct inv_platform_s {
|
||||
int id;
|
||||
char name[64];
|
||||
};
|
||||
|
||||
struct inv_ioexp_layout_s {
|
||||
int ioexp_id;
|
||||
int ioexp_type;
|
||||
struct ioexp_addr_s addr[4];
|
||||
};
|
||||
|
||||
struct inv_port_layout_s {
|
||||
int port_id;
|
||||
int chan_id;
|
||||
int ioexp_id;
|
||||
int ioexp_offset;
|
||||
int transvr_type;
|
||||
int chipset_type;
|
||||
int lane_id[8];
|
||||
};
|
||||
|
||||
|
||||
/* ==========================================
|
||||
* Inventec Platform Settings
|
||||
* ==========================================
|
||||
*/
|
||||
struct inv_platform_s platform_map[] = {
|
||||
{PLATFORM_TYPE_AUTO, "Auto-Detect" },
|
||||
{PLATFORM_TYPE_MAGNOLIA, "Magnolia" },
|
||||
{PLATFORM_TYPE_MAGNOLIA_FNC, "Magnolia_FNC" },
|
||||
{PLATFORM_TYPE_REDWOOD, "Redwood" },
|
||||
{PLATFORM_TYPE_REDWOOD_FSL, "Redwood_FSL" },
|
||||
{PLATFORM_TYPE_HUDSON32I_GA, "Hudson32i" },
|
||||
{PLATFORM_TYPE_SPRUCE, "Spruce" },
|
||||
{PLATFORM_TYPE_CYPRESS_GA1, "Cypress_GA1" },
|
||||
{PLATFORM_TYPE_CYPRESS_GA2, "Cypress_GA2" },
|
||||
{PLATFORM_TYPE_CYPRESS_BAI, "Cypress_BAI" },
|
||||
{PLATFORM_TYPE_TAHOE, "Tahoe" },
|
||||
{PLATFORM_TYPE_SEQUOIA_GA, "Sequoia_GA" },
|
||||
};
|
||||
|
||||
|
||||
/* ==========================================
|
||||
* Magnolia Layout configuration
|
||||
* ==========================================
|
||||
*/
|
||||
#ifdef SWPS_MAGNOLIA
|
||||
unsigned magnolia_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548;
|
||||
|
||||
struct inv_ioexp_layout_s magnolia_ioexp_layout[] = {
|
||||
/* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
|
||||
{0, IOEXP_TYPE_MAGINOLIA_NAB, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */
|
||||
},
|
||||
{1, IOEXP_TYPE_MAGINOLIA_NAB, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */
|
||||
},
|
||||
{2, IOEXP_TYPE_MAGINOLIA_NAB, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */
|
||||
},
|
||||
{3, IOEXP_TYPE_MAGINOLIA_4AB, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander 4 A */
|
||||
{5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xf0, 0xff}, {0xf0, 0xff}, }, }, /* addr[1] = I/O Expander 4 B */
|
||||
},
|
||||
{4, IOEXP_TYPE_MAGINOLIA_NAB, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */
|
||||
},
|
||||
{5, IOEXP_TYPE_MAGINOLIA_NAB, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, }, /* addr[1] = I/O Expander N B */
|
||||
},
|
||||
{6, IOEXP_TYPE_MAGINOLIA_7AB, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 7 A */
|
||||
{8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xf0, 0x33}, }, }, /* addr[1] = I/O Expander 7 B */
|
||||
},
|
||||
};
|
||||
|
||||
struct inv_port_layout_s magnolia_port_layout[] = {
|
||||
/* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
|
||||
{ 0, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 16} },
|
||||
{ 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 15} },
|
||||
{ 2, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 14} },
|
||||
{ 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 13} },
|
||||
{ 4, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 24} },
|
||||
{ 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 23} },
|
||||
{ 6, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 22} },
|
||||
{ 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 21} },
|
||||
{ 8, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 28} },
|
||||
{ 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 27} },
|
||||
{10, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 26} },
|
||||
{11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 25} },
|
||||
{12, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 32} },
|
||||
{13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 31} },
|
||||
{14, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 30} },
|
||||
{15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 29} },
|
||||
{16, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 48} },
|
||||
{17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 47} },
|
||||
{18, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 46} },
|
||||
{19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 45} },
|
||||
{20, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 52} },
|
||||
{21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 51} },
|
||||
{22, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 50} },
|
||||
{23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 49} },
|
||||
{24, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 56} },
|
||||
{25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 55} },
|
||||
{26, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 54} },
|
||||
{27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 53} },
|
||||
{28, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 60} },
|
||||
{29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 59} },
|
||||
{30, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 58} },
|
||||
{31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 57} },
|
||||
{32, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 64} },
|
||||
{33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 63} },
|
||||
{34, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 62} },
|
||||
{35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 61} },
|
||||
{36, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 68} },
|
||||
{37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 67} },
|
||||
{38, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 66} },
|
||||
{39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 65} },
|
||||
{40, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 72} },
|
||||
{41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 71} },
|
||||
{42, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 70} },
|
||||
{43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 69} },
|
||||
{44, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 76} },
|
||||
{45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 75} },
|
||||
{46, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 74} },
|
||||
{47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TRIDENT_2, { 73} },
|
||||
{48, 58, 6, 0, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} },
|
||||
{49, 59, 6, 1, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} },
|
||||
{50, 60, 6, 2, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} },
|
||||
{51, 61, 6, 3, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} },
|
||||
{52, 62, 6, 4, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} },
|
||||
{53, 63, 6, 5, TRANSVR_TYPE_QSFP, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* ==========================================
|
||||
* Redwood Layout configuration
|
||||
* ==========================================
|
||||
*/
|
||||
#ifdef SWPS_REDWOOD
|
||||
unsigned redwood_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548;
|
||||
|
||||
struct inv_ioexp_layout_s redwood_ioexp_layout[] = {
|
||||
/* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
|
||||
{0, IOEXP_TYPE_REDWOOD_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */
|
||||
{4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */
|
||||
{0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */
|
||||
},
|
||||
{1, IOEXP_TYPE_REDWOOD_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */
|
||||
{5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */
|
||||
{0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */
|
||||
},
|
||||
{2, IOEXP_TYPE_REDWOOD_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */
|
||||
{2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */
|
||||
{0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */
|
||||
},
|
||||
{3, IOEXP_TYPE_REDWOOD_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */
|
||||
{3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */
|
||||
{0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */
|
||||
},
|
||||
};
|
||||
|
||||
struct inv_port_layout_s redwood_port_layout[] = {
|
||||
/* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
|
||||
{ 0, 22, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} },
|
||||
{ 1, 23, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} },
|
||||
{ 2, 24, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} },
|
||||
{ 3, 25, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} },
|
||||
{ 4, 26, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} },
|
||||
{ 5, 27, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} },
|
||||
{ 6, 28, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} },
|
||||
{ 7, 29, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} },
|
||||
{ 8, 30, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} },
|
||||
{ 9, 31, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} },
|
||||
{10, 32, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} },
|
||||
{11, 33, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} },
|
||||
{12, 34, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} },
|
||||
{13, 35, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} },
|
||||
{14, 36, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} },
|
||||
{15, 37, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} },
|
||||
{16, 6, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} },
|
||||
{17, 7, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} },
|
||||
{18, 8, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} },
|
||||
{19, 9, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} },
|
||||
{20, 10, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} },
|
||||
{21, 11, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} },
|
||||
{22, 12, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} },
|
||||
{23, 13, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} },
|
||||
{24, 14, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} },
|
||||
{25, 15, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} },
|
||||
{26, 16, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} },
|
||||
{27, 17, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} },
|
||||
{28, 18, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113,114,115,116} },
|
||||
{29, 19, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} },
|
||||
{30, 20, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121,122,123,124} },
|
||||
{31, 21, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125,126,127,128} },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* ==========================================
|
||||
* Hudson32i Layout configuration
|
||||
* ==========================================
|
||||
*/
|
||||
#ifdef SWPS_HUDSON32I_GA
|
||||
unsigned hudsin32iga_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548;
|
||||
|
||||
struct inv_ioexp_layout_s hudson32iga_ioexp_layout[] = {
|
||||
/* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
|
||||
{0, IOEXP_TYPE_HUDSON32IGA_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */
|
||||
{2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */
|
||||
{0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x24 */
|
||||
},
|
||||
{1, IOEXP_TYPE_HUDSON32IGA_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */
|
||||
{3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */
|
||||
{0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x24 */
|
||||
},
|
||||
{2, IOEXP_TYPE_HUDSON32IGA_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */
|
||||
{4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */
|
||||
{0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x25 */
|
||||
},
|
||||
{3, IOEXP_TYPE_HUDSON32IGA_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander A */
|
||||
{5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander B */
|
||||
{0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0x25 */
|
||||
},
|
||||
};
|
||||
|
||||
struct inv_port_layout_s hudson32iga_port_layout[] = {
|
||||
/* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
|
||||
{ 0, 6, 0, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 1, 2, 3, 4} },
|
||||
{ 1, 7, 0, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 5, 6, 7, 8} },
|
||||
{ 2, 8, 0, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 9, 10, 11, 12} },
|
||||
{ 3, 9, 0, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 13, 14, 15, 16} },
|
||||
{ 4, 10, 0, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 17, 18, 19, 20} },
|
||||
{ 5, 11, 0, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 21, 22, 23, 24} },
|
||||
{ 6, 12, 0, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 25, 26, 27, 28} },
|
||||
{ 7, 13, 0, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 29, 30, 31, 32} },
|
||||
{ 8, 14, 1, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 33, 34, 35, 36} },
|
||||
{ 9, 15, 1, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 37, 38, 39, 40} },
|
||||
{10, 16, 1, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 41, 42, 43, 44} },
|
||||
{11, 17, 1, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 45, 46, 47, 48} },
|
||||
{12, 18, 1, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 49, 50, 51, 52} },
|
||||
{13, 19, 1, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 53, 54, 55, 56} },
|
||||
{14, 20, 1, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 57, 58, 59, 60} },
|
||||
{15, 21, 1, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 61, 62, 63, 64} },
|
||||
{16, 22, 2, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 65, 66, 67, 68} },
|
||||
{17, 23, 2, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 69, 70, 71, 72} },
|
||||
{18, 24, 2, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 73, 74, 75, 76} },
|
||||
{19, 25, 2, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} },
|
||||
{20, 26, 2, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} },
|
||||
{21, 27, 2, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 85, 86, 87, 88} },
|
||||
{22, 28, 2, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 89, 90, 91, 92} },
|
||||
{23, 29, 2, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 93, 94, 95, 96} },
|
||||
{24, 30, 3, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} },
|
||||
{25, 31, 3, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} },
|
||||
{26, 32, 3, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} },
|
||||
{27, 33, 3, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} },
|
||||
{28, 34, 3, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {113,114,115,116} },
|
||||
{29, 35, 3, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {117,118,119,120} },
|
||||
{30, 36, 3, 6, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {121,122,123,124} },
|
||||
{31, 37, 3, 7, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {125,126,127,128} },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* ==========================================
|
||||
* Spruce Layout configuration
|
||||
* ==========================================
|
||||
*/
|
||||
#ifdef SWPS_SPRUCE
|
||||
unsigned spruce_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548;
|
||||
|
||||
struct inv_ioexp_layout_s spruce_ioexp_layout[] = {
|
||||
/* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
|
||||
{0, IOEXP_TYPE_SPRUCE_7AB, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 7A */
|
||||
{2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xf0, 0x33}, }, }, /* addr[2] = I/O Expander 7B */
|
||||
},
|
||||
};
|
||||
|
||||
struct inv_port_layout_s spruce_port_layout[] = {
|
||||
/* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
|
||||
{ 0, 6, 0, 0, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 81, 82, 83, 84} },
|
||||
{ 1, 7, 0, 1, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 77, 78, 79, 80} },
|
||||
{ 2, 8, 0, 2, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, { 97, 98, 99,100} },
|
||||
{ 3, 9, 0, 3, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {101,102,103,104} },
|
||||
{ 4, 10, 0, 4, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {105,106,107,108} },
|
||||
{ 5, 11, 0, 5, TRANSVR_TYPE_QSFP_PLUS, BCM_CHIP_TYPE_TRIDENT_2, {109,110,111,112} },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* ==========================================
|
||||
* Cypress Layout configuration (Inventec version [Up->Down])
|
||||
* ==========================================
|
||||
*/
|
||||
#ifdef SWPS_CYPRESS_GA1
|
||||
unsigned cypress_ga1_gpio_rest_mux = MUX_RST_GPIO_69_PAC9548;
|
||||
|
||||
struct inv_ioexp_layout_s cypress_ga1_ioexp_layout[] = {
|
||||
/* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
|
||||
{0, IOEXP_TYPE_CYPRESS_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{1, IOEXP_TYPE_CYPRESS_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{2, IOEXP_TYPE_CYPRESS_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{3, IOEXP_TYPE_CYPRESS_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{4, IOEXP_TYPE_CYPRESS_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{5, IOEXP_TYPE_CYPRESS_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */
|
||||
{8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */
|
||||
{8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */
|
||||
},
|
||||
};
|
||||
|
||||
struct inv_port_layout_s cypress_ga1_port_layout[] = {
|
||||
/* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
|
||||
{ 0, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} },
|
||||
{ 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} },
|
||||
{ 2, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} },
|
||||
{ 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} },
|
||||
{ 4, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} },
|
||||
{ 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} },
|
||||
{ 6, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} },
|
||||
{ 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} },
|
||||
{ 8, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} },
|
||||
{ 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} },
|
||||
{10, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} },
|
||||
{11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} },
|
||||
{12, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} },
|
||||
{13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} },
|
||||
{14, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} },
|
||||
{15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} },
|
||||
{16, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} },
|
||||
{17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} },
|
||||
{18, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} },
|
||||
{19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} },
|
||||
{20, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} },
|
||||
{21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} },
|
||||
{22, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} },
|
||||
{23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} },
|
||||
{24, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} },
|
||||
{25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} },
|
||||
{26, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} },
|
||||
{27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} },
|
||||
{28, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} },
|
||||
{29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} },
|
||||
{30, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} },
|
||||
{31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} },
|
||||
{32, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} },
|
||||
{33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} },
|
||||
{34, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} },
|
||||
{35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} },
|
||||
{36, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} },
|
||||
{37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} },
|
||||
{38, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} },
|
||||
{39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} },
|
||||
{40, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} },
|
||||
{41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} },
|
||||
{42, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} },
|
||||
{43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} },
|
||||
{44, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} },
|
||||
{45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} },
|
||||
{46, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} },
|
||||
{47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} },
|
||||
{48, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} },
|
||||
{49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} },
|
||||
{50, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} },
|
||||
{51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} },
|
||||
{52, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} },
|
||||
{53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* ==========================================
|
||||
* Cypress Layout configuration (Inventec version [Down->Up])
|
||||
* ==========================================
|
||||
*/
|
||||
#ifdef SWPS_CYPRESS_GA2
|
||||
unsigned cypress_ga2_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA;
|
||||
|
||||
struct inv_ioexp_layout_s cypress_ga2_ioexp_layout[] = {
|
||||
/* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
|
||||
{0, IOEXP_TYPE_CYPRESS_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{1, IOEXP_TYPE_CYPRESS_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{2, IOEXP_TYPE_CYPRESS_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{3, IOEXP_TYPE_CYPRESS_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{4, IOEXP_TYPE_CYPRESS_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{5, IOEXP_TYPE_CYPRESS_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */
|
||||
{8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */
|
||||
{8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */
|
||||
},
|
||||
};
|
||||
|
||||
struct inv_port_layout_s cypress_ga2_port_layout[] = {
|
||||
/* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
|
||||
{ 0, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} },
|
||||
{ 1, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} },
|
||||
{ 2, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} },
|
||||
{ 3, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} },
|
||||
{ 4, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} },
|
||||
{ 5, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} },
|
||||
{ 6, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} },
|
||||
{ 7, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} },
|
||||
{ 8, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} },
|
||||
{ 9, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} },
|
||||
{10, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} },
|
||||
{11, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} },
|
||||
{12, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} },
|
||||
{13, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} },
|
||||
{14, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} },
|
||||
{15, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} },
|
||||
{16, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} },
|
||||
{17, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} },
|
||||
{18, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} },
|
||||
{19, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} },
|
||||
{20, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} },
|
||||
{21, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} },
|
||||
{22, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} },
|
||||
{23, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} },
|
||||
{24, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} },
|
||||
{25, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} },
|
||||
{26, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} },
|
||||
{27, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} },
|
||||
{28, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} },
|
||||
{29, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} },
|
||||
{30, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} },
|
||||
{31, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} },
|
||||
{32, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} },
|
||||
{33, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} },
|
||||
{34, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} },
|
||||
{35, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} },
|
||||
{36, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} },
|
||||
{37, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} },
|
||||
{38, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} },
|
||||
{39, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} },
|
||||
{40, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} },
|
||||
{41, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} },
|
||||
{42, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} },
|
||||
{43, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} },
|
||||
{44, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} },
|
||||
{45, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} },
|
||||
{46, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} },
|
||||
{47, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} },
|
||||
{48, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} },
|
||||
{49, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} },
|
||||
{50, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} },
|
||||
{51, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} },
|
||||
{52, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} },
|
||||
{53, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* ==========================================
|
||||
* Cypress Layout configuration (BaiDu version)
|
||||
* ==========================================
|
||||
*/
|
||||
#ifdef SWPS_CYPRESS_BAI
|
||||
unsigned cypress_b_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA;
|
||||
|
||||
struct inv_ioexp_layout_s cypress_b_ioexp_layout[] = {
|
||||
/* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
|
||||
{0, IOEXP_TYPE_CYPRESS_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{1, IOEXP_TYPE_CYPRESS_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{2, IOEXP_TYPE_CYPRESS_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{3, IOEXP_TYPE_CYPRESS_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{4, IOEXP_TYPE_CYPRESS_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{5, IOEXP_TYPE_CYPRESS_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[0] = I/O Expander N A */
|
||||
{7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xf0}, {0xff, 0xf0}, }, /* addr[1] = I/O Expander N B */
|
||||
{7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0x00, 0x00}, }, }, /* addr[2] = I/O Expander N C */
|
||||
},
|
||||
{6, IOEXP_TYPE_CYPRESS_7ABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xc0, 0xc0}, }, /* addr[0] = I/O Expander 7 A */
|
||||
{8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xc0, 0xc0}, {0xff, 0xc0}, }, /* addr[1] = I/O Expander 7 B */
|
||||
{8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */
|
||||
},
|
||||
};
|
||||
|
||||
struct inv_port_layout_s cypress_b_port_layout[] = {
|
||||
/* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
|
||||
{ 1, 11, 0, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 2} },
|
||||
{ 2, 10, 0, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 1} },
|
||||
{ 3, 13, 0, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 4} },
|
||||
{ 4, 12, 0, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 3} },
|
||||
{ 5, 15, 0, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 6} },
|
||||
{ 6, 14, 0, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 5} },
|
||||
{ 7, 17, 0, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 8} },
|
||||
{ 8, 16, 0, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 7} },
|
||||
{ 9, 19, 1, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 10} },
|
||||
{10, 18, 1, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 9} },
|
||||
{11, 21, 1, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 12} },
|
||||
{12, 20, 1, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 11} },
|
||||
{13, 23, 1, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 22} },
|
||||
{14, 22, 1, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 21} },
|
||||
{15, 25, 1, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 24} },
|
||||
{16, 24, 1, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 23} },
|
||||
{17, 27, 2, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 34} },
|
||||
{18, 26, 2, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 33} },
|
||||
{19, 29, 2, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 36} },
|
||||
{20, 28, 2, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 35} },
|
||||
{21, 31, 2, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 38} },
|
||||
{22, 30, 2, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 37} },
|
||||
{23, 33, 2, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 40} },
|
||||
{24, 32, 2, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 39} },
|
||||
{25, 35, 3, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 42} },
|
||||
{26, 34, 3, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 41} },
|
||||
{27, 37, 3, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 44} },
|
||||
{28, 36, 3, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 43} },
|
||||
{29, 39, 3, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 50} },
|
||||
{30, 38, 3, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 49} },
|
||||
{31, 41, 3, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 52} },
|
||||
{32, 40, 3, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 51} },
|
||||
{33, 43, 4, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 54} },
|
||||
{34, 42, 4, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 53} },
|
||||
{35, 45, 4, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 56} },
|
||||
{36, 44, 4, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 55} },
|
||||
{37, 47, 4, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 66} },
|
||||
{38, 46, 4, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 65} },
|
||||
{39, 49, 4, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 68} },
|
||||
{40, 48, 4, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 67} },
|
||||
{41, 51, 5, 1, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 70} },
|
||||
{42, 50, 5, 0, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 69} },
|
||||
{43, 53, 5, 3, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 72} },
|
||||
{44, 52, 5, 2, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 71} },
|
||||
{45, 55, 5, 5, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 82} },
|
||||
{46, 54, 5, 4, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 81} },
|
||||
{47, 57, 5, 7, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 84} },
|
||||
{48, 56, 5, 6, TRANSVR_TYPE_SFP, BCM_CHIP_TYPE_TOMAHAWK, { 83} },
|
||||
{49, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} },
|
||||
{50, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} },
|
||||
{51, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} },
|
||||
{52, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} },
|
||||
{53, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} },
|
||||
{54, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* ==========================================
|
||||
* Redwood_fsl Layout configuration
|
||||
* ==========================================
|
||||
*/
|
||||
#ifdef SWPS_REDWOOD_FSL
|
||||
unsigned redwood_fsl_gpio_rest_mux = MUX_RST_GPIO_48_PAC9548;
|
||||
|
||||
struct inv_ioexp_layout_s redwood_fsl_ioexp_layout[] = {
|
||||
/* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
|
||||
{0, IOEXP_TYPE_REDWOOD_P01P08, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */
|
||||
{4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */
|
||||
{0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */
|
||||
},
|
||||
{1, IOEXP_TYPE_REDWOOD_P09P16, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */
|
||||
{5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */
|
||||
{0, 0x25, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */
|
||||
},
|
||||
{2, IOEXP_TYPE_REDWOOD_P01P08, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */
|
||||
{2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */
|
||||
{0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */
|
||||
},
|
||||
{3, IOEXP_TYPE_REDWOOD_P09P16, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[0] = I/O Expander 1-4 A */
|
||||
{3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0x0f}, }, /* addr[1] = I/O Expander 1-4 B */
|
||||
{0, 0x24, {0, 1}, {2, 3}, {6, 7}, {0xff, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 B */
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
struct inv_port_layout_s redwood_fsl_port_layout[] = {
|
||||
/* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
|
||||
{ 0, 22, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} },
|
||||
{ 1, 23, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} },
|
||||
{ 2, 24, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} },
|
||||
{ 3, 25, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} },
|
||||
{ 4, 26, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} },
|
||||
{ 5, 27, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} },
|
||||
{ 6, 28, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} },
|
||||
{ 7, 29, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} },
|
||||
{ 8, 30, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} },
|
||||
{ 9, 31, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} },
|
||||
{10, 32, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} },
|
||||
{11, 33, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} },
|
||||
{12, 34, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} },
|
||||
{13, 35, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} },
|
||||
{14, 36, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} },
|
||||
{15, 37, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} },
|
||||
{16, 6, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} },
|
||||
{17, 7, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} },
|
||||
{18, 8, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} },
|
||||
{19, 9, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} },
|
||||
{20, 10, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} },
|
||||
{21, 11, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} },
|
||||
{22, 12, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} },
|
||||
{23, 13, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} },
|
||||
{24, 14, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99,100} },
|
||||
{25, 15, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101,102,103,104} },
|
||||
{26, 16, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105,106,107,108} },
|
||||
{27, 17, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109,110,111,112} },
|
||||
{28, 18, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113,114,115,116} },
|
||||
{29, 19, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117,118,119,120} },
|
||||
{30, 20, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121,122,123,124} },
|
||||
{31, 21, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125,126,127,128} },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* ==========================================
|
||||
* Tahoe Layout configuration
|
||||
* ==========================================
|
||||
*/
|
||||
#ifdef SWPS_TAHOE
|
||||
unsigned tahoe_gpio_rest_mux = MUX_RST_GPIO_249_PCA9548;
|
||||
|
||||
struct inv_ioexp_layout_s tahoe_ioexp_layout[] = {
|
||||
/* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
|
||||
{0, IOEXP_TYPE_TAHOE_6ABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, /* addr[0] = I/O Expander 6 A */
|
||||
{7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, /* addr[1] = I/O Expander 6 B */
|
||||
{7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, }, /* addr[2] = I/O Expander 6 C */
|
||||
},
|
||||
{1, IOEXP_TYPE_TAHOE_5A, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0xce, 0xb9}, {0x18, 0xe3}, }, }, /* addr[0] = I/O Expander 5 A */
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
struct inv_port_layout_s tahoe_port_layout[] = {
|
||||
/* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
|
||||
{ 0, 12, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} },
|
||||
{ 1, 11, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} },
|
||||
{ 2, 22, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} },
|
||||
{ 3, 21, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} },
|
||||
{ 4, 24, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99, 100} },
|
||||
{ 5, 23, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} },
|
||||
{ 6, 18, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101, 102, 103, 104} },
|
||||
{ 7, 17, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105, 106, 107, 108} },
|
||||
{ 8, 20, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113, 114, 115, 116} },
|
||||
{ 9, 19, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109, 110, 111, 112} },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* ==========================================
|
||||
* Sequoia Layout configuration
|
||||
* ==========================================
|
||||
*/
|
||||
#ifdef SWPS_SEQUOIA
|
||||
unsigned sequoia_gpio_rest_mux = MUX_RST_GPIO_FORCE_HEDERA;
|
||||
|
||||
struct inv_ioexp_layout_s secquoia_ioexp_layout[] = {
|
||||
/* IOEXP_ID / IOEXP_TYPE / { Chan_ID, Chip_addr, Read_offset, Write_offset, config_offset, data_default, conf_default } */
|
||||
{0, IOEXP_TYPE_SEQUOIA_NABC, { {2, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 0 A */
|
||||
{2, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 0 B */
|
||||
{2, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 0 C */
|
||||
},
|
||||
{1, IOEXP_TYPE_SEQUOIA_NABC, { {3, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 1 A */
|
||||
{3, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 1 B */
|
||||
{3, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 1 C */
|
||||
},
|
||||
{2, IOEXP_TYPE_SEQUOIA_NABC, { {4, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 2 A */
|
||||
{4, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 2 B */
|
||||
{4, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 2 C */
|
||||
},
|
||||
{3, IOEXP_TYPE_SEQUOIA_NABC, { {5, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 3 A */
|
||||
{5, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 3 B */
|
||||
{5, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 3 C */
|
||||
},
|
||||
{4, IOEXP_TYPE_SEQUOIA_NABC, { {6, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 4 A */
|
||||
{6, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 4 B */
|
||||
{6, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 4 C */
|
||||
},
|
||||
{5, IOEXP_TYPE_SEQUOIA_NABC, { {7, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 5 A */
|
||||
{7, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 5 B */
|
||||
{7, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 5 C */
|
||||
},
|
||||
{6, IOEXP_TYPE_SEQUOIA_NABC, { {8, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 6 A */
|
||||
{8, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 6 B */
|
||||
{8, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 6 C */
|
||||
},
|
||||
{7, IOEXP_TYPE_SEQUOIA_NABC, { {9, 0x20, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0x00, 0x00}, }, /* addr[0] = I/O Expander 7 A */
|
||||
{9, 0x21, {0, 1}, {2, 3}, {6, 7}, {0xff, 0x00}, {0x00, 0xff}, }, /* addr[1] = I/O Expander 7 B */
|
||||
{9, 0x22, {0, 1}, {2, 3}, {6, 7}, {0x00, 0xff}, {0xff, 0xff}, }, }, /* addr[2] = I/O Expander 7 C */
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
struct inv_port_layout_s secquoia_port_layout[] = {
|
||||
/* Port_ID / Chan_ID / IOEXP_ID / IOEXP_VIRT_OFFSET / TRANSCEIVER_TYPE / BCM_CHIP_TYPE / LANE_ID */
|
||||
{ 0, 10, 0, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 9, 10, 11, 12} },
|
||||
{ 1, 11, 0, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 1, 2, 3, 4} },
|
||||
{ 2, 12, 0, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 25, 26, 27, 28} },
|
||||
{ 3, 13, 0, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 17, 18, 19, 20} },
|
||||
{ 4, 14, 0, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 41, 42, 43, 44} },
|
||||
{ 5, 15, 0, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 33, 34, 35, 36} },
|
||||
{ 6, 16, 0, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 57, 58, 59, 60} },
|
||||
{ 7, 17, 0, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 49, 50, 51, 52} },
|
||||
{ 8, 18, 1, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 73, 74, 75, 76} },
|
||||
{ 9, 19, 1, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 65, 66, 67, 68} },
|
||||
{10, 20, 1, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 89, 90, 91, 92} },
|
||||
{11, 21, 1, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 81, 82, 83, 84} },
|
||||
{12, 22, 1, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {105, 106, 107, 108} },
|
||||
{13, 23, 1, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 97, 98, 99, 100} },
|
||||
{14, 24, 1, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {121, 122, 123, 124} },
|
||||
{15, 25, 1, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {113, 114, 115, 116} },
|
||||
{16, 26, 2, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {137, 138, 139, 140} },
|
||||
{17, 27, 2, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {129, 130, 131, 132} },
|
||||
{18, 28, 2, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {153, 154, 155, 156} },
|
||||
{19, 29, 2, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {145, 146, 147, 148} },
|
||||
{20, 30, 2, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {169, 170, 171, 172} },
|
||||
{21, 31, 2, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {161, 162, 163, 164} },
|
||||
{22, 32, 2, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {185, 186, 187, 188} },
|
||||
{23, 33, 2, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {177, 178, 179, 180} },
|
||||
{24, 34, 3, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {201, 202, 203, 204} },
|
||||
{25, 35, 3, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {193, 194, 195, 196} },
|
||||
{26, 36, 3, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {217, 218, 219, 220} },
|
||||
{27, 37, 3, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {209, 210, 211, 212} },
|
||||
{28, 38, 3, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {233, 234, 235, 236} },
|
||||
{29, 39, 3, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {225, 226, 227, 228} },
|
||||
{30, 40, 3, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {249, 250, 251, 252} },
|
||||
{31, 41, 3, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {241, 242, 243, 244} },
|
||||
{32, 45, 4, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 13, 14, 15, 16} },
|
||||
{33, 44, 4, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 5, 6, 7, 8} },
|
||||
{34, 43, 4, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 29, 30, 31, 32} },
|
||||
{35, 42, 4, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 21, 22, 23, 24} },
|
||||
{36, 49, 4, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 45, 46, 47, 48} },
|
||||
{37, 48, 4, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 37, 38, 39, 40} },
|
||||
{38, 47, 4, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 61, 62, 63, 64} },
|
||||
{39, 46, 4, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 53, 54, 55, 56} },
|
||||
{40, 53, 5, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 77, 78, 79, 80} },
|
||||
{41, 52, 5, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 69, 70, 71, 72} },
|
||||
{42, 51, 5, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 93, 94, 95, 96} },
|
||||
{43, 50, 5, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, { 85, 86, 87, 88} },
|
||||
{44, 57, 5, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {109, 110, 111, 112} },
|
||||
{45, 56, 5, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {101, 102, 103, 104} },
|
||||
{46, 55, 5, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {125, 126, 127, 128} },
|
||||
{47, 54, 5, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {117, 118, 119, 120} },
|
||||
{48, 61, 6, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {141, 142, 143, 144} },
|
||||
{49, 60, 6, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {133, 134, 135, 136} },
|
||||
{50, 59, 6, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {157, 158, 159, 160} },
|
||||
{51, 58, 6, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {149, 150, 151, 152} },
|
||||
{52, 65, 6, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {173, 174, 175, 176} },
|
||||
{53, 64, 6, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {165, 166, 167, 168} },
|
||||
{54, 63, 6, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {189, 190, 191, 192} },
|
||||
{55, 62, 6, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {181, 182, 183, 184} },
|
||||
{56, 69, 7, 3, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {205, 206, 207, 208} },
|
||||
{57, 68, 7, 2, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {197, 198, 199, 200} },
|
||||
{58, 67, 7, 1, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {221, 222, 223, 224} },
|
||||
{59, 66, 7, 0, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {213, 214, 215, 216} },
|
||||
{60, 73, 7, 7, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {237, 238, 239, 240} },
|
||||
{61, 72, 7, 6, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {229, 230, 231, 232} },
|
||||
{62, 71, 7, 5, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {253, 254, 255, 256} },
|
||||
{63, 70, 7, 4, TRANSVR_TYPE_QSFP_28, BCM_CHIP_TYPE_TOMAHAWK, {245, 246, 247, 248} },
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* INV_SWPS_H */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/i2c.h>
|
||||
#include "inv_vpd.h"
|
||||
#include "onie_tlvinfo.h"
|
||||
|
||||
static int vpd_major;
|
||||
static struct class *vpd_class_p = NULL;
|
||||
static char cEeprom[SYS_EEPROM_MAX_SIZE];
|
||||
static DEFINE_MUTEX(vpd_mutex);
|
||||
|
||||
static int
|
||||
__swp_match(struct device *dev, const void *data){
|
||||
|
||||
char *name = (char *)data;
|
||||
if (strcmp(dev_name(dev), name) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int get_vpd_data(struct i2c_client *pi2c_client, int i_offset, char *c_buf)
|
||||
{
|
||||
int iRet;
|
||||
|
||||
read_eeprom( pi2c_client, cEeprom);
|
||||
iRet = tlvinfo_decode_tlv(cEeprom, i_offset,c_buf);
|
||||
return iRet;
|
||||
}
|
||||
|
||||
static
|
||||
int write_vpd_data(struct i2c_client *pi2c_client, int i_offset, const char *c_buf)
|
||||
{
|
||||
int iErr = 0;
|
||||
|
||||
if (read_eeprom(pi2c_client, cEeprom)) {
|
||||
printk(KERN_ERR "write vpd data eror at %d-%s\n", __LINE__, __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tlvinfo_delete_tlv(cEeprom, i_offset) == TRUE) {
|
||||
}
|
||||
if (c_buf) {
|
||||
if(!tlvinfo_add_tlv(cEeprom, i_offset , c_buf)) {
|
||||
printk(KERN_ERR "write vpd data eror at %d-%s\n", __LINE__, __FUNCTION__);
|
||||
iErr = -1;
|
||||
} else {
|
||||
iErr = prog_eeprom(pi2c_client,cEeprom);
|
||||
}
|
||||
}
|
||||
return iErr;
|
||||
}
|
||||
|
||||
static struct device *
|
||||
get_swpdev_by_name(char *name){
|
||||
struct device *dev = class_find_device(vpd_class_p,
|
||||
NULL,
|
||||
name,
|
||||
__swp_match);
|
||||
return dev;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
store_attr_vpd(struct device *dev_p,
|
||||
struct device_attribute *attr_p,
|
||||
const char *buf_p,
|
||||
size_t count){
|
||||
struct i2c_client *pi2c_client = dev_get_drvdata(dev_p);
|
||||
struct vpd_device_attribute *attr = to_vpd_dev_attr(attr_p);
|
||||
int iOffset = attr->index;
|
||||
int iErr , iLen;
|
||||
char *pChar;
|
||||
|
||||
if (!pi2c_client){
|
||||
return -ENODEV;
|
||||
}
|
||||
mutex_lock(&vpd_mutex);
|
||||
|
||||
//-strip 0x0a in the last byte.
|
||||
for (iLen = 0, pChar = (char*)buf_p;
|
||||
iLen < 255 && *pChar != 0;
|
||||
iLen++, pChar++) ;
|
||||
if (iLen !=0 && *pChar == 0 && *(pChar-1) == 0x0a)
|
||||
*(pChar - 1) = 0;
|
||||
//-
|
||||
|
||||
iErr = write_vpd_data( pi2c_client, iOffset, buf_p);
|
||||
|
||||
mutex_unlock(&vpd_mutex);
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
show_attr_vpd(struct device *dev_p,
|
||||
struct device_attribute *attr_p,
|
||||
char *buf_p){
|
||||
|
||||
struct i2c_client *pi2c_client = dev_get_drvdata(dev_p);
|
||||
struct vpd_device_attribute *attr = to_vpd_dev_attr(attr_p);
|
||||
int iOffset = attr->index;
|
||||
int iErr , iLen;
|
||||
|
||||
if (!pi2c_client){
|
||||
return -ENODEV;
|
||||
}
|
||||
mutex_lock(&vpd_mutex);
|
||||
iErr = get_vpd_data( pi2c_client, iOffset, buf_p);
|
||||
mutex_unlock(&vpd_mutex);
|
||||
|
||||
if( iErr <= 0 )
|
||||
iLen = 0;
|
||||
else
|
||||
iLen = snprintf(buf_p, TLV_DECODE_VALUE_MAX_LEN, "%s\n", buf_p);
|
||||
|
||||
return iLen;
|
||||
}
|
||||
|
||||
/* ================= Vpd attribute ========================
|
||||
*/
|
||||
static VPD_DEVICE_ATTR(product_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PRODUCT_NAME );
|
||||
static VPD_DEVICE_ATTR(pn ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PART_NUMBER );
|
||||
static VPD_DEVICE_ATTR(sn ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_SERIAL_NUMBER );
|
||||
static VPD_DEVICE_ATTR(base_mac_addr,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MAC_BASE );
|
||||
static VPD_DEVICE_ATTR(man_date ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_DATE );
|
||||
static VPD_DEVICE_ATTR(dev_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_DEVICE_VERSION );
|
||||
static VPD_DEVICE_ATTR(label_rev ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_LABEL_REVISION );
|
||||
static VPD_DEVICE_ATTR(plat_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_PLATFORM_NAME );
|
||||
static VPD_DEVICE_ATTR(ldr_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_ONIE_VERSION );
|
||||
static VPD_DEVICE_ATTR(mac_addr ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MAC_SIZE );
|
||||
static VPD_DEVICE_ATTR(manufacturer ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_NAME );
|
||||
static VPD_DEVICE_ATTR(country_code ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_MANUF_COUNTRY );
|
||||
static VPD_DEVICE_ATTR(vendor_name ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_VENDOR_NAME );
|
||||
static VPD_DEVICE_ATTR(diag_ver ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_DIAG_VERSION );
|
||||
static VPD_DEVICE_ATTR(service_tag ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_SERVICE_TAG );
|
||||
static VPD_DEVICE_ATTR(vendor_ext ,S_IWUSR|S_IRUGO, show_attr_vpd, store_attr_vpd, TLV_CODE_VENDOR_EXT );
|
||||
static VPD_DEVICE_ATTR(crc32 ,S_IRUGO, show_attr_vpd, NULL, TLV_CODE_CRC_32 );
|
||||
|
||||
static void
|
||||
clean_vpd_common(void)
|
||||
{
|
||||
dev_t dev_num;
|
||||
struct device *device_p;
|
||||
|
||||
device_p = get_swpdev_by_name(VPD_DEVICE);
|
||||
if (device_p){
|
||||
dev_num = MKDEV(vpd_major, 1);
|
||||
device_unregister(device_p);
|
||||
device_destroy(vpd_class_p, dev_num);
|
||||
}
|
||||
VPD_DEBUG("%s: done.\n", __func__);
|
||||
}
|
||||
|
||||
|
||||
static struct register_attr VpdRegAttr[VPD_ENTRY_SIZE ] ={
|
||||
{ &vpd_dev_attr_product_name.dev_attr, "vpd_dev_attr_product_name"},
|
||||
{ &vpd_dev_attr_pn.dev_attr, "vpd_dev_attr_pn"},
|
||||
{ &vpd_dev_attr_sn.dev_attr, "vpd_dev_attr_sn"},
|
||||
{ &vpd_dev_attr_base_mac_addr.dev_attr, "vpd_dev_attr_base_mac_addr"},
|
||||
{ &vpd_dev_attr_man_date.dev_attr, "vpd_dev_attr_man_date"},
|
||||
{ &vpd_dev_attr_dev_ver.dev_attr, "vpd_dev_attr_dev_ver"},
|
||||
{ &vpd_dev_attr_label_rev.dev_attr, "vpd_dev_attr_label_rev"},
|
||||
{ &vpd_dev_attr_plat_name.dev_attr, "vpd_dev_attr_plat_name"},
|
||||
{ &vpd_dev_attr_ldr_ver.dev_attr, "vpd_dev_attr_ldr_ver"},
|
||||
{ &vpd_dev_attr_mac_addr.dev_attr, "vpd_dev_attr_mac_addr"},
|
||||
{ &vpd_dev_attr_manufacturer.dev_attr, "vpd_dev_attr_manufacturer"},
|
||||
{ &vpd_dev_attr_country_code.dev_attr, "vpd_dev_attr_country_code"},
|
||||
{ &vpd_dev_attr_vendor_name.dev_attr, "vpd_dev_attr_vendor_name"},
|
||||
{ &vpd_dev_attr_diag_ver.dev_attr, "vpd_dev_attr_diag_ver"},
|
||||
{ &vpd_dev_attr_service_tag.dev_attr, "vpd_dev_attr_service_tag"},
|
||||
{ &vpd_dev_attr_vendor_ext.dev_attr, "vpd_dev_attr_vendor_ext"},
|
||||
{ &vpd_dev_attr_crc32.dev_attr, "vpd_dev_attr_crc32"},
|
||||
};
|
||||
|
||||
static int
|
||||
register_vpd_attr(struct device *device_p){
|
||||
|
||||
char *err_attr = NULL;
|
||||
int i;
|
||||
|
||||
for( i = 0 ; i <VPD_ENTRY_SIZE ;i++ ){
|
||||
if(device_create_file(device_p, VpdRegAttr[ i ].attr) < 0) {
|
||||
err_attr = VpdRegAttr[ i ].errmsg;
|
||||
goto err_register_vpd_attr;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_register_vpd_attr:
|
||||
VPD_ERR("%s: %s\n", __func__, err_attr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
register_vpd_device(void)
|
||||
{
|
||||
struct device *device_p = NULL;
|
||||
int minor_comm = 0; /* Default minor number for common device */
|
||||
dev_t dev_num = MKDEV(vpd_major, minor_comm);
|
||||
char *err_msg = "ERROR";
|
||||
struct i2c_adapter *adap;
|
||||
struct i2c_client *vpd_i2c_client = NULL;
|
||||
|
||||
vpd_i2c_client = kzalloc(sizeof(*vpd_i2c_client), GFP_KERNEL);
|
||||
if (!vpd_i2c_client){
|
||||
printk(KERN_ERR "can not kzalloc client:%d", VPD_I2C_BUS);
|
||||
goto err_register_vpd_device;
|
||||
}
|
||||
|
||||
adap = i2c_get_adapter(VPD_I2C_BUS);
|
||||
vpd_i2c_client->adapter = adap;
|
||||
vpd_i2c_client->addr = VPD_I2C_ADDR;
|
||||
|
||||
device_p = device_create(vpd_class_p, /* struct class *cls */
|
||||
NULL, /* struct device *parent */
|
||||
dev_num, /* dev_t devt */
|
||||
vpd_i2c_client, /* void *private_data */
|
||||
VPD_DEVICE); /* const char *fmt */
|
||||
if (IS_ERR(device_p)){
|
||||
err_msg = "device_create fail";
|
||||
goto err_register_vpd_device_1;
|
||||
}
|
||||
if (register_vpd_attr(device_p) < 0) {
|
||||
err_msg = "register_vpd_attr fail";
|
||||
goto err_register_vpd_device_2;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_register_vpd_device_2:
|
||||
device_unregister(device_p);
|
||||
device_destroy(vpd_class_p, dev_num);
|
||||
err_register_vpd_device_1:
|
||||
kfree(vpd_i2c_client);
|
||||
vpd_i2c_client = NULL;
|
||||
err_register_vpd_device:
|
||||
VPD_ERR("%s: %s\n", __func__, err_msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
register_vpd_module(void)
|
||||
{
|
||||
dev_t vpd_devt = 0;
|
||||
|
||||
if (alloc_chrdev_region(&vpd_devt, 0, 1, VPD_DEVICE) < 0){
|
||||
VPD_WARN("Allocate VPD MAJOR failure! \n");
|
||||
goto err_register_vpd_module;
|
||||
}
|
||||
vpd_major = MAJOR(vpd_devt);
|
||||
|
||||
/* Create class object */
|
||||
vpd_class_p = class_create(THIS_MODULE, EEPROM_CLASS);
|
||||
if (IS_ERR(vpd_class_p)) {
|
||||
VPD_ERR("Create class failure! \n");
|
||||
goto err_register_vpd_module_1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_register_vpd_module_1:
|
||||
unregister_chrdev_region(MKDEV(vpd_major, 0), 1);
|
||||
err_register_vpd_module:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
init_vpd_common(void)
|
||||
{
|
||||
char *err_msg = "ERR";
|
||||
|
||||
if (register_vpd_device() < 0) {
|
||||
err_msg = "register_vpd_device fail";
|
||||
goto err_init_vpd_common;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_init_vpd_common:
|
||||
VPD_ERR("%s: %s\n", __func__, err_msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int __init
|
||||
vpd_module_init(void)
|
||||
{
|
||||
if (register_vpd_module() < 0){
|
||||
goto err_vpd_module_init;
|
||||
}
|
||||
if (init_vpd_common() < 0){
|
||||
goto err_vpd_module_init_1;
|
||||
}
|
||||
VPD_INFO("Inventec vpd module V.%s initial success.\n", VPD_VERSION);
|
||||
return 0;
|
||||
|
||||
err_vpd_module_init_1:
|
||||
class_unregister(vpd_class_p);
|
||||
class_destroy(vpd_class_p);
|
||||
unregister_chrdev_region(MKDEV(vpd_major, 0), 1);
|
||||
err_vpd_module_init:
|
||||
VPD_ERR("Inventec vpd module V.%s initial failure.\n", VPD_VERSION);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void __exit
|
||||
vpd_module_exit(void)
|
||||
{
|
||||
clean_vpd_common();
|
||||
class_unregister(vpd_class_p);
|
||||
class_destroy(vpd_class_p);
|
||||
unregister_chrdev_region(MKDEV(vpd_major, 0), 1);
|
||||
VPD_INFO("Remove Inventec vpd module success.\n");
|
||||
}
|
||||
|
||||
|
||||
/* Module information */
|
||||
MODULE_AUTHOR(VPD_AUTHOR);
|
||||
MODULE_DESCRIPTION(VPD_DESC);
|
||||
MODULE_VERSION(VPD_VERSION);
|
||||
MODULE_LICENSE(VPD_LICENSE);
|
||||
|
||||
module_init(vpd_module_init);
|
||||
module_exit(vpd_module_exit);
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef INV_VPD_H
|
||||
#define INV_VPD_H
|
||||
|
||||
#define EEPROM_CLASS "eeprom"
|
||||
#define VPD_DEVICE "vpd"
|
||||
#define VPD_AUTHOR "Neil <liao.neil@inventec.com>"
|
||||
#define VPD_DESC "Inventec eeprom vpd driver"
|
||||
#define VPD_VERSION "1.0.0"
|
||||
#define VPD_LICENSE "GPL"
|
||||
|
||||
#define VPD_ENTRY_SIZE (17)
|
||||
#define VPD_I2C_BUS (0)
|
||||
#define VPD_I2C_ADDR (0x53)
|
||||
|
||||
struct register_attr {
|
||||
struct device_attribute *attr;
|
||||
char * errmsg;
|
||||
};
|
||||
|
||||
struct vpd_device_attribute{
|
||||
struct device_attribute dev_attr;
|
||||
int index;
|
||||
};
|
||||
|
||||
#define to_vpd_dev_attr(_dev_attr) \
|
||||
container_of(_dev_attr, struct vpd_device_attribute, dev_attr)
|
||||
|
||||
#define VPD_ATTR(_name, _mode, _show, _store, _index) \
|
||||
{ .dev_attr = __ATTR(_name, _mode, _show, _store), \
|
||||
.index = _index }
|
||||
|
||||
#define VPD_DEVICE_ATTR(_name, _mode, _show, _store, _index) \
|
||||
struct vpd_device_attribute vpd_dev_attr_##_name \
|
||||
= VPD_ATTR(_name, _mode, _show, _store, _index)
|
||||
|
||||
#define VPD_INFO(fmt, args...) printk( KERN_INFO "[VPD] " fmt, ##args)
|
||||
#define VPD_WARN(fmt, args...) printk( KERN_WARNING "[VPD] " fmt, ##args)
|
||||
#define VPD_ERR(fmt, args...) printk( KERN_ERR "[VPD] " fmt, ##args)
|
||||
|
||||
#ifdef DEBUG_VPD
|
||||
# define VPD_DEBUG(fmt, args...) printk( KERN_DEBUG "[VPD] " fmt, ##args)
|
||||
#else
|
||||
# define VPD_DEBUG(fmt, args...)
|
||||
#endif
|
||||
|
||||
#endif /* INV_VPD_H */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user