platform/nephos/sonic-platform-modules-pegatron/common/modules/pegatron_hwmon_mcu.c (1,070 lines of code) (raw):

/* * A MCU driver connect to hwmon * * Copyright (C) 2018 Pegatron Corporation. * Peter5_Lin <Peter5_Lin@pegatroncorp.com.tw> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/module.h> #include <linux/i2c.h> #include <linux/slab.h> #include <linux/list.h> #include <linux/dmi.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/err.h> #include <linux/mutex.h> #undef pega_DEBUG /*#define pega_DEBUG*/ #ifdef pega_DEBUG #define DBG(x) x #else #define DBG(x) #endif /* DEBUG */ #define FW_UPGRADE_COMMAND 0xA5 #define FAN_DISABLE_COMMAND 0x20 #define FAN_ENABLE_COMMAND 0x21 #define FAN_LED_SETTO_MANUAL_COMMAND 0x30 #define FAN_LED_SETTO_AUTO_COMMAND 0x31 #define FAN_LED_GREENON_COMMAND 0x40 #define FAN_LED_GREENOFF_COMMAND 0x41 #define FAN_LED_AMBERON_COMMAND 0x50 #define FAN_LED_AMBEROFF_COMMAND 0x51 #define SMART_FAN_ENABLE_BIT 0 #define SMART_FAN_SETTING_ENABLE_BIT 0 #define SA56004X_REMOTE_TEMP_ALERT_BIT 4 #define I2C_FANBOARD_TIMEOUT_BIT 0 #define ALERT_MODE_BIT 0 #define GET_BIT(data, bit, value) value = (data >> bit) & 0x1 #define SET_BIT(data, bit) data |= (1 << bit) #define CLEAR_BIT(data, bit) data &= ~(1 << bit) enum chips { mercedes3 = 0, cadillac, porsche, }; enum fan_alert { FAN_OUTER_RPM_OVER_ALERT_BIT = 0, FAN_OUTER_RPM_UNDER_ALERT_BIT, FAN_INNER_RPM_OVER_ALERT_BIT, FAN_INNER_RPM_UNDER_ALERT_BIT, FAN_CONNECT_ALERT_BIT, FAN_DISCONNECT_ALERT_BIT, }; enum fan_status { FAN_ALERT_BIT = 2, FAN_LED_AMBER_BIT, FAN_LED_GREEN_BIT, FAN_LED_AUTO_BIT, FAN_ENABLE_BIT, FAN_PRESENT_BIT, }; enum hwmon_mcu_register { MB_FW_UG_REG = 0, FB_FW_UG_REG, MB_HW_VER_REG, FB_HW_SKUVER_REG, MB_FW_VER_REG, FB_FW_VER_REG, FAN_PWM_REG = 16, SF_ENABLE_REG, SF_SETTING_ENABLE_REG, SF_DEVICE_REG, SF_UPDATE_REG, SF_TEMP_MAX_REG, SF_TEMP_MID_REG, SF_TEMP_MIN_REG, SF_PWM_MAX_REG, SF_PWM_MID_REG, SF_PWM_MIN_REG, FAN1_INNER_RPM_REG = 32, FAN2_INNER_RPM_REG, FAN3_INNER_RPM_REG, FAN4_INNER_RPM_REG, FAN5_INNER_RPM_REG, FAN1_OUTER_RPM_REG = 48, FAN2_OUTER_RPM_REG, FAN3_OUTER_RPM_REG, FAN4_OUTER_RPM_REG, FAN5_OUTER_RPM_REG, FAN1_STATUS_REG = 64, FAN2_STATUS_REG, FAN3_STATUS_REG, FAN4_STATUS_REG, FAN5_STATUS_REG, ADC_UNDER_VOL_ALERT_REG = 80, ADC_OVER_VOL_ALERT_REG, TS_OVER_TEMP_ALERT_REG, FAN1_ALERT_REG, FAN2_ALERT_REG, FAN3_ALERT_REG, FAN4_ALERT_REG, FAN5_ALERT_REG, I2C_BUS_ALERT_REG, ALERT_MODE_REG, MONITOR_ADC_VOLTAGE_REG = 96, LM_0X49_TEMP_REG = 112, LM_0X48_TEMP_REG, SA56004X_LOCAL_TEMP_REG, SA56004X_REMOTE_TEMP_REG, }; static struct mutex pega_hwmon_mcu_lock; static int pega_hwmon_mcu_read(struct i2c_client *client, u8 reg) { int data = -EPERM; mutex_lock(&pega_hwmon_mcu_lock); data = i2c_smbus_read_word_data(client, reg); mutex_unlock(&pega_hwmon_mcu_lock); return data; } static int pega_hwmon_mcu_write(struct i2c_client *client, u8 reg, u8 val) { int ret = -EIO; mutex_lock(&pega_hwmon_mcu_lock); ret = i2c_smbus_write_byte_data(client, reg, val); mutex_unlock(&pega_hwmon_mcu_lock); return ret; } static ssize_t mainBoardUpgrade(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = MB_FW_UG_REG; long val = 0; if (kstrtol(buf, 16, &val)) { return -EINVAL; } if(val) pega_hwmon_mcu_write(client, reg, FW_UPGRADE_COMMAND); else pega_hwmon_mcu_write(client, reg, 0xff); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, FW_UPGRADE_COMMAND)); return count; } static ssize_t fanBoardUpgrade(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = FB_FW_UG_REG; long val = 0; if (kstrtol(buf, 16, &val)) { return -EINVAL; } if(val) pega_hwmon_mcu_write(client, reg, FW_UPGRADE_COMMAND); else pega_hwmon_mcu_write(client, reg, 0xff); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, FW_UPGRADE_COMMAND)); return count; } static ssize_t get_MB_HW_version(struct device *dev, struct device_attribute *da, char *buf) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = MB_HW_VER_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); data &= 0x1f; return sprintf(buf, "%02x\n", data); } static ssize_t get_FB_HW_version(struct device *dev, struct device_attribute *da, char *buf) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = FB_HW_SKUVER_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); data = (data >> 5) & 0x7; return sprintf(buf, "%02x\n", data); } static ssize_t get_FB_boardId(struct device *dev, struct device_attribute *da, char *buf) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = FB_HW_SKUVER_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); data &= 0x1f; return sprintf(buf, "%02x\n", data); } static ssize_t get_MB_FW_version(struct device *dev, struct device_attribute *da, char *buf) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0, major_ver = 0, minor_ver = 0; u8 reg = MB_FW_VER_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); major_ver = (data >> 4) & 0xf; minor_ver = data & 0xf; return sprintf(buf, "%d.%d\n", major_ver, minor_ver); } static ssize_t get_FB_FW_version(struct device *dev, struct device_attribute *da, char *buf) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0, major_ver = 0, minor_ver = 0; u8 reg = FB_FW_VER_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); major_ver = (data >> 4) & 0xf; minor_ver = data & 0xf; return sprintf(buf, "%d.%d\n", major_ver, minor_ver); } static ssize_t get_fan_PWM(struct device *dev, struct device_attribute *da, char *buf) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = FAN_PWM_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); return sprintf(buf, "%d\n", data); } static ssize_t set_fan_pwm(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = FAN_PWM_REG; long val = 0; if (kstrtol(buf, 10, &val)) { return -EINVAL; } DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); pega_hwmon_mcu_write(client, reg, val); return count; } static ssize_t get_smartFan_enable(struct device *dev, struct device_attribute *da, char *buf) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0, val = 0; u8 reg = SF_ENABLE_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, SMART_FAN_ENABLE_BIT, val); return sprintf(buf, "%d\n", val); } static ssize_t set_smartFan_enable(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_ENABLE_REG; long val = 0; if (kstrtol(buf, 10, &val)) { return -EINVAL; } data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); if(val) SET_BIT(data, SMART_FAN_ENABLE_BIT); else CLEAR_BIT(data, SMART_FAN_ENABLE_BIT); pega_hwmon_mcu_write(client, reg, data); return count; } static ssize_t get_smartFan_setting_enable(struct device *dev, struct device_attribute *da, char *buf) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0, val = 0; u8 reg = SF_SETTING_ENABLE_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, SMART_FAN_SETTING_ENABLE_BIT, val); return sprintf(buf, "%d\n", val); } static ssize_t set_smartFan_setting_enable(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_SETTING_ENABLE_REG; long val = 0; if (kstrtol(buf, 10, &val)) { return -EINVAL; } data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); if(val) SET_BIT(data, SMART_FAN_SETTING_ENABLE_BIT); else CLEAR_BIT(data, SMART_FAN_SETTING_ENABLE_BIT); pega_hwmon_mcu_write(client, reg, data); return count; } static ssize_t get_smartFan_device(struct device *dev, struct device_attribute *da, char *buf) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_DEVICE_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); return sprintf(buf, "%x\n", data); } static ssize_t set_smartFan_device(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_DEVICE_REG; long val = 0; if (kstrtol(buf, 16, &val)) { return -EINVAL; } DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); pega_hwmon_mcu_write(client, reg, val); return count; } static ssize_t get_smartFan_update(struct device *dev, struct device_attribute *da, char *buf) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_UPDATE_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); return sprintf(buf, "%d\n", data); } static ssize_t set_smartFan_update(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_UPDATE_REG; long val = 0; if (kstrtol(buf, 10, &val)) { return -EINVAL; } DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); pega_hwmon_mcu_write(client, reg, val); return count; } static ssize_t get_smartFan_max_temp(struct device *dev, struct device_attribute *da, char *buf) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_TEMP_MAX_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); return sprintf(buf, "%d\n", data); } static ssize_t set_smartFan_max_temp(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_TEMP_MAX_REG; long val = 0; if (kstrtol(buf, 10, &val)) { return -EINVAL; } DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); pega_hwmon_mcu_write(client, reg, val); return count; } static ssize_t get_smartFan_mid_temp(struct device *dev, struct device_attribute *da, char *buf) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_TEMP_MID_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); return sprintf(buf, "%d\n", data); } static ssize_t set_smartFan_mid_temp(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_TEMP_MID_REG; long val = 0; if (kstrtol(buf, 10, &val)) { return -EINVAL; } DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); pega_hwmon_mcu_write(client, reg, val); return count; } static ssize_t get_smartFan_min_temp(struct device *dev, struct device_attribute *da, char *buf) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_TEMP_MID_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); return sprintf(buf, "%d\n", data); } static ssize_t set_smartFan_min_temp(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_TEMP_MID_REG; long val = 0; if (kstrtol(buf, 10, &val)) { return -EINVAL; } DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); pega_hwmon_mcu_write(client, reg, val); return count; } static ssize_t get_smartFan_max_pwm(struct device *dev, struct device_attribute *da, char *buf) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_PWM_MAX_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); return sprintf(buf, "%d\n", data); } static ssize_t set_smartFan_max_pwm(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_PWM_MAX_REG; long val = 0; if (kstrtol(buf, 10, &val)) { return -EINVAL; } DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); pega_hwmon_mcu_write(client, reg, val); return count; } static ssize_t get_smartFan_mid_pwm(struct device *dev, struct device_attribute *da, char *buf) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_PWM_MID_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); return sprintf(buf, "%d\n", data); } static ssize_t set_smartFan_mid_pwm(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_PWM_MID_REG; long val = 0; if (kstrtol(buf, 10, &val)) { return -EINVAL; } DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); pega_hwmon_mcu_write(client, reg, val); return count; } static ssize_t get_smartFan_min_pwm(struct device *dev, struct device_attribute *da, char *buf) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_PWM_MIN_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); return sprintf(buf, "%d\n", data); } static ssize_t set_smartFan_min_pwm(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_PWM_MIN_REG; long val = 0; if (kstrtol(buf, 10, &val)) { return -EINVAL; } DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, val)); pega_hwmon_mcu_write(client, reg, val); return count; } static ssize_t get_fan_inner_rpm(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); u16 data = 0; u8 reg = FAN1_INNER_RPM_REG + attr->index; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); return sprintf(buf, "%d\n", data); } static ssize_t get_fan_outer_rpm(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); u16 data = 0; u8 reg = FAN1_OUTER_RPM_REG + attr->index; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); return sprintf(buf, "%d\n", data); } static ssize_t get_fan_present(struct device *dev, struct device_attribute *da, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct i2c_client *client = to_i2c_client(dev); u8 data = 0, val = 0; u8 reg = FAN1_STATUS_REG + attr->index; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, FAN_PRESENT_BIT, val); return sprintf(buf, "%d\n", val); } static ssize_t get_fan_enable(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); u8 data = 0, val = 0; u8 reg = FAN1_STATUS_REG + attr->index; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, FAN_ENABLE_BIT, val); return sprintf(buf, "%d\n", val); } static ssize_t set_fan_enable(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_PWM_MID_REG; long val = 0; if (kstrtol(buf, 10, &val)) { return -EINVAL; } DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); if(val) pega_hwmon_mcu_write(client, reg, FAN_ENABLE_COMMAND); else pega_hwmon_mcu_write(client, reg, FAN_DISABLE_COMMAND); return count; } static ssize_t get_fan_led_auto(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); u8 data = 0, val = 0; u8 reg = FAN1_STATUS_REG + attr->index; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, FAN_LED_AUTO_BIT, val); return sprintf(buf, "%d\n", val); } static ssize_t set_fan_led_auto(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_PWM_MID_REG; long val = 0; if (kstrtol(buf, 10, &val)) { return -EINVAL; } DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); if(val) pega_hwmon_mcu_write(client, reg, FAN_LED_SETTO_AUTO_COMMAND); else pega_hwmon_mcu_write(client, reg, FAN_LED_SETTO_MANUAL_COMMAND); return count; } static ssize_t get_fan_led_green(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); u8 data = 0, val = 0; u8 reg = FAN1_STATUS_REG + attr->index; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, FAN_LED_GREEN_BIT, val); return sprintf(buf, "%d\n", val); } static ssize_t set_fan_led_green(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_PWM_MID_REG; long val = 0; if (kstrtol(buf, 10, &val)) { return -EINVAL; } DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); if(val) pega_hwmon_mcu_write(client, reg, FAN_LED_GREENON_COMMAND); else pega_hwmon_mcu_write(client, reg, FAN_LED_GREENOFF_COMMAND); return count; } static ssize_t get_fan_led_amber(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); u8 data = 0, val = 0; u8 reg = FAN1_STATUS_REG + attr->index; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, FAN_LED_AMBER_BIT, val); return sprintf(buf, "%d\n", val); } static ssize_t set_fan_led_amber(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = SF_PWM_MID_REG; long val = 0; if (kstrtol(buf, 10, &val)) { return -EINVAL; } DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); if(val) pega_hwmon_mcu_write(client, reg, FAN_LED_AMBERON_COMMAND); else pega_hwmon_mcu_write(client, reg, FAN_LED_AMBEROFF_COMMAND); return count; } static ssize_t get_fan_status_alert(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); u8 data = 0, val = 0; u8 reg = FAN1_STATUS_REG + attr->index; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, FAN_ALERT_BIT, val); return sprintf(buf, "%d\n", val); } static ssize_t get_adc_under_vol_alert(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); u8 data = 0, val = 0; u8 reg = ADC_UNDER_VOL_ALERT_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, attr->index, val); return sprintf(buf, "%d\n", val); } static ssize_t get_adc_over_vol_alert(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); u8 data = 0, val = 0; u8 reg = ADC_OVER_VOL_ALERT_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, attr->index, val); return sprintf(buf, "%d\n", val); } static ssize_t get_temp_alert(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); u8 data = 0, val = 0; u8 reg = TS_OVER_TEMP_ALERT_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, SA56004X_REMOTE_TEMP_ALERT_BIT + attr->index, val); return sprintf(buf, "%d\n", val); } static ssize_t get_fan_outerRPMOver_alert(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); u8 data = 0, val = 0; u8 reg = FAN1_ALERT_REG + attr->index; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, FAN_OUTER_RPM_OVER_ALERT_BIT, val); return sprintf(buf, "%d\n", val); } static ssize_t get_fan_outerRPMUnder_alert(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); u8 data = 0, val = 0; u8 reg = FAN1_ALERT_REG + attr->index; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, FAN_OUTER_RPM_UNDER_ALERT_BIT, val); return sprintf(buf, "%d\n", val); } static ssize_t get_fan_innerRPMOver_alert(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); u8 data = 0, val = 0; u8 reg = FAN1_ALERT_REG + attr->index; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, FAN_INNER_RPM_OVER_ALERT_BIT, val); return sprintf(buf, "%d\n", val); } static ssize_t get_fan_innerRPMUnder_alert(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); u8 data = 0, val = 0; u8 reg = FAN1_ALERT_REG + attr->index; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, FAN_INNER_RPM_UNDER_ALERT_BIT, val); return sprintf(buf, "%d\n", val); } static ssize_t get_fan_connect_alert(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); u8 data = 0, val = 0; u8 reg = FAN1_ALERT_REG + attr->index; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, FAN_CONNECT_ALERT_BIT, val); return sprintf(buf, "%d\n", val); } static ssize_t get_fan_disconnect_alert(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); u8 data = 0, val = 0; u8 reg = FAN1_ALERT_REG + attr->index; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, FAN_DISCONNECT_ALERT_BIT, val); return sprintf(buf, "%d\n", val); } static ssize_t get_i2c_timeout(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); u8 data = 0, val = 0; u8 reg = I2C_BUS_ALERT_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, I2C_FANBOARD_TIMEOUT_BIT + attr->index, val); return sprintf(buf, "%d\n", val); } static ssize_t get_alert_mode(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); u8 data = 0, val = 0; u8 reg = ALERT_MODE_REG; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); GET_BIT(data, ALERT_MODE_BIT, val); return sprintf(buf, "%d\n", val); } static ssize_t set_alert_mode(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); u8 data = 0; u8 reg = ALERT_MODE_REG; long val = 0; if (kstrtol(buf, 10, &val)) { return -EINVAL; } DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, val: %x\r\n", __func__, client->addr, reg, val)); if(val) SET_BIT(data, ALERT_MODE_BIT); else CLEAR_BIT(data, ALERT_MODE_BIT); pega_hwmon_mcu_write(client, reg, data); return count; } static ssize_t get_adc_vol(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); u16 data = 0, reg = MONITOR_ADC_VOLTAGE_REG + attr->index; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); return sprintf(buf, "%d.%02d\n", data/1000, (data/10)%12); } static ssize_t get_hwmon_temp(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); u8 data = 0; u8 reg = LM_0X49_TEMP_REG + attr->index; data = pega_hwmon_mcu_read(client, reg); DBG(printk(KERN_ALERT "%s - addr: 0x%x, reg: %x, data: %x\r\n", __func__, client->addr, reg, data)); return sprintf(buf, "%d\n", data); } #define SET_FAN_ATTR(_num) \ static SENSOR_DEVICE_ATTR(fan##_num##_inner_rpm, S_IRUGO, get_fan_inner_rpm, NULL, _num-1); \ static SENSOR_DEVICE_ATTR(fan##_num##_outer_rpm, S_IRUGO, get_fan_outer_rpm, NULL, _num-1); \ static SENSOR_DEVICE_ATTR(fan##_num##_present, S_IRUGO, get_fan_present, NULL, _num-1); \ static SENSOR_DEVICE_ATTR(fan##_num##_enable, S_IRUGO | S_IWUSR, get_fan_enable, set_fan_enable, _num-1); \ static SENSOR_DEVICE_ATTR(fan##_num##_led_auto, S_IRUGO | S_IWUSR, get_fan_led_auto, set_fan_led_auto, _num-1); \ static SENSOR_DEVICE_ATTR(fan##_num##_led_green, S_IRUGO | S_IWUSR, get_fan_led_green, set_fan_led_green, _num-1); \ static SENSOR_DEVICE_ATTR(fan##_num##_led_amber, S_IRUGO | S_IWUSR, get_fan_led_amber, set_fan_led_amber, _num-1); \ static SENSOR_DEVICE_ATTR(fan##_num##_status_alert, S_IRUGO, get_fan_status_alert, NULL, _num-1); \ static SENSOR_DEVICE_ATTR(fan##_num##_outerRPMOver_alert, S_IRUGO, get_fan_outerRPMOver_alert, NULL, _num-1); \ static SENSOR_DEVICE_ATTR(fan##_num##_outerRPMUnder_alert, S_IRUGO, get_fan_outerRPMUnder_alert, NULL, _num-1); \ static SENSOR_DEVICE_ATTR(fan##_num##_innerRPMOver_alert, S_IRUGO, get_fan_innerRPMOver_alert, NULL, _num-1); \ static SENSOR_DEVICE_ATTR(fan##_num##_innerRPMUnder_alert, S_IRUGO, get_fan_innerRPMUnder_alert, NULL, _num-1); \ static SENSOR_DEVICE_ATTR(fan##_num##_connect_alert, S_IRUGO, get_fan_connect_alert, NULL, _num-1); \ static SENSOR_DEVICE_ATTR(fan##_num##_disconnect_alert, S_IRUGO, get_fan_disconnect_alert, NULL, _num-1) SET_FAN_ATTR(1);SET_FAN_ATTR(2);SET_FAN_ATTR(3);SET_FAN_ATTR(4);SET_FAN_ATTR(5); #define SET_ADC_ATTR(_num) \ static SENSOR_DEVICE_ATTR(ADC##_num##_under_alert, S_IRUGO, get_adc_under_vol_alert, NULL, _num-1); \ static SENSOR_DEVICE_ATTR(ADC##_num##_over_alert, S_IRUGO, get_adc_over_vol_alert, NULL, _num-1); \ static SENSOR_DEVICE_ATTR(ADC##_num##_vol, S_IRUGO, get_adc_vol, NULL, 8-_num) SET_ADC_ATTR(1);SET_ADC_ATTR(2);SET_ADC_ATTR(3);SET_ADC_ATTR(4);SET_ADC_ATTR(5);SET_ADC_ATTR(6);SET_ADC_ATTR(7);SET_ADC_ATTR(8); static SENSOR_DEVICE_ATTR(mb_fw_upgrade, S_IWUSR, NULL, mainBoardUpgrade, 0); static SENSOR_DEVICE_ATTR(fb_fw_upgrade, S_IWUSR, NULL, fanBoardUpgrade, 0); static SENSOR_DEVICE_ATTR(mb_hw_version, S_IRUGO, get_MB_HW_version, NULL, 0); static SENSOR_DEVICE_ATTR(fb_hw_version, S_IRUGO, get_FB_HW_version, NULL, 0); static SENSOR_DEVICE_ATTR(fb_board_id, S_IRUGO, get_FB_boardId, NULL, 0); static SENSOR_DEVICE_ATTR(mb_fw_version, S_IRUGO, get_MB_FW_version, NULL, 0); static SENSOR_DEVICE_ATTR(fb_fw_version, S_IRUGO, get_FB_FW_version, NULL, 0); static SENSOR_DEVICE_ATTR(fan_pwm, S_IRUGO | S_IWUSR, get_fan_PWM, set_fan_pwm, 0); static SENSOR_DEVICE_ATTR(smartFan_enable, S_IRUGO | S_IWUSR, get_smartFan_enable, set_smartFan_enable, 0); static SENSOR_DEVICE_ATTR(smartFan_setting_enable, S_IRUGO | S_IWUSR, get_smartFan_setting_enable, set_smartFan_setting_enable, 0); static SENSOR_DEVICE_ATTR(smartFan_device, S_IRUGO | S_IWUSR, get_smartFan_device, set_smartFan_device, 0); static SENSOR_DEVICE_ATTR(smartFan_update, S_IRUGO | S_IWUSR, get_smartFan_update, set_smartFan_update, 0); static SENSOR_DEVICE_ATTR(smartFan_max_temp, S_IRUGO | S_IWUSR, get_smartFan_max_temp, set_smartFan_max_temp, 0); static SENSOR_DEVICE_ATTR(smartFan_mid_temp, S_IRUGO | S_IWUSR, get_smartFan_mid_temp, set_smartFan_mid_temp, 0); static SENSOR_DEVICE_ATTR(smartFan_min_temp, S_IRUGO | S_IWUSR, get_smartFan_min_temp, set_smartFan_min_temp, 0); static SENSOR_DEVICE_ATTR(smartFan_max_pwm, S_IRUGO | S_IWUSR, get_smartFan_max_pwm, set_smartFan_max_pwm, 0); static SENSOR_DEVICE_ATTR(smartFan_mid_pwm, S_IRUGO | S_IWUSR, get_smartFan_mid_pwm, set_smartFan_mid_pwm, 0); static SENSOR_DEVICE_ATTR(smartFan_min_pwm, S_IRUGO | S_IWUSR, get_smartFan_min_pwm, set_smartFan_min_pwm, 0); static SENSOR_DEVICE_ATTR(lm75_49_temp_alert, S_IRUGO, get_temp_alert, NULL, 3); static SENSOR_DEVICE_ATTR(lm75_48_temp_alert, S_IRUGO, get_temp_alert, NULL, 2); static SENSOR_DEVICE_ATTR(SA56004X_Ltemp_alert, S_IRUGO, get_temp_alert, NULL, 1); static SENSOR_DEVICE_ATTR(SA56004X_Rtemp_alert, S_IRUGO, get_temp_alert, NULL, 0); static SENSOR_DEVICE_ATTR(i2c_fb_timeout, S_IRUGO, get_i2c_timeout, NULL, 0); static SENSOR_DEVICE_ATTR(i2c_remote_timeout, S_IRUGO, get_i2c_timeout, NULL, 1); static SENSOR_DEVICE_ATTR(i2c_local_timeout, S_IRUGO, get_i2c_timeout, NULL, 2); static SENSOR_DEVICE_ATTR(i2c_lm75_48_timeout, S_IRUGO, get_i2c_timeout, NULL, 3); static SENSOR_DEVICE_ATTR(i2c_lm75_49_timeout, S_IRUGO, get_i2c_timeout, NULL, 4); static SENSOR_DEVICE_ATTR(alert_mode, S_IRUGO | S_IWUSR, get_alert_mode, set_alert_mode, 0); static SENSOR_DEVICE_ATTR(lm75_49_temp, S_IRUGO, get_hwmon_temp, NULL, 0); static SENSOR_DEVICE_ATTR(lm75_48_temp, S_IRUGO, get_hwmon_temp, NULL, 1); static SENSOR_DEVICE_ATTR(SA56004_local_temp, S_IRUGO, get_hwmon_temp, NULL, 2); static SENSOR_DEVICE_ATTR(SA56004_remote_temp, S_IRUGO, get_hwmon_temp, NULL, 3); static struct attribute *pega_hwmon_mcu_attributes[] = { &sensor_dev_attr_mb_fw_upgrade.dev_attr.attr, &sensor_dev_attr_fb_fw_upgrade.dev_attr.attr, &sensor_dev_attr_mb_hw_version.dev_attr.attr, &sensor_dev_attr_fb_hw_version.dev_attr.attr, &sensor_dev_attr_fb_board_id.dev_attr.attr, &sensor_dev_attr_mb_fw_version.dev_attr.attr, &sensor_dev_attr_fb_fw_version.dev_attr.attr, &sensor_dev_attr_fan_pwm.dev_attr.attr, &sensor_dev_attr_smartFan_enable.dev_attr.attr, &sensor_dev_attr_smartFan_setting_enable.dev_attr.attr, &sensor_dev_attr_smartFan_device.dev_attr.attr, &sensor_dev_attr_smartFan_update.dev_attr.attr, &sensor_dev_attr_smartFan_max_temp.dev_attr.attr, &sensor_dev_attr_smartFan_mid_temp.dev_attr.attr, &sensor_dev_attr_smartFan_min_temp.dev_attr.attr, &sensor_dev_attr_smartFan_max_pwm.dev_attr.attr, &sensor_dev_attr_smartFan_mid_pwm.dev_attr.attr, &sensor_dev_attr_smartFan_min_pwm.dev_attr.attr, &sensor_dev_attr_fan1_inner_rpm.dev_attr.attr, &sensor_dev_attr_fan2_inner_rpm.dev_attr.attr, &sensor_dev_attr_fan3_inner_rpm.dev_attr.attr, &sensor_dev_attr_fan4_inner_rpm.dev_attr.attr, &sensor_dev_attr_fan5_inner_rpm.dev_attr.attr, &sensor_dev_attr_fan1_outer_rpm.dev_attr.attr, &sensor_dev_attr_fan2_outer_rpm.dev_attr.attr, &sensor_dev_attr_fan3_outer_rpm.dev_attr.attr, &sensor_dev_attr_fan4_outer_rpm.dev_attr.attr, &sensor_dev_attr_fan5_outer_rpm.dev_attr.attr, &sensor_dev_attr_fan1_present.dev_attr.attr, &sensor_dev_attr_fan2_present.dev_attr.attr, &sensor_dev_attr_fan3_present.dev_attr.attr, &sensor_dev_attr_fan4_present.dev_attr.attr, &sensor_dev_attr_fan5_present.dev_attr.attr, &sensor_dev_attr_fan1_enable.dev_attr.attr, &sensor_dev_attr_fan2_enable.dev_attr.attr, &sensor_dev_attr_fan3_enable.dev_attr.attr, &sensor_dev_attr_fan4_enable.dev_attr.attr, &sensor_dev_attr_fan5_enable.dev_attr.attr, &sensor_dev_attr_fan1_led_auto.dev_attr.attr, &sensor_dev_attr_fan2_led_auto.dev_attr.attr, &sensor_dev_attr_fan3_led_auto.dev_attr.attr, &sensor_dev_attr_fan4_led_auto.dev_attr.attr, &sensor_dev_attr_fan5_led_auto.dev_attr.attr, &sensor_dev_attr_fan1_led_green.dev_attr.attr, &sensor_dev_attr_fan2_led_green.dev_attr.attr, &sensor_dev_attr_fan3_led_green.dev_attr.attr, &sensor_dev_attr_fan4_led_green.dev_attr.attr, &sensor_dev_attr_fan5_led_green.dev_attr.attr, &sensor_dev_attr_fan1_led_amber.dev_attr.attr, &sensor_dev_attr_fan2_led_amber.dev_attr.attr, &sensor_dev_attr_fan3_led_amber.dev_attr.attr, &sensor_dev_attr_fan4_led_amber.dev_attr.attr, &sensor_dev_attr_fan5_led_amber.dev_attr.attr, &sensor_dev_attr_fan1_status_alert.dev_attr.attr, &sensor_dev_attr_fan2_status_alert.dev_attr.attr, &sensor_dev_attr_fan3_status_alert.dev_attr.attr, &sensor_dev_attr_fan4_status_alert.dev_attr.attr, &sensor_dev_attr_fan5_status_alert.dev_attr.attr, &sensor_dev_attr_ADC1_under_alert.dev_attr.attr, &sensor_dev_attr_ADC2_under_alert.dev_attr.attr, &sensor_dev_attr_ADC3_under_alert.dev_attr.attr, &sensor_dev_attr_ADC4_under_alert.dev_attr.attr, &sensor_dev_attr_ADC5_under_alert.dev_attr.attr, &sensor_dev_attr_ADC6_under_alert.dev_attr.attr, &sensor_dev_attr_ADC7_under_alert.dev_attr.attr, &sensor_dev_attr_ADC8_under_alert.dev_attr.attr, &sensor_dev_attr_ADC1_over_alert.dev_attr.attr, &sensor_dev_attr_ADC2_over_alert.dev_attr.attr, &sensor_dev_attr_ADC3_over_alert.dev_attr.attr, &sensor_dev_attr_ADC4_over_alert.dev_attr.attr, &sensor_dev_attr_ADC5_over_alert.dev_attr.attr, &sensor_dev_attr_ADC6_over_alert.dev_attr.attr, &sensor_dev_attr_ADC7_over_alert.dev_attr.attr, &sensor_dev_attr_ADC8_over_alert.dev_attr.attr, &sensor_dev_attr_lm75_48_temp_alert.dev_attr.attr, &sensor_dev_attr_lm75_49_temp_alert.dev_attr.attr, &sensor_dev_attr_SA56004X_Ltemp_alert.dev_attr.attr, &sensor_dev_attr_SA56004X_Rtemp_alert.dev_attr.attr, &sensor_dev_attr_fan1_outerRPMOver_alert.dev_attr.attr, &sensor_dev_attr_fan2_outerRPMOver_alert.dev_attr.attr, &sensor_dev_attr_fan3_outerRPMOver_alert.dev_attr.attr, &sensor_dev_attr_fan4_outerRPMOver_alert.dev_attr.attr, &sensor_dev_attr_fan5_outerRPMOver_alert.dev_attr.attr, &sensor_dev_attr_fan1_outerRPMUnder_alert.dev_attr.attr, &sensor_dev_attr_fan2_outerRPMUnder_alert.dev_attr.attr, &sensor_dev_attr_fan3_outerRPMUnder_alert.dev_attr.attr, &sensor_dev_attr_fan4_outerRPMUnder_alert.dev_attr.attr, &sensor_dev_attr_fan5_outerRPMUnder_alert.dev_attr.attr, &sensor_dev_attr_fan1_innerRPMOver_alert.dev_attr.attr, &sensor_dev_attr_fan2_innerRPMOver_alert.dev_attr.attr, &sensor_dev_attr_fan3_innerRPMOver_alert.dev_attr.attr, &sensor_dev_attr_fan4_innerRPMOver_alert.dev_attr.attr, &sensor_dev_attr_fan5_innerRPMOver_alert.dev_attr.attr, &sensor_dev_attr_fan1_innerRPMUnder_alert.dev_attr.attr, &sensor_dev_attr_fan2_innerRPMUnder_alert.dev_attr.attr, &sensor_dev_attr_fan3_innerRPMUnder_alert.dev_attr.attr, &sensor_dev_attr_fan4_innerRPMUnder_alert.dev_attr.attr, &sensor_dev_attr_fan5_innerRPMUnder_alert.dev_attr.attr, &sensor_dev_attr_fan1_connect_alert.dev_attr.attr, &sensor_dev_attr_fan2_connect_alert.dev_attr.attr, &sensor_dev_attr_fan3_connect_alert.dev_attr.attr, &sensor_dev_attr_fan4_connect_alert.dev_attr.attr, &sensor_dev_attr_fan5_connect_alert.dev_attr.attr, &sensor_dev_attr_fan1_disconnect_alert.dev_attr.attr, &sensor_dev_attr_fan2_disconnect_alert.dev_attr.attr, &sensor_dev_attr_fan3_disconnect_alert.dev_attr.attr, &sensor_dev_attr_fan4_disconnect_alert.dev_attr.attr, &sensor_dev_attr_fan5_disconnect_alert.dev_attr.attr, &sensor_dev_attr_i2c_fb_timeout.dev_attr.attr, &sensor_dev_attr_i2c_remote_timeout.dev_attr.attr, &sensor_dev_attr_i2c_local_timeout.dev_attr.attr, &sensor_dev_attr_i2c_lm75_48_timeout.dev_attr.attr, &sensor_dev_attr_i2c_lm75_49_timeout.dev_attr.attr, &sensor_dev_attr_alert_mode.dev_attr.attr, &sensor_dev_attr_ADC1_vol.dev_attr.attr, &sensor_dev_attr_ADC2_vol.dev_attr.attr, &sensor_dev_attr_ADC3_vol.dev_attr.attr, &sensor_dev_attr_ADC4_vol.dev_attr.attr, &sensor_dev_attr_ADC5_vol.dev_attr.attr, &sensor_dev_attr_ADC6_vol.dev_attr.attr, &sensor_dev_attr_ADC7_vol.dev_attr.attr, &sensor_dev_attr_ADC8_vol.dev_attr.attr, &sensor_dev_attr_lm75_49_temp.dev_attr.attr, &sensor_dev_attr_lm75_48_temp.dev_attr.attr, &sensor_dev_attr_SA56004_local_temp.dev_attr.attr, &sensor_dev_attr_SA56004_remote_temp.dev_attr.attr, NULL }; static const struct attribute_group pega_hwmon_mcu_group = { .attrs = pega_hwmon_mcu_attributes}; static int pega_hwmon_mcu_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) { int status; status = sysfs_create_group(&client->dev.kobj, &pega_hwmon_mcu_group); if (status) { goto exit; } dev_info(&client->dev, "chip found\n"); return 0; exit: return status; } static int pega_hwmon_mcu_remove(struct i2c_client *client) { sysfs_remove_group(&client->dev.kobj, &pega_hwmon_mcu_group); return 0; } static const struct i2c_device_id pega_hwmon_mcu_id[] = { { "porsche_hwmon_mcu", porsche }, {} }; MODULE_DEVICE_TABLE(i2c, pega_hwmon_mcu_id); static struct i2c_driver pega_hwmon_mcu_driver = { .class = I2C_CLASS_HWMON, .driver = { .name = "pegatron_hwmon_mcu", }, .probe = pega_hwmon_mcu_probe, .remove = pega_hwmon_mcu_remove, .id_table = pega_hwmon_mcu_id, }; static int __init pega_hwmon_mcu_init(void) { mutex_init(&pega_hwmon_mcu_lock); return i2c_add_driver(&pega_hwmon_mcu_driver); } static void __exit pega_hwmon_mcu_exit(void) { i2c_del_driver(&pega_hwmon_mcu_driver); } MODULE_AUTHOR("Peter5 Lin <Peter5_Lin@pegatroncorp.com.tw>"); MODULE_DESCRIPTION("pega_hwmon_mcu driver"); MODULE_LICENSE("GPL"); module_init(pega_hwmon_mcu_init); module_exit(pega_hwmon_mcu_exit);