Add MAX31785 driver

Change-Id: Ie435a0dd50cb528d5d3686c586dd65794ec3909e
Signed-off-by: Edward A. James <eajames@us.ibm.com>
diff --git a/meta-phosphor/common/recipes-kernel/linux/linux-obmc.inc b/meta-phosphor/common/recipes-kernel/linux/linux-obmc.inc
index 92aaef2..4702ffe 100644
--- a/meta-phosphor/common/recipes-kernel/linux/linux-obmc.inc
+++ b/meta-phosphor/common/recipes-kernel/linux/linux-obmc.inc
@@ -20,6 +20,7 @@
 SRC_URI += "file://linux-dev-4.10-1-3-drivers-fsi-sbefifo-Add-in-kernel-API.patch"
 SRC_URI += "file://linux-dev-4.10-2-3-drivers-fsi-sbefifo-Add-OCC-driver.patch"
 SRC_URI += "file://0001-arm-dts-aspeed-Add-FSI-devices.patch"
+SRC_URI += "file://0001-hwmon-Add-support-for-MAX31785-intelligent-fan-contr.patch"
 
 LINUX_VERSION_EXTENSION ?= "-${SRCREV}"
 
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
new file mode 100644
index 0000000..8ade1be
--- /dev/null
+++ b/meta-phosphor/common/recipes-kernel/linux/linux-obmc/0001-hwmon-Add-support-for-MAX31785-intelligent-fan-contr.patch
@@ -0,0 +1,821 @@
+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
+