940aaa0cbe
Fix #8068 Update Innovium configs on Cameo and Wistron platforms
383 lines
11 KiB
C
383 lines
11 KiB
C
/* An hwmon driver for Cameo ESC600-128Q Innovium i2c Module */
|
|
#pragma GCC diagnostic ignored "-Wformat-zero-length"
|
|
#include "x86-64-cameo-esc600-128q.h"
|
|
#include "x86-64-cameo-esc600-128q-common.h"
|
|
|
|
/* Addresses scanned */
|
|
static const unsigned short normal_i2c[] = { 0x30, 0x31, 0x32, I2C_CLIENT_END };
|
|
static int debug = 0;
|
|
|
|
|
|
/* i2c_client Declaration */
|
|
struct i2c_client *Cameo_CPLD_30_client; //0x30 CPLD ,XO2-2000HC-4FTG256C
|
|
struct i2c_client *Cameo_CPLD_31_client; //0x31 CPLD ,XO2-7000HC-4TG144C
|
|
struct i2c_client *Cameo_CPLD_33_client; //0x33 I/O Board CPLD ,XO2-640
|
|
struct i2c_client *Cameo_CPLD_35_client; //0x35 CPLD ,XO2-2000HC-4FTG256C
|
|
struct i2c_client *Cameo_Extpand_20_client; //0x20 I/O Extpander ,PCA9534PW
|
|
struct i2c_client *Cameo_Extpand_21_client; //0x21 I/O Extpander ,PCA9534PW
|
|
struct i2c_client *Cameo_BMC_14_client; //0x14 BMC ,Aspeed
|
|
/* end of i2c_client Declaration */
|
|
|
|
/* register offset define */
|
|
#define BMC_EN_REG 0xA3
|
|
/* end of register offset define */
|
|
|
|
/* common function */
|
|
int bmc_enable(void)
|
|
{
|
|
if ((i2c_smbus_read_byte_data(Cameo_CPLD_31_client, BMC_EN_REG) & BIT_0_MASK) == 0x01)
|
|
{
|
|
return ENABLE;
|
|
}
|
|
else
|
|
{
|
|
return DISABLE;
|
|
}
|
|
}
|
|
|
|
int read_8bit_temp(u8 sign,u8 value)
|
|
{
|
|
int result = 0;
|
|
if(sign)
|
|
{
|
|
//printf("read_8bit_temp UP %d\n", value & 0x80);
|
|
value = ~(value)+1;
|
|
result = value;
|
|
return result;
|
|
}
|
|
else
|
|
{
|
|
//printf("read_8bit_temp DOWN %d\n", value & 0x80);
|
|
result = value;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/* end of common function*/
|
|
|
|
static int Cameo_i2c_probe(struct i2c_client *client, const struct i2c_device_id *dev_id)
|
|
{
|
|
struct Cameo_i2c_data *Cameo_CPLD_30_data; //0x30 CPLD ,XO2-2000HC-4FTG256C
|
|
struct Cameo_i2c_data *Cameo_CPLD_31_data; //0x31 CPLD ,XO2-7000HC-4TG144C
|
|
struct Cameo_i2c_data *Cameo_CPLD_33_data; //0x33 I/O Board CPLD ,XO2-640
|
|
struct Cameo_i2c_data *Cameo_CPLD_35_data; //0x35 CPLD ,XO2-2000HC-4FTG256C
|
|
struct Cameo_i2c_data *Cameo_Extpand_20_data; //0x20 I/O Extpander ,PCA9534PW
|
|
struct Cameo_i2c_data *Cameo_Extpand_21_data; //0x21 I/O Extpander ,PCA9534PW
|
|
struct Cameo_i2c_data *Cameo_BMC_14_data; //0x14 BMC ,Aspeed
|
|
int status;
|
|
|
|
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
|
|
{
|
|
status = -EIO;
|
|
goto exit;
|
|
}
|
|
Cameo_CPLD_30_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL);
|
|
if (!Cameo_CPLD_30_data)
|
|
{
|
|
printk(KERN_ALERT "kzalloc fail\n");
|
|
status = -ENOMEM;
|
|
goto exit;
|
|
}
|
|
|
|
Cameo_CPLD_31_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL);
|
|
if (!Cameo_CPLD_31_data)
|
|
{
|
|
printk(KERN_ALERT "kzalloc fail\n");
|
|
status = -ENOMEM;
|
|
goto exit;
|
|
}
|
|
|
|
Cameo_CPLD_33_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL);
|
|
if (!Cameo_CPLD_33_data)
|
|
{
|
|
printk(KERN_ALERT "kzalloc fail\n");
|
|
status = -ENOMEM;
|
|
goto exit;
|
|
}
|
|
|
|
Cameo_CPLD_35_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL);
|
|
if (!Cameo_CPLD_35_data)
|
|
{
|
|
printk(KERN_ALERT "kzalloc fail\n");
|
|
status = -ENOMEM;
|
|
goto exit;
|
|
}
|
|
|
|
Cameo_Extpand_20_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL);
|
|
if (!Cameo_Extpand_20_data)
|
|
{
|
|
printk(KERN_ALERT "kzalloc fail\n");
|
|
status = -ENOMEM;
|
|
goto exit;
|
|
}
|
|
|
|
Cameo_Extpand_21_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL);
|
|
if (!Cameo_Extpand_21_data)
|
|
{
|
|
printk(KERN_ALERT "kzalloc fail\n");
|
|
status = -ENOMEM;
|
|
goto exit;
|
|
}
|
|
|
|
Cameo_BMC_14_data = kzalloc(sizeof(struct Cameo_i2c_data), GFP_KERNEL);
|
|
if (!Cameo_BMC_14_data)
|
|
{
|
|
printk(KERN_ALERT "kzalloc fail\n");
|
|
status = -ENOMEM;
|
|
goto exit;
|
|
}
|
|
|
|
i2c_set_clientdata(Cameo_CPLD_30_client, Cameo_CPLD_30_data);
|
|
i2c_set_clientdata(Cameo_CPLD_31_client, Cameo_CPLD_31_data);
|
|
i2c_set_clientdata(Cameo_CPLD_33_client, Cameo_CPLD_33_data);
|
|
i2c_set_clientdata(Cameo_CPLD_35_client, Cameo_CPLD_35_data);
|
|
i2c_set_clientdata(Cameo_Extpand_20_client, Cameo_Extpand_20_data);
|
|
i2c_set_clientdata(Cameo_Extpand_21_client, Cameo_Extpand_21_data);
|
|
i2c_set_clientdata(Cameo_BMC_14_client , Cameo_BMC_14_data);
|
|
|
|
mutex_init(&Cameo_CPLD_30_data->update_lock);
|
|
mutex_init(&Cameo_CPLD_31_data->update_lock);
|
|
mutex_init(&Cameo_CPLD_33_data->update_lock);
|
|
mutex_init(&Cameo_CPLD_35_data->update_lock);
|
|
mutex_init(&Cameo_Extpand_20_data->update_lock);
|
|
mutex_init(&Cameo_Extpand_21_data->update_lock);
|
|
mutex_init(&Cameo_BMC_14_data->update_lock);
|
|
|
|
Cameo_CPLD_30_data->valid = 0;
|
|
mutex_init(&Cameo_CPLD_30_data->update_lock);
|
|
dev_info(&client->dev, "chip found\n");
|
|
|
|
/* Register sysfs hooks */
|
|
status = sysfs_create_group(&client->dev.kobj, &ESC600_SYS_group);
|
|
if (status)
|
|
{
|
|
goto exit_free;
|
|
}
|
|
|
|
status = sysfs_create_group(&client->dev.kobj, &ESC600_LED_group);
|
|
if (status)
|
|
{
|
|
goto exit_free;
|
|
}
|
|
|
|
status = sysfs_create_group(&client->dev.kobj, &ESC600_FAN_group);
|
|
if (status)
|
|
{
|
|
goto exit_free;
|
|
}
|
|
|
|
status = sysfs_create_group(&client->dev.kobj, &ESC600_THERMAL_group);
|
|
if (status)
|
|
{
|
|
goto exit_free;
|
|
}
|
|
|
|
status = sysfs_create_group(&client->dev.kobj, &ESC600_POWER_group);
|
|
if (status)
|
|
{
|
|
goto exit_free;
|
|
}
|
|
|
|
Cameo_CPLD_30_data->hwmon_dev = hwmon_device_register(&client->dev);
|
|
if (IS_ERR(Cameo_CPLD_30_data->hwmon_dev))
|
|
{
|
|
status = PTR_ERR(Cameo_CPLD_30_data->hwmon_dev);
|
|
goto exit_remove;
|
|
}
|
|
dev_info(&client->dev, "%s: '%s'\n", dev_name(Cameo_CPLD_30_data->hwmon_dev), client->name);
|
|
return 0;
|
|
|
|
exit_remove:
|
|
sysfs_remove_group(&client->dev.kobj, &ESC600_SYS_group);
|
|
sysfs_remove_group(&client->dev.kobj, &ESC600_LED_group);
|
|
sysfs_remove_group(&client->dev.kobj, &ESC600_FAN_group);
|
|
sysfs_remove_group(&client->dev.kobj, &ESC600_THERMAL_group);
|
|
sysfs_remove_group(&client->dev.kobj, &ESC600_POWER_group);
|
|
|
|
exit_free:
|
|
kfree(Cameo_CPLD_30_data);
|
|
|
|
exit:
|
|
return status;
|
|
}
|
|
|
|
static int Cameo_i2c_remove(struct i2c_client *client)
|
|
{
|
|
struct Cameo_i2c_data *data = i2c_get_clientdata(client);
|
|
hwmon_device_unregister(data->hwmon_dev);
|
|
sysfs_remove_group(&client->dev.kobj, &ESC600_SYS_group);
|
|
sysfs_remove_group(&client->dev.kobj, &ESC600_LED_group);
|
|
sysfs_remove_group(&client->dev.kobj, &ESC600_FAN_group);
|
|
sysfs_remove_group(&client->dev.kobj, &ESC600_THERMAL_group);
|
|
sysfs_remove_group(&client->dev.kobj, &ESC600_POWER_group);
|
|
|
|
kfree(data);
|
|
return 0;
|
|
}
|
|
|
|
static const struct i2c_device_id Cameo_i2c_id[] =
|
|
{
|
|
{ "Cameo_CPLD_30", 0 },
|
|
{},
|
|
};
|
|
MODULE_DEVICE_TABLE(i2c, Cameo_i2c_id);
|
|
|
|
static struct i2c_driver Cameo_i2c_driver =
|
|
{
|
|
.class = I2C_CLASS_HWMON,
|
|
.driver =
|
|
{
|
|
.name = "ESC_600_i2c",
|
|
},
|
|
.probe = Cameo_i2c_probe,
|
|
.remove = Cameo_i2c_remove,
|
|
.id_table = Cameo_i2c_id,
|
|
.address_list = normal_i2c,
|
|
};
|
|
|
|
/*0x30 CPLD ,XO2-2000HC-4FTG256C*/
|
|
static struct i2c_board_info Cameo_CPLD_30_info[] __initdata =
|
|
{
|
|
{
|
|
I2C_BOARD_INFO("Cameo_CPLD_30", 0x30),
|
|
.platform_data = NULL,
|
|
},
|
|
};
|
|
|
|
/*0x31 CPLD ,XO2-7000HC-4TG144C*/
|
|
static struct i2c_board_info Cameo_CPLD_31_info[] __initdata =
|
|
{
|
|
{
|
|
I2C_BOARD_INFO("Cameo_CPLD_31", 0x31),
|
|
.platform_data = NULL,
|
|
},
|
|
};
|
|
/*0x33 I/O Board CPLD ,XO2-640*/
|
|
static struct i2c_board_info Cameo_CPLD_33_info[] __initdata =
|
|
{
|
|
{
|
|
I2C_BOARD_INFO("Cameo_CPLD_33", 0x33),
|
|
.platform_data = NULL,
|
|
},
|
|
};
|
|
/*0x35 CPLD ,XO2-2000HC-4FTG256C*/
|
|
static struct i2c_board_info Cameo_CPLD_35_info[] __initdata =
|
|
{
|
|
{
|
|
I2C_BOARD_INFO("Cameo_CPLD_35", 0x35),
|
|
.platform_data = NULL,
|
|
},
|
|
};
|
|
/*0x20 I/O Extpander ,PCA9534PW*/
|
|
static struct i2c_board_info Cameo_Extpand_20_info[] __initdata =
|
|
{
|
|
{
|
|
I2C_BOARD_INFO("Cameo_Extpand_20", 0x20),
|
|
.platform_data = NULL,
|
|
},
|
|
};
|
|
/*0x21 I/O Extpander ,PCA9534PW*/
|
|
static struct i2c_board_info Cameo_Extpand_21_info[] __initdata =
|
|
{
|
|
{
|
|
I2C_BOARD_INFO("Cameo_Extpand_21", 0x21),
|
|
.platform_data = NULL,
|
|
},
|
|
};
|
|
/*0x14 BMC ,Aspeed*/
|
|
static struct i2c_board_info Cameo_BMC_14_info[] __initdata =
|
|
{
|
|
{
|
|
I2C_BOARD_INFO("Cameo_BMC_14", 0x14),
|
|
.platform_data = NULL,
|
|
},
|
|
};
|
|
|
|
static int __init Cameo_i2c_init(void)
|
|
{
|
|
int ret;
|
|
int cmp;
|
|
char keyword[] = "SMBus I801";
|
|
char buf1[128];
|
|
struct i2c_adapter *i2c_adap;
|
|
struct file *fp;
|
|
mm_segment_t fs;
|
|
loff_t pos;
|
|
|
|
printk("Open file...\n");
|
|
fp = filp_open("/sys/class/i2c-dev/i2c-0/name", O_RDONLY , 0644);
|
|
if (IS_ERR(fp)) {
|
|
printk("Open file FAILED\n");
|
|
return -1;
|
|
}
|
|
|
|
fs = get_fs();
|
|
set_fs(KERNEL_DS);
|
|
pos = 0;
|
|
vfs_read(fp, buf1, sizeof(buf1), &pos);
|
|
printk("Detect %s\n", buf1);
|
|
cmp = strncmp(keyword, buf1, sizeof(keyword)-1);
|
|
set_fs(fs);
|
|
|
|
filp_close(fp, NULL);
|
|
|
|
if(cmp == 0)
|
|
{
|
|
i2c_adap = i2c_get_adapter(0);
|
|
printk("SMBus I801 is at bus 0\n");
|
|
}
|
|
else
|
|
{
|
|
i2c_adap = i2c_get_adapter(1);
|
|
printk("SMBus I801 is at bus 1\n");
|
|
}
|
|
|
|
if (i2c_adap == NULL)
|
|
{
|
|
printk("ERROR: i2c_get_adapter FAILED!\n");
|
|
return -1;
|
|
}
|
|
Cameo_CPLD_30_client = i2c_new_device(i2c_adap, &Cameo_CPLD_30_info[0]);
|
|
Cameo_CPLD_31_client = i2c_new_device(i2c_adap, &Cameo_CPLD_31_info[0]);
|
|
Cameo_CPLD_33_client = i2c_new_device(i2c_adap, &Cameo_CPLD_33_info[0]);
|
|
Cameo_CPLD_35_client = i2c_new_device(i2c_adap, &Cameo_CPLD_35_info[0]);
|
|
Cameo_Extpand_20_client = i2c_new_device(i2c_adap, &Cameo_Extpand_20_info[0]);
|
|
Cameo_Extpand_21_client = i2c_new_device(i2c_adap, &Cameo_Extpand_21_info[0]);
|
|
Cameo_BMC_14_client = i2c_new_device(i2c_adap, &Cameo_BMC_14_info[0]);
|
|
|
|
if (Cameo_CPLD_30_info == NULL || Cameo_CPLD_31_info == NULL || Cameo_CPLD_33_info == NULL
|
|
|| Cameo_CPLD_35_info == NULL || Cameo_Extpand_20_info == NULL || Cameo_Extpand_21_info == NULL || Cameo_BMC_14_info == NULL)
|
|
{
|
|
printk("ERROR: i2c_new_device FAILED!\n");
|
|
return -1;
|
|
}
|
|
|
|
i2c_put_adapter(i2c_adap);
|
|
ret = i2c_add_driver(&Cameo_i2c_driver);
|
|
printk(KERN_ALERT "ESC600-128Q i2c Driver Version: %s\n", DRIVER_VERSION);
|
|
printk(KERN_ALERT "ESC600-128Q i2c Driver INSTALL SUCCESS\n");
|
|
return ret;
|
|
}
|
|
|
|
static void __exit Cameo_i2c_exit(void)
|
|
{
|
|
i2c_unregister_device(Cameo_CPLD_30_client);
|
|
i2c_unregister_device(Cameo_CPLD_31_client);
|
|
i2c_unregister_device(Cameo_CPLD_33_client);
|
|
i2c_unregister_device(Cameo_CPLD_35_client);
|
|
i2c_unregister_device(Cameo_Extpand_20_client);
|
|
i2c_unregister_device(Cameo_Extpand_21_client);
|
|
i2c_unregister_device(Cameo_BMC_14_client);
|
|
i2c_del_driver(&Cameo_i2c_driver);
|
|
printk(KERN_ALERT "ESC600-128Q i2c Driver UNINSTALL SUCCESS\n");
|
|
}
|
|
|
|
MODULE_AUTHOR("Cameo Inc.");
|
|
MODULE_DESCRIPTION("Cameo ESC600-128Q i2c Driver");
|
|
MODULE_LICENSE("GPL");
|
|
module_param(debug, int, 0);
|
|
MODULE_PARM_DESC(debug, "Enable debugging (0-1)");
|
|
|
|
module_init(Cameo_i2c_init);
|
|
module_exit(Cameo_i2c_exit);
|