From 99acdd37b20eb6596963a3aacdfeb101fb49e9fc Mon Sep 17 00:00:00 2001 From: Yagami-Jiang <119273528+Yagami-Jiang@users.noreply.github.com> Date: Wed, 24 May 2023 10:03:12 +0800 Subject: [PATCH] Add files via upload --- .../pddf_fan_custom/pddf_custom_fan_api.c | 656 ++++++++++++++++++ .../pddf_fan_custom/pddf_custom_fan_defs.h | 93 +++ .../pddf_fan_custom/pddf_custom_fan_driver.c | 525 ++++++++++++++ .../pddf_fan_custom/pddf_custom_fan_driver.h | 117 ++++ .../modules/pddf_fan_custom/readme.txt | 2 + 5 files changed, 1393 insertions(+) create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/pddf_custom_fan_api.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/pddf_custom_fan_defs.h create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/pddf_custom_fan_driver.c create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/pddf_custom_fan_driver.h create mode 100644 platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/readme.txt diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/pddf_custom_fan_api.c b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/pddf_custom_fan_api.c new file mode 100644 index 000000000000..9dc6b23534dd --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/pddf_custom_fan_api.c @@ -0,0 +1,656 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description of various APIs related to FAN component + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pddf_custom_fan_defs.h" +#include "pddf_custom_fan_driver.h" + +/*#define FAN_DEBUG*/ +#ifdef FAN_DEBUG +#define fan_dbg(...) printk(__VA_ARGS__) +#else +#define fan_dbg(...) +#endif + +extern void *get_device_table(char *name); + +void get_fan_duplicate_sysfs(int idx, char *str) +{ + switch (idx) + { + default: + break; + } + + return; +} + + +int fan_update_hw(struct device *dev, struct fan_attr_info *info, FAN_DATA_ATTR *udata) +{ + int status = 0; + struct i2c_client *client = to_i2c_client(dev); + FAN_SYSFS_ATTR_DATA *sysfs_attr_data = NULL; + + + mutex_lock(&info->update_lock); + + sysfs_attr_data = udata->access_data; + if (sysfs_attr_data->pre_set != NULL) + { + status = (sysfs_attr_data->pre_set)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: pre_set function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + if (sysfs_attr_data->do_set != NULL) + { + status = (sysfs_attr_data->do_set)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: do_set function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + + } + if (sysfs_attr_data->post_set != NULL) + { + status = (sysfs_attr_data->post_set)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: post_set function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + + mutex_unlock(&info->update_lock); + + return 0; +} + +int fan_update_attr(struct device *dev, struct fan_attr_info *info, FAN_DATA_ATTR *udata) +{ + int status = 0; + struct i2c_client *client = to_i2c_client(dev); + FAN_SYSFS_ATTR_DATA *sysfs_attr_data = NULL; + + + mutex_lock(&info->update_lock); + + if (time_after(jiffies, info->last_updated + HZ + HZ / 2) || !info->valid) + { + dev_dbg(&client->dev, "Starting pddf_fan update\n"); + info->valid = 0; + + sysfs_attr_data = udata->access_data; + if (sysfs_attr_data->pre_get != NULL) + { + status = (sysfs_attr_data->pre_get)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: pre_get function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + } + if (sysfs_attr_data->do_get != NULL) + { + status = (sysfs_attr_data->do_get)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: do_get function fails for %s attribute. ret %d\n", __FUNCTION__, udata->aname, status); + + } + if (sysfs_attr_data->post_get != NULL) + { + status = (sysfs_attr_data->post_get)(client, udata, info); + if (status!=0) + dev_warn(&client->dev, "%s: post_get function fails for %s attribute.ret %d\n", __FUNCTION__, udata->aname, status); + } + + + info->last_updated = jiffies; + info->valid = 1; + } + + mutex_unlock(&info->update_lock); + + return 0; +} + +ssize_t fan_show_default(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; + + for (i=0;inum_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; + } + + fan_update_attr(dev, attr_info, usr_data); + + /*Decide the o/p based on attribute type */ + switch(attr->index) + { + case FAN1_PRESENT: + case FAN2_PRESENT: + case FAN3_PRESENT: + case FAN4_PRESENT: + case FAN5_PRESENT: + case FAN6_PRESENT: + case FAN7_PRESENT: + case FAN8_PRESENT: + case FAN9_PRESENT: + case FAN10_PRESENT: + case FAN11_PRESENT: + case FAN12_PRESENT: + case FAN13_PRESENT: + case FAN14_PRESENT: + case FAN1_DIRECTION: + case FAN2_DIRECTION: + case FAN3_DIRECTION: + case FAN4_DIRECTION: + case FAN5_DIRECTION: + case FAN6_DIRECTION: + case FAN7_DIRECTION: + case FAN8_DIRECTION: + case FAN9_DIRECTION: + case FAN10_DIRECTION: + case FAN11_DIRECTION: + case FAN12_DIRECTION: + case FAN13_DIRECTION: + case FAN14_DIRECTION: + case FAN1_INPUT: + case FAN2_INPUT: + case FAN3_INPUT: + case FAN4_INPUT: + case FAN5_INPUT: + case FAN6_INPUT: + case FAN7_INPUT: + case FAN8_INPUT: + case FAN9_INPUT: + case FAN10_INPUT: + case FAN11_INPUT: + case FAN12_INPUT: + case FAN13_INPUT: + case FAN14_INPUT: + case FAN1_PWM: + case FAN2_PWM: + case FAN3_PWM: + case FAN4_PWM: + case FAN5_PWM: + case FAN6_PWM: + case FAN7_PWM: + case FAN8_PWM: + case FAN9_PWM: + case FAN10_PWM: + case FAN11_PWM: + case FAN12_PWM: + case FAN13_PWM: + case FAN14_PWM: + case FAN1_FAULT: + case FAN2_FAULT: + case FAN3_FAULT: + case FAN4_FAULT: + case FAN5_FAULT: + case FAN6_FAULT: + case FAN7_FAULT: + case FAN8_FAULT: + case FAN9_FAULT: + case FAN10_FAULT: + case FAN11_FAULT: + case FAN12_FAULT: + case FAN13_FAULT: + case FAN14_FAULT: + status = attr_info->val.intval; + break; + default: + fan_dbg(KERN_ERR "%s: Unable to find the attribute index for %s\n", __FUNCTION__, usr_data->aname); + status = 0; + } + +exit: + return sprintf(buf, "%d\n", status); +} + + +ssize_t fan_store_default(struct device *dev, struct device_attribute *da, const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct 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, ret ; + uint32_t val; + + for (i=0;inum_attr;i++) + { + if (strcmp(data->attr_info[i].name, attr->dev_attr.attr.name) == 0 && strcmp(pdata->fan_attrs[i].aname, attr->dev_attr.attr.name) == 0) + { + attr_info = &data->attr_info[i]; + usr_data = &pdata->fan_attrs[i]; + } + } + + if (attr_info==NULL || usr_data==NULL) { + printk(KERN_ERR "%s is not supported attribute for this client\n", attr->dev_attr.attr.name); + goto exit; + } + + switch(attr->index) + { + case FAN1_PWM: + case FAN2_PWM: + case FAN3_PWM: + case FAN4_PWM: + case FAN5_PWM: + case FAN6_PWM: + case FAN7_PWM: + case FAN8_PWM: + case FAN9_PWM: + case FAN10_PWM: + case FAN11_PWM: + case FAN12_PWM: + case FAN13_PWM: + case FAN14_PWM: + 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; + } + /*Update the value of attr_info here, and use it to update the HW values*/ + attr_info->val.intval = val; + break; + default: + printk(KERN_ERR "%s: Unable to find the attr index for %s\n", __FUNCTION__, usr_data->aname); + goto exit; + } + + fan_dbg(KERN_ERR "%s: pwm to be set is %d\n", __FUNCTION__, val); + fan_update_hw(dev, attr_info, usr_data); + +exit: + return count; +} + +int fan_cpld_client_read(FAN_DATA_ATTR *udata) +{ + int status = -1; + + if (udata!=NULL) + { + if (udata->len==1) + { + status = board_i2c_cpld_read(udata->devaddr , udata->offset); + } + else + { + /* Get the I2C client for the CPLD */ + struct i2c_client *client_ptr=NULL; + client_ptr = (struct i2c_client *)get_device_table(udata->devname); + if (client_ptr) + { + if (udata->len==2) + { + status = i2c_smbus_read_word_swapped(client_ptr, udata->offset); + } + else + printk(KERN_ERR "PDDF_FAN: Doesn't support block CPLD read yet"); + } + else + printk(KERN_ERR "Unable to get the client handle for %s\n", udata->devname); + } + + } + + return status; +} + +int fan_cpld_client_write(FAN_DATA_ATTR *udata, uint32_t val) +{ + int status = 0; + + if (udata->len==1) + { + status = board_i2c_cpld_write(udata->devaddr, udata->offset, val); + } + else + { + /* Get the I2C client for the CPLD */ + struct i2c_client *client_ptr=NULL; + client_ptr = (struct i2c_client *)get_device_table(udata->devname); + if (client_ptr) + { + if (udata->len==2) + { + uint8_t val_lsb = val & 0xFF; + uint8_t val_hsb = (val >> 8) & 0xFF; + /* TODO: Check this logic for LE and BE */ + status = i2c_smbus_write_byte_data(client_ptr, udata->offset, val_lsb); + if (status==0) status = i2c_smbus_write_byte_data(client_ptr, udata->offset+1, val_hsb); + } + else + printk(KERN_ERR "PDDF_FAN: Doesn't support block CPLD write yet"); + } + else + printk(KERN_ERR "Unable to get the client handle for %s\n", udata->devname); + } + + return status; +} + +int fan_fpgai2c_client_read(FAN_DATA_ATTR *udata) +{ + int status = -1; + + if (udata!=NULL) + { + if (udata->len==1) + { + status = board_i2c_fpga_read(udata->devaddr , udata->offset); + /*printk(KERN_ERR "### Reading offset 0x%x from 0x%x device ... val 0x%x\n", udata->offset, udata->devaddr, status);*/ + } + else + { + /* Get the I2C client for the FPGAI2C */ + struct i2c_client *client_ptr=NULL; + client_ptr = (struct i2c_client *)get_device_table(udata->devname); + if (client_ptr) + { + if (udata->len==2) + { + status = i2c_smbus_read_word_swapped(client_ptr, udata->offset); + } + else + printk(KERN_ERR "PDDF_FAN: Doesn't support block FPGAI2C read yet"); + } + else + printk(KERN_ERR "Unable to get the client handle for %s\n", udata->devname); + } + + } + + return status; +} + +int fan_fpgai2c_client_write(FAN_DATA_ATTR *udata, uint32_t val) +{ + int status = 0; + + if (udata->len==1) + { + status = board_i2c_fpga_write(udata->devaddr, udata->offset, val); + } + else + { + /* Get the I2C client for the FPGAI2C */ + struct i2c_client *client_ptr=NULL; + client_ptr = (struct i2c_client *)get_device_table(udata->devname); + if (client_ptr) + { + if (udata->len==2) + { + uint8_t val_lsb = val & 0xFF; + uint8_t val_hsb = (val >> 8) & 0xFF; + /* TODO: Check this logic for LE and BE */ + status = i2c_smbus_write_byte_data(client_ptr, udata->offset, val_lsb); + if (status==0) status = i2c_smbus_write_byte_data(client_ptr, udata->offset+1, val_hsb); + } + else + printk(KERN_ERR "PDDF_FAN: Doesn't support block FPGAI2C write yet"); + } + else + printk(KERN_ERR "Unable to get the client handle for %s\n", udata->devname); + } + + return status; +} + + +int sonic_i2c_get_fan_present_default(void *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + int val = 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 + { + val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset); + } + + if (val < 0) + status = val; + else + painfo->val.intval = ((val & udata->mask) == udata->cmpval); + + + return status; +} + +int sonic_i2c_get_fan_rpm_default(void *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + int val = 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 + { + if (udata->is_divisor) + painfo->val.intval = udata->mult / (val >> 3); + else + painfo->val.intval = udata->mult * val; + } + + return status; +} + + +int sonic_i2c_get_fan_direction_default(void *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + int val = 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 + { + val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset); + } + + if (val < 0) + status = val; + else + painfo->val.intval = ((val & udata->mask) == udata->cmpval); + + return status; +} + + +int sonic_i2c_set_fan_pwm_default(struct i2c_client *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + int val = 0; + struct fan_attr_info *painfo = (struct fan_attr_info *)info; + + val = painfo->val.intval & udata->mask; + + if (val > 255) + { + return -EINVAL; + } + + if (strcmp(udata->devtype, "cpld") == 0) + { + status = fan_cpld_client_write(udata, val); + } + else if (strcmp(udata->devtype, "fpgai2c") == 0) + { + status = fan_fpgai2c_client_write(udata, val); + } + else + { + if (udata->len == 1) + status = i2c_smbus_write_byte_data(client, udata->offset, val); + else if (udata->len == 2) + { + uint8_t val_lsb = val & 0xFF; + uint8_t val_hsb = (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; +} + + +int sonic_i2c_get_fan_pwm_default(void *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + int val = 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; + painfo->val.intval = val; + } + return status; +} + +int sonic_i2c_get_fan_fault_default(void *client, FAN_DATA_ATTR *udata, void *info) +{ + int status = 0; + int val = 0; + struct fan_attr_info *painfo = (struct fan_attr_info *)info; + + /*Assuming fan fault to be denoted by 1 byte only*/ + 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 + { + val = i2c_smbus_read_byte_data((struct i2c_client *)client, udata->offset); + } + + if (val < 0) + status = val; + else + painfo->val.intval = ((val & udata->mask) == udata->cmpval); + return status; +} + + +int pddf_fan_post_probe_default(struct i2c_client *client, const struct i2c_device_id *dev_id) +{ + + /*Dummy func for now - check the respective platform modules*/ + return 0; +} \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/pddf_custom_fan_defs.h b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/pddf_custom_fan_defs.h new file mode 100644 index 000000000000..987ad25e95a2 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/pddf_custom_fan_defs.h @@ -0,0 +1,93 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description: + * Platform FAN defines/structures header file + */ + +#ifndef __PDDF_FAN_DEFS_H__ +#define __PDDF_FAN_DEFS_H__ + + +#define MAX_NUM_FAN 7 +#define MAX_FAN_ATTRS 128 +#define ATTR_NAME_LEN 32 +#define STR_ATTR_SIZE 32 +#define DEV_TYPE_LEN 32 + +/* Each client has this additional data + */ + +typedef struct FAN_DATA_ATTR +{ + char aname[ATTR_NAME_LEN]; // attr name, taken from enum fan_sysfs_attributes + char devtype[DEV_TYPE_LEN]; // Type of FAN controller, i.e EMC2305, EMC2302, or FAN-CPLD etc + char devname[DEV_TYPE_LEN]; // Name of the device from where this informatin is to be read + uint32_t devaddr; + uint32_t offset; + uint32_t mask; + uint32_t cmpval; + uint32_t len; + int mult; // Multiplication factor to get the actual data + uint8_t is_divisor; // Check if the value is a divisor and mult is dividend + void *access_data; + +}FAN_DATA_ATTR; + + +typedef struct FAN_SYSFS_ATTR_DATA +{ + int index; + unsigned short mode; + ssize_t (*show)(struct device *dev, struct device_attribute *da, char *buf); + int (*pre_get)(void *client, FAN_DATA_ATTR *adata, void *data); + int (*do_get)(void *client, FAN_DATA_ATTR *adata, void *data); + int (*post_get)(void *client, FAN_DATA_ATTR *adata, void *data); + ssize_t (*store)(struct device *dev, struct device_attribute *da, const char *buf, size_t count); + int (*pre_set)(void *client, FAN_DATA_ATTR *adata, void *data); + int (*do_set)(void *client, FAN_DATA_ATTR *adata, void *data); + int (*post_set)(void *client, FAN_DATA_ATTR *adata, void *data); + void *data; +} FAN_SYSFS_ATTR_DATA; + +typedef struct FAN_SYSFS_ATTR_DATA_ENTRY +{ + char name[ATTR_NAME_LEN]; + FAN_SYSFS_ATTR_DATA *a_ptr; +} FAN_SYSFS_ATTR_DATA_ENTRY; + + +/* FAN CLIENT DATA - PLATFORM DATA FOR FAN CLIENT */ +typedef struct FAN_DATA +{ + int num_fantrays; // num of fans controlled by this fan client + FAN_DATA_ATTR fan_attr; + int len; // no of valid attributes for this fan client + FAN_DATA_ATTR fan_attrs[MAX_FAN_ATTRS]; +}FAN_DATA; + +typedef struct FAN_PDATA +{ + int num_fantrays; // num of fans controlled by this fan client + int len; // no of valid attributes for this fan client + FAN_DATA_ATTR *fan_attrs; +}FAN_PDATA; + +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); + +extern int board_i2c_fpga_read(unsigned short cpld_addr, u8 reg); +extern int board_i2c_fpga_write(unsigned short cpld_addr, u8 reg, u8 value); +#endif \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/pddf_custom_fan_driver.c b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/pddf_custom_fan_driver.c new file mode 100644 index 000000000000..51ff12e2a970 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/pddf_custom_fan_driver.c @@ -0,0 +1,525 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * A pddf kernel driver module for a FAN controller + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../../../../pddf/i2c/modules/include/pddf_client_defs.h" +#include "pddf_custom_fan_defs.h" +#include "pddf_custom_fan_driver.h" +#include "../../../../../pddf/i2c/modules/include/pddf_fan_api.h" + +#define DRVNAME "pddf_fan" + +struct pddf_ops_t pddf_fan_ops = { + .pre_init = NULL, + .post_init = NULL, + + .pre_probe = NULL, + .post_probe = pddf_fan_post_probe_default, + + .pre_remove = NULL, + .post_remove = NULL, + + .pre_exit = NULL, + .post_exit = NULL, +}; +EXPORT_SYMBOL(pddf_fan_ops); + + + +FAN_SYSFS_ATTR_DATA data_fan1_present = {FAN1_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan1_present); +FAN_SYSFS_ATTR_DATA data_fan2_present = {FAN2_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan2_present); +FAN_SYSFS_ATTR_DATA data_fan3_present = {FAN3_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan3_present); +FAN_SYSFS_ATTR_DATA data_fan4_present = {FAN4_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan4_present); +FAN_SYSFS_ATTR_DATA data_fan5_present = {FAN5_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan5_present); +FAN_SYSFS_ATTR_DATA data_fan6_present = {FAN6_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan6_present); +FAN_SYSFS_ATTR_DATA data_fan7_present = {FAN7_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan7_present); +FAN_SYSFS_ATTR_DATA data_fan8_present = {FAN8_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan8_present); +FAN_SYSFS_ATTR_DATA data_fan9_present = {FAN9_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan9_present); +FAN_SYSFS_ATTR_DATA data_fan10_present = {FAN10_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan10_present); +FAN_SYSFS_ATTR_DATA data_fan11_present = {FAN11_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan11_present); +FAN_SYSFS_ATTR_DATA data_fan12_present = {FAN12_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan12_present); +FAN_SYSFS_ATTR_DATA data_fan13_present = {FAN13_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan13_present); +FAN_SYSFS_ATTR_DATA data_fan14_present = {FAN14_PRESENT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_present_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan14_present); + + +FAN_SYSFS_ATTR_DATA data_fan1_direction = {FAN1_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan1_direction); +FAN_SYSFS_ATTR_DATA data_fan2_direction = {FAN2_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan2_direction); +FAN_SYSFS_ATTR_DATA data_fan3_direction = {FAN3_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan3_direction); +FAN_SYSFS_ATTR_DATA data_fan4_direction = {FAN4_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan4_direction); +FAN_SYSFS_ATTR_DATA data_fan5_direction = {FAN5_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan5_direction); +FAN_SYSFS_ATTR_DATA data_fan6_direction = {FAN6_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan6_direction); +FAN_SYSFS_ATTR_DATA data_fan7_direction = {FAN7_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan7_direction); +FAN_SYSFS_ATTR_DATA data_fan8_direction = {FAN8_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan8_direction); +FAN_SYSFS_ATTR_DATA data_fan9_direction = {FAN9_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan9_direction); +FAN_SYSFS_ATTR_DATA data_fan10_direction = {FAN10_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan10_direction); +FAN_SYSFS_ATTR_DATA data_fan11_direction = {FAN11_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan11_direction); +FAN_SYSFS_ATTR_DATA data_fan12_direction = {FAN12_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan12_direction); +FAN_SYSFS_ATTR_DATA data_fan13_direction = {FAN13_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan13_direction); +FAN_SYSFS_ATTR_DATA data_fan14_direction = {FAN14_DIRECTION, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_direction_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan14_direction); + + +FAN_SYSFS_ATTR_DATA data_fan1_input = {FAN1_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan1_input); +FAN_SYSFS_ATTR_DATA data_fan2_input = {FAN2_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan2_input); +FAN_SYSFS_ATTR_DATA data_fan3_input = {FAN3_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan3_input); +FAN_SYSFS_ATTR_DATA data_fan4_input = {FAN4_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan4_input); +FAN_SYSFS_ATTR_DATA data_fan5_input = {FAN5_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan5_input); +FAN_SYSFS_ATTR_DATA data_fan6_input = {FAN6_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan6_input); +FAN_SYSFS_ATTR_DATA data_fan7_input = {FAN7_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan7_input); +FAN_SYSFS_ATTR_DATA data_fan8_input = {FAN8_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan8_input); +FAN_SYSFS_ATTR_DATA data_fan9_input = {FAN9_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan9_input); +FAN_SYSFS_ATTR_DATA data_fan10_input = {FAN10_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan10_input); +FAN_SYSFS_ATTR_DATA data_fan11_input = {FAN11_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan11_input); +FAN_SYSFS_ATTR_DATA data_fan12_input = {FAN12_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan12_input); +FAN_SYSFS_ATTR_DATA data_fan13_input = {FAN13_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan13_input); +FAN_SYSFS_ATTR_DATA data_fan14_input = {FAN14_INPUT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_rpm_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan14_input); + +FAN_SYSFS_ATTR_DATA data_fan1_pwm = {FAN1_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan1_pwm); +FAN_SYSFS_ATTR_DATA data_fan2_pwm = {FAN2_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan2_pwm); +FAN_SYSFS_ATTR_DATA data_fan3_pwm = {FAN3_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan3_pwm); +FAN_SYSFS_ATTR_DATA data_fan4_pwm = {FAN4_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan4_pwm); +FAN_SYSFS_ATTR_DATA data_fan5_pwm = {FAN5_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan5_pwm); +FAN_SYSFS_ATTR_DATA data_fan6_pwm = {FAN6_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan6_pwm); +FAN_SYSFS_ATTR_DATA data_fan7_pwm = {FAN7_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan7_pwm); +FAN_SYSFS_ATTR_DATA data_fan8_pwm = {FAN8_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan8_pwm); +FAN_SYSFS_ATTR_DATA data_fan9_pwm = {FAN9_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan9_pwm); +FAN_SYSFS_ATTR_DATA data_fan10_pwm = {FAN10_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan10_pwm); +FAN_SYSFS_ATTR_DATA data_fan11_pwm = {FAN11_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan11_pwm); +FAN_SYSFS_ATTR_DATA data_fan12_pwm = {FAN12_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan12_pwm); +FAN_SYSFS_ATTR_DATA data_fan13_pwm = {FAN13_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan13_pwm); +FAN_SYSFS_ATTR_DATA data_fan14_pwm = {FAN14_PWM, S_IRUGO | S_IWUSR, fan_show_default, NULL, sonic_i2c_get_fan_pwm_default, NULL, fan_store_default, NULL, sonic_i2c_set_fan_pwm_default, NULL, NULL}; +EXPORT_SYMBOL(data_fan14_pwm); + + +FAN_SYSFS_ATTR_DATA data_fan1_fault = {FAN1_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan1_fault); +FAN_SYSFS_ATTR_DATA data_fan2_fault = {FAN2_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan2_fault); +FAN_SYSFS_ATTR_DATA data_fan3_fault = {FAN3_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan3_fault); +FAN_SYSFS_ATTR_DATA data_fan4_fault = {FAN4_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan4_fault); +FAN_SYSFS_ATTR_DATA data_fan5_fault = {FAN5_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan5_fault); +FAN_SYSFS_ATTR_DATA data_fan6_fault = {FAN6_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan6_fault); +FAN_SYSFS_ATTR_DATA data_fan7_fault = {FAN7_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan7_fault); +FAN_SYSFS_ATTR_DATA data_fan8_fault = {FAN8_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan8_fault); +FAN_SYSFS_ATTR_DATA data_fan9_fault = {FAN9_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan9_fault); +FAN_SYSFS_ATTR_DATA data_fan10_fault = {FAN10_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan10_fault); +FAN_SYSFS_ATTR_DATA data_fan11_fault = {FAN11_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +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); +FAN_SYSFS_ATTR_DATA data_fan13_fault = {FAN13_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan13_fault); +FAN_SYSFS_ATTR_DATA data_fan14_fault = {FAN14_FAULT, S_IRUGO, fan_show_default, NULL, sonic_i2c_get_fan_fault_default, NULL, NULL, NULL, NULL, NULL, NULL}; +EXPORT_SYMBOL(data_fan14_fault); + + +FAN_SYSFS_ATTR_DATA_ENTRY fan_sysfs_attr_data_tbl[]= +{ + { "fan1_present", &data_fan1_present}, + { "fan2_present", &data_fan2_present}, + { "fan3_present", &data_fan3_present}, + { "fan4_present", &data_fan4_present}, + { "fan5_present", &data_fan5_present}, + { "fan6_present", &data_fan6_present}, + { "fan7_present", &data_fan7_present}, + { "fan8_present", &data_fan8_present}, + { "fan9_present", &data_fan9_present}, + { "fan10_present", &data_fan10_present}, + { "fan11_present", &data_fan11_present}, + { "fan12_present", &data_fan12_present}, + { "fan13_present", &data_fan13_present}, + { "fan14_present", &data_fan14_present}, + { "fan1_direction", &data_fan1_direction}, + { "fan2_direction", &data_fan2_direction}, + { "fan3_direction", &data_fan3_direction}, + { "fan4_direction", &data_fan4_direction}, + { "fan5_direction", &data_fan5_direction}, + { "fan6_direction", &data_fan6_direction}, + { "fan7_direction", &data_fan7_direction}, + { "fan8_direction", &data_fan8_direction}, + { "fan9_direction", &data_fan9_direction}, + { "fan10_direction", &data_fan10_direction}, + { "fan11_direction", &data_fan11_direction}, + { "fan12_direction", &data_fan12_direction}, + { "fan13_direction", &data_fan13_direction}, + { "fan14_direction", &data_fan14_direction}, + { "fan1_input", &data_fan1_input}, + { "fan2_input", &data_fan2_input}, + { "fan3_input", &data_fan3_input}, + { "fan4_input", &data_fan4_input}, + { "fan5_input", &data_fan5_input}, + { "fan6_input", &data_fan6_input}, + { "fan7_input", &data_fan7_input}, + { "fan8_input", &data_fan8_input}, + { "fan9_input", &data_fan9_input}, + { "fan10_input", &data_fan10_input}, + { "fan11_input", &data_fan11_input}, + { "fan12_input", &data_fan12_input}, + { "fan13_input", &data_fan13_input}, + { "fan14_input", &data_fan14_input}, + { "fan1_pwm", &data_fan1_pwm}, + { "fan2_pwm", &data_fan2_pwm}, + { "fan3_pwm", &data_fan3_pwm}, + { "fan4_pwm", &data_fan4_pwm}, + { "fan5_pwm", &data_fan5_pwm}, + { "fan6_pwm", &data_fan6_pwm}, + { "fan7_pwm", &data_fan7_pwm}, + { "fan8_pwm", &data_fan8_pwm}, + { "fan9_pwm", &data_fan9_pwm}, + { "fan10_pwm", &data_fan10_pwm}, + { "fan11_pwm", &data_fan11_pwm}, + { "fan12_pwm", &data_fan12_pwm}, + { "fan13_pwm", &data_fan13_pwm}, + { "fan14_pwm", &data_fan14_pwm}, + { "fan1_fault", &data_fan1_fault}, + { "fan2_fault", &data_fan2_fault}, + { "fan3_fault", &data_fan3_fault}, + { "fan4_fault", &data_fan4_fault}, + { "fan5_fault", &data_fan5_fault}, + { "fan6_fault", &data_fan6_fault}, + { "fan7_fault", &data_fan7_fault}, + { "fan8_fault", &data_fan8_fault}, + { "fan9_fault", &data_fan9_fault}, + { "fan10_fault", &data_fan10_fault}, + { "fan11_fault", &data_fan11_fault}, + { "fan12_fault", &data_fan12_fault}, + { "fan13_fault", &data_fan13_fault}, + { "fan14_fault", &data_fan14_fault}, +}; + +void *get_fan_access_data(char *name) +{ + int i=0; + for(i=0; i<(sizeof(fan_sysfs_attr_data_tbl)/sizeof(fan_sysfs_attr_data_tbl[0])); i++) + { + if(strcmp(name, fan_sysfs_attr_data_tbl[i].name) ==0) + { + return &fan_sysfs_attr_data_tbl[i]; + } + } + return NULL; +} +EXPORT_SYMBOL(get_fan_access_data); + + + +static int pddf_fan_probe(struct i2c_client *client, + const struct i2c_device_id *dev_id) +{ + struct fan_data *data; + int status=0,i,num, j=0; + FAN_PDATA *fan_platform_data; + FAN_DATA_ATTR *data_attr; + FAN_SYSFS_ATTR_DATA_ENTRY *sysfs_data_entry; + char new_str[ATTR_NAME_LEN] = ""; + + if (client == NULL) { + printk("NULL Client.. \n"); + goto exit; + } + + if (pddf_fan_ops.pre_probe) + { + status = (pddf_fan_ops.pre_probe)(client, dev_id); + if (status != 0) + goto exit; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { + status = -EIO; + goto exit; + } + + /* Add support for a pre probe function */ + data = kzalloc(sizeof(struct fan_data), GFP_KERNEL); + if (!data) { + status = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + dev_info(&client->dev, "chip found\n"); + + + /*Take control of the platform data*/ + fan_platform_data = (FAN_PDATA *)(client->dev.platform_data); + num = fan_platform_data->len; + data->num_attr = num; + + for (i=0;ifan_attrs + i; + sysfs_data_entry = get_fan_access_data(data_attr->aname); + if (sysfs_data_entry == NULL) + { + printk(KERN_ERR "%s: Wrong attribute name provided by user '%s'\n", __FUNCTION__, data_attr->aname); + 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, data_attr->aname); + 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; + dy_ptr->index = sysfs_data_entry->a_ptr->index; + + data->fan_attribute_list[i] = &dy_ptr->dev_attr.attr; + strcpy(data->attr_info[i].name, data_attr->aname); + 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,"")) + { + 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); + 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; + dy_ptr->index = sysfs_data_entry->a_ptr->index; + + data->fan_attribute_list[num+j] = &dy_ptr->dev_attr.attr; + j++; + strcpy(new_str, ""); + } + } + data->fan_attribute_list[i+j] = NULL; + data->fan_attribute_group.attrs = data->fan_attribute_list; + + /* Register sysfs hooks */ + status = sysfs_create_group(&client->dev.kobj, &data->fan_attribute_group); + if (status) { + goto exit_free; + } + + data->hwmon_dev = hwmon_device_register_with_info(&client->dev, client->name, NULL, NULL, NULL); + if (IS_ERR(data->hwmon_dev)) { + status = PTR_ERR(data->hwmon_dev); + goto exit_remove; + } + + dev_info(&client->dev, "%s: fan '%s'\n", + dev_name(data->hwmon_dev), client->name); + + /* Add a support for post probe function */ + if (pddf_fan_ops.post_probe) + { + status = (pddf_fan_ops.post_probe)(client, dev_id); + if (status != 0) + goto exit_remove; + } + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &data->fan_attribute_group); +exit_free: + /* Free all the allocated attributes */ + for (i=0; data->fan_attribute_list[i]!=NULL; i++) + { + struct sensor_device_attribute *ptr = (struct sensor_device_attribute *)data->fan_attribute_list[i]; + kfree(ptr); + } + pddf_dbg(FAN, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__); + kfree(data); +exit: + return status; +} + +static int pddf_fan_remove(struct i2c_client *client) +{ + int i = 0, ret = 0; + struct sensor_device_attribute *ptr = NULL; + struct fan_data *data = i2c_get_clientdata(client); + FAN_PDATA *platdata = (FAN_PDATA *)client->dev.platform_data; + FAN_DATA_ATTR *platdata_sub = platdata->fan_attrs; + + if (pddf_fan_ops.pre_remove) + { + ret = (pddf_fan_ops.pre_remove)(client); + if (ret!=0) + printk(KERN_ERR "FAN pre_remove function failed\n"); + } + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &data->fan_attribute_group); + for (i=0; data->fan_attribute_list[i]!=NULL; i++) + { + ptr = (struct sensor_device_attribute *)data->fan_attribute_list[i]; + kfree(ptr); + } + pddf_dbg(FAN, KERN_ERR "%s: Freed all the memory allocated for attributes\n", __FUNCTION__); + kfree(data); + + if (platdata_sub) { + printk(KERN_DEBUG "%s: Freeing platform subdata\n", __FUNCTION__); + kfree(platdata_sub); + } + if (platdata) { + printk(KERN_DEBUG "%s: Freeing platform data\n", __FUNCTION__); + kfree(platdata); + } + + if (pddf_fan_ops.post_remove) + { + ret = (pddf_fan_ops.post_remove)(client); + if (ret!=0) + printk(KERN_ERR "FAN post_remove function failed\n"); + } + + return 0; +} + +/* Addresses to scan */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +static const struct i2c_device_id pddf_fan_id[] = { + { "fan_ctrl", 0 }, + { "fan_cpld", 1 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, pddf_fan_id); + +static struct i2c_driver pddf_fan_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = DRVNAME, + }, + .probe = pddf_fan_probe, + .remove = pddf_fan_remove, + .id_table = pddf_fan_id, + .address_list = normal_i2c, +}; + +static int __init pddf_fan_init(void) +{ + int status = 0; + + if (pddf_fan_ops.pre_init) + { + status = (pddf_fan_ops.pre_init)(); + if (status!=0) + return status; + } + + status = i2c_add_driver(&pddf_fan_driver); + if (status!=0) + return status; + + if (pddf_fan_ops.post_init) + { + status = (pddf_fan_ops.post_init)(); + if (status!=0) + return status; + } + return status; + +} + +static void __exit pddf_fan_exit(void) +{ + if (pddf_fan_ops.pre_exit) (pddf_fan_ops.pre_exit)(); + i2c_del_driver(&pddf_fan_driver); + if (pddf_fan_ops.post_exit) (pddf_fan_ops.post_exit)(); +} + +module_init(pddf_fan_init); +module_exit(pddf_fan_exit); + +MODULE_AUTHOR("Broadcom, yajiang@celestica.com"); +MODULE_DESCRIPTION("pddf_fan driver"); +MODULE_LICENSE("GPL"); \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/pddf_custom_fan_driver.h b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/pddf_custom_fan_driver.h new file mode 100644 index 000000000000..e1ef562ecd76 --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/pddf_custom_fan_driver.h @@ -0,0 +1,117 @@ +/* + * Copyright 2019 Broadcom. + * The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * 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. + * + * + * Description + * FAN driver related data structures + */ +#ifndef __PDDF_FAN_DRIVER_H__ +#define __PDDF_FAN_DRIVER_H__ + +enum fan_sysfs_attributes { + FAN1_PRESENT, + FAN2_PRESENT, + FAN3_PRESENT, + FAN4_PRESENT, + FAN5_PRESENT, + FAN6_PRESENT, + FAN7_PRESENT, + FAN8_PRESENT, + FAN9_PRESENT, + FAN10_PRESENT, + FAN11_PRESENT, + FAN12_PRESENT, + FAN13_PRESENT, + FAN14_PRESENT, + FAN1_DIRECTION, + FAN2_DIRECTION, + FAN3_DIRECTION, + FAN4_DIRECTION, + FAN5_DIRECTION, + FAN6_DIRECTION, + FAN7_DIRECTION, + FAN8_DIRECTION, + FAN9_DIRECTION, + FAN10_DIRECTION, + FAN11_DIRECTION, + FAN12_DIRECTION, + FAN13_DIRECTION, + FAN14_DIRECTION, + FAN1_INPUT, + FAN2_INPUT, + FAN3_INPUT, + FAN4_INPUT, + FAN5_INPUT, + FAN6_INPUT, + FAN7_INPUT, + FAN8_INPUT, + FAN9_INPUT, + FAN10_INPUT, + FAN11_INPUT, + FAN12_INPUT, + FAN13_INPUT, + FAN14_INPUT, + FAN1_PWM, + FAN2_PWM, + FAN3_PWM, + FAN4_PWM, + FAN5_PWM, + FAN6_PWM, + FAN7_PWM, + FAN8_PWM, + FAN9_PWM, + FAN10_PWM, + FAN11_PWM, + FAN12_PWM, + FAN13_PWM, + FAN14_PWM, + FAN1_FAULT, + FAN2_FAULT, + FAN3_FAULT, + FAN4_FAULT, + FAN5_FAULT, + FAN6_FAULT, + FAN7_FAULT, + FAN8_FAULT, + FAN9_FAULT, + FAN10_FAULT, + FAN11_FAULT, + FAN12_FAULT, + FAN13_FAULT, + FAN14_FAULT, + FAN_MAX_ATTR +}; +/* Each client has this additional data */ +struct fan_attr_info { + char name[ATTR_NAME_LEN]; + struct mutex update_lock; + char valid; /* != 0 if registers are valid */ + unsigned long last_updated; /* In jiffies */ + union { + char strval[STR_ATTR_SIZE]; + int intval; + u16 shortval; + u8 charval; + }val; +}; + +struct fan_data { + struct device *hwmon_dev; + int num_attr; + struct attribute *fan_attribute_list[MAX_FAN_ATTRS]; + struct attribute_group fan_attribute_group; + struct fan_attr_info attr_info[MAX_FAN_ATTRS]; +}; + +#endif \ No newline at end of file diff --git a/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/readme.txt b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/readme.txt new file mode 100644 index 000000000000..e38ae3d9cceb --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/silverstone-v2/modules/pddf_fan_custom/readme.txt @@ -0,0 +1,2 @@ +5/23/2023: Added information about the seventh fan drawers + -yajiang@celestica.com \ No newline at end of file