summaryrefslogtreecommitdiffstats
path: root/meta-phosphor/common/recipes-kernel/linux/linux-obmc/0001-hwmon-Add-support-for-MAX31785-intelligent-fan-contr.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-phosphor/common/recipes-kernel/linux/linux-obmc/0001-hwmon-Add-support-for-MAX31785-intelligent-fan-contr.patch')
-rw-r--r--meta-phosphor/common/recipes-kernel/linux/linux-obmc/0001-hwmon-Add-support-for-MAX31785-intelligent-fan-contr.patch821
1 files changed, 0 insertions, 821 deletions
diff --git a/meta-phosphor/common/recipes-kernel/linux/linux-obmc/0001-hwmon-Add-support-for-MAX31785-intelligent-fan-contr.patch b/meta-phosphor/common/recipes-kernel/linux/linux-obmc/0001-hwmon-Add-support-for-MAX31785-intelligent-fan-contr.patch
deleted file mode 100644
index 8ade1be61..000000000
--- a/meta-phosphor/common/recipes-kernel/linux/linux-obmc/0001-hwmon-Add-support-for-MAX31785-intelligent-fan-contr.patch
+++ /dev/null
@@ -1,821 +0,0 @@
-From b3991e27b26930ef46206dad17715d8ac2f38a4e Mon Sep 17 00:00:00 2001
-From: Timothy Pearson <tpearson@raptorengineering.com>
-Date: Tue, 11 Oct 2016 09:35:51 -0500
-Subject: [PATCH] hwmon: Add support for MAX31785 intelligent fan controller
-
-Add a basic driver for the MAX31785, focusing on the fan control
-features but ignoring the temperature and voltage monitoring
-features of the device.
-
-This driver supports all fan control modes and tachometer / PWM
-readback where applicable.
-
-Signed-off-by: Timothy Pearson <tpearson@raptorengineering.com>
-Signed-off-by: Joel Stanley <joel@jms.id.au>
----
- Documentation/hwmon/max31785 | 36 +++
- drivers/hwmon/Kconfig | 10 +
- drivers/hwmon/Makefile | 1 +
- drivers/hwmon/max31785.c | 714 +++++++++++++++++++++++++++++++++++++++++++
- 4 files changed, 761 insertions(+)
- create mode 100644 Documentation/hwmon/max31785
- create mode 100644 drivers/hwmon/max31785.c
-
-diff --git a/Documentation/hwmon/max31785 b/Documentation/hwmon/max31785
-new file mode 100644
-index 0000000..0911d20
---- /dev/null
-+++ b/Documentation/hwmon/max31785
-@@ -0,0 +1,36 @@
-+Kernel driver max31785
-+======================
-+
-+Supported chips:
-+ * Maxim MAX31785
-+ Prefix: 'max31785'
-+ Addresses scanned: 0x52 0x53 0x54 0x55
-+ Datasheet: http://pdfserv.maximintegrated.com/en/ds/MAX31785.pdf
-+
-+Author: Timothy Pearson <tpearson@raptorengineering.com>
-+
-+
-+Description
-+-----------
-+
-+This driver implements support for the Maxim MAX31785 chip.
-+
-+The MAX31785 controls the speeds of up to six fans using six independent
-+PWM outputs. The desired fan speeds (or PWM duty cycles) are written
-+through the I2C interface. The outputs drive "4-wire" fans directly,
-+or can be used to modulate the fan's power terminals using an external
-+pass transistor.
-+
-+Tachometer inputs monitor fan tachometer logic outputs for precise (+/-1%)
-+monitoring and control of fan RPM as well as detection of fan failure.
-+
-+
-+Sysfs entries
-+-------------
-+
-+fan[1-6]_input RO fan tachometer speed in RPM
-+fan[1-6]_fault RO fan experienced fault
-+fan[1-6]_pulses RW tachometer pulses per fan revolution
-+fan[1-6]_target RW desired fan speed in RPM
-+pwm[1-6]_enable RW pwm mode, 0=disabled, 1=pwm, 2=rpm, 3=automatic
-+pwm[1-6] RW fan target duty cycle (0-255)
-diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
-index 190d270..136605d 100644
---- a/drivers/hwmon/Kconfig
-+++ b/drivers/hwmon/Kconfig
-@@ -886,6 +886,16 @@ config SENSORS_MAX6697
- This driver can also be built as a module. If so, the module
- will be called max6697.
-
-+config SENSORS_MAX31785
-+ tristate "Maxim MAX31785 sensor chip"
-+ depends on I2C
-+ help
-+ If you say yes here you get support for 6-Channel PWM-Output
-+ Fan RPM Controller.
-+
-+ This driver can also be built as a module. If so, the module
-+ will be called max31785.
-+
- config SENSORS_MAX31790
- tristate "Maxim MAX31790 sensor chip"
- depends on I2C
-diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
-index d2cb7e8..e8ba5c6 100644
---- a/drivers/hwmon/Makefile
-+++ b/drivers/hwmon/Makefile
-@@ -119,6 +119,7 @@ obj-$(CONFIG_SENSORS_MAX6639) += max6639.o
- obj-$(CONFIG_SENSORS_MAX6642) += max6642.o
- obj-$(CONFIG_SENSORS_MAX6650) += max6650.o
- obj-$(CONFIG_SENSORS_MAX6697) += max6697.o
-+obj-$(CONFIG_SENSORS_MAX31785) += max31785.o
- obj-$(CONFIG_SENSORS_MAX31790) += max31790.o
- obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
- obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o
-diff --git a/drivers/hwmon/max31785.c b/drivers/hwmon/max31785.c
-new file mode 100644
-index 0000000..fb7b3f0
---- /dev/null
-+++ b/drivers/hwmon/max31785.c
-@@ -0,0 +1,714 @@
-+/*
-+ * max31785.c - Part of lm_sensors, Linux kernel modules for hardware
-+ * monitoring.
-+ *
-+ * (C) 2016 Raptor Engineering, LLC
-+ *
-+ * 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.
-+ */
-+
-+#include <linux/err.h>
-+#include <linux/hwmon.h>
-+#include <linux/hwmon-sysfs.h>
-+#include <linux/i2c.h>
-+#include <linux/init.h>
-+#include <linux/jiffies.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+
-+/* MAX31785 device IDs */
-+#define MAX31785_MFR_ID 0x4d
-+#define MAX31785_MFR_MODEL 0x53
-+
-+/* MAX31785 registers */
-+#define MAX31785_REG_PAGE 0x00
-+#define MAX31785_PAGE_FAN_CONFIG(ch) (0x00 + (ch))
-+#define MAX31785_REG_FAN_CONFIG_1_2 0x3a
-+#define MAX31785_REG_FAN_COMMAND_1 0x3b
-+#define MAX31785_REG_STATUS_FANS_1_2 0x81
-+#define MAX31785_REG_FAN_SPEED_1 0x90
-+#define MAX31785_REG_MFR_ID 0x99
-+#define MAX31785_REG_MFR_MODEL 0x9a
-+#define MAX31785_REG_MFR_FAN_CONFIG 0xf1
-+#define MAX31785_REG_READ_FAN_PWM 0xf3
-+
-+/* Fan Config register bits */
-+#define MAX31785_FAN_CFG_PWM_ENABLE 0x80
-+#define MAX31785_FAN_CFG_CONTROL_MODE_RPM 0x40
-+#define MAX31785_FAN_CFG_PULSE_MASK 0x30
-+#define MAX31785_FAN_CFG_PULSE_SHIFT 4
-+#define MAX31785_FAN_CFG_PULSE_OFFSET 1
-+
-+/* Fan Status register bits */
-+#define MAX31785_FAN_STATUS_FAULT_MASK 0x80
-+
-+/* Fan Command constants */
-+#define MAX31785_FAN_COMMAND_PWM_RATIO 40
-+
-+#define NR_CHANNEL 6
-+
-+/* Addresses to scan */
-+static const unsigned short normal_i2c[] = { 0x52, 0x53, 0x54, 0x55,
-+ I2C_CLIENT_END };
-+
-+/*
-+ * Client data (each client gets its own)
-+ */
-+struct max31785_data {
-+ struct i2c_client *client;
-+ struct mutex device_lock;
-+ bool valid; /* zero until following fields are valid */
-+ unsigned long last_updated; /* in jiffies */
-+
-+ /* register values */
-+ u8 fan_config[NR_CHANNEL];
-+ u16 fan_command[NR_CHANNEL];
-+ u8 mfr_fan_config[NR_CHANNEL];
-+ u8 fault_status[NR_CHANNEL];
-+ u16 tach_rpm[NR_CHANNEL];
-+ u16 pwm[NR_CHANNEL];
-+};
-+
-+static int max31785_set_page(struct i2c_client *client,
-+ u8 page)
-+{
-+ return i2c_smbus_write_byte_data(client,
-+ MAX31785_REG_PAGE,
-+ page);
-+}
-+
-+static int max31785_read_fan_data(struct i2c_client *client,
-+ u8 fan, u8 reg, u8 byte_mode)
-+{
-+ int rv;
-+
-+ rv = max31785_set_page(client, MAX31785_PAGE_FAN_CONFIG(fan));
-+ if (rv < 0)
-+ return rv;
-+
-+ if (byte_mode)
-+ rv = i2c_smbus_read_byte_data(client, reg);
-+ else
-+ rv = i2c_smbus_read_word_data(client, reg);
-+
-+ return rv;
-+}
-+
-+static int max31785_write_fan_data(struct i2c_client *client,
-+ u8 fan, u8 reg, u16 data,
-+ u8 byte_mode)
-+{
-+ int err;
-+
-+ err = max31785_set_page(client, MAX31785_PAGE_FAN_CONFIG(fan));
-+ if (err < 0)
-+ return err;
-+
-+ if (byte_mode)
-+ err = i2c_smbus_write_byte_data(client, reg, data);
-+ else
-+ err = i2c_smbus_write_word_data(client, reg, data);
-+
-+ if (err < 0)
-+ return err;
-+
-+ return 0;
-+}
-+
-+static bool is_automatic_control_mode(struct max31785_data *data,
-+ int index)
-+{
-+ if (data->fan_command[index] > 0x7fff)
-+ return true;
-+ else
-+ return false;
-+}
-+
-+static struct max31785_data *max31785_update_device(struct device *dev)
-+{
-+ struct max31785_data *data = dev_get_drvdata(dev);
-+ struct i2c_client *client = data->client;
-+ struct max31785_data *ret = data;
-+ int i;
-+ int rv;
-+
-+ mutex_lock(&data->device_lock);
-+
-+ if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
-+ for (i = 0; i < NR_CHANNEL; i++) {
-+ rv = max31785_read_fan_data(client, i,
-+ MAX31785_REG_STATUS_FANS_1_2, 1);
-+ if (rv < 0)
-+ goto abort;
-+ data->fault_status[i] = rv;
-+
-+ rv = max31785_read_fan_data(client, i,
-+ MAX31785_REG_FAN_SPEED_1, 0);
-+ if (rv < 0)
-+ goto abort;
-+ data->tach_rpm[i] = rv;
-+
-+ if ((data->fan_config[i]
-+ & MAX31785_FAN_CFG_CONTROL_MODE_RPM)
-+ || is_automatic_control_mode(data, i)) {
-+ rv = max31785_read_fan_data(client, i,
-+ MAX31785_REG_READ_FAN_PWM, 0);
-+ if (rv < 0)
-+ goto abort;
-+ data->pwm[i] = rv;
-+ }
-+
-+ if (!is_automatic_control_mode(data, i)) {
-+ /* Poke watchdog for manual fan control */
-+ rv = max31785_write_fan_data(client,
-+ i, MAX31785_REG_FAN_COMMAND_1,
-+ data->fan_command[i], 0);
-+ if (rv < 0)
-+ goto abort;
-+ }
-+ }
-+
-+ data->last_updated = jiffies;
-+ data->valid = true;
-+ }
-+ goto done;
-+
-+abort:
-+ data->valid = false;
-+ ret = ERR_PTR(rv);
-+
-+done:
-+ mutex_unlock(&data->device_lock);
-+
-+ return ret;
-+}
-+
-+static ssize_t get_fan(struct device *dev,
-+ struct device_attribute *devattr, char *buf)
-+{
-+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+ struct max31785_data *data = max31785_update_device(dev);
-+
-+ if (IS_ERR(data))
-+ return PTR_ERR(data);
-+
-+ return sprintf(buf, "%d\n", data->tach_rpm[attr->index]);
-+}
-+
-+static ssize_t get_fan_target(struct device *dev,
-+ struct device_attribute *devattr, char *buf)
-+{
-+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+ struct max31785_data *data = max31785_update_device(dev);
-+ int rpm;
-+
-+ if (IS_ERR(data))
-+ return PTR_ERR(data);
-+
-+ if (data->fan_config[attr->index]
-+ & MAX31785_FAN_CFG_CONTROL_MODE_RPM)
-+ rpm = data->fan_command[attr->index];
-+ else
-+ rpm = data->fan_command[attr->index]
-+ / MAX31785_FAN_COMMAND_PWM_RATIO;
-+
-+ return sprintf(buf, "%d\n", rpm);
-+}
-+
-+static ssize_t set_fan_target(struct device *dev,
-+ struct device_attribute *devattr,
-+ const char *buf, size_t count)
-+{
-+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+ struct max31785_data *data = dev_get_drvdata(dev);
-+ struct i2c_client *client = data->client;
-+ unsigned long rpm;
-+ int err;
-+
-+ err = kstrtoul(buf, 10, &rpm);
-+ if (err)
-+ return err;
-+
-+ if (rpm > 0x7fff)
-+ return -EINVAL;
-+
-+ mutex_lock(&data->device_lock);
-+
-+ /* Write new RPM value */
-+ data->fan_command[attr->index] = rpm;
-+ err = max31785_write_fan_data(client, attr->index,
-+ MAX31785_REG_FAN_COMMAND_1,
-+ data->fan_command[attr->index], 0);
-+
-+ mutex_unlock(&data->device_lock);
-+
-+ if (err < 0)
-+ return err;
-+
-+ return count;
-+}
-+
-+static ssize_t get_fan_pulses(struct device *dev,
-+ struct device_attribute *devattr, char *buf)
-+{
-+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+ struct max31785_data *data = max31785_update_device(dev);
-+ int pulses;
-+
-+ if (IS_ERR(data))
-+ return PTR_ERR(data);
-+
-+ pulses = ((data->fan_config[attr->index] & MAX31785_FAN_CFG_PULSE_MASK)
-+ >> MAX31785_FAN_CFG_PULSE_SHIFT)
-+ + MAX31785_FAN_CFG_PULSE_OFFSET;
-+
-+ return sprintf(buf, "%d\n", pulses);
-+}
-+
-+static ssize_t set_fan_pulses(struct device *dev,
-+ struct device_attribute *devattr,
-+ const char *buf, size_t count)
-+{
-+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+ struct max31785_data *data = dev_get_drvdata(dev);
-+ struct i2c_client *client = data->client;
-+ unsigned long pulses;
-+ int err;
-+
-+ err = kstrtoul(buf, 10, &pulses);
-+ if (err)
-+ return err;
-+
-+ if (pulses > 4)
-+ return -EINVAL;
-+
-+ data->fan_config[attr->index] &= MAX31785_FAN_CFG_PULSE_MASK;
-+ data->fan_config[attr->index] |=
-+ ((pulses - MAX31785_FAN_CFG_PULSE_OFFSET)
-+ << MAX31785_FAN_CFG_PULSE_SHIFT);
-+
-+ mutex_lock(&data->device_lock);
-+
-+ /* Write new pulse value */
-+ data->fan_command[attr->index] = pulses;
-+ err = max31785_write_fan_data(client, attr->index,
-+ MAX31785_REG_FAN_CONFIG_1_2,
-+ data->fan_config[attr->index], 1);
-+
-+ mutex_unlock(&data->device_lock);
-+
-+ if (err < 0)
-+ return err;
-+
-+ return count;
-+}
-+
-+static ssize_t get_pwm(struct device *dev,
-+ struct device_attribute *devattr, char *buf)
-+{
-+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+ struct max31785_data *data = max31785_update_device(dev);
-+ int pwm;
-+
-+ if (IS_ERR(data))
-+ return PTR_ERR(data);
-+
-+ if ((data->fan_config[attr->index]
-+ & MAX31785_FAN_CFG_CONTROL_MODE_RPM)
-+ || is_automatic_control_mode(data, attr->index))
-+ pwm = data->pwm[attr->index] / 100;
-+ else
-+ pwm = data->fan_command[attr->index]
-+ / MAX31785_FAN_COMMAND_PWM_RATIO;
-+
-+ return sprintf(buf, "%d\n", pwm);
-+}
-+
-+static ssize_t set_pwm(struct device *dev,
-+ struct device_attribute *devattr,
-+ const char *buf, size_t count)
-+{
-+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+ struct max31785_data *data = dev_get_drvdata(dev);
-+ struct i2c_client *client = data->client;
-+ unsigned long pwm;
-+ int err;
-+
-+ err = kstrtoul(buf, 10, &pwm);
-+ if (err)
-+ return err;
-+
-+ if (pwm > 255)
-+ return -EINVAL;
-+
-+ mutex_lock(&data->device_lock);
-+
-+ /* Write new PWM value */
-+ data->fan_command[attr->index] = pwm * MAX31785_FAN_COMMAND_PWM_RATIO;
-+ err = max31785_write_fan_data(client, attr->index,
-+ MAX31785_REG_FAN_COMMAND_1,
-+ data->fan_command[attr->index], 0);
-+
-+ mutex_unlock(&data->device_lock);
-+
-+ if (err < 0)
-+ return err;
-+
-+ return count;
-+}
-+
-+static ssize_t get_pwm_enable(struct device *dev,
-+ struct device_attribute *devattr, char *buf)
-+{
-+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+ struct max31785_data *data = max31785_update_device(dev);
-+ int mode;
-+
-+ if (IS_ERR(data))
-+ return PTR_ERR(data);
-+
-+ if (!(data->fan_config[attr->index] & MAX31785_FAN_CFG_PWM_ENABLE))
-+ mode = 0;
-+ else if (is_automatic_control_mode(data, attr->index))
-+ mode = 3;
-+ else if (data->fan_config[attr->index]
-+ & MAX31785_FAN_CFG_CONTROL_MODE_RPM)
-+ mode = 2;
-+ else
-+ mode = 1;
-+
-+ return sprintf(buf, "%d\n", mode);
-+}
-+
-+static ssize_t set_pwm_enable(struct device *dev,
-+ struct device_attribute *devattr,
-+ const char *buf, size_t count)
-+{
-+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+ struct max31785_data *data = dev_get_drvdata(dev);
-+ struct i2c_client *client = data->client;
-+ unsigned long mode;
-+ int err;
-+
-+ err = kstrtoul(buf, 10, &mode);
-+ if (err)
-+ return err;
-+
-+ switch (mode) {
-+ case 0:
-+ data->fan_config[attr->index] =
-+ data->fan_config[attr->index]
-+ & ~MAX31785_FAN_CFG_PWM_ENABLE;
-+ break;
-+ case 1:
-+ case 2:
-+ case 3:
-+ data->fan_config[attr->index] =
-+ data->fan_config[attr->index]
-+ | MAX31785_FAN_CFG_PWM_ENABLE;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ switch (mode) {
-+ case 0:
-+ break;
-+ case 1:
-+ data->fan_config[attr->index] =
-+ data->fan_config[attr->index]
-+ & ~MAX31785_FAN_CFG_CONTROL_MODE_RPM;
-+ break;
-+ case 2:
-+ data->fan_config[attr->index] =
-+ data->fan_config[attr->index]
-+ | MAX31785_FAN_CFG_CONTROL_MODE_RPM;
-+ break;
-+ case 3:
-+ data->fan_command[attr->index] = 0xffff;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ mutex_lock(&data->device_lock);
-+
-+ err = max31785_write_fan_data(client, attr->index,
-+ MAX31785_REG_FAN_CONFIG_1_2,
-+ data->fan_config[attr->index], 1);
-+
-+ if (err < 0)
-+ goto abort;
-+
-+ err = max31785_write_fan_data(client, attr->index,
-+ MAX31785_REG_FAN_COMMAND_1,
-+ data->fan_command[attr->index], 0);
-+
-+abort:
-+ mutex_unlock(&data->device_lock);
-+
-+ if (err < 0)
-+ return err;
-+
-+ return count;
-+}
-+
-+static ssize_t get_fan_fault(struct device *dev,
-+ struct device_attribute *devattr, char *buf)
-+{
-+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-+ struct max31785_data *data = max31785_update_device(dev);
-+ int fault;
-+
-+ if (IS_ERR(data))
-+ return PTR_ERR(data);
-+
-+ fault = !!(data->fault_status[attr->index]
-+ & MAX31785_FAN_STATUS_FAULT_MASK);
-+
-+ return sprintf(buf, "%d\n", fault);
-+}
-+
-+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, 0);
-+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan, NULL, 1);
-+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, get_fan, NULL, 2);
-+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, get_fan, NULL, 3);
-+static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, get_fan, NULL, 4);
-+static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, get_fan, NULL, 5);
-+
-+static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, get_fan_fault, NULL, 0);
-+static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, get_fan_fault, NULL, 1);
-+static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, get_fan_fault, NULL, 2);
-+static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, get_fan_fault, NULL, 3);
-+static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, get_fan_fault, NULL, 4);
-+static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, get_fan_fault, NULL, 5);
-+
-+static SENSOR_DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO,
-+ get_fan_target, set_fan_target, 0);
-+static SENSOR_DEVICE_ATTR(fan2_target, S_IWUSR | S_IRUGO,
-+ get_fan_target, set_fan_target, 1);
-+static SENSOR_DEVICE_ATTR(fan3_target, S_IWUSR | S_IRUGO,
-+ get_fan_target, set_fan_target, 2);
-+static SENSOR_DEVICE_ATTR(fan4_target, S_IWUSR | S_IRUGO,
-+ get_fan_target, set_fan_target, 3);
-+static SENSOR_DEVICE_ATTR(fan5_target, S_IWUSR | S_IRUGO,
-+ get_fan_target, set_fan_target, 4);
-+static SENSOR_DEVICE_ATTR(fan6_target, S_IWUSR | S_IRUGO,
-+ get_fan_target, set_fan_target, 5);
-+
-+static SENSOR_DEVICE_ATTR(fan1_pulses, S_IWUSR | S_IRUGO,
-+ get_fan_pulses, set_fan_pulses, 0);
-+static SENSOR_DEVICE_ATTR(fan2_pulses, S_IWUSR | S_IRUGO,
-+ get_fan_pulses, set_fan_pulses, 1);
-+static SENSOR_DEVICE_ATTR(fan3_pulses, S_IWUSR | S_IRUGO,
-+ get_fan_pulses, set_fan_pulses, 2);
-+static SENSOR_DEVICE_ATTR(fan4_pulses, S_IWUSR | S_IRUGO,
-+ get_fan_pulses, set_fan_pulses, 3);
-+static SENSOR_DEVICE_ATTR(fan5_pulses, S_IWUSR | S_IRUGO,
-+ get_fan_pulses, set_fan_pulses, 4);
-+static SENSOR_DEVICE_ATTR(fan6_pulses, S_IWUSR | S_IRUGO,
-+ get_fan_pulses, set_fan_pulses, 5);
-+
-+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 0);
-+static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 1);
-+static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 2);
-+static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 3);
-+static SENSOR_DEVICE_ATTR(pwm5, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 4);
-+static SENSOR_DEVICE_ATTR(pwm6, S_IWUSR | S_IRUGO, get_pwm, set_pwm, 5);
-+
-+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
-+ get_pwm_enable, set_pwm_enable, 0);
-+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO,
-+ get_pwm_enable, set_pwm_enable, 1);
-+static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO,
-+ get_pwm_enable, set_pwm_enable, 2);
-+static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO,
-+ get_pwm_enable, set_pwm_enable, 3);
-+static SENSOR_DEVICE_ATTR(pwm5_enable, S_IWUSR | S_IRUGO,
-+ get_pwm_enable, set_pwm_enable, 4);
-+static SENSOR_DEVICE_ATTR(pwm6_enable, S_IWUSR | S_IRUGO,
-+ get_pwm_enable, set_pwm_enable, 5);
-+
-+static struct attribute *max31785_attrs[] = {
-+ &sensor_dev_attr_fan1_input.dev_attr.attr,
-+ &sensor_dev_attr_fan2_input.dev_attr.attr,
-+ &sensor_dev_attr_fan3_input.dev_attr.attr,
-+ &sensor_dev_attr_fan4_input.dev_attr.attr,
-+ &sensor_dev_attr_fan5_input.dev_attr.attr,
-+ &sensor_dev_attr_fan6_input.dev_attr.attr,
-+
-+ &sensor_dev_attr_fan1_fault.dev_attr.attr,
-+ &sensor_dev_attr_fan2_fault.dev_attr.attr,
-+ &sensor_dev_attr_fan3_fault.dev_attr.attr,
-+ &sensor_dev_attr_fan4_fault.dev_attr.attr,
-+ &sensor_dev_attr_fan5_fault.dev_attr.attr,
-+ &sensor_dev_attr_fan6_fault.dev_attr.attr,
-+
-+ &sensor_dev_attr_fan1_target.dev_attr.attr,
-+ &sensor_dev_attr_fan2_target.dev_attr.attr,
-+ &sensor_dev_attr_fan3_target.dev_attr.attr,
-+ &sensor_dev_attr_fan4_target.dev_attr.attr,
-+ &sensor_dev_attr_fan5_target.dev_attr.attr,
-+ &sensor_dev_attr_fan6_target.dev_attr.attr,
-+
-+ &sensor_dev_attr_fan1_pulses.dev_attr.attr,
-+ &sensor_dev_attr_fan2_pulses.dev_attr.attr,
-+ &sensor_dev_attr_fan3_pulses.dev_attr.attr,
-+ &sensor_dev_attr_fan4_pulses.dev_attr.attr,
-+ &sensor_dev_attr_fan5_pulses.dev_attr.attr,
-+ &sensor_dev_attr_fan6_pulses.dev_attr.attr,
-+
-+ &sensor_dev_attr_pwm1.dev_attr.attr,
-+ &sensor_dev_attr_pwm2.dev_attr.attr,
-+ &sensor_dev_attr_pwm3.dev_attr.attr,
-+ &sensor_dev_attr_pwm4.dev_attr.attr,
-+ &sensor_dev_attr_pwm5.dev_attr.attr,
-+ &sensor_dev_attr_pwm6.dev_attr.attr,
-+
-+ &sensor_dev_attr_pwm1_enable.dev_attr.attr,
-+ &sensor_dev_attr_pwm2_enable.dev_attr.attr,
-+ &sensor_dev_attr_pwm3_enable.dev_attr.attr,
-+ &sensor_dev_attr_pwm4_enable.dev_attr.attr,
-+ &sensor_dev_attr_pwm5_enable.dev_attr.attr,
-+ &sensor_dev_attr_pwm6_enable.dev_attr.attr,
-+ NULL
-+};
-+
-+static umode_t max31785_attrs_visible(struct kobject *kobj,
-+ struct attribute *a, int n)
-+{
-+ return a->mode;
-+}
-+
-+static const struct attribute_group max31785_group = {
-+ .attrs = max31785_attrs,
-+ .is_visible = max31785_attrs_visible,
-+};
-+__ATTRIBUTE_GROUPS(max31785);
-+
-+static int max31785_init_client(struct i2c_client *client,
-+ struct max31785_data *data)
-+{
-+ int i, rv;
-+
-+ for (i = 0; i < NR_CHANNEL; i++) {
-+ rv = max31785_read_fan_data(client, i,
-+ MAX31785_REG_FAN_CONFIG_1_2, 1);
-+ if (rv < 0)
-+ return rv;
-+ data->fan_config[i] = rv;
-+
-+ rv = max31785_read_fan_data(client, i,
-+ MAX31785_REG_FAN_COMMAND_1, 0);
-+ if (rv < 0)
-+ return rv;
-+ data->fan_command[i] = rv;
-+
-+ rv = max31785_read_fan_data(client, i,
-+ MAX31785_REG_MFR_FAN_CONFIG, 1);
-+ if (rv < 0)
-+ return rv;
-+ data->mfr_fan_config[i] = rv;
-+
-+ if (!((data->fan_config[i]
-+ & MAX31785_FAN_CFG_CONTROL_MODE_RPM)
-+ || is_automatic_control_mode(data, i))) {
-+ data->pwm[i] = 0;
-+ }
-+ }
-+
-+ return rv;
-+}
-+
-+/* Return 0 if detection is successful, -ENODEV otherwise */
-+static int max31785_detect(struct i2c_client *client,
-+ struct i2c_board_info *info)
-+{
-+ struct i2c_adapter *adapter = client->adapter;
-+ int rv;
-+
-+ if (!i2c_check_functionality(adapter,
-+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
-+ return -ENODEV;
-+
-+ /* Probe manufacturer / model registers */
-+ rv = i2c_smbus_read_byte_data(client, MAX31785_REG_MFR_ID);
-+ if (rv < 0)
-+ return -ENODEV;
-+ if (rv != MAX31785_MFR_ID)
-+ return -ENODEV;
-+
-+ rv = i2c_smbus_read_byte_data(client, MAX31785_REG_MFR_MODEL);
-+ if (rv < 0)
-+ return -ENODEV;
-+ if (rv != MAX31785_MFR_MODEL)
-+ return -ENODEV;
-+
-+ strlcpy(info->type, "max31785", I2C_NAME_SIZE);
-+
-+ return 0;
-+}
-+
-+static int max31785_probe(struct i2c_client *client,
-+ const struct i2c_device_id *id)
-+{
-+ struct i2c_adapter *adapter = client->adapter;
-+ struct device *dev = &client->dev;
-+ struct max31785_data *data;
-+ struct device *hwmon_dev;
-+ int err;
-+
-+ if (!i2c_check_functionality(adapter,
-+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
-+ return -ENODEV;
-+
-+ data = devm_kzalloc(dev, sizeof(struct max31785_data), GFP_KERNEL);
-+ if (!data)
-+ return -ENOMEM;
-+
-+ data->client = client;
-+ mutex_init(&data->device_lock);
-+
-+ /*
-+ * Initialize the max31785 chip
-+ */
-+ err = max31785_init_client(client, data);
-+ if (err)
-+ return err;
-+
-+ hwmon_dev = devm_hwmon_device_register_with_groups(dev,
-+ client->name, data, max31785_groups);
-+
-+ return PTR_ERR_OR_ZERO(hwmon_dev);
-+}
-+
-+static const struct i2c_device_id max31785_id[] = {
-+ { "max31785", 0 },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(i2c, max31785_id);
-+
-+static struct i2c_driver max31785_driver = {
-+ .class = I2C_CLASS_HWMON,
-+ .probe = max31785_probe,
-+ .driver = {
-+ .name = "max31785",
-+ },
-+ .id_table = max31785_id,
-+ .detect = max31785_detect,
-+ .address_list = normal_i2c,
-+};
-+
-+module_i2c_driver(max31785_driver);
-+
-+MODULE_AUTHOR("Timothy Pearson <tpearson@raptorengineering.com>");
-+MODULE_DESCRIPTION("MAX31785 sensor driver");
-+MODULE_LICENSE("GPL");
---
-1.8.3.1
-
OpenPOWER on IntegriCloud