mirror of
https://github.com/Telecominfraproject/OpenNetworkLinux.git
synced 2025-12-25 17:27:01 +00:00
Merge pull request #301 from brandonchuang/as5812_54t
[as5812-54t] Add support for OOM driver
This commit is contained in:
@@ -0,0 +1,457 @@
|
||||
/*
|
||||
* A hwmon driver for the as5812_54t_cpld
|
||||
*
|
||||
* Copyright (C) 2013 Accton Technology Corporation.
|
||||
* Brandon Chuang <brandon_chuang@accton.com.tw>
|
||||
*
|
||||
* Based on ad7414.c
|
||||
* Copyright 2006 Stefan Roese <sr at denx.de>, DENX Software Engineering
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
static LIST_HEAD(cpld_client_list);
|
||||
static struct mutex list_lock;
|
||||
|
||||
struct cpld_client_node {
|
||||
struct i2c_client *client;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
#define I2C_RW_RETRY_COUNT 10
|
||||
#define I2C_RW_RETRY_INTERVAL 60 /* ms */
|
||||
|
||||
static ssize_t show_present(struct device *dev, struct device_attribute *da,
|
||||
char *buf);
|
||||
static ssize_t show_present_all(struct device *dev, struct device_attribute *da,
|
||||
char *buf);
|
||||
static ssize_t access(struct device *dev, struct device_attribute *da,
|
||||
const char *buf, size_t count);
|
||||
static ssize_t show_version(struct device *dev, struct device_attribute *da,
|
||||
char *buf);
|
||||
static int as5812_54t_cpld_read_internal(struct i2c_client *client, u8 reg);
|
||||
static int as5812_54t_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value);
|
||||
|
||||
struct as5812_54t_cpld_data {
|
||||
struct device *hwmon_dev;
|
||||
struct mutex update_lock;
|
||||
};
|
||||
|
||||
/* Addresses scanned for as5812_54t_cpld
|
||||
*/
|
||||
static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
|
||||
|
||||
#define TRANSCEIVER_PRESENT_ATTR_ID(index) MODULE_PRESENT_##index
|
||||
|
||||
enum as5812_54t_cpld_sysfs_attributes {
|
||||
CPLD_VERSION,
|
||||
ACCESS,
|
||||
MODULE_PRESENT_ALL,
|
||||
/* transceiver attributes */
|
||||
TRANSCEIVER_PRESENT_ATTR_ID(49),
|
||||
TRANSCEIVER_PRESENT_ATTR_ID(50),
|
||||
TRANSCEIVER_PRESENT_ATTR_ID(51),
|
||||
TRANSCEIVER_PRESENT_ATTR_ID(52),
|
||||
TRANSCEIVER_PRESENT_ATTR_ID(53),
|
||||
TRANSCEIVER_PRESENT_ATTR_ID(54),
|
||||
};
|
||||
|
||||
/* sysfs attributes for hwmon
|
||||
*/
|
||||
|
||||
/* transceiver attributes */
|
||||
#define DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(index) \
|
||||
static SENSOR_DEVICE_ATTR(module_present_##index, S_IRUGO, show_present, NULL, MODULE_PRESENT_##index)
|
||||
#define DECLARE_TRANSCEIVER_ATTR(index) &sensor_dev_attr_module_present_##index.dev_attr.attr
|
||||
|
||||
static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, CPLD_VERSION);
|
||||
static SENSOR_DEVICE_ATTR(access, S_IWUSR, NULL, access, ACCESS);
|
||||
/* transceiver attributes */
|
||||
static SENSOR_DEVICE_ATTR(module_present_all, S_IRUGO, show_present_all, NULL, MODULE_PRESENT_ALL);
|
||||
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(49);
|
||||
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(50);
|
||||
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(51);
|
||||
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(52);
|
||||
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(53);
|
||||
DECLARE_TRANSCEIVER_SENSOR_DEVICE_ATTR(54);
|
||||
|
||||
static struct attribute *as5812_54t_cpld_attributes[] = {
|
||||
&sensor_dev_attr_version.dev_attr.attr,
|
||||
&sensor_dev_attr_access.dev_attr.attr,
|
||||
/* transceiver attributes */
|
||||
&sensor_dev_attr_module_present_all.dev_attr.attr,
|
||||
DECLARE_TRANSCEIVER_ATTR(49),
|
||||
DECLARE_TRANSCEIVER_ATTR(50),
|
||||
DECLARE_TRANSCEIVER_ATTR(51),
|
||||
DECLARE_TRANSCEIVER_ATTR(52),
|
||||
DECLARE_TRANSCEIVER_ATTR(53),
|
||||
DECLARE_TRANSCEIVER_ATTR(54),
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct attribute_group as5812_54t_cpld_group = {
|
||||
.attrs = as5812_54t_cpld_attributes,
|
||||
};
|
||||
|
||||
static ssize_t show_present_all(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
int status;
|
||||
u8 value = 0;
|
||||
u8 reg = 0x22;
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct as5812_54t_cpld_data *data = i2c_get_clientdata(client);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
|
||||
status = as5812_54t_cpld_read_internal(client, reg);
|
||||
if (status < 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
value = ~(u8)status;
|
||||
value &= 0x3F;
|
||||
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
/* Return values 49 -> 54 in order */
|
||||
return sprintf(buf, "%.2x\n", value);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&data->update_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
static ssize_t show_present(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct as5812_54t_cpld_data *data = i2c_get_clientdata(client);
|
||||
int status = 0;
|
||||
u8 reg = 0, mask = 0;
|
||||
|
||||
reg = 0x22;
|
||||
mask = 0x1 << (attr->index - MODULE_PRESENT_49);
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
status = as5812_54t_cpld_read_internal(client, reg);
|
||||
if (unlikely(status < 0)) {
|
||||
goto exit;
|
||||
}
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return sprintf(buf, "%d\n", !(status & mask));
|
||||
|
||||
exit:
|
||||
mutex_unlock(&data->update_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
static ssize_t show_version(struct device *dev, struct device_attribute *da,
|
||||
char *buf)
|
||||
{
|
||||
u8 reg = 0, mask = 0;
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct as5812_54t_cpld_data *data = i2c_get_clientdata(client);
|
||||
int status = 0;
|
||||
|
||||
switch (attr->index) {
|
||||
case CPLD_VERSION:
|
||||
reg = 0x1;
|
||||
mask = 0xFF;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
status = as5812_54t_cpld_read_internal(client, reg);
|
||||
if (unlikely(status < 0)) {
|
||||
goto exit;
|
||||
}
|
||||
mutex_unlock(&data->update_lock);
|
||||
return sprintf(buf, "%d\n", (status & mask));
|
||||
|
||||
exit:
|
||||
mutex_unlock(&data->update_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
static ssize_t access(struct device *dev, struct device_attribute *da,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int status;
|
||||
u32 addr, val;
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct as5812_54t_cpld_data *data = i2c_get_clientdata(client);
|
||||
|
||||
if (sscanf(buf, "0x%x 0x%x", &addr, &val) != 2) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (addr > 0xFF || val > 0xFF) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&data->update_lock);
|
||||
status = as5812_54t_cpld_write_internal(client, addr, val);
|
||||
if (unlikely(status < 0)) {
|
||||
goto exit;
|
||||
}
|
||||
mutex_unlock(&data->update_lock);
|
||||
return count;
|
||||
|
||||
exit:
|
||||
mutex_unlock(&data->update_lock);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int as5812_54t_cpld_read_internal(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
int status = 0, retry = I2C_RW_RETRY_COUNT;
|
||||
|
||||
while (retry) {
|
||||
status = i2c_smbus_read_byte_data(client, reg);
|
||||
if (unlikely(status < 0)) {
|
||||
msleep(I2C_RW_RETRY_INTERVAL);
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int as5812_54t_cpld_write_internal(struct i2c_client *client, u8 reg, u8 value)
|
||||
{
|
||||
int status = 0, retry = I2C_RW_RETRY_COUNT;
|
||||
|
||||
while (retry) {
|
||||
status = i2c_smbus_write_byte_data(client, reg, value);
|
||||
if (unlikely(status < 0)) {
|
||||
msleep(I2C_RW_RETRY_INTERVAL);
|
||||
retry--;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void as5812_54t_cpld_add_client(struct i2c_client *client)
|
||||
{
|
||||
struct cpld_client_node *node = kzalloc(sizeof(struct cpld_client_node), GFP_KERNEL);
|
||||
|
||||
if (!node) {
|
||||
dev_dbg(&client->dev, "Can't allocate cpld_client_node (0x%x)\n", client->addr);
|
||||
return;
|
||||
}
|
||||
|
||||
node->client = client;
|
||||
|
||||
mutex_lock(&list_lock);
|
||||
list_add(&node->list, &cpld_client_list);
|
||||
mutex_unlock(&list_lock);
|
||||
}
|
||||
|
||||
static void as5812_54t_cpld_remove_client(struct i2c_client *client)
|
||||
{
|
||||
struct list_head *list_node = NULL;
|
||||
struct cpld_client_node *cpld_node = NULL;
|
||||
int found = 0;
|
||||
|
||||
mutex_lock(&list_lock);
|
||||
|
||||
list_for_each(list_node, &cpld_client_list)
|
||||
{
|
||||
cpld_node = list_entry(list_node, struct cpld_client_node, list);
|
||||
|
||||
if (cpld_node->client == client) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
list_del(list_node);
|
||||
kfree(cpld_node);
|
||||
}
|
||||
|
||||
mutex_unlock(&list_lock);
|
||||
}
|
||||
|
||||
static int as5812_54t_cpld_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *dev_id)
|
||||
{
|
||||
int status;
|
||||
struct as5812_54t_cpld_data *data = NULL;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
|
||||
dev_dbg(&client->dev, "i2c_check_functionality failed (0x%x)\n", client->addr);
|
||||
status = -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
data = kzalloc(sizeof(struct as5812_54t_cpld_data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
status = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->update_lock);
|
||||
dev_info(&client->dev, "chip found\n");
|
||||
|
||||
/* Register sysfs hooks */
|
||||
status = sysfs_create_group(&client->dev.kobj, &as5812_54t_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;
|
||||
}
|
||||
|
||||
as5812_54t_cpld_add_client(client);
|
||||
|
||||
dev_info(&client->dev, "%s: cpld '%s'\n",
|
||||
dev_name(data->hwmon_dev), client->name);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_remove:
|
||||
sysfs_remove_group(&client->dev.kobj, &as5812_54t_cpld_group);
|
||||
exit_free:
|
||||
kfree(data);
|
||||
exit:
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int as5812_54t_cpld_remove(struct i2c_client *client)
|
||||
{
|
||||
struct as5812_54t_cpld_data *data = i2c_get_clientdata(client);
|
||||
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &as5812_54t_cpld_group);
|
||||
kfree(data);
|
||||
as5812_54t_cpld_remove_client(client);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int as5812_54t_cpld_read(unsigned short cpld_addr, u8 reg)
|
||||
{
|
||||
struct list_head *list_node = NULL;
|
||||
struct cpld_client_node *cpld_node = NULL;
|
||||
int ret = -EPERM;
|
||||
|
||||
mutex_lock(&list_lock);
|
||||
|
||||
list_for_each(list_node, &cpld_client_list)
|
||||
{
|
||||
cpld_node = list_entry(list_node, struct cpld_client_node, list);
|
||||
|
||||
if (cpld_node->client->addr == cpld_addr) {
|
||||
ret = i2c_smbus_read_byte_data(cpld_node->client, reg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&list_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(as5812_54t_cpld_read);
|
||||
|
||||
int as5812_54t_cpld_write(unsigned short cpld_addr, u8 reg, u8 value)
|
||||
{
|
||||
struct list_head *list_node = NULL;
|
||||
struct cpld_client_node *cpld_node = NULL;
|
||||
int ret = -EIO;
|
||||
|
||||
mutex_lock(&list_lock);
|
||||
|
||||
list_for_each(list_node, &cpld_client_list)
|
||||
{
|
||||
cpld_node = list_entry(list_node, struct cpld_client_node, list);
|
||||
|
||||
if (cpld_node->client->addr == cpld_addr) {
|
||||
ret = i2c_smbus_write_byte_data(cpld_node->client, reg, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&list_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(as5812_54t_cpld_write);
|
||||
|
||||
static const struct i2c_device_id as5812_54t_cpld_id[] = {
|
||||
{ "as5812_54t_cpld", 0 },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, as5812_54t_cpld_id);
|
||||
|
||||
static struct i2c_driver as5812_54t_cpld_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "as5812_54t_cpld",
|
||||
},
|
||||
.probe = as5812_54t_cpld_probe,
|
||||
.remove = as5812_54t_cpld_remove,
|
||||
.id_table = as5812_54t_cpld_id,
|
||||
.address_list = normal_i2c,
|
||||
};
|
||||
|
||||
static int __init as5812_54t_cpld_init(void)
|
||||
{
|
||||
mutex_init(&list_lock);
|
||||
return i2c_add_driver(&as5812_54t_cpld_driver);
|
||||
}
|
||||
|
||||
static void __exit as5812_54t_cpld_exit(void)
|
||||
{
|
||||
i2c_del_driver(&as5812_54t_cpld_driver);
|
||||
}
|
||||
|
||||
module_init(as5812_54t_cpld_init);
|
||||
module_exit(as5812_54t_cpld_exit);
|
||||
|
||||
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
|
||||
MODULE_DESCRIPTION("as5812_54t_cpld driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -131,8 +131,8 @@ static ssize_t fan_set_duty_cycle(struct device *dev,
|
||||
static ssize_t fan_show_value(struct device *dev,
|
||||
struct device_attribute *da, char *buf);
|
||||
|
||||
extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
|
||||
extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
|
||||
extern int as5812_54t_cpld_read(unsigned short cpld_addr, u8 reg);
|
||||
extern int as5812_54t_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
|
||||
|
||||
|
||||
/*******************/
|
||||
@@ -258,12 +258,12 @@ static const struct attribute_group accton_as5812_54t_fan_group = {
|
||||
|
||||
static int accton_as5812_54t_fan_read_value(u8 reg)
|
||||
{
|
||||
return accton_i2c_cpld_read(0x60, reg);
|
||||
return as5812_54t_cpld_read(0x60, reg);
|
||||
}
|
||||
|
||||
static int accton_as5812_54t_fan_write_value(u8 reg, u8 value)
|
||||
{
|
||||
return accton_i2c_cpld_write(0x60, reg, value);
|
||||
return as5812_54t_cpld_write(0x60, reg, value);
|
||||
}
|
||||
|
||||
static void accton_as5812_54t_fan_update_device(struct device *dev)
|
||||
@@ -394,12 +394,7 @@ static int __init accton_as5812_54t_fan_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
extern int platform_accton_as5812_54t(void);
|
||||
if (!platform_accton_as5812_54t()) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = platform_driver_register(&accton_as5812_54t_fan_driver);
|
||||
ret = platform_driver_register(&accton_as5812_54t_fan_driver);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
#include <linux/leds.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
|
||||
extern int accton_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
|
||||
extern int as5812_54t_cpld_read(unsigned short cpld_addr, u8 reg);
|
||||
extern int as5812_54t_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
|
||||
|
||||
extern void led_classdev_unregister(struct led_classdev *led_cdev);
|
||||
extern int led_classdev_register(struct device *parent, struct led_classdev *led_cdev);
|
||||
@@ -223,12 +223,12 @@ static u8 led_light_mode_to_reg_val(enum led_type type,
|
||||
|
||||
static int accton_as5812_54t_led_read_value(u8 reg)
|
||||
{
|
||||
return accton_i2c_cpld_read(0x60, reg);
|
||||
return as5812_54t_cpld_read(0x60, reg);
|
||||
}
|
||||
|
||||
static int accton_as5812_54t_led_write_value(u8 reg, u8 value)
|
||||
{
|
||||
return accton_i2c_cpld_write(0x60, reg, value);
|
||||
return as5812_54t_cpld_write(0x60, reg, value);
|
||||
}
|
||||
|
||||
static void accton_as5812_54t_led_update(void)
|
||||
@@ -555,12 +555,7 @@ static int __init accton_as5812_54t_led_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
extern int platform_accton_as5812_54t(void);
|
||||
if (!platform_accton_as5812_54t()) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = platform_driver_register(&accton_as5812_54t_led_driver);
|
||||
ret = platform_driver_register(&accton_as5812_54t_led_driver);
|
||||
if (ret < 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ static ssize_t show_index(struct device *dev, struct device_attribute *da, char
|
||||
static ssize_t show_status(struct device *dev, struct device_attribute *da, char *buf);
|
||||
static ssize_t show_model_name(struct device *dev, struct device_attribute *da, char *buf);
|
||||
static int as5812_54t_psu_read_block(struct i2c_client *client, u8 command, u8 *data,int data_len);
|
||||
extern int accton_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
|
||||
extern int as5812_54t_cpld_read(unsigned short cpld_addr, u8 reg);
|
||||
static int as5812_54t_psu_model_name_get(struct device *dev);
|
||||
|
||||
/* Addresses scanned
|
||||
@@ -328,7 +328,7 @@ static struct as5812_54t_psu_data *as5812_54t_psu_update_device(struct device *d
|
||||
data->valid = 0;
|
||||
|
||||
/* Read psu status */
|
||||
status = accton_i2c_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET);
|
||||
status = as5812_54t_cpld_read(PSU_STATUS_I2C_ADDR, PSU_STATUS_I2C_REG_OFFSET);
|
||||
|
||||
if (status < 0) {
|
||||
dev_dbg(&client->dev, "cpld reg (0x%x) err %d\n", PSU_STATUS_I2C_ADDR, status);
|
||||
@@ -348,25 +348,9 @@ exit:
|
||||
return data;
|
||||
}
|
||||
|
||||
static int __init as5812_54t_psu_init(void)
|
||||
{
|
||||
extern int platform_accton_as5812_54t(void);
|
||||
if (!platform_accton_as5812_54t()) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return i2c_add_driver(&as5812_54t_psu_driver);
|
||||
}
|
||||
|
||||
static void __exit as5812_54t_psu_exit(void)
|
||||
{
|
||||
i2c_del_driver(&as5812_54t_psu_driver);
|
||||
}
|
||||
module_i2c_driver(as5812_54t_psu_driver);
|
||||
|
||||
MODULE_AUTHOR("Brandon Chuang <brandon_chuang@accton.com.tw>");
|
||||
MODULE_DESCRIPTION("accton as5812_54t_psu driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(as5812_54t_psu_init);
|
||||
module_exit(as5812_54t_psu_exit);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,80 +25,23 @@
|
||||
***********************************************************/
|
||||
#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"
|
||||
|
||||
#define MAX_SFP_PATH 64
|
||||
static char sfp_node_path[MAX_SFP_PATH] = {0};
|
||||
#define MUX_START_INDEX 2
|
||||
#define NUM_OF_SFP_PORT 6
|
||||
static const int port_bus_index[NUM_OF_SFP_PORT] = {
|
||||
2, 4, 1, 3, 5, 0
|
||||
};
|
||||
|
||||
static int front_port_to_cpld_mux_index(int port)
|
||||
{
|
||||
int rport = 0;
|
||||
#define PORT_BUS_INDEX(port) (port_bus_index[port-48]+MUX_START_INDEX)
|
||||
#define PORT_FORMAT "/sys/bus/i2c/devices/%d-0050/%s"
|
||||
|
||||
switch (port)
|
||||
{
|
||||
case 48:
|
||||
rport = 2;
|
||||
break;
|
||||
case 49:
|
||||
rport = 4;
|
||||
break;
|
||||
case 50:
|
||||
rport = 1;
|
||||
break;
|
||||
case 51:
|
||||
rport = 3;
|
||||
break;
|
||||
case 52:
|
||||
rport = 5;
|
||||
break;
|
||||
case 53:
|
||||
rport = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (rport + MUX_START_INDEX);
|
||||
}
|
||||
|
||||
static int
|
||||
as5812_54t_sfp_node_read_int(char *node_path, int *value, int data_len)
|
||||
{
|
||||
int ret = 0;
|
||||
char buf[8] = {0};
|
||||
*value = 0;
|
||||
|
||||
ret = deviceNodeReadString(node_path, buf, sizeof(buf), data_len);
|
||||
|
||||
if (ret == 0) {
|
||||
*value = atoi(buf);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char*
|
||||
as5812_54t_sfp_get_port_path_addr(int port, int addr, char *node_name)
|
||||
{
|
||||
sprintf(sfp_node_path, "/sys/bus/i2c/devices/%d-00%d/%s",
|
||||
front_port_to_cpld_mux_index(port), addr,
|
||||
node_name);
|
||||
return sfp_node_path;
|
||||
}
|
||||
|
||||
static char*
|
||||
as5812_54t_sfp_get_port_path(int port, char *node_name)
|
||||
{
|
||||
return as5812_54t_sfp_get_port_path_addr(port, 50, node_name);
|
||||
}
|
||||
#define MODULE_PRESENT_FORMAT "/sys/bus/i2c/devices/0-0060/module_present_%d"
|
||||
#define MODULE_PRESENT_ALL_ATTR "/sys/bus/i2c/devices/0-0060/module_present_all"
|
||||
|
||||
#define VALIDATE_PORT(p) { if ((p < 48) || (p > 53)) return ONLP_STATUS_E_PARAM; }
|
||||
|
||||
/************************************************************
|
||||
*
|
||||
@@ -136,10 +79,9 @@ onlp_sfpi_is_present(int port)
|
||||
* Return < 0 if error.
|
||||
*/
|
||||
int present;
|
||||
char* path = as5812_54t_sfp_get_port_path(port, "sfp_is_present");
|
||||
|
||||
if (as5812_54t_sfp_node_read_int(path, &present, 1) != 0) {
|
||||
AIM_LOG_INFO("Unable to read present status from port(%d)\r\n", port);
|
||||
if (onlp_file_read_int(&present, MODULE_PRESENT_FORMAT, (port+1)) < 0) {
|
||||
AIM_LOG_ERROR("Unable to read present status from port(%d)\r\n", port);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
|
||||
@@ -150,11 +92,9 @@ int
|
||||
onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
|
||||
{
|
||||
uint32_t bytes[1];
|
||||
char* path;
|
||||
FILE* fp;
|
||||
|
||||
path = as5812_54t_sfp_get_port_path(0, "sfp_is_present_all");
|
||||
fp = fopen(path, "r");
|
||||
fp = fopen(MODULE_PRESENT_ALL_ATTR, "r");
|
||||
|
||||
if(fp == NULL) {
|
||||
AIM_LOG_ERROR("Unable to open the sfp_is_present_all device file.");
|
||||
@@ -188,24 +128,23 @@ onlp_sfpi_presence_bitmap_get(onlp_sfp_bitmap_t* dst)
|
||||
int
|
||||
onlp_sfpi_rx_los_bitmap_get(onlp_sfp_bitmap_t* dst)
|
||||
{
|
||||
return ONLP_STATUS_OK;
|
||||
return ONLP_STATUS_E_UNSUPPORTED;
|
||||
}
|
||||
|
||||
int
|
||||
onlp_sfpi_eeprom_read(int port, uint8_t data[256])
|
||||
{
|
||||
char* path = as5812_54t_sfp_get_port_path(port, "sfp_eeprom");
|
||||
|
||||
/*
|
||||
* Read the SFP eeprom into data[]
|
||||
*
|
||||
* Return MISSING if SFP is missing.
|
||||
* Return OK if eeprom is read
|
||||
*/
|
||||
int size = 0;
|
||||
memset(data, 0, 256);
|
||||
|
||||
if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) {
|
||||
AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port);
|
||||
if(onlp_file_read(data, 256, &size, PORT_FORMAT, PORT_BUS_INDEX(port), "eeprom") != ONLP_STATUS_OK) {
|
||||
AIM_LOG_ERROR("Unable to read eeprom from port(%d)\r\n", port);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
|
||||
@@ -213,29 +152,35 @@ onlp_sfpi_eeprom_read(int port, uint8_t data[256])
|
||||
}
|
||||
|
||||
int
|
||||
onlp_sfpi_dom_read(int port, uint8_t data[256])
|
||||
onlp_sfpi_dev_readb(int port, uint8_t devaddr, uint8_t addr)
|
||||
{
|
||||
char* path = as5812_54t_sfp_get_port_path_addr(port, 51, "sfp_eeprom");
|
||||
memset(data, 0, 256);
|
||||
|
||||
if (deviceNodeReadBinary(path, (char*)data, 256, 256) != 0) {
|
||||
AIM_LOG_INFO("Unable to read eeprom from port(%d)\r\n", port);
|
||||
return ONLP_STATUS_E_INTERNAL;
|
||||
}
|
||||
|
||||
return ONLP_STATUS_OK;
|
||||
VALIDATE_PORT(port);
|
||||
int bus = PORT_BUS_INDEX(port);
|
||||
return onlp_i2c_readb(bus, devaddr, addr, ONLP_I2C_F_FORCE);
|
||||
}
|
||||
|
||||
int
|
||||
onlp_sfpi_control_set(int port, onlp_sfp_control_t control, int value)
|
||||
onlp_sfpi_dev_writeb(int port, uint8_t devaddr, uint8_t addr, uint8_t value)
|
||||
{
|
||||
return ONLP_STATUS_E_UNSUPPORTED;
|
||||
VALIDATE_PORT(port);
|
||||
int bus = PORT_BUS_INDEX(port);
|
||||
return onlp_i2c_writeb(bus, devaddr, addr, value, ONLP_I2C_F_FORCE);
|
||||
}
|
||||
|
||||
int
|
||||
onlp_sfpi_control_get(int port, onlp_sfp_control_t control, int* value)
|
||||
onlp_sfpi_dev_readw(int port, uint8_t devaddr, uint8_t addr)
|
||||
{
|
||||
return ONLP_STATUS_E_UNSUPPORTED;
|
||||
VALIDATE_PORT(port);
|
||||
int bus = PORT_BUS_INDEX(port);
|
||||
return onlp_i2c_readw(bus, devaddr, addr, ONLP_I2C_F_FORCE);
|
||||
}
|
||||
|
||||
int
|
||||
onlp_sfpi_dev_writew(int port, uint8_t devaddr, uint8_t addr, uint16_t value)
|
||||
{
|
||||
VALIDATE_PORT(port);
|
||||
int bus = PORT_BUS_INDEX(port);
|
||||
return onlp_i2c_writew(bus, devaddr, addr, value, ONLP_I2C_F_FORCE);
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -10,25 +10,28 @@ class OnlPlatform_x86_64_accton_as5812_54t_r0(OnlPlatformAccton,
|
||||
|
||||
def baseconfig(self):
|
||||
########### initialize I2C bus 0 ###########
|
||||
self.insmod("accton_i2c_cpld")
|
||||
self.insmod("optoe")
|
||||
self.insmod("cpr_4011_4mxx")
|
||||
self.insmod("ym2651y")
|
||||
for m in [ "sfp", "psu", "fan", "leds" ]:
|
||||
for m in [ "cpld", "psu", "fan", "leds" ]:
|
||||
self.insmod("x86-64-accton-as5812-54t-%s" % m)
|
||||
|
||||
# initialize CPLDs
|
||||
self.new_i2c_device('accton_i2c_cpld', 0x60, 0)
|
||||
self.new_i2c_device('as5812_54t_cpld', 0x60, 0)
|
||||
|
||||
# initiate multiplexer (PCA9548)
|
||||
self.new_i2c_device('pca9548', 0x71, 0)
|
||||
|
||||
# Initialize QSFP devices
|
||||
self.new_i2c_device('as5812_54t_port49', 0x50, 4)
|
||||
self.new_i2c_device('as5812_54t_port50', 0x50, 6)
|
||||
self.new_i2c_device('as5812_54t_port51', 0x50, 3)
|
||||
self.new_i2c_device('as5812_54t_port52', 0x50, 5)
|
||||
self.new_i2c_device('as5812_54t_port53', 0x50, 7)
|
||||
self.new_i2c_device('as5812_54t_port54', 0x50, 2)
|
||||
for bus in range(2, 8):
|
||||
self.new_i2c_device('optoe1', 0x50, bus)
|
||||
|
||||
subprocess.call('echo port54 > /sys/bus/i2c/devices/2-0050/port_name', shell=True)
|
||||
subprocess.call('echo port51 > /sys/bus/i2c/devices/3-0050/port_name', shell=True)
|
||||
subprocess.call('echo port49 > /sys/bus/i2c/devices/4-0050/port_name', shell=True)
|
||||
subprocess.call('echo port52 > /sys/bus/i2c/devices/5-0050/port_name', shell=True)
|
||||
subprocess.call('echo port50 > /sys/bus/i2c/devices/6-0050/port_name', shell=True)
|
||||
subprocess.call('echo port53 > /sys/bus/i2c/devices/7-0050/port_name', shell=True)
|
||||
|
||||
########### initialize I2C bus 1 ###########
|
||||
self.new_i2c_devices(
|
||||
|
||||
Reference in New Issue
Block a user