Skip to content

Commit

Permalink
pmbus: Add driver for Maxim MAX31785 Intelligent Fan Controller
Browse files Browse the repository at this point in the history
The Maxim MAX31785 is a PMBus device providing closed-loop, multi-channel
fan management with temperature and remote voltage sensing. It supports
various fan control features, including PWM frequency control, temperature
hysteresis, dual tachometer measurements, and fan health monitoring.

This patch presents a basic driver using only the existing features of the
PMBus subsystem.

Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
[groeck: Modified description to clarify that fan control is not yet provided]
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
  • Loading branch information
Andrew Jeffery authored and Guenter Roeck committed Nov 5, 2017
1 parent 54b943e commit 4d420a6
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 0 deletions.
51 changes: 51 additions & 0 deletions Documentation/hwmon/max31785
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
Kernel driver max31785
======================

Supported chips:
* Maxim MAX31785, MAX31785A
Prefix: 'max31785' or 'max31785a'
Addresses scanned: -
Datasheet: https://datasheets.maximintegrated.com/en/ds/MAX31785.pdf

Author: Andrew Jeffery <andrew@aj.id.au>

Description
-----------

The Maxim MAX31785 is a PMBus device providing closed-loop, multi-channel fan
management with temperature and remote voltage sensing. Various fan control
features are provided, including PWM frequency control, temperature hysteresis,
dual tachometer measurements, and fan health monitoring.

For dual rotor fan configuration, the MAX31785 exposes the slowest rotor of the
two in the fan[1-4]_input attributes.

Usage Notes
-----------

This driver does not probe for PMBus devices. You will have to instantiate
devices explicitly.

Sysfs attributes
----------------

fan[1-4]_alarm Fan alarm.
fan[1-4]_fault Fan fault.
fan[1-4]_input Fan RPM.

in[1-6]_crit Critical maximum output voltage
in[1-6]_crit_alarm Output voltage critical high alarm
in[1-6]_input Measured output voltage
in[1-6]_label "vout[18-23]"
in[1-6]_lcrit Critical minimum output voltage
in[1-6]_lcrit_alarm Output voltage critical low alarm
in[1-6]_max Maximum output voltage
in[1-6]_max_alarm Output voltage high alarm
in[1-6]_min Minimum output voltage
in[1-6]_min_alarm Output voltage low alarm

temp[1-11]_crit Critical high temperature
temp[1-11]_crit_alarm Chip temperature critical high alarm
temp[1-11]_input Measured temperature
temp[1-11]_max Maximum temperature
temp[1-11]_max_alarm Chip temperature high alarm
10 changes: 10 additions & 0 deletions drivers/hwmon/pmbus/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,16 @@ config SENSORS_MAX20751
This driver can also be built as a module. If so, the module will
be called max20751.

config SENSORS_MAX31785
tristate "Maxim MAX31785 and compatibles"
default n
help
If you say yes here you get hardware monitoring support for Maxim
MAX31785.

This driver can also be built as a module. If so, the module will
be called max31785.

config SENSORS_MAX34440
tristate "Maxim MAX34440 and compatibles"
default n
Expand Down
1 change: 1 addition & 0 deletions drivers/hwmon/pmbus/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o
obj-$(CONFIG_SENSORS_LTC3815) += ltc3815.o
obj-$(CONFIG_SENSORS_MAX16064) += max16064.o
obj-$(CONFIG_SENSORS_MAX20751) += max20751.o
obj-$(CONFIG_SENSORS_MAX31785) += max31785.o
obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
obj-$(CONFIG_SENSORS_MAX8688) += max8688.o
obj-$(CONFIG_SENSORS_TPS40422) += tps40422.o
Expand Down
116 changes: 116 additions & 0 deletions drivers/hwmon/pmbus/max31785.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Copyright (C) 2017 IBM Corp.
*
* 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.
*/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include "pmbus.h"

enum max31785_regs {
MFR_REVISION = 0x9b,
};

#define MAX31785_NR_PAGES 23

#define MAX31785_FAN_FUNCS \
(PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12)

#define MAX31785_TEMP_FUNCS \
(PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP)

#define MAX31785_VOUT_FUNCS \
(PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT)

static const struct pmbus_driver_info max31785_info = {
.pages = MAX31785_NR_PAGES,

/* RPM */
.format[PSC_FAN] = direct,
.m[PSC_FAN] = 1,
.b[PSC_FAN] = 0,
.R[PSC_FAN] = 0,
.func[0] = MAX31785_FAN_FUNCS,
.func[1] = MAX31785_FAN_FUNCS,
.func[2] = MAX31785_FAN_FUNCS,
.func[3] = MAX31785_FAN_FUNCS,
.func[4] = MAX31785_FAN_FUNCS,
.func[5] = MAX31785_FAN_FUNCS,

.format[PSC_TEMPERATURE] = direct,
.m[PSC_TEMPERATURE] = 1,
.b[PSC_TEMPERATURE] = 0,
.R[PSC_TEMPERATURE] = 2,
.func[6] = MAX31785_TEMP_FUNCS,
.func[7] = MAX31785_TEMP_FUNCS,
.func[8] = MAX31785_TEMP_FUNCS,
.func[9] = MAX31785_TEMP_FUNCS,
.func[10] = MAX31785_TEMP_FUNCS,
.func[11] = MAX31785_TEMP_FUNCS,
.func[12] = MAX31785_TEMP_FUNCS,
.func[13] = MAX31785_TEMP_FUNCS,
.func[14] = MAX31785_TEMP_FUNCS,
.func[15] = MAX31785_TEMP_FUNCS,
.func[16] = MAX31785_TEMP_FUNCS,

.format[PSC_VOLTAGE_OUT] = direct,
.m[PSC_VOLTAGE_OUT] = 1,
.b[PSC_VOLTAGE_OUT] = 0,
.R[PSC_VOLTAGE_OUT] = 0,
.func[17] = MAX31785_VOUT_FUNCS,
.func[18] = MAX31785_VOUT_FUNCS,
.func[19] = MAX31785_VOUT_FUNCS,
.func[20] = MAX31785_VOUT_FUNCS,
.func[21] = MAX31785_VOUT_FUNCS,
.func[22] = MAX31785_VOUT_FUNCS,
};

static int max31785_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct pmbus_driver_info *info;
s64 ret;

info = devm_kzalloc(dev, sizeof(struct pmbus_driver_info), GFP_KERNEL);
if (!info)
return -ENOMEM;

*info = max31785_info;

ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 255);
if (ret < 0)
return ret;

return pmbus_do_probe(client, id, info);
}

static const struct i2c_device_id max31785_id[] = {
{ "max31785", 0 },
{ "max31785a", 0 },
{ },
};

MODULE_DEVICE_TABLE(i2c, max31785_id);

static struct i2c_driver max31785_driver = {
.driver = {
.name = "max31785",
},
.probe = max31785_probe,
.remove = pmbus_do_remove,
.id_table = max31785_id,
};

module_i2c_driver(max31785_driver);

MODULE_AUTHOR("Andrew Jeffery <andrew@aj.id.au>");
MODULE_DESCRIPTION("PMBus driver for the Maxim MAX31785");
MODULE_LICENSE("GPL");

0 comments on commit 4d420a6

Please sign in to comment.