Commit 0c0a0615163e025eb978547969467012529e01d5

Authored by Guenter Roeck
1 parent 84fc4585c1

hwmon: (pmbus) Support for TI UCD90xxx series Sequencer and System Health Controllers

Hardware monitoring support for TI UCD90120, UCD90124, UCD9090, and UCD90910
Sequencer and System Health Controllers.

Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
Reviewed-by: Tom Grennan <tom.grennan@ericsson.com>

Showing 4 changed files with 402 additions and 1 deletions Side-by-side Diff

Documentation/hwmon/ucd9000
  1 +Kernel driver ucd9000
  2 +=====================
  3 +
  4 +Supported chips:
  5 + * TI UCD90120, UCD90124, UCD9090, and UCD90910
  6 + Prefixes: 'ucd90120', 'ucd90124', 'ucd9090', 'ucd90910'
  7 + Addresses scanned: -
  8 + Datasheets:
  9 + http://focus.ti.com/lit/ds/symlink/ucd90120.pdf
  10 + http://focus.ti.com/lit/ds/symlink/ucd90124.pdf
  11 + http://focus.ti.com/lit/ds/symlink/ucd9090.pdf
  12 + http://focus.ti.com/lit/ds/symlink/ucd90910.pdf
  13 +
  14 +Author: Guenter Roeck <guenter.roeck@ericsson.com>
  15 +
  16 +
  17 +Description
  18 +-----------
  19 +
  20 +From datasheets:
  21 +
  22 +The UCD90120 Power Supply Sequencer and System Health Monitor monitors and
  23 +sequences up to 12 independent voltage rails. The device integrates a 12-bit
  24 +ADC with a 2.5V internal reference for monitoring up to 13 power supply voltage,
  25 +current, or temperature inputs.
  26 +
  27 +The UCD90124 is a 12-rail PMBus/I2C addressable power-supply sequencer and
  28 +system-health monitor. The device integrates a 12-bit ADC for monitoring up to
  29 +13 power-supply voltage, current, or temperature inputs. Twenty-six GPIO pins
  30 +can be used for power supply enables, power-on reset signals, external
  31 +interrupts, cascading, or other system functions. Twelve of these pins offer PWM
  32 +functionality. Using these pins, the UCD90124 offers support for fan control,
  33 +margining, and general-purpose PWM functions.
  34 +
  35 +The UCD9090 is a 10-rail PMBus/I2C addressable power-supply sequencer and
  36 +monitor. The device integrates a 12-bit ADC for monitoring up to 10 power-supply
  37 +voltage inputs. Twenty-three GPIO pins can be used for power supply enables,
  38 +power-on reset signals, external interrupts, cascading, or other system
  39 +functions. Ten of these pins offer PWM functionality. Using these pins, the
  40 +UCD9090 offers support for margining, and general-purpose PWM functions.
  41 +
  42 +The UCD90910 is a ten-rail I2C / PMBus addressable power-supply sequencer and
  43 +system-health monitor. The device integrates a 12-bit ADC for monitoring up to
  44 +13 power-supply voltage, current, or temperature inputs.
  45 +
  46 +This driver is a client driver to the core PMBus driver. Please see
  47 +Documentation/hwmon/pmbus for details on PMBus client drivers.
  48 +
  49 +
  50 +Usage Notes
  51 +-----------
  52 +
  53 +This driver does not auto-detect devices. You will have to instantiate the
  54 +devices explicitly. Please see Documentation/i2c/instantiating-devices for
  55 +details.
  56 +
  57 +
  58 +Platform data support
  59 +---------------------
  60 +
  61 +The driver supports standard PMBus driver platform data. Please see
  62 +Documentation/hwmon/pmbus for details.
  63 +
  64 +
  65 +Sysfs entries
  66 +-------------
  67 +
  68 +The following attributes are supported. Limits are read-write; all other
  69 +attributes are read-only.
  70 +
  71 +in[1-12]_label "vout[1-12]".
  72 +in[1-12]_input Measured voltage. From READ_VOUT register.
  73 +in[1-12]_min Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
  74 +in[1-12]_max Maximum voltage. From VOUT_OV_WARN_LIMIT register.
  75 +in[1-12]_lcrit Critical minumum Voltage. VOUT_UV_FAULT_LIMIT register.
  76 +in[1-12]_crit Critical maximum voltage. From VOUT_OV_FAULT_LIMIT register.
  77 +in[1-12]_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status.
  78 +in[1-12]_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status.
  79 +in[1-12]_lcrit_alarm Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
  80 +in[1-12]_crit_alarm Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
  81 +
  82 +curr[1-12]_label "iout[1-12]".
  83 +curr[1-12]_input Measured current. From READ_IOUT register.
  84 +curr[1-12]_max Maximum current. From IOUT_OC_WARN_LIMIT register.
  85 +curr[1-12]_lcrit Critical minumum output current. From IOUT_UC_FAULT_LIMIT
  86 + register.
  87 +curr[1-12]_crit Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
  88 +curr[1-12]_max_alarm Current high alarm. From IOUT_OC_WARNING status.
  89 +curr[1-12]_crit_alarm Current critical high alarm. From IOUT_OC_FAULT status.
  90 +
  91 + For each attribute index, either voltage or current is
  92 + reported, but not both. If voltage or current is
  93 + reported depends on the chip configuration.
  94 +
  95 +temp[1-2]_input Measured temperatures. From READ_TEMPERATURE_1 and
  96 + READ_TEMPERATURE_2 registers.
  97 +temp[1-2]_max Maximum temperature. From OT_WARN_LIMIT register.
  98 +temp[1-2]_crit Critical high temperature. From OT_FAULT_LIMIT register.
  99 +temp[1-2]_max_alarm Temperature high alarm.
  100 +temp[1-2]_crit_alarm Temperature critical high alarm.
  101 +
  102 +fan[1-4]_input Fan RPM.
  103 +fan[1-4]_alarm Fan alarm.
  104 +fan[1-4]_fault Fan fault.
  105 +
  106 + Fan attributes are only available on chips supporting
  107 + fan control (UCD90124, UCD90910). Attribute files are
  108 + created only for enabled fans.
  109 + Note that even though UCD90910 supports up to 10 fans,
  110 + only up to four fans are currently supported.
