[pddf]: Adding S3IP supported attribute for FAN in PDDF (#15075)
The S3IP (Simplified Switch System INtegration Program) sysfs specification defines a unified interface to access peripheral hardware on devices from different vendors, making it easier for SONiC to support different devices and platforms. PDDF is a framework to simplify the driver and SONiC platform APIs development for new platforms. This effort is first step in combining the two frameworks. This specific PR adds S3IP supported sysfs attribute in common FAN driver of PDDF.
This commit is contained in:
parent
d6768b3259
commit
37eddd479d
@ -16,6 +16,8 @@
|
||||
* Description of various APIs related to FAN component
|
||||
*/
|
||||
|
||||
#define __STDC_WANT_LIB_EXT1__ 1
|
||||
#include <linux/string.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
@ -38,6 +40,22 @@
|
||||
|
||||
extern void *get_device_table(char *name);
|
||||
|
||||
uint32_t pddf_fan_dc_to_pwm_default(uint32_t dc)
|
||||
{
|
||||
return ((dc*100)/625 - 1);
|
||||
}
|
||||
|
||||
uint32_t pddf_fan_pwm_to_dc_default(uint32_t reg_val)
|
||||
{
|
||||
return ((uint32_t)(reg_val+1) * 625 + 75)/ 100;
|
||||
}
|
||||
|
||||
struct pddf_fan_ops_t pddf_fan_funcs = {
|
||||
.duty_cycle_to_reg_value = pddf_fan_dc_to_pwm_default,
|
||||
.reg_value_to_duty_cycle = pddf_fan_pwm_to_dc_default,
|
||||
};
|
||||
EXPORT_SYMBOL(pddf_fan_funcs);
|
||||
|
||||
void get_fan_duplicate_sysfs(int idx, char *str)
|
||||
{
|
||||
switch (idx)
|
||||
@ -49,6 +67,53 @@ void get_fan_duplicate_sysfs(int idx, char *str)
|
||||
return;
|
||||
}
|
||||
|
||||
void get_fan_extra_default_sysfs(int idx, char *str)
|
||||
{
|
||||
switch (idx)
|
||||
{
|
||||
case FAN1_PRESENT:
|
||||
strcpy(str, "fan1_status");
|
||||
break;
|
||||
case FAN2_PRESENT:
|
||||
strcpy(str, "fan2_status");
|
||||
break;
|
||||
case FAN3_PRESENT:
|
||||
strcpy(str, "fan3_status");
|
||||
break;
|
||||
case FAN4_PRESENT:
|
||||
strcpy(str, "fan4_status");
|
||||
break;
|
||||
case FAN5_PRESENT:
|
||||
strcpy(str, "fan5_status");
|
||||
break;
|
||||
case FAN6_PRESENT:
|
||||
strcpy(str, "fan6_status");
|
||||
break;
|
||||
case FAN7_PRESENT:
|
||||
strcpy(str, "fan7_status");
|
||||
break;
|
||||
case FAN8_PRESENT:
|
||||
strcpy(str, "fan8_status");
|
||||
break;
|
||||
case FAN9_PRESENT:
|
||||
strcpy(str, "fan9_status");
|
||||
break;
|
||||
case FAN10_PRESENT:
|
||||
strcpy(str, "fan10_status");
|
||||
break;
|
||||
case FAN11_PRESENT:
|
||||
strcpy(str, "fan11_status");
|
||||
break;
|
||||
case FAN12_PRESENT:
|
||||
strcpy(str, "fan12_status");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int fan_update_hw(struct device *dev, struct fan_attr_info *info, FAN_DATA_ATTR *udata)
|
||||
{
|
||||
@ -225,6 +290,7 @@ ssize_t fan_show_default(struct device *dev, struct device_attribute *da, char *
|
||||
case FAN10_FAULT:
|
||||
case FAN11_FAULT:
|
||||
case FAN12_FAULT:
|
||||
case FAN_DUTY_CYCLE:
|
||||
status = attr_info->val.intval;
|
||||
break;
|
||||
default:
|
||||
@ -264,6 +330,23 @@ ssize_t fan_store_default(struct device *dev, struct device_attribute *da, const
|
||||
|
||||
switch(attr->index)
|
||||
{
|
||||
case FAN_DUTY_CYCLE:
|
||||
ret = kstrtoint(buf, 10, &val);
|
||||
if (ret)
|
||||
{
|
||||
printk(KERN_ERR "%s: Unable to convert string into value for %s\n", __FUNCTION__, usr_data->aname);
|
||||
return ret;
|
||||
}
|
||||
/* The value passed by the user should be in the range 0-100 as its a percentage */
|
||||
if (val<0 || val>100)
|
||||
{
|
||||
printk(KERN_ERR "%s: Duty cycle %d is not valid. Valid range [0-100]\n", __FUNCTION__, val);
|
||||
return -EINVAL;
|
||||
}
|
||||
/*Update the value of attr_info here, and use it to update the HW values*/
|
||||
attr_info->val.intval = val;
|
||||
break;
|
||||
|
||||
case FAN1_PWM:
|
||||
case FAN2_PWM:
|
||||
case FAN3_PWM:
|
||||
@ -635,6 +718,271 @@ int sonic_i2c_get_fan_fault_default(void *client, FAN_DATA_ATTR *udata, void *in
|
||||
return status;
|
||||
}
|
||||
|
||||
ssize_t fan_show_status(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 fan_data *data = i2c_get_clientdata(client);
|
||||
FAN_PDATA *pdata = (FAN_PDATA *)(client->dev.platform_data);
|
||||
FAN_DATA_ATTR *pres_usr_data = NULL, *speed_usr_data = NULL;
|
||||
struct fan_attr_info *pres_attr_info = NULL, *speed_attr_info = NULL;
|
||||
int i, status=0;
|
||||
char *fan_id;
|
||||
char fan_attr[ATTR_NAME_LEN]="";
|
||||
char *attr_name, *end;
|
||||
int fan_attr_len = 0, presence = 0, speed = 0;
|
||||
|
||||
|
||||
/* Find out the fan_id */
|
||||
fan_attr_len = strlen(attr->dev_attr.attr.name);
|
||||
attr_name = end = (char *)kzalloc(fan_attr_len+1, GFP_KERNEL);
|
||||
memcpy(attr_name, attr->dev_attr.attr.name, fan_attr_len+1);
|
||||
fan_id = strsep(&end, "_");
|
||||
/* fan_id is fan1/fan2/.../fan12 */
|
||||
#ifdef __STDC_LIB_EXT1__
|
||||
memset_s(fan_attr, sizeof(fan_attr), 0 , ATTR_NAME_LEN);
|
||||
#else
|
||||
memset(fan_attr, 0, ATTR_NAME_LEN);
|
||||
#endif
|
||||
snprintf(fan_attr, ATTR_NAME_LEN, "%s_present", fan_id);
|
||||
for (i=0;i<data->num_attr;i++)
|
||||
{
|
||||
if (strcmp(fan_attr, pdata->fan_attrs[i].aname) == 0)
|
||||
{
|
||||
pres_attr_info = &data->attr_info[i];
|
||||
pres_usr_data = &pdata->fan_attrs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
#ifdef __STDC_LIB_EXT1__
|
||||
memset_s(fan_attr, sizeof(fan_attr), 0 , ATTR_NAME_LEN);
|
||||
#else
|
||||
memset(fan_attr, 0, ATTR_NAME_LEN);
|
||||
#endif
|
||||
snprintf(fan_attr, ATTR_NAME_LEN, "%s_input", fan_id);
|
||||
for (i=0;i<data->num_attr;i++)
|
||||
{
|
||||
if (strcmp(fan_attr, pdata->fan_attrs[i].aname) == 0)
|
||||
{
|
||||
speed_attr_info = &data->attr_info[i];
|
||||
speed_usr_data = &pdata->fan_attrs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (pres_attr_info==NULL || pres_usr_data==NULL || speed_attr_info ==NULL || speed_usr_data==NULL)
|
||||
{
|
||||
printk(KERN_ERR "%s_present or %s_input is not a supported attribute for this client\n", fan_id, fan_id);
|
||||
kfree(attr_name);
|
||||
goto exit;
|
||||
}
|
||||
kfree(attr_name);
|
||||
|
||||
fan_update_attr(dev, pres_attr_info, pres_usr_data);
|
||||
fan_update_attr(dev, speed_attr_info, speed_usr_data);
|
||||
|
||||
/*Decide the o/p based on attribute type */
|
||||
presence = pres_attr_info->val.intval;
|
||||
speed = speed_attr_info->val.intval;
|
||||
|
||||
/* As per S3IP spec, 0:Not present, 1:Present and normal, 2:Present and not normal */
|
||||
if (presence == 0)
|
||||
return sprintf(buf, "0\n");
|
||||
else if ( (presence == 1) && (speed > 0) )
|
||||
return sprintf(buf, "1\n");
|
||||
else
|
||||
return sprintf(buf, "2\n");
|
||||
exit:
|
||||
return sprintf(buf, "%d\n", status);
|
||||
}
|
||||
|
||||
int sonic_i2c_get_fan_dc_default(void *client, FAN_DATA_ATTR *udata, void *info)
|
||||
{
|
||||
int status = 0;
|
||||
int val = 0;
|
||||
uint32_t dc = 0;
|
||||
struct fan_attr_info *painfo = (struct fan_attr_info *)info;
|
||||
|
||||
if (strcmp(udata->devtype, "cpld") == 0)
|
||||
{
|
||||
val = fan_cpld_client_read(udata);
|
||||
}
|
||||
else if (strcmp(udata->devtype, "fpgai2c") == 0)
|
||||
{
|
||||
val = fan_fpgai2c_client_read(udata);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (udata->len == 1)
|
||||
{
|
||||
val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset);
|
||||
}
|
||||
else if (udata->len ==2)
|
||||
{
|
||||
val = i2c_smbus_read_word_swapped((struct i2c_client *)client, udata->offset);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (val < 0)
|
||||
status = val;
|
||||
else
|
||||
{
|
||||
val = val & udata->mask;
|
||||
/* val is the fan_pwm which needs to be converted to duty cycle */
|
||||
if (pddf_fan_funcs.reg_value_to_duty_cycle)
|
||||
{
|
||||
dc = (pddf_fan_funcs.reg_value_to_duty_cycle)((uint32_t)val);
|
||||
if ((dc < 0 ) || (dc > 100))
|
||||
printk(KERN_ERR "Error: Invalid duty cycle value (%d) obtained for register vlaue (0x%x)\n", dc, val);
|
||||
else
|
||||
{
|
||||
painfo->val.intval = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
int sonic_i2c_set_fan_dc_default(void *client, FAN_DATA_ATTR *udata, void *info)
|
||||
{
|
||||
int status = 0;
|
||||
int val = 0;
|
||||
uint32_t reg_val = 0;
|
||||
struct fan_attr_info *painfo = (struct fan_attr_info *)info;
|
||||
|
||||
val = painfo->val.intval;
|
||||
if ((val > 255) || (val < 0))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pddf_fan_funcs.duty_cycle_to_reg_value)
|
||||
{
|
||||
reg_val = (pddf_fan_funcs.duty_cycle_to_reg_value)((uint32_t)val);
|
||||
}
|
||||
else
|
||||
{
|
||||
reg_val = val;
|
||||
}
|
||||
|
||||
reg_val = reg_val & udata->mask;
|
||||
|
||||
if (strcmp(udata->devtype, "cpld") == 0)
|
||||
{
|
||||
status = fan_cpld_client_write(udata, reg_val);
|
||||
}
|
||||
else if (strcmp(udata->devtype, "fpgai2c") == 0)
|
||||
{
|
||||
status = fan_fpgai2c_client_write(udata, reg_val);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (udata->len == 1)
|
||||
status = i2c_smbus_write_byte_data(client, udata->offset, reg_val);
|
||||
else if (udata->len == 2)
|
||||
{
|
||||
uint8_t val_lsb = reg_val & 0xFF;
|
||||
uint8_t val_hsb = (reg_val >> 8) & 0xFF;
|
||||
/* TODO: Check this logic for LE and BE */
|
||||
status = i2c_smbus_write_byte_data(client, udata->offset, val_lsb);
|
||||
if (status == 0) status = i2c_smbus_write_byte_data(client, udata->offset+1, val_hsb);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_DEBUG "%s: pwm should be of len 1/2 bytes. Not setting the pwm as the length is %d\n", __FUNCTION__, udata->len);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
ssize_t fan_show_string(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 fan_data *data = i2c_get_clientdata(client);
|
||||
FAN_PDATA *pdata = (FAN_PDATA *)(client->dev.platform_data);
|
||||
FAN_DATA_ATTR *usr_data = NULL;
|
||||
struct fan_attr_info *attr_info = NULL;
|
||||
int i, status = 0;
|
||||
char new_str[ATTR_NAME_LEN] = "";
|
||||
FAN_SYSFS_ATTR_DATA *ptr = NULL;
|
||||
char temp_buf[32] = "";
|
||||
|
||||
for (i=0;i<data->num_attr;i++)
|
||||
{
|
||||
ptr = (FAN_SYSFS_ATTR_DATA *)pdata->fan_attrs[i].access_data;
|
||||
get_fan_duplicate_sysfs(ptr->index , new_str);
|
||||
if (strcmp(attr->dev_attr.attr.name, pdata->fan_attrs[i].aname) == 0 || strcmp(attr->dev_attr.attr.name, new_str) == 0)
|
||||
{
|
||||
attr_info = &data->attr_info[i];
|
||||
usr_data = &pdata->fan_attrs[i];
|
||||
strcpy(new_str, "");
|
||||
}
|
||||
}
|
||||
|
||||
if (attr_info==NULL || usr_data==NULL)
|
||||
{
|
||||
printk(KERN_ERR "%s is not supported attribute for this client\n", usr_data->aname);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mutex_lock(&attr_info->update_lock);
|
||||
|
||||
if (time_after(jiffies, attr_info->last_updated + HZ + HZ / 2) || !attr_info->valid)
|
||||
{
|
||||
attr_info->valid = 0;
|
||||
|
||||
if (strcmp(usr_data->devtype, "eeprom") == 0)
|
||||
{
|
||||
status = i2c_smbus_read_i2c_block_data(client, usr_data->offset, usr_data->len-1, temp_buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
printk(KERN_ERR "Error: Unable to read block data from non-eeprom device\n");
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
temp_buf[0] = '\0';
|
||||
fan_dbg(KERN_ERR "unable to read block of data from (0x%x)\n", ((struct i2c_client *)client)->addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_buf[usr_data->len-1] = '\0';
|
||||
}
|
||||
|
||||
strncpy(attr_info->val.strval, temp_buf, usr_data->len);
|
||||
|
||||
attr_info->last_updated = jiffies;
|
||||
attr_info->valid = 1;
|
||||
}
|
||||
|
||||
mutex_unlock(&attr_info->update_lock);
|
||||
|
||||
|
||||
/*Decide the o/p based on attribute type */
|
||||
switch(attr->index)
|
||||
{
|
||||
case FAN_MODEL_NAME:
|
||||
case FAN_SERIAL_NUM:
|
||||
case FAN_PART_NUM:
|
||||
case FAN_HW_VERSION:
|
||||
return sprintf(buf, "%s\n", attr_info->val.strval);
|
||||
break;
|
||||
default:
|
||||
fan_dbg(KERN_ERR "%s: Unable to find the attribute index for %s\n", __FUNCTION__, usr_data->aname);
|
||||
status = 0;
|
||||
}
|
||||
|
||||
exit:
|
||||
/* Even if there is an error, strval is having empty string */
|
||||
return sprintf(buf, "%s\n", attr_info->val.strval);
|
||||
}
|
||||
|
||||
int pddf_fan_post_probe_default(struct i2c_client *client, const struct i2c_device_id *dev_id)
|
||||
{
|
||||
|
@ -182,6 +182,47 @@ EXPORT_SYMBOL(data_fan11_fault);
|
||||
FAN_SYSFS_ATTR_DATA data_fan12_fault = {FAN12_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan12_fault);
|
||||
|
||||
/* Derived attributes like status (should be derived from 'presence' and 'speed'/'fault' attributes) etc */
|
||||
FAN_SYSFS_ATTR_DATA data_fan1_status = {FAN1_STATUS, S_IRUGO, fan_show_status, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan1_status);
|
||||
FAN_SYSFS_ATTR_DATA data_fan2_status = {FAN2_STATUS, S_IRUGO, fan_show_status, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan2_status);
|
||||
FAN_SYSFS_ATTR_DATA data_fan3_status = {FAN3_STATUS, S_IRUGO, fan_show_status, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan3_status);
|
||||
FAN_SYSFS_ATTR_DATA data_fan4_status = {FAN4_STATUS, S_IRUGO, fan_show_status, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan4_status);
|
||||
FAN_SYSFS_ATTR_DATA data_fan5_status = {FAN5_STATUS, S_IRUGO, fan_show_status, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan5_status);
|
||||
FAN_SYSFS_ATTR_DATA data_fan6_status = {FAN6_STATUS, S_IRUGO, fan_show_status, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan6_status);
|
||||
FAN_SYSFS_ATTR_DATA data_fan7_status = {FAN7_STATUS, S_IRUGO, fan_show_status, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan7_status);
|
||||
FAN_SYSFS_ATTR_DATA data_fan8_status = {FAN8_STATUS, S_IRUGO, fan_show_status, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan8_status);
|
||||
FAN_SYSFS_ATTR_DATA data_fan9_status = {FAN9_STATUS, S_IRUGO, fan_show_status, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan9_status);
|
||||
FAN_SYSFS_ATTR_DATA data_fan10_status = {FAN10_STATUS, S_IRUGO, fan_show_status, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan10_status);
|
||||
FAN_SYSFS_ATTR_DATA data_fan11_status = {FAN11_STATUS, S_IRUGO, fan_show_status, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan11_status);
|
||||
FAN_SYSFS_ATTR_DATA data_fan12_status = {FAN12_STATUS, S_IRUGO, fan_show_status, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan12_status);
|
||||
|
||||
/* Some generic fan attributes */
|
||||
FAN_SYSFS_ATTR_DATA data_fan_duty_cycle = {FAN_DUTY_CYCLE, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_dc_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_dc_default, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan_duty_cycle);
|
||||
|
||||
FAN_SYSFS_ATTR_DATA data_fan_model_name = {FAN_MODEL_NAME, S_IRUGO, fan_show_string, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan_model_name);
|
||||
|
||||
FAN_SYSFS_ATTR_DATA data_fan_serial_num = {FAN_SERIAL_NUM, S_IRUGO, fan_show_string, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan_serial_num);
|
||||
|
||||
FAN_SYSFS_ATTR_DATA data_fan_part_num = {FAN_PART_NUM, S_IRUGO, fan_show_string, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan_part_num);
|
||||
|
||||
FAN_SYSFS_ATTR_DATA data_fan_hw_version = {FAN_HW_VERSION, S_IRUGO, fan_show_string, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
EXPORT_SYMBOL(data_fan_hw_version);
|
||||
|
||||
FAN_SYSFS_ATTR_DATA_ENTRY fan_sysfs_attr_data_tbl[]=
|
||||
{
|
||||
@ -245,6 +286,23 @@ FAN_SYSFS_ATTR_DATA_ENTRY fan_sysfs_attr_data_tbl[]=
|
||||
{ "fan10_fault", &data_fan10_fault},
|
||||
{ "fan11_fault", &data_fan11_fault},
|
||||
{ "fan12_fault", &data_fan12_fault},
|
||||
{ "fan1_status", &data_fan1_status},
|
||||
{ "fan2_status", &data_fan2_status},
|
||||
{ "fan3_status", &data_fan3_status},
|
||||
{ "fan4_status", &data_fan4_status},
|
||||
{ "fan5_status", &data_fan5_status},
|
||||
{ "fan6_status", &data_fan6_status},
|
||||
{ "fan7_status", &data_fan7_status},
|
||||
{ "fan8_status", &data_fan8_status},
|
||||
{ "fan9_status", &data_fan9_status},
|
||||
{ "fan10_status", &data_fan10_status},
|
||||
{ "fan11_status", &data_fan11_status},
|
||||
{ "fan12_status", &data_fan12_status},
|
||||
{ "fan_duty_cycle", &data_fan_duty_cycle},
|
||||
{ "fan_model_name", &data_fan_model_name},
|
||||
{ "fan_serial_num", &data_fan_serial_num},
|
||||
{ "fan_part_num", &data_fan_part_num},
|
||||
{ "fan_hw_version", &data_fan_hw_version},
|
||||
};
|
||||
|
||||
void *get_fan_access_data(char *name)
|
||||
@ -271,7 +329,10 @@ static int pddf_fan_probe(struct i2c_client *client,
|
||||
FAN_PDATA *fan_platform_data;
|
||||
FAN_DATA_ATTR *data_attr;
|
||||
FAN_SYSFS_ATTR_DATA_ENTRY *sysfs_data_entry;
|
||||
char new_str[ATTR_NAME_LEN] = "";
|
||||
FAN_SYSFS_ATTR_DATA_ENTRY *extra_sysfs_data_entry;
|
||||
char new_duplicate_str[ATTR_NAME_LEN] = "";
|
||||
char new_default_str[ATTR_NAME_LEN] = "";
|
||||
int idx = 0;
|
||||
|
||||
if (client == NULL) {
|
||||
printk("NULL Client.. \n");
|
||||
@ -331,13 +392,14 @@ static int pddf_fan_probe(struct i2c_client *client,
|
||||
data->attr_info[i].valid = 0;
|
||||
mutex_init(&data->attr_info[i].update_lock);
|
||||
|
||||
/*Create a duplicate entry*/
|
||||
get_fan_duplicate_sysfs(dy_ptr->index, new_str);
|
||||
if (strcmp(new_str,""))
|
||||
/*Create a duplicate entry i.e. show, store funcs etc and other access data is same as data_attr->aname*/
|
||||
idx = dy_ptr->index;
|
||||
get_fan_duplicate_sysfs(idx, new_duplicate_str);
|
||||
if (strcmp(new_duplicate_str,""))
|
||||
{
|
||||
dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL);
|
||||
dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1];
|
||||
strcpy((char *)dy_ptr->dev_attr.attr.name, new_str);
|
||||
strcpy((char *)dy_ptr->dev_attr.attr.name, new_duplicate_str);
|
||||
dy_ptr->dev_attr.attr.mode = sysfs_data_entry->a_ptr->mode;
|
||||
dy_ptr->dev_attr.show = sysfs_data_entry->a_ptr->show;
|
||||
dy_ptr->dev_attr.store = sysfs_data_entry->a_ptr->store;
|
||||
@ -345,7 +407,32 @@ static int pddf_fan_probe(struct i2c_client *client,
|
||||
|
||||
data->fan_attribute_list[num+j] = &dy_ptr->dev_attr.attr;
|
||||
j++;
|
||||
strcpy(new_str, "");
|
||||
strcpy(new_duplicate_str, "");
|
||||
}
|
||||
/*Create a default sysfs entry which might not be present in the JSON file*/
|
||||
get_fan_extra_default_sysfs(idx, new_default_str);
|
||||
if (strcmp(new_default_str,""))
|
||||
{
|
||||
extra_sysfs_data_entry = get_fan_access_data(new_default_str);
|
||||
if (extra_sysfs_data_entry == NULL)
|
||||
{
|
||||
printk(KERN_ERR "%s: Invalid name for extra default attribute '%s'. No access data exists\n", __FUNCTION__, new_default_str);
|
||||
continue;
|
||||
}
|
||||
dy_ptr = (struct sensor_device_attribute *)kzalloc(sizeof(struct sensor_device_attribute)+ATTR_NAME_LEN, GFP_KERNEL);
|
||||
dy_ptr->dev_attr.attr.name = (char *)&dy_ptr[1];
|
||||
strcpy((char *)dy_ptr->dev_attr.attr.name, new_default_str);
|
||||
dy_ptr->dev_attr.attr.mode = extra_sysfs_data_entry->a_ptr->mode;
|
||||
dy_ptr->dev_attr.show = extra_sysfs_data_entry->a_ptr->show;
|
||||
dy_ptr->dev_attr.store = extra_sysfs_data_entry->a_ptr->store;
|
||||
dy_ptr->index = extra_sysfs_data_entry->a_ptr->index;
|
||||
|
||||
data->fan_attribute_list[num+j] = &dy_ptr->dev_attr.attr;
|
||||
strcpy(data->attr_info[num+j].name, new_default_str);
|
||||
data->attr_info[num+j].valid = 0;
|
||||
mutex_init(&data->attr_info[num+j].update_lock);
|
||||
j++;
|
||||
strcpy(new_default_str, "");
|
||||
}
|
||||
}
|
||||
data->fan_attribute_list[i+j] = NULL;
|
||||
|
@ -21,10 +21,15 @@
|
||||
#define __PDDF_FAN_API_H__
|
||||
|
||||
extern int pddf_fan_post_probe_default(struct i2c_client *client, const struct i2c_device_id *dev_id);
|
||||
extern uint32_t pddf_fan_dc_to_pwm_default(uint32_t dc);
|
||||
extern uint32_t pddf_fan_pwm_to_dc_default(uint32_t reg_val);
|
||||
|
||||
extern void get_fan_duplicate_sysfs(int idx, char *str);
|
||||
extern void get_fan_extra_default_sysfs(int idx, char *str);
|
||||
extern ssize_t fan_show_default(struct device *dev, struct device_attribute *da, char *buf);
|
||||
extern ssize_t fan_store_default(struct device *dev, struct device_attribute *da, const char *buf, size_t count);
|
||||
extern ssize_t fan_show_status(struct device *dev, struct device_attribute *da, char *buf);
|
||||
extern ssize_t fan_show_string(struct device *dev, struct device_attribute *da, char *buf);
|
||||
|
||||
|
||||
extern int sonic_i2c_get_fan_present_default(void *client, FAN_DATA_ATTR *adata, void *data);
|
||||
@ -33,5 +38,8 @@ extern int sonic_i2c_get_fan_direction_default(void *client, FAN_DATA_ATTR *adat
|
||||
extern int sonic_i2c_get_fan_pwm_default(void *client, FAN_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_fan_fault_default(void *client, FAN_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_set_fan_pwm_default(void *client, FAN_DATA_ATTR *adata, void *data);
|
||||
extern int sonic_i2c_get_fan_dc_default(void *client, FAN_DATA_ATTR *udata, void *info);
|
||||
extern int sonic_i2c_set_fan_dc_default(void *client, FAN_DATA_ATTR *udata, void *info);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -21,7 +21,7 @@
|
||||
#define __PDDF_FAN_DEFS_H__
|
||||
|
||||
|
||||
#define MAX_NUM_FAN 6
|
||||
#define MAX_NUM_FAN 12
|
||||
#define MAX_FAN_ATTRS 128
|
||||
#define ATTR_NAME_LEN 32
|
||||
#define STR_ATTR_SIZE 32
|
||||
@ -85,6 +85,13 @@ typedef struct FAN_PDATA
|
||||
FAN_DATA_ATTR *fan_attrs;
|
||||
}FAN_PDATA;
|
||||
|
||||
struct pddf_fan_ops_t
|
||||
{
|
||||
/*Fan duty cycle conversion ops*/
|
||||
uint32_t (*duty_cycle_to_reg_value)(uint32_t dc);
|
||||
uint32_t (*reg_value_to_duty_cycle)(uint32_t reg_val);
|
||||
};
|
||||
|
||||
extern int board_i2c_cpld_read(unsigned short cpld_addr, u8 reg);
|
||||
extern int board_i2c_cpld_write(unsigned short cpld_addr, u8 reg, u8 value);
|
||||
|
||||
|
@ -80,6 +80,23 @@ enum fan_sysfs_attributes {
|
||||
FAN10_FAULT,
|
||||
FAN11_FAULT,
|
||||
FAN12_FAULT,
|
||||
FAN1_STATUS,
|
||||
FAN2_STATUS,
|
||||
FAN3_STATUS,
|
||||
FAN4_STATUS,
|
||||
FAN5_STATUS,
|
||||
FAN6_STATUS,
|
||||
FAN7_STATUS,
|
||||
FAN8_STATUS,
|
||||
FAN9_STATUS,
|
||||
FAN10_STATUS,
|
||||
FAN11_STATUS,
|
||||
FAN12_STATUS,
|
||||
FAN_DUTY_CYCLE,
|
||||
FAN_MODEL_NAME,
|
||||
FAN_SERIAL_NUM,
|
||||
FAN_PART_NUM,
|
||||
FAN_HW_VERSION,
|
||||
FAN_MAX_ATTR
|
||||
};
|
||||
/* Each client has this additional data */
|
||||
|
Reference in New Issue
Block a user