mirror of
https://github.com/Telecominfraproject/OpenNetworkLinux.git
synced 2025-12-25 17:27:01 +00:00
Initial common quanta module package.
This commit is contained in:
@@ -1 +1 @@
|
||||
!include $ONL_TEMPLATES/no-arch-vendor-modules.yml ARCH=amd64 VENDOR=quanta
|
||||
!include $ONL_TEMPLATES/arch-vendor-modules.yml ARCH=amd64 VENDOR=quanta KERNELS="onl-kernel-3.16-lts-x86-64-all:amd64"
|
||||
|
||||
1
packages/platforms/quanta/x86-64/modules/builds/.gitignore
vendored
Normal file
1
packages/platforms/quanta/x86-64/modules/builds/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
lib
|
||||
6
packages/platforms/quanta/x86-64/modules/builds/Makefile
Normal file
6
packages/platforms/quanta/x86-64/modules/builds/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
KERNELS := onl-kernel-3.16-lts-x86-64-all:amd64
|
||||
KMODULES := $(wildcard *.c)
|
||||
VENDOR := quanta
|
||||
BASENAME := common
|
||||
ARCH := x86_64
|
||||
include $(ONL)/make/kmodule.mk
|
||||
603
packages/platforms/quanta/x86-64/modules/builds/qci_cpld.c
Executable file
603
packages/platforms/quanta/x86-64/modules/builds/qci_cpld.c
Executable file
@@ -0,0 +1,603 @@
|
||||
/*
|
||||
* A CPLD driver for monitor QSFP28 module I/O
|
||||
*
|
||||
* The CPLD is customize by Quanta for controlling QSFP28 module signals,
|
||||
* they are RESET , INTERREPT , Module_Present, LPMODE
|
||||
* Each CPLD control 16 modules, each module use 4 bits in register.
|
||||
*
|
||||
* Copyright (C) 2015 Quanta Inc.
|
||||
*
|
||||
* Author: Luffy Cheng <luffy.cheng@quantatw.com>
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
static DEFINE_IDA(cpld_ida);
|
||||
|
||||
enum platform_type {
|
||||
SFP = 0,
|
||||
QSFP,
|
||||
QSFP28,
|
||||
NONE
|
||||
};
|
||||
|
||||
static struct class *cpld_class = NULL;
|
||||
|
||||
struct sfp_data {
|
||||
struct i2c_client *cpld_client;
|
||||
char name[8];
|
||||
char type[8];
|
||||
u8 port_id;
|
||||
u8 cpld_port;
|
||||
};
|
||||
|
||||
struct cpld_data {
|
||||
struct mutex lock;
|
||||
struct device *port_dev[16];
|
||||
struct sfp_data *port_data[16];
|
||||
};
|
||||
|
||||
static int cpld_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id);
|
||||
static int cpld_remove(struct i2c_client *client);
|
||||
|
||||
static const struct i2c_device_id cpld_id[] = {
|
||||
{ "CPLD-SFP", SFP },
|
||||
{ "CPLD-QSFP", QSFP },
|
||||
{ "CPLD-QSFP28", QSFP28 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cpld_id);
|
||||
|
||||
static struct i2c_driver cpld_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "qci_cpld",
|
||||
},
|
||||
.probe = cpld_probe,
|
||||
.remove = cpld_remove,
|
||||
.id_table = cpld_id,
|
||||
// .address_list = normal_i2c,
|
||||
};
|
||||
|
||||
#define CPLD_ID_PREFIX "port-"
|
||||
#define CPLD_ID_FORMAT CPLD_ID_PREFIX "%d"
|
||||
|
||||
#define RESET_MASK 0x08
|
||||
#define INTERRUPT_MASK 0x04
|
||||
#define MODULE_PRESENT_MASK 0x02
|
||||
#define LPMODE_MASK 0x01
|
||||
//#define I2C_MONITOR_MASK 0x01
|
||||
|
||||
static inline u8 get_group_cmd(u8 group)
|
||||
{
|
||||
//FIXME: if group cmd change
|
||||
return (group + 1);
|
||||
}
|
||||
|
||||
static inline u8 port_remapping(u8 phy_port)
|
||||
{
|
||||
/* FIXME: implement by hardware design */
|
||||
/* The CPLD register port mapping is weird :
|
||||
* MSB -------- LSB (word data)
|
||||
* P3 P4 P1 P2 (per port 4 bits)
|
||||
* For easy coding bit shift, we treat it as hw port swap
|
||||
*/
|
||||
return (phy_port % 2) ? (phy_port - 1) : (phy_port + 1);
|
||||
}
|
||||
|
||||
static ssize_t get_reset(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
struct sfp_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->cpld_client;
|
||||
u8 group = (u8)(data->cpld_port / 4);
|
||||
u8 group_port = data->cpld_port % 4;
|
||||
s32 value;
|
||||
|
||||
dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id,
|
||||
data->cpld_port + 1, group + 1, group_port + 1);
|
||||
|
||||
value = i2c_smbus_read_word_data(client, get_group_cmd(group));
|
||||
if (value < 0)
|
||||
return -ENODEV;
|
||||
|
||||
dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value);
|
||||
|
||||
value >>= (group_port * 4);
|
||||
value &= RESET_MASK;
|
||||
|
||||
return sprintf(buf, "%d\n", value ? 1 : 0);
|
||||
}
|
||||
|
||||
static ssize_t get_interrupt(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
struct sfp_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->cpld_client;
|
||||
u8 group = (u8)(data->cpld_port / 4);
|
||||
u8 group_port = data->cpld_port % 4;
|
||||
s32 value;
|
||||
|
||||
dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id,
|
||||
data->cpld_port + 1, group + 1, group_port + 1);
|
||||
|
||||
value = i2c_smbus_read_word_data(client, get_group_cmd(group));
|
||||
if (value < 0)
|
||||
return -ENODEV;
|
||||
|
||||
dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value);
|
||||
|
||||
value >>= (group_port * 4);
|
||||
value &= INTERRUPT_MASK;
|
||||
|
||||
return sprintf(buf, "%d\n", value ? 1 : 0);
|
||||
}
|
||||
|
||||
static ssize_t get_module_present(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
struct sfp_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->cpld_client;
|
||||
u8 group = (u8)(data->cpld_port / 4);
|
||||
u8 group_port = data->cpld_port % 4;
|
||||
s32 value;
|
||||
|
||||
dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id,
|
||||
data->cpld_port + 1, group + 1, group_port + 1);
|
||||
|
||||
value = i2c_smbus_read_word_data(client, get_group_cmd(group));
|
||||
if (value < 0)
|
||||
return -ENODEV;
|
||||
|
||||
dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value);
|
||||
|
||||
value >>= (group_port * 4);
|
||||
value &= MODULE_PRESENT_MASK;
|
||||
|
||||
//FIXME: if present is not low active
|
||||
return sprintf(buf, "%d\n", value ? 0 : 1);
|
||||
}
|
||||
|
||||
static ssize_t get_lpmode(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
struct sfp_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->cpld_client;
|
||||
u8 group = (u8)(data->cpld_port / 4);
|
||||
u8 group_port = data->cpld_port % 4;
|
||||
s32 value;
|
||||
|
||||
dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id,
|
||||
data->cpld_port + 1, group + 1, group_port + 1);
|
||||
|
||||
value = i2c_smbus_read_word_data(client, get_group_cmd(group));
|
||||
if (value < 0)
|
||||
return -ENODEV;
|
||||
|
||||
dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value);
|
||||
|
||||
value >>= (group_port * 4);
|
||||
value &= LPMODE_MASK;
|
||||
|
||||
return sprintf(buf, "%d\n", value ? 1 : 0);
|
||||
}
|
||||
|
||||
static ssize_t set_reset(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct sfp_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->cpld_client;
|
||||
u8 group = (u8)(data->cpld_port / 4);
|
||||
u8 group_port = data->cpld_port % 4;
|
||||
s32 value;
|
||||
long disable;
|
||||
|
||||
dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id,
|
||||
data->cpld_port + 1, group + 1, group_port + 1);
|
||||
|
||||
if (kstrtol(buf, 0, &disable))
|
||||
return -EINVAL;
|
||||
|
||||
if ((disable != 1) && (disable != 0))
|
||||
return -EINVAL;
|
||||
|
||||
// mutex_lock(&data->lock);
|
||||
value = i2c_smbus_read_word_data(client, get_group_cmd(group));
|
||||
if (value < 0)
|
||||
return -ENODEV;
|
||||
|
||||
dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value);
|
||||
|
||||
value &= ~(RESET_MASK << (group_port * 4));
|
||||
if (disable)
|
||||
value |= (RESET_MASK << (group_port * 4));
|
||||
|
||||
dev_dbg(&client->dev, "write group%d value= %x\n", group + 1, value);
|
||||
|
||||
i2c_smbus_write_word_data(client, get_group_cmd(group), (u16)value);
|
||||
// mutex_unlock(&data->lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t set_lpmode(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct sfp_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->cpld_client;
|
||||
u8 group = (u8)(data->cpld_port / 4);
|
||||
u8 group_port = data->cpld_port % 4;
|
||||
s32 value;
|
||||
long disable;
|
||||
|
||||
dev_dbg(&client->dev, "port_id %d => cpld_port %d, group %d(%d)\n", data->port_id,
|
||||
data->cpld_port + 1, group + 1, group_port + 1);
|
||||
|
||||
if (kstrtol(buf, 0, &disable))
|
||||
return -EINVAL;
|
||||
|
||||
if ((disable != 1) && (disable != 0))
|
||||
return -EINVAL;
|
||||
|
||||
// mutex_lock(&data->lock);
|
||||
value = i2c_smbus_read_word_data(client, get_group_cmd(group));
|
||||
if (value < 0)
|
||||
return -ENODEV;
|
||||
|
||||
dev_dbg(&client->dev, "read group%d value= %x\n", group + 1, value);
|
||||
|
||||
value &= ~(LPMODE_MASK << (group_port * 4));
|
||||
if (disable)
|
||||
value |= (LPMODE_MASK << (group_port * 4));
|
||||
|
||||
dev_dbg(&client->dev, "write group%d value= %x\n", group + 1, value);
|
||||
|
||||
i2c_smbus_write_word_data(client, get_group_cmd(group), (u16)value);
|
||||
// mutex_unlock(&data->lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static ssize_t get_led_enable(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
struct sfp_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->cpld_client;
|
||||
u8 group = 3;
|
||||
u8 group_port = data->cpld_port;
|
||||
s32 value;
|
||||
|
||||
dev_dbg(&client->dev, "get_led_enable port_id %d => cpld_port %d, group %d(%d)\n", data->port_id,
|
||||
data->cpld_port + 1, group, group_port + 1);
|
||||
|
||||
value = i2c_smbus_read_word_data(client, group);
|
||||
if (value < 0)
|
||||
return -ENODEV;
|
||||
|
||||
dev_dbg(&client->dev, "read group%d value= %x\n", group, value);
|
||||
|
||||
value >>= (group_port);
|
||||
value &= LED_ENABLE_MASK;
|
||||
|
||||
return sprintf(buf, "%d\n", value ? 1 : 0);
|
||||
}
|
||||
|
||||
static ssize_t set_led_enable(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct sfp_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->cpld_client;
|
||||
u8 group = 3;
|
||||
u8 group_port = data->cpld_port;
|
||||
s32 value;
|
||||
long disable;
|
||||
|
||||
dev_dbg(&client->dev, "set_led_enable port_id %d => cpld_port %d, group %d(%d)\n", data->port_id,
|
||||
data->cpld_port + 1, group, group_port + 1);
|
||||
|
||||
if (kstrtol(buf, 0, &disable))
|
||||
return -EINVAL;
|
||||
|
||||
if ((disable != 1) && (disable != 0))
|
||||
return -EINVAL;
|
||||
|
||||
// mutex_lock(&data->lock);
|
||||
value = i2c_smbus_read_word_data(client, group);
|
||||
if (value < 0)
|
||||
return -ENODEV;
|
||||
|
||||
dev_dbg(&client->dev, "read group%d value= %x\n", group, value);
|
||||
|
||||
value &= ~(LED_ENABLE_MASK << group_port);
|
||||
if (disable)
|
||||
value |= (LED_ENABLE_MASK << group_port);
|
||||
|
||||
dev_dbg(&client->dev, "write group%d value= %x\n", group, value);
|
||||
|
||||
i2c_smbus_write_word_data(client, group, (u16)value);
|
||||
// mutex_unlock(&data->lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
static ssize_t get_monitor_enable(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
struct i2c_monitor_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->cpld_client;
|
||||
u8 group = 4;
|
||||
s32 value;
|
||||
|
||||
value = i2c_smbus_read_word_data(client, group);
|
||||
if (value < 0)
|
||||
return -ENODEV;
|
||||
|
||||
dev_dbg(&client->dev, "read group%d value= %x\n", group, value);
|
||||
|
||||
value &= I2C_MONITOR_MASK;
|
||||
|
||||
return sprintf(buf, "%d\n", value ? 1 : 0);
|
||||
}
|
||||
|
||||
static ssize_t set_monitor_enable(struct device *dev,
|
||||
struct device_attribute *devattr,
|
||||
const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct i2c_monitor_data *data = dev_get_drvdata(dev);
|
||||
struct i2c_client *client = data->cpld_client;
|
||||
u8 group = 4;
|
||||
s32 value;
|
||||
long disable;
|
||||
|
||||
if (kstrtol(buf, 0, &disable))
|
||||
return -EINVAL;
|
||||
|
||||
if ((disable != 1) && (disable != 0))
|
||||
return -EINVAL;
|
||||
|
||||
// mutex_lock(&data->lock);
|
||||
value = i2c_smbus_read_word_data(client, group);
|
||||
if (value < 0)
|
||||
return -ENODEV;
|
||||
|
||||
dev_dbg(&client->dev, "read group%d value= %x\n", group, value);
|
||||
|
||||
value &= ~(I2C_MONITOR_MASK);
|
||||
if (disable)
|
||||
value |= (I2C_MONITOR_MASK);
|
||||
|
||||
dev_dbg(&client->dev, "write group%d value= %x\n", group, value);
|
||||
|
||||
i2c_smbus_write_word_data(client, group, (u16)value);
|
||||
// mutex_unlock(&data->lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
static DEVICE_ATTR(reset, S_IWUSR | S_IRUGO, get_reset, set_reset);
|
||||
static DEVICE_ATTR(lpmode, S_IWUSR | S_IRUGO, get_lpmode, set_lpmode);
|
||||
static DEVICE_ATTR(module_present, S_IRUGO, get_module_present, NULL);
|
||||
static DEVICE_ATTR(interrupt, S_IRUGO, get_interrupt, NULL);
|
||||
//static DEVICE_ATTR(led_enable, S_IWUSR | S_IRUGO, get_led_enable, set_led_enable);
|
||||
//static DEVICE_ATTR(monitor_enable, S_IWUSR | S_IRUGO, get_monitor_enable, set_monitor_enable);
|
||||
|
||||
static const struct attribute *sfp_attrs[] = {
|
||||
&dev_attr_reset.attr,
|
||||
&dev_attr_lpmode.attr,
|
||||
&dev_attr_module_present.attr,
|
||||
&dev_attr_interrupt.attr,
|
||||
// &dev_attr_led_enable.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group sfp_attr_group = {
|
||||
.attrs = (struct attribute **) sfp_attrs,
|
||||
};
|
||||
|
||||
#if 0
|
||||
static const struct attribute *i2c_monitor_attrs[] = {
|
||||
&dev_attr_monitor_enable.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group i2c_monitor_attr_group = {
|
||||
.attrs = (struct attribute **) i2c_monitor_attrs,
|
||||
};
|
||||
#endif
|
||||
|
||||
static int cpld_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct cpld_data *data;
|
||||
struct sfp_data *port_data;
|
||||
// struct i2c_monitor_data *monitor_data;
|
||||
struct device *port_dev;
|
||||
// struct device *i2c_dev;
|
||||
int port_nr, i=0, err, max_port_num;
|
||||
char name[I2C_NAME_SIZE], type[I2C_NAME_SIZE];
|
||||
|
||||
printk("cpld cpld_probe\n");
|
||||
|
||||
while(id->name[i])
|
||||
{
|
||||
name[i]=tolower(id->name[i]);
|
||||
i++;
|
||||
}
|
||||
name[i]='\0';
|
||||
strncpy(type,name+5,strlen(name)-5);
|
||||
type[strlen(name)-5]='\0';
|
||||
|
||||
if (!cpld_class)
|
||||
{
|
||||
cpld_class = class_create(THIS_MODULE, name);
|
||||
if (IS_ERR(cpld_class)) {
|
||||
pr_err("couldn't create sysfs class\n");
|
||||
return PTR_ERR(cpld_class);
|
||||
}
|
||||
}
|
||||
|
||||
data = devm_kzalloc(&client->dev, sizeof(struct cpld_data),
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
if(!strcmp(client->name, "CPLD-QSFP28")){
|
||||
max_port_num = 16;
|
||||
}
|
||||
else{
|
||||
max_port_num = 4;
|
||||
}
|
||||
|
||||
/* register sfp port data to sysfs */
|
||||
for (i = 0; i < max_port_num; i++)
|
||||
{
|
||||
port_nr = ida_simple_get(&cpld_ida, 1, 99, GFP_KERNEL);
|
||||
if (port_nr < 0)
|
||||
return ERR_PTR(port_nr);
|
||||
|
||||
port_data = kzalloc(sizeof(struct sfp_data), GFP_KERNEL);
|
||||
|
||||
port_dev = device_create(cpld_class, &client->dev, MKDEV(0,0), port_data, CPLD_ID_FORMAT, port_nr);
|
||||
if (IS_ERR(port_dev)) {
|
||||
err = PTR_ERR(port_dev);
|
||||
printk("err_status\n");
|
||||
}
|
||||
|
||||
data->port_dev[i] = port_dev;
|
||||
data->port_data[i] = port_data;
|
||||
|
||||
strcpy(port_data->type, type);
|
||||
|
||||
dev_info(&client->dev, "Register %s port-%d\n", port_data->type , port_nr);
|
||||
|
||||
/* FIXME: implement Logical/Physical port remapping */
|
||||
//port_data->cpld_port = i;
|
||||
port_data->cpld_port = port_remapping(i);
|
||||
sprintf(port_data->name, "port-%d", port_nr);
|
||||
port_data->port_id = port_nr;
|
||||
dev_set_drvdata(port_dev, port_data);
|
||||
port_dev->init_name = port_data->name;
|
||||
port_data->cpld_client = client;
|
||||
|
||||
err = sysfs_create_group(&port_dev->kobj, &sfp_attr_group);
|
||||
// if (status) printk("err status\n");
|
||||
}
|
||||
#if 0
|
||||
/* register i2c monitor to sysfs */
|
||||
monitor_data = kzalloc(sizeof(struct i2c_monitor_data), GFP_KERNEL);
|
||||
|
||||
i2c_dev = device_create(cpld_class, &client->dev, MKDEV(0, 0), monitor_data, "i2c_monitor");
|
||||
if (IS_ERR(i2c_dev)) {
|
||||
err = PTR_ERR(i2c_dev);
|
||||
printk("i2c_dev err_status\n");
|
||||
}
|
||||
|
||||
monitor_data->cpld_client = client;
|
||||
err = sysfs_create_group(&i2c_dev->kobj, &i2c_monitor_attr_group);
|
||||
if (err)
|
||||
printk("err sysfs\n");
|
||||
#endif
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->lock);
|
||||
|
||||
dev_info(&client->dev, "%s device found\n", client->name);
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
//FIXME: implement error check
|
||||
//exit_remove:
|
||||
// sysfs_remove_group(&client->dev.kobj, &data->attrs);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* FIXME: for older kernel doesn't with idr_is_empty function, implement here */
|
||||
#if 1
|
||||
static int idr_has_entry(int id, void *p, void *data)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool cpld_idr_is_empty(struct idr *idp)
|
||||
{
|
||||
return !idr_for_each(idp, idr_has_entry, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int cpld_remove(struct i2c_client *client)
|
||||
{
|
||||
struct cpld_data *data = i2c_get_clientdata(client);
|
||||
int i, max_port_num;
|
||||
// int id;
|
||||
|
||||
if(!strcmp(client->name, "CPLD-QSFP28")){
|
||||
max_port_num = 16;
|
||||
}
|
||||
else{
|
||||
max_port_num = 4;
|
||||
}
|
||||
|
||||
for (i = (max_port_num - 1); i >= 0; i--)
|
||||
{
|
||||
dev_info(data->port_dev[i], "Remove %s port-%d\n", data->port_data[i]->type , data->port_data[i]->port_id);
|
||||
device_unregister(data->port_dev[i]);
|
||||
ida_simple_remove(&cpld_ida, data->port_data[i]->port_id);
|
||||
kfree(data->port_data[i]);
|
||||
}
|
||||
|
||||
if (cpld_idr_is_empty(&cpld_ida.idr))
|
||||
class_destroy(cpld_class);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_i2c_driver(cpld_driver);
|
||||
|
||||
MODULE_AUTHOR("Luffy Cheng <luffy.cheng@quantatw.com>");
|
||||
MODULE_DESCRIPTION("Quanta Switch QSFP28 CPLD driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
250
packages/platforms/quanta/x86-64/modules/builds/quanta_hwmon.c
Normal file
250
packages/platforms/quanta/x86-64/modules/builds/quanta_hwmon.c
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* <bsn.cl fy=2013 v=gpl>
|
||||
*
|
||||
* Copyright 2013, 2014 BigSwitch Networks, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it
|
||||
* and/or modify it under the terms ofthe GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
*
|
||||
* </bsn.cl>
|
||||
*
|
||||
* A hwmon driver for the Quanta LY6
|
||||
*/
|
||||
|
||||
#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/delay.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
static const unsigned short normal_i2c[] = { 0x4E, I2C_CLIENT_END };
|
||||
|
||||
#define QUANTA_HWMON_REG_TEMP_INPUT_BASE 0x20
|
||||
#define QUANTA_HWMON_REG_FAN_MODE 0x33
|
||||
#define QUANTA_HWMON_REG_FAN_DIR 0x56
|
||||
#define QUANTA_HWMON_REG_FAN_PWM_BASE 0x3C
|
||||
#define QUANTA_HWMON_REG_FAN_INPUT_BASE 0x40
|
||||
|
||||
#define QUANTA_HWMON_FAN_MANUAL_MODE 1
|
||||
#define QUANTA_HWMON_FAN_SMART_MODE 3
|
||||
|
||||
#define QUANTA_HWMON_NUM_FANS 6
|
||||
|
||||
struct quanta_hwmon_data {
|
||||
struct device *hwmon_dev;
|
||||
struct attribute_group attrs;
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
enum quanta_hwmon_s {
|
||||
quanta_ly6_hwmon,
|
||||
quanta_ly6f_hwmon,
|
||||
quanta_ly8_hwmon,
|
||||
quanta_ly9_hwmon,
|
||||
};
|
||||
|
||||
static int quanta_hwmon_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id);
|
||||
static int quanta_hwmon_remove(struct i2c_client *client);
|
||||
|
||||
static const struct i2c_device_id quanta_hwmon_id[] = {
|
||||
{ "quanta_ly6_hwmon", quanta_ly6_hwmon },
|
||||
{ "quanta_ly6f_hwmon", quanta_ly6f_hwmon },
|
||||
{ "quanta_ly8_hwmon", quanta_ly8_hwmon },
|
||||
{ "quanta_ly9_hwmon", quanta_ly9_hwmon },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, quanta_hwmon_id);
|
||||
|
||||
static struct i2c_driver quanta_hwmon_driver = {
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.driver = {
|
||||
.name = "quanta_hwmon",
|
||||
},
|
||||
.probe = quanta_hwmon_probe,
|
||||
.remove = quanta_hwmon_remove,
|
||||
.id_table = quanta_hwmon_id,
|
||||
.address_list = normal_i2c,
|
||||
};
|
||||
|
||||
static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct quanta_hwmon_data *data = i2c_get_clientdata(client);
|
||||
int temp;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
temp = i2c_smbus_read_byte_data(client,
|
||||
QUANTA_HWMON_REG_TEMP_INPUT_BASE
|
||||
+ attr->index);
|
||||
mutex_unlock(&data->lock);
|
||||
return sprintf(buf, "%d\n", 1000 * temp);
|
||||
}
|
||||
|
||||
static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct quanta_hwmon_data *data = i2c_get_clientdata(client);
|
||||
int fan;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
fan = i2c_smbus_read_word_swapped(client,
|
||||
QUANTA_HWMON_REG_FAN_INPUT_BASE
|
||||
+ 2 * attr->index);
|
||||
mutex_unlock(&data->lock);
|
||||
return sprintf(buf, "%d\n", fan);
|
||||
}
|
||||
|
||||
static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
|
||||
char *buf)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct quanta_hwmon_data *data = i2c_get_clientdata(client);
|
||||
int pwm;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
pwm = i2c_smbus_read_word_swapped(client,
|
||||
QUANTA_HWMON_REG_FAN_PWM_BASE
|
||||
+ 2 * attr->index);
|
||||
mutex_unlock(&data->lock);
|
||||
return sprintf(buf, "%d\n", pwm * 255 / 10000);
|
||||
}
|
||||
|
||||
static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct quanta_hwmon_data *data = i2c_get_clientdata(client);
|
||||
long val;
|
||||
int ret;
|
||||
|
||||
ret = kstrtol(buf, 10, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
mutex_lock(&data->lock);
|
||||
i2c_smbus_write_word_swapped(client,
|
||||
QUANTA_HWMON_REG_FAN_PWM_BASE
|
||||
+ 2 * attr->index, val * 10000 / 255);
|
||||
mutex_unlock(&data->lock);
|
||||
return count;
|
||||
}
|
||||
|
||||
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
|
||||
static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);//For LY9
|
||||
static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4);
|
||||
static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp, NULL, 5);
|
||||
static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
|
||||
static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
|
||||
static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
|
||||
static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4);
|
||||
static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 5);
|
||||
static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 6);
|
||||
static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0);
|
||||
|
||||
static struct attribute *quanta_hwmon_attr[] = {
|
||||
&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_temp5_input.dev_attr.attr,
|
||||
&sensor_dev_attr_temp6_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan5_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan6_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan7_input.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm1.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute *quanta_hwmon_attr_6temps_3fans[] = {
|
||||
&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_temp6_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan1_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan2_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan3_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan5_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan6_input.dev_attr.attr,
|
||||
&sensor_dev_attr_fan7_input.dev_attr.attr,
|
||||
&sensor_dev_attr_pwm1.dev_attr.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int quanta_hwmon_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct quanta_hwmon_data *data;
|
||||
int err;
|
||||
|
||||
data = devm_kzalloc(&client->dev, sizeof(struct quanta_hwmon_data),
|
||||
GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->lock);
|
||||
|
||||
dev_info(&client->dev, "%s chip found\n", client->name);
|
||||
|
||||
if(!strcmp(client->name, "quanta_ly9_hwmon")){
|
||||
data->attrs.attrs = quanta_hwmon_attr_6temps_3fans;
|
||||
}
|
||||
else{
|
||||
data->attrs.attrs = quanta_hwmon_attr;
|
||||
}
|
||||
err = sysfs_create_group(&client->dev.kobj, &data->attrs);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
||||
if (IS_ERR(data->hwmon_dev)) {
|
||||
err = PTR_ERR(data->hwmon_dev);
|
||||
goto exit_remove;
|
||||
}
|
||||
|
||||
i2c_smbus_write_byte_data(client,
|
||||
QUANTA_HWMON_REG_FAN_MODE,
|
||||
QUANTA_HWMON_FAN_SMART_MODE);
|
||||
|
||||
return 0;
|
||||
|
||||
exit_remove:
|
||||
sysfs_remove_group(&client->dev.kobj, &data->attrs);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int quanta_hwmon_remove(struct i2c_client *client)
|
||||
{
|
||||
struct quanta_hwmon_data *data = i2c_get_clientdata(client);
|
||||
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, &data->attrs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_i2c_driver(quanta_hwmon_driver);
|
||||
|
||||
MODULE_AUTHOR("QCT Technical <support@quantaqct.com>");
|
||||
MODULE_DESCRIPTION("Quanta LY6 hardware monitor driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
499
packages/platforms/quanta/x86-64/modules/builds/quanta_switch.c
Normal file
499
packages/platforms/quanta/x86-64/modules/builds/quanta_switch.c
Normal file
@@ -0,0 +1,499 @@
|
||||
/*
|
||||
* Quanta Switch platform driver
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2014 Quanta Computer inc.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/platform_data/pca953x.h>
|
||||
#include <linux/i2c/pca954x.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <linux/i2c-mux-gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dmi.h>
|
||||
|
||||
#define DRIVER_NAME "quanta-switch"
|
||||
#define VENDOR_NAME "Quanta"
|
||||
#define PRODUCT_NAME_LY6 "Quanta LY6"
|
||||
#define PRODUCT_NAME_LY8 "Quanta LY8"
|
||||
#define PRODUCT_NAME_LY9 "Quanta LY9"
|
||||
|
||||
#define MAX_I2C_CLIENTS 512
|
||||
#define I2C_GPIO_BASE 0x80
|
||||
#define XSTR(x) STR(X)
|
||||
#define STR(x) #x
|
||||
|
||||
enum i2c_types {
|
||||
i2c_type_spd,
|
||||
i2c_type_rtc,
|
||||
i2c_type_pca9546,
|
||||
i2c_type_pca9548,
|
||||
i2c_type_pca9554,
|
||||
i2c_type_pca9555,
|
||||
i2c_type_pca9698,
|
||||
i2c_type_quanta_ly6_i2c_mux,
|
||||
i2c_type_qci_cpld_4_ports,
|
||||
i2c_type_24c02,
|
||||
i2c_type_pmbus,
|
||||
i2c_type_emerson700,
|
||||
i2c_type_quanta_ly6_hwmon,
|
||||
i2c_type_quanta_ly8_hwmon,
|
||||
i2c_type_quanta_ly9_hwmon,
|
||||
};
|
||||
|
||||
char *i2c_type_names[] = {
|
||||
"spd",
|
||||
"ds1339",
|
||||
"pca9546",
|
||||
"pca9548",
|
||||
"pca9554",
|
||||
"pca9555",
|
||||
"pca9698",
|
||||
"quanta_ly6_i2c_mux",
|
||||
"CPLD-QSFP",
|
||||
"24c02",
|
||||
"pmbus",
|
||||
"emerson700",
|
||||
"quanta_ly6_hwmon",
|
||||
"quanta_ly8_hwmon",
|
||||
"quanta_ly9_hwmon",
|
||||
};
|
||||
|
||||
struct i2c_init_data {
|
||||
int parent_bus;
|
||||
int type;
|
||||
int addr;
|
||||
int busno;
|
||||
int gpio_base;
|
||||
char name[I2C_NAME_SIZE];
|
||||
};
|
||||
|
||||
static struct i2c_init_data quanta_ly6_i2c_init_data[] = {
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_pca9546, .addr = 0x71, .busno = 0x02, .name = "PCA9546(CPU)\0" },
|
||||
{ .parent_bus = (0x02 + 0), .type = i2c_type_pca9555, .addr = 0x20, .gpio_base = 0x40, .name = "PCA9555_1(CPU)\0" },
|
||||
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_quanta_ly6_hwmon, .addr = 0x4e, .name = "PSoc\0" },
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_spd, .addr = 0x52, .name = "SPD\0" },
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_rtc, .addr = 0x68, .name = "RTC\0" },
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_pca9548, .addr = 0x77, .busno = 0x10, .name = "PCA9548_1\0" },
|
||||
|
||||
{ .parent_bus = (0x10 + 0), .type = i2c_type_pca9548, .addr = 0x73, .busno = 0x20, .name = "PCA9548(SFP_1-8)\0" },
|
||||
{ .parent_bus = (0x10 + 1), .type = i2c_type_pca9548, .addr = 0x74, .busno = 0x28, .name = "PCA9548(SFP_9-16)\0" },
|
||||
{ .parent_bus = (0x10 + 2), .type = i2c_type_pca9548, .addr = 0x75, .busno = 0x30, .name = "PCA9548(SFP_17-24)\0" },
|
||||
{ .parent_bus = (0x10 + 3), .type = i2c_type_pca9548, .addr = 0x76, .busno = 0x38, .name = "PCA9548(SFP_25-32)\0" },
|
||||
{ .parent_bus = (0x10 + 4), .type = i2c_type_quanta_ly6_i2c_mux, .addr = 0x3a, .name = "quanta_ly6_i2c_mux1\0" },
|
||||
{ .parent_bus = (0x10 + 5), .type = i2c_type_quanta_ly6_i2c_mux, .addr = 0x3b, .name = "quanta_ly6_i2c_mux2\0" },
|
||||
{ .parent_bus = (0x10 + 6), .type = i2c_type_pca9555, .addr = 0x24, .name = "PCA9555_3(FAN)\0" },
|
||||
{ .parent_bus = (0x10 + 7), .type = i2c_type_pca9555, .addr = 0x23, .name = "PCA9555_4(QSFP_EN)\0" },
|
||||
{ .parent_bus = (0x20 + 0), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_1_EEPROM\0" },
|
||||
{ .parent_bus = (0x20 + 1), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_2_EEPROM\0" },
|
||||
{ .parent_bus = (0x20 + 2), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_3_EEPROM\0" },
|
||||
{ .parent_bus = (0x20 + 3), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_4_EEPROM\0" },
|
||||
{ .parent_bus = (0x20 + 4), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_5_EEPROM\0" },
|
||||
{ .parent_bus = (0x20 + 5), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_6_EEPROM\0" },
|
||||
{ .parent_bus = (0x20 + 6), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_7_EEPROM\0" },
|
||||
{ .parent_bus = (0x20 + 7), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_8_EEPROM\0" },
|
||||
{ .parent_bus = (0x28 + 0), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_9_EEPROM\0" },
|
||||
{ .parent_bus = (0x28 + 1), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_10_EEPROM\0" },
|
||||
{ .parent_bus = (0x28 + 2), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_11_EEPROM\0" },
|
||||
{ .parent_bus = (0x28 + 3), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_12_EEPROM\0" },
|
||||
{ .parent_bus = (0x28 + 4), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_13_EEPROM\0" },
|
||||
{ .parent_bus = (0x28 + 5), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_14_EEPROM\0" },
|
||||
{ .parent_bus = (0x28 + 6), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_15_EEPROM\0" },
|
||||
{ .parent_bus = (0x28 + 7), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_16_EEPROM\0" },
|
||||
{ .parent_bus = (0x30 + 0), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_17_EEPROM\0" },
|
||||
{ .parent_bus = (0x30 + 1), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_18_EEPROM\0" },
|
||||
{ .parent_bus = (0x30 + 2), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_19_EEPROM\0" },
|
||||
{ .parent_bus = (0x30 + 3), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_20_EEPROM\0" },
|
||||
{ .parent_bus = (0x30 + 4), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_21_EEPROM\0" },
|
||||
{ .parent_bus = (0x30 + 5), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_22_EEPROM\0" },
|
||||
{ .parent_bus = (0x30 + 6), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_23_EEPROM\0" },
|
||||
{ .parent_bus = (0x30 + 7), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_24_EEPROM\0" },
|
||||
{ .parent_bus = (0x38 + 0), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_25_EEPROM\0" },
|
||||
{ .parent_bus = (0x38 + 1), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_26_EEPROM\0" },
|
||||
{ .parent_bus = (0x38 + 2), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_27_EEPROM\0" },
|
||||
{ .parent_bus = (0x38 + 3), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_28_EEPROM\0" },
|
||||
{ .parent_bus = (0x38 + 4), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_29_EEPROM\0" },
|
||||
{ .parent_bus = (0x38 + 5), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_30_EEPROM\0" },
|
||||
{ .parent_bus = (0x38 + 6), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_31_EEPROM\0" },
|
||||
{ .parent_bus = (0x38 + 7), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_32_EEPROM\0" },
|
||||
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_pca9546, .addr = 0x72, .busno = 0x18, .name = "PCA9546\0" },
|
||||
{ .parent_bus = (0x18 + 0), .type = i2c_type_pmbus, .addr = 0x58, .name = "PSU_1\0" }, /* RPSU 1 */
|
||||
{ .parent_bus = (0x18 + 1), .type = i2c_type_pmbus, .addr = 0x59, .name = "PSU_2\0" }, /* RPSU 2 */
|
||||
{ .parent_bus = (0x18 + 2), .type = i2c_type_pca9555, .addr = 0x26, .name = "PCA9555_PSU\0" },
|
||||
{ .parent_bus = (0x18 + 3), .type = i2c_type_24c02, .addr = 0x54, .name = "Board_EEPROM\0" },
|
||||
};
|
||||
|
||||
static struct i2c_init_data quanta_ly8_i2c_init_data[] = {
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_pca9546, .addr = 0x71, .busno = 0x02, .name = "PCA9546(CPU)\0" },
|
||||
{ .parent_bus = (0x02 + 0), .type = i2c_type_pca9555, .addr = 0x20, .gpio_base = 0x40, .name = "PCA9555_1(CPU)\0" },
|
||||
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_quanta_ly8_hwmon, .addr = 0x4e, .name = "PSoc\0" },
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_spd, .addr = 0x52, .name = "SPD\0" },
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_rtc, .addr = 0x68, .name = "RTC\0" },
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_pca9548, .addr = 0x77, .busno = 0x10, .name = "PCA9548_1\0" },
|
||||
|
||||
{ .parent_bus = (0x10 + 1), .type = i2c_type_pca9548, .addr = 0x73, .busno = 0x20, .name = "PCA9548(SFP_1-8)\0" },
|
||||
{ .parent_bus = (0x10 + 1), .type = i2c_type_pca9548, .addr = 0x74, .busno = 0x28, .name = "PCA9548(SFP_9-16)\0" },
|
||||
{ .parent_bus = (0x10 + 1), .type = i2c_type_pca9548, .addr = 0x76, .busno = 0x30, .name = "PCA9548(SFP_17-24)\0" },
|
||||
{ .parent_bus = (0x10 + 2), .type = i2c_type_pca9548, .addr = 0x73, .busno = 0x38, .name = "PCA9548(SFP_25-32)\0" },
|
||||
{ .parent_bus = (0x10 + 2), .type = i2c_type_pca9548, .addr = 0x74, .busno = 0x40, .name = "PCA9548(SFP_33-40)\0" },
|
||||
{ .parent_bus = (0x10 + 2), .type = i2c_type_pca9548, .addr = 0x75, .busno = 0x48, .name = "PCA9548(SFP_41-48)\0" },
|
||||
{ .parent_bus = (0x10 + 0), .type = i2c_type_pca9554, .addr = 0x25, .name = "PCA9554(PCA9698INT)\0" },
|
||||
{ .parent_bus = (0x10 + 0), .type = i2c_type_pca9555, .addr = 0x24, .name = "PCA9555_3(FAN)\0" },
|
||||
{ .parent_bus = (0x10 + 0), .type = i2c_type_pca9555, .addr = 0x23, .name = "PCA9555_4(QSFP_EN)\0" },
|
||||
{ .parent_bus = (0x20 + 0), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_1_EEPROM\0" },
|
||||
{ .parent_bus = (0x20 + 1), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_2_EEPROM\0" },
|
||||
{ .parent_bus = (0x20 + 2), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_3_EEPROM\0" },
|
||||
{ .parent_bus = (0x20 + 3), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_4_EEPROM\0" },
|
||||
{ .parent_bus = (0x20 + 4), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_5_EEPROM\0" },
|
||||
{ .parent_bus = (0x20 + 5), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_6_EEPROM\0" },
|
||||
{ .parent_bus = (0x20 + 6), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_7_EEPROM\0" },
|
||||
{ .parent_bus = (0x20 + 7), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_8_EEPROM\0" },
|
||||
{ .parent_bus = (0x28 + 0), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_9_EEPROM\0" },
|
||||
{ .parent_bus = (0x28 + 1), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_10_EEPROM\0" },
|
||||
{ .parent_bus = (0x28 + 2), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_11_EEPROM\0" },
|
||||
{ .parent_bus = (0x28 + 3), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_12_EEPROM\0" },
|
||||
{ .parent_bus = (0x28 + 4), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_13_EEPROM\0" },
|
||||
{ .parent_bus = (0x28 + 5), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_14_EEPROM\0" },
|
||||
{ .parent_bus = (0x28 + 6), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_15_EEPROM\0" },
|
||||
{ .parent_bus = (0x28 + 7), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_16_EEPROM\0" },
|
||||
{ .parent_bus = (0x30 + 0), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_17_EEPROM\0" },
|
||||
{ .parent_bus = (0x30 + 1), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_18_EEPROM\0" },
|
||||
{ .parent_bus = (0x30 + 2), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_19_EEPROM\0" },
|
||||
{ .parent_bus = (0x30 + 3), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_20_EEPROM\0" },
|
||||
{ .parent_bus = (0x30 + 4), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_21_EEPROM\0" },
|
||||
{ .parent_bus = (0x30 + 5), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_22_EEPROM\0" },
|
||||
{ .parent_bus = (0x30 + 6), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_23_EEPROM\0" },
|
||||
{ .parent_bus = (0x30 + 7), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_24_EEPROM\0" },
|
||||
{ .parent_bus = (0x38 + 0), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_25_EEPROM\0" },
|
||||
{ .parent_bus = (0x38 + 1), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_26_EEPROM\0" },
|
||||
{ .parent_bus = (0x38 + 2), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_27_EEPROM\0" },
|
||||
{ .parent_bus = (0x38 + 3), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_28_EEPROM\0" },
|
||||
{ .parent_bus = (0x38 + 4), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_29_EEPROM\0" },
|
||||
{ .parent_bus = (0x38 + 5), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_30_EEPROM\0" },
|
||||
{ .parent_bus = (0x38 + 6), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_31_EEPROM\0" },
|
||||
{ .parent_bus = (0x38 + 7), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_32_EEPROM\0" },
|
||||
{ .parent_bus = (0x40 + 0), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_33_EEPROM\0" },
|
||||
{ .parent_bus = (0x40 + 1), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_34_EEPROM\0" },
|
||||
{ .parent_bus = (0x40 + 2), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_35_EEPROM\0" },
|
||||
{ .parent_bus = (0x40 + 3), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_36_EEPROM\0" },
|
||||
{ .parent_bus = (0x40 + 4), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_37_EEPROM\0" },
|
||||
{ .parent_bus = (0x40 + 5), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_38_EEPROM\0" },
|
||||
{ .parent_bus = (0x40 + 6), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_39_EEPROM\0" },
|
||||
{ .parent_bus = (0x40 + 7), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_40_EEPROM\0" },
|
||||
{ .parent_bus = (0x48 + 0), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_41_EEPROM\0" },
|
||||
{ .parent_bus = (0x48 + 1), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_42_EEPROM\0" },
|
||||
{ .parent_bus = (0x48 + 2), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_43_EEPROM\0" },
|
||||
{ .parent_bus = (0x48 + 3), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_44_EEPROM\0" },
|
||||
{ .parent_bus = (0x48 + 4), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_45_EEPROM\0" },
|
||||
{ .parent_bus = (0x48 + 5), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_46_EEPROM\0" },
|
||||
{ .parent_bus = (0x48 + 6), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_47_EEPROM\0" },
|
||||
{ .parent_bus = (0x48 + 7), .type = i2c_type_24c02, .addr = 0x50, .name = "SFP_48_EEPROM\0" },
|
||||
|
||||
{ .parent_bus = (0x10 + 3), .type = i2c_type_pca9698, .addr = 0x23, .name = "PCA9698(SFP_1-8)\0" },
|
||||
{ .parent_bus = (0x10 + 3), .type = i2c_type_pca9698, .addr = 0x21, .name = "PCA9698(SFP_9-16)\0" },
|
||||
{ .parent_bus = (0x10 + 3), .type = i2c_type_pca9698, .addr = 0x22, .name = "PCA9698(SFP_17-24)\0" },
|
||||
{ .parent_bus = (0x10 + 4), .type = i2c_type_pca9698, .addr = 0x23, .name = "PCA9698(SFP_25-32)\0" },
|
||||
{ .parent_bus = (0x10 + 4), .type = i2c_type_pca9698, .addr = 0x24, .name = "PCA9698(SFP_33-40)\0" },
|
||||
{ .parent_bus = (0x10 + 4), .type = i2c_type_pca9698, .addr = 0x25, .name = "PCA9698(SFP_41-48)\0" },
|
||||
|
||||
{ .parent_bus = (0x10 + 5), .type = i2c_type_pca9548, .addr = 0x76, .busno = 0x50, .name = "PCA9548_8\0" },
|
||||
{ .parent_bus = (0x50 + 0), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_1_EEPROM\0" },
|
||||
{ .parent_bus = (0x50 + 1), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_2_EEPROM\0" },
|
||||
{ .parent_bus = (0x50 + 2), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_3_EEPROM\0" },
|
||||
{ .parent_bus = (0x50 + 3), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_4_EEPROM\0" },
|
||||
|
||||
{ .parent_bus = (0x10 + 5), .type = i2c_type_pca9555, .addr = 0x24, .name = "PCA9555_1(LED)\0" },
|
||||
{ .parent_bus = (0x10 + 6), .type = i2c_type_pca9555, .addr = 0x23, .name = "PCA9555_2(QSFP)\0" },
|
||||
|
||||
/* QSFP+ DB */
|
||||
{ .parent_bus = (0x10 + 7), .type = i2c_type_pca9555, .addr = 0x23, .name = "PCA9555(QDB)\0" },
|
||||
{ .parent_bus = (0x10 + 7), .type = i2c_type_pca9546, .addr = 0x76, .busno = 0x58, .name = "PCA9546(QDB)\0" },
|
||||
{ .parent_bus = (0x58 + 0), .type = i2c_type_24c02, .addr = 0x50, .name = "QDB_QSFP_1_EEPROM\0" },
|
||||
{ .parent_bus = (0x58 + 1), .type = i2c_type_24c02, .addr = 0x50, .name = "QDB_QSFP_2_EEPROM\0" },
|
||||
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_pca9546, .addr = 0x72, .busno = 0x18, .name = "PCA9546\0" },
|
||||
{ .parent_bus = (0x18 + 0), .type = i2c_type_emerson700, .addr = 0x6f, .name = "PSU_1\0" }, /* RPSU 1 */
|
||||
{ .parent_bus = (0x18 + 1), .type = i2c_type_emerson700, .addr = 0x69, .name = "PSU_2\0" }, /* RPSU 2 */
|
||||
{ .parent_bus = (0x18 + 2), .type = i2c_type_pca9555, .addr = 0x26, .name = "PCA9555_5(PSU)\0" },
|
||||
{ .parent_bus = (0x18 + 3), .type = i2c_type_24c02, .addr = 0x54, .name = "Board_EEPROM\0" },
|
||||
};
|
||||
|
||||
static struct i2c_init_data quanta_ly9_i2c_init_data[] = {
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_pca9546, .addr = 0x71, .busno = 0x02, .name = "PCA9546(CPU)\0" },
|
||||
{ .parent_bus = (0x02 + 0), .type = i2c_type_pca9555, .addr = 0x20, .gpio_base = 0x40, .name = "PCA9555_1(CPU)\0" },
|
||||
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_quanta_ly9_hwmon, .addr = 0x4e, .name = "PSoc\0" },
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_spd, .addr = 0x52, .name = "SPD\0" },
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_rtc, .addr = 0x68, .name = "RTC\0" },
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_pca9548, .addr = 0x77, .busno = 0x10, .name = "PCA9548APW1\0" },
|
||||
|
||||
{ .parent_bus = (0x10 + 5), .type = i2c_type_pca9548, .addr = 0x76, .busno = 0x20, .name = "PCA9548APW2\0" },
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_qci_cpld_4_ports, .addr = 0x3a, .name = "quanta_ly9_cpld\0" },
|
||||
{ .parent_bus = (0x10 + 0), .type = i2c_type_pca9555, .addr = 0x24, .name = "PCA9555_3(FAN)\0" },
|
||||
{ .parent_bus = (0x10 + 0), .type = i2c_type_pca9555, .addr = 0x23, .name = "PCA9555_4(QSFP_EN)\0" },
|
||||
{ .parent_bus = (0x20 + 0), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_49_EEPROM\0" },
|
||||
{ .parent_bus = (0x20 + 1), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_50_EEPROM\0" },
|
||||
{ .parent_bus = (0x20 + 2), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_51_EEPROM\0" },
|
||||
{ .parent_bus = (0x20 + 3), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_52_EEPROM\0" },
|
||||
|
||||
/* QSFP+ DB */
|
||||
{ .parent_bus = (0x10 + 7), .type = i2c_type_pca9555, .addr = 0x23, .name = "PCA9555(QDB)\0" },
|
||||
{ .parent_bus = (0x10 + 7), .type = i2c_type_pca9546, .addr = 0x76, .busno = 0x30, .name = "PCA9546(QDB)\0" },
|
||||
{ .parent_bus = (0x30 + 0), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_53_EEPROM\0" },
|
||||
{ .parent_bus = (0x30 + 1), .type = i2c_type_24c02, .addr = 0x50, .name = "QSFP_54_EEPROM\0" },
|
||||
|
||||
{ .parent_bus = (0x00 + 0), .type = i2c_type_pca9546, .addr = 0x72, .busno = 0x18, .name = "PCA9546\0" },
|
||||
{ .parent_bus = (0x18 + 0), .type = i2c_type_emerson700, .addr = 0x6f, .name = "PSU_1\0" }, /* RPSU 1 */
|
||||
{ .parent_bus = (0x18 + 1), .type = i2c_type_emerson700, .addr = 0x69, .name = "PSU_2\0" }, /* RPSU 2 */
|
||||
{ .parent_bus = (0x18 + 2), .type = i2c_type_pca9555, .addr = 0x26, .name = "PCA9555_1(PSU)\0" },
|
||||
{ .parent_bus = (0x18 + 3), .type = i2c_type_24c02, .addr = 0x54, .name = "Board_EEPROM\0" },
|
||||
};
|
||||
static inline struct pca954x_platform_data *pca954x_platform_data_get(int type, int busno) {
|
||||
static struct pca954x_platform_mode platform_modes[8];
|
||||
static struct pca954x_platform_data platform_data;
|
||||
int num_modes, i;
|
||||
|
||||
switch(type) {
|
||||
case i2c_type_pca9546:
|
||||
num_modes = 4;
|
||||
break;
|
||||
|
||||
case i2c_type_pca9548:
|
||||
num_modes = 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
return (struct pca954x_platform_data *) NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
for(i=0;i<num_modes;i++) {
|
||||
platform_modes[i] = (struct pca954x_platform_mode) {
|
||||
.adap_id = (busno + i),
|
||||
.deselect_on_exit = 1,
|
||||
};
|
||||
}
|
||||
|
||||
platform_data = (struct pca954x_platform_data) {
|
||||
.modes = platform_modes,
|
||||
.num_modes = num_modes,
|
||||
};
|
||||
|
||||
return &platform_data;
|
||||
}
|
||||
|
||||
static int base_gpio_num = I2C_GPIO_BASE;
|
||||
static inline struct pca953x_platform_data *pca953x_platform_data_get(int type, int gpio_base) {
|
||||
static struct pca953x_platform_data platform_data;
|
||||
int num_gpios, num_gpio;
|
||||
|
||||
switch(type) {
|
||||
case i2c_type_pca9554:
|
||||
num_gpios = 0x8;
|
||||
break;
|
||||
|
||||
case i2c_type_pca9555:
|
||||
num_gpios = 0x10;
|
||||
break;
|
||||
|
||||
case i2c_type_pca9698:
|
||||
num_gpios = 0x28;
|
||||
break;
|
||||
|
||||
case i2c_type_quanta_ly6_i2c_mux:
|
||||
num_gpios = 0x40;
|
||||
break;
|
||||
|
||||
default:
|
||||
return (struct pca953x_platform_data *) NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if(gpio_base == 0) {
|
||||
num_gpio = base_gpio_num;
|
||||
base_gpio_num += num_gpios;
|
||||
}
|
||||
else {
|
||||
num_gpio = gpio_base;
|
||||
}
|
||||
|
||||
platform_data = (struct pca953x_platform_data) {
|
||||
.gpio_base = num_gpio,
|
||||
};
|
||||
|
||||
return &platform_data;
|
||||
}
|
||||
|
||||
static inline struct i2c_board_info *i2c_board_info_get(struct i2c_init_data data) {
|
||||
struct pca954x_platform_data *mux_platform_data;
|
||||
struct pca953x_platform_data *gpio_platform_data;
|
||||
static struct i2c_board_info board_info;
|
||||
|
||||
switch(data.type) {
|
||||
case i2c_type_pca9546:
|
||||
case i2c_type_pca9548:
|
||||
mux_platform_data = pca954x_platform_data_get(data.type, data.busno);
|
||||
if(mux_platform_data == NULL) {
|
||||
return (struct i2c_board_info *) NULL;
|
||||
}
|
||||
|
||||
board_info = (struct i2c_board_info) {
|
||||
.platform_data = mux_platform_data,
|
||||
};
|
||||
break;
|
||||
|
||||
case i2c_type_pca9554:
|
||||
case i2c_type_pca9555:
|
||||
case i2c_type_pca9698:
|
||||
case i2c_type_quanta_ly6_i2c_mux:
|
||||
gpio_platform_data = pca953x_platform_data_get(data.type, data.gpio_base);
|
||||
if(gpio_platform_data == NULL) {
|
||||
return (struct i2c_board_info *) NULL;
|
||||
}
|
||||
|
||||
board_info = (struct i2c_board_info) {
|
||||
.platform_data = gpio_platform_data,
|
||||
};
|
||||
break;
|
||||
|
||||
case i2c_type_rtc:
|
||||
case i2c_type_spd:
|
||||
case i2c_type_24c02:
|
||||
case i2c_type_pmbus:
|
||||
case i2c_type_emerson700:
|
||||
case i2c_type_quanta_ly6_hwmon:
|
||||
case i2c_type_quanta_ly8_hwmon:
|
||||
case i2c_type_quanta_ly9_hwmon:
|
||||
case i2c_type_qci_cpld_4_ports:
|
||||
board_info = (struct i2c_board_info) {
|
||||
.platform_data = (void *) NULL,
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
return (struct i2c_board_info *) NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
board_info.addr = data.addr;
|
||||
strcpy(board_info.type, i2c_type_names[data.type]);
|
||||
|
||||
return &board_info;
|
||||
}
|
||||
|
||||
static struct platform_driver quanta_switch_platform_driver = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static struct i2c_init_data *init_data;
|
||||
static int init_data_size;
|
||||
static struct i2c_client *registered_i2c_clients[MAX_I2C_CLIENTS];
|
||||
|
||||
static char* platform = "None.";
|
||||
module_param(platform, charp, 0000);
|
||||
MODULE_PARM_DESC(platform, "Set platform.");
|
||||
|
||||
|
||||
static int __init quanta_switch_init(void)
|
||||
{
|
||||
char const *vendor, *product;
|
||||
struct i2c_adapter *adapter;
|
||||
struct i2c_board_info *board_info;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
vendor = dmi_get_system_info(DMI_SYS_VENDOR);
|
||||
product = dmi_get_system_info(DMI_PRODUCT_NAME);
|
||||
|
||||
if((!strcmp(vendor, VENDOR_NAME) &&
|
||||
(strstr(product, PRODUCT_NAME_LY6) != NULL)) ||
|
||||
(!strcmp(platform, "x86-64-quanta-ly6-rangeley"))) {
|
||||
init_data = quanta_ly6_i2c_init_data;
|
||||
init_data_size = ARRAY_SIZE(quanta_ly6_i2c_init_data);
|
||||
}
|
||||
else if((!strcmp(vendor, VENDOR_NAME) &&
|
||||
(strstr(product, PRODUCT_NAME_LY8) != NULL)) ||
|
||||
(!strcmp(platform, "x86-64-quanta-ly8-rangeley"))) {
|
||||
init_data = quanta_ly8_i2c_init_data;
|
||||
init_data_size = ARRAY_SIZE(quanta_ly8_i2c_init_data);
|
||||
}
|
||||
else if((!strcmp(vendor, VENDOR_NAME) &&
|
||||
(strstr(product, PRODUCT_NAME_LY9) != NULL)) ||
|
||||
(!strcmp(platform, "x86-64-quanta-ly9-rangeley"))) {
|
||||
init_data = quanta_ly9_i2c_init_data;
|
||||
init_data_size = ARRAY_SIZE(quanta_ly9_i2c_init_data);
|
||||
}
|
||||
else {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = platform_driver_register(&quanta_switch_platform_driver);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/**
|
||||
* Register I2C devices on new buses
|
||||
*/
|
||||
for(i = 0; i < init_data_size; i++) {
|
||||
adapter = i2c_get_adapter(init_data[i].parent_bus);
|
||||
board_info = i2c_board_info_get(init_data[i]);
|
||||
pr_info("register i2c_new_device\n\t%s for bus 0x%x:0x%x. ",
|
||||
init_data[i].name, init_data[i].parent_bus, init_data[i].addr);
|
||||
if((registered_i2c_clients[i] = i2c_new_device(adapter, board_info)) == NULL) {
|
||||
pr_err("%s: i2c_new_device for bus 0x%x:0x%x failed.",
|
||||
__FUNCTION__, init_data[i].parent_bus, init_data[i].addr);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit quanta_switch_cleanup(void)
|
||||
{
|
||||
int i;
|
||||
/**
|
||||
* Unregister I2C devices
|
||||
*/
|
||||
for(i = 0; i < init_data_size; i++) {
|
||||
if(registered_i2c_clients[i] != NULL) {
|
||||
i2c_unregister_device(registered_i2c_clients[init_data_size-(i+1)]);
|
||||
}
|
||||
}
|
||||
platform_driver_unregister(&quanta_switch_platform_driver);
|
||||
}
|
||||
|
||||
module_init(quanta_switch_init);
|
||||
module_exit(quanta_switch_cleanup);
|
||||
|
||||
MODULE_AUTHOR("Audi Hsu (audi.hsu@quantatw.com)");
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_DESCRIPTION("Quanta Switch");
|
||||
MODULE_LICENSE("GPL");
|
||||
Reference in New Issue
Block a user