drivers/hwmon/Kconfig
... ... @@ -857,12 +857,24 @@
857 857 This driver can also be built as a module. If so, the module will
858 858 be called max8688.
859 859  
  860 +config SENSORS_UCD9000
  861 + tristate "TI UCD90120, UCD90124, UCD9090, UCD90910"
  862 + default n
  863 + help
  864 + If you say yes here you get hardware monitoring support for TI
  865 + UCD90120, UCD90124, UCD9090, UCD90910 Sequencer and System Health
  866 + Controllers.
  867 +
  868 + This driver can also be built as a module. If so, the module will
  869 + be called ucd9000.
  870 +
860 871 config SENSORS_UCD9200
861 872 tristate "TI UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, UCD9248"
862 873 default n
863 874 help
864 875 If you say yes here you get hardware monitoring support for TI
865   - UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, and UCD9248.
  876 + UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, and UCD9248
  877 + Digital PWM System Controllers.
866 878  
867 879 This driver can also be built as a module. If so, the module will
868 880 be called ucd9200.
drivers/hwmon/Makefile
... ... @@ -123,6 +123,7 @@
123 123 obj-$(CONFIG_SENSORS_MAX16064) += max16064.o
124 124 obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
125 125 obj-$(CONFIG_SENSORS_MAX8688) += max8688.o
  126 +obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o
126 127 obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o
127 128  
128 129 ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG
drivers/hwmon/ucd9000.c
  1 +/*
  2 + * Hardware monitoring driver for UCD90xxx Sequencer and System Health
  3 + * Controller series
  4 + *
  5 + * Copyright (C) 2011 Ericsson AB.
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20 + */
  21 +
  22 +#include <linux/kernel.h>
  23 +#include <linux/module.h>
  24 +#include <linux/init.h>
  25 +#include <linux/err.h>
  26 +#include <linux/slab.h>
  27 +#include <linux/i2c.h>
  28 +#include <linux/i2c/pmbus.h>
  29 +#include "pmbus.h"
  30 +
  31 +enum chips { ucd9000, ucd90120, ucd90124, ucd9090, ucd90910 };
  32 +
  33 +#define UCD9000_MONITOR_CONFIG 0xd5
  34 +#define UCD9000_NUM_PAGES 0xd6
  35 +#define UCD9000_FAN_CONFIG_INDEX 0xe7
  36 +#define UCD9000_FAN_CONFIG 0xe8
  37 +#define UCD9000_DEVICE_ID 0xfd
  38 +
  39 +#define UCD9000_MON_TYPE(x) (((x) >> 5) & 0x07)
  40 +#define UCD9000_MON_PAGE(x) ((x) & 0x0f)
  41 +
  42 +#define UCD9000_MON_VOLTAGE 1
  43 +#define UCD9000_MON_TEMPERATURE 2
  44 +#define UCD9000_MON_CURRENT 3
  45 +#define UCD9000_MON_VOLTAGE_HW 4
  46 +
  47 +#define UCD9000_NUM_FAN 4
  48 +
  49 +struct ucd9000_data {
  50 + u8 fan_data[UCD9000_NUM_FAN][I2C_SMBUS_BLOCK_MAX];
  51 + struct pmbus_driver_info info;
  52 +};
  53 +#define to_ucd9000_data(_info) container_of(_info, struct ucd9000_data, info)
  54 +
  55 +static int ucd9000_get_fan_config(struct i2c_client *client, int fan)
  56 +{
  57 + int fan_config = 0;
  58 + struct ucd9000_data *data
  59 + = to_ucd9000_data(pmbus_get_driver_info(client));
  60 +
  61 + if (data->fan_data[fan][3] & 1)
  62 + fan_config |= PB_FAN_2_INSTALLED; /* Use lower bit position */
  63 +
  64 + /* Pulses/revolution */
  65 + fan_config |= (data->fan_data[fan][3] & 0x06) >> 1;
  66 +
  67 + return fan_config;
  68 +}
  69 +
  70 +static int ucd9000_read_byte_data(struct i2c_client *client, int page, int reg)
  71 +{
  72 + int ret = 0;
  73 + int fan_config;
  74 +
  75 + switch (reg) {
  76 + case PMBUS_FAN_CONFIG_12:
  77 + if (page)
  78 + return -EINVAL;
  79 +
  80 + ret = ucd9000_get_fan_config(client, 0);
  81 + if (ret < 0)
  82 + return ret;
  83 + fan_config = ret << 4;
  84 + ret = ucd9000_get_fan_config(client, 1);
  85 + if (ret < 0)
  86 + return ret;
  87 + fan_config |= ret;
  88 + ret = fan_config;
  89 + break;
  90 + case PMBUS_FAN_CONFIG_34:
  91 + if (page)
  92 + return -EINVAL;
  93 +
  94 + ret = ucd9000_get_fan_config(client, 2);
  95 + if (ret < 0)
  96 + return ret;
  97 + fan_config = ret << 4;
  98 + ret = ucd9000_get_fan_config(client, 3);
  99 + if (ret < 0)
  100 + return ret;
  101 + fan_config |= ret;
  102 + ret = fan_config;
  103 + break;
  104 + default:
  105 + ret = -ENODATA;
  106 + break;
  107 + }
  108 + return ret;
  109 +}
  110 +
  111 +static const struct i2c_device_id ucd9000_id[] = {
  112 + {"ucd9000", ucd9000},
  113 + {"ucd90120", ucd90120},
  114 + {"ucd90124", ucd90124},
  115 + {"ucd9090", ucd9090},
  116 + {"ucd90910", ucd90910},
  117 + {}
  118 +};
  119 +MODULE_DEVICE_TABLE(i2c, ucd9000_id);
  120 +
  121 +static int ucd9000_probe(struct i2c_client *client,
  122 + const struct i2c_device_id *id)
  123 +{
  124 + u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];
  125 + struct ucd9000_data *data;
  126 + struct pmbus_driver_info *info;
  127 + const struct i2c_device_id *mid;
  128 + int i, ret;
  129 +
  130 + if (!i2c_check_functionality(client->adapter,
  131 + I2C_FUNC_SMBUS_BYTE_DATA |
  132 + I2C_FUNC_SMBUS_BLOCK_DATA))
  133 + return -ENODEV;
  134 +
  135 + ret = i2c_smbus_read_block_data(client, UCD9000_DEVICE_ID,
  136 + block_buffer);
  137 + if (ret < 0) {
  138 + dev_err(&client->dev, "Failed to read device ID\n");
  139 + return ret;
  140 + }
  141 + block_buffer[ret] = '\0';
  142 + dev_info(&client->dev, "Device ID %s\n", block_buffer);
  143 +
  144 + mid = NULL;
  145 + for (i = 0; i < ARRAY_SIZE(ucd9000_id); i++) {
  146 + mid = &ucd9000_id[i];
  147 + if (!strncasecmp(mid->name, block_buffer, strlen(mid->name)))
  148 + break;
  149 + }
  150 + if (!mid || !strlen(mid->name)) {
  151 + dev_err(&client->dev, "Unsupported device\n");
  152 + return -ENODEV;
  153 + }
  154 +
  155 + if (id->driver_data != ucd9000 && id->driver_data != mid->driver_data)
  156 + dev_notice(&client->dev,
  157 + "Device mismatch: Configured %s, detected %s\n",
  158 + id->name, mid->name);
  159 +
  160 + data = kzalloc(sizeof(struct ucd9000_data), GFP_KERNEL);
  161 + if (!data)
  162 + return -ENOMEM;
  163 + info = &data->info;
  164 +
  165 + ret = i2c_smbus_read_byte_data(client, UCD9000_NUM_PAGES);
  166 + if (ret < 0) {
  167 + dev_err(&client->dev,
  168 + "Failed to read number of active pages\n");
  169 + goto out;
  170 + }
  171 + info->pages = ret;
  172 + if (!info->pages) {
  173 + dev_err(&client->dev, "No pages configured\n");
  174 + ret = -ENODEV;
  175 + goto out;
  176 + }
  177 +
  178 + /* The internal temperature sensor is always active */
  179 + info->func[0] = PMBUS_HAVE_TEMP;
  180 +
  181 + /* Everything else is configurable */
  182 + ret = i2c_smbus_read_block_data(client, UCD9000_MONITOR_CONFIG,
  183 + block_buffer);
  184 + if (ret <= 0) {
  185 + dev_err(&client->dev, "Failed to read configuration data\n");
  186 + ret = -ENODEV;
  187 + goto out;
  188 + }
  189 + for (i = 0; i < ret; i++) {
  190 + int page = UCD9000_MON_PAGE(block_buffer[i]);
  191 +
  192 + if (page >= info->pages)
  193 + continue;
  194 +
  195 + switch (UCD9000_MON_TYPE(block_buffer[i])) {
  196 + case UCD9000_MON_VOLTAGE:
  197 + case UCD9000_MON_VOLTAGE_HW:
  198 + info->func[page] |= PMBUS_HAVE_VOUT
  199 + | PMBUS_HAVE_STATUS_VOUT;
  200 + break;
  201 + case UCD9000_MON_TEMPERATURE:
  202 + info->func[page] |= PMBUS_HAVE_TEMP2
  203 + | PMBUS_HAVE_STATUS_TEMP;
  204 + break;
  205 + case UCD9000_MON_CURRENT:
  206 + info->func[page] |= PMBUS_HAVE_IOUT
  207 + | PMBUS_HAVE_STATUS_IOUT;
  208 + break;
  209 + default:
  210 + break;
  211 + }
  212 + }
  213 +
  214 + /* Fan configuration */
  215 + if (mid->driver_data == ucd90124) {
  216 + for (i = 0; i < UCD9000_NUM_FAN; i++) {
  217 + i2c_smbus_write_byte_data(client,
  218 + UCD9000_FAN_CONFIG_INDEX, i);
  219 + ret = i2c_smbus_read_block_data(client,
  220 + UCD9000_FAN_CONFIG,
  221 + data->fan_data[i]);
  222 + if (ret < 0)
  223 + goto out;
  224 + }
  225 + i2c_smbus_write_byte_data(client, UCD9000_FAN_CONFIG_INDEX, 0);
  226 +
  227 + info->read_byte_data = ucd9000_read_byte_data;
  228 + info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12
  229 + | PMBUS_HAVE_FAN34 | PMBUS_HAVE_STATUS_FAN34;
  230 + }
  231 +
  232 + ret = pmbus_do_probe(client, mid, info);
  233 + if (ret < 0)
  234 + goto out;
  235 + return 0;
  236 +
  237 +out:
  238 + kfree(data);
  239 + return ret;
  240 +}
  241 +
  242 +static int ucd9000_remove(struct i2c_client *client)
  243 +{
  244 + int ret;
  245 + struct ucd9000_data *data;
  246 +
  247 + data = to_ucd9000_data(pmbus_get_driver_info(client));
  248 + ret = pmbus_do_remove(client);
  249 + kfree(data);
  250 + return ret;
  251 +}
  252 +
  253 +
  254 +/* This is the driver that will be inserted */
  255 +static struct i2c_driver ucd9000_driver = {
  256 + .driver = {
  257 + .name = "ucd9000",
  258 + },
  259 + .probe = ucd9000_probe,
  260 + .remove = ucd9000_remove,
  261 + .id_table = ucd9000_id,
  262 +};
  263 +
  264 +static int __init ucd9000_init(void)
  265 +{
  266 + return i2c_add_driver(&ucd9000_driver);
  267 +}
  268 +
  269 +static void __exit ucd9000_exit(void)
  270 +{
  271 + i2c_del_driver(&ucd9000_driver);
  272 +}
  273 +
  274 +MODULE_AUTHOR("Guenter Roeck");
  275 +MODULE_DESCRIPTION("PMBus driver for TI UCD90xxx");
  276 +MODULE_LICENSE("GPL");
  277 +module_init(ucd9000_init);
  278 +module_exit(ucd9000_exit);