hwmon: (pmbus/ucd9000) Add support for UCD90320 Power Sequencer

Add support for the UCD90320 chip and its expanded set of GPIO pins.

Signed-off-by: Jim Wright <wrightj@linux.vnet.ibm.com>
Link: https://lore.kernel.org/r/20191205232411.21492-3-wrightj@linux.vnet.ibm.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
This commit is contained in:
Jim Wright 2019-12-05 17:24:11 -06:00 committed by Guenter Roeck
parent 8a36e38d8b
commit a470f11c5b
3 changed files with 40 additions and 17 deletions

View File

@ -3,9 +3,10 @@ Kernel driver ucd9000
Supported chips:
* TI UCD90120, UCD90124, UCD90160, UCD9090, and UCD90910
* TI UCD90120, UCD90124, UCD90160, UCD90320, UCD9090, and UCD90910
Prefixes: 'ucd90120', 'ucd90124', 'ucd90160', 'ucd9090', 'ucd90910'
Prefixes: 'ucd90120', 'ucd90124', 'ucd90160', 'ucd90320', 'ucd9090',
'ucd90910'
Addresses scanned: -
@ -14,6 +15,7 @@ Supported chips:
- http://focus.ti.com/lit/ds/symlink/ucd90120.pdf
- http://focus.ti.com/lit/ds/symlink/ucd90124.pdf
- http://focus.ti.com/lit/ds/symlink/ucd90160.pdf
- http://focus.ti.com/lit/ds/symlink/ucd90320.pdf
- http://focus.ti.com/lit/ds/symlink/ucd9090.pdf
- http://focus.ti.com/lit/ds/symlink/ucd90910.pdf
@ -45,6 +47,12 @@ power-on reset signals, external interrupts, cascading, or other system
functions. Twelve of these pins offer PWM functionality. Using these pins, the
UCD90160 offers support for margining, and general-purpose PWM functions.
The UCD90320 is a 32-rail PMBus/I2C addressable power-supply sequencer and
monitor. The 24 integrated ADC channels (AMONx) monitor the power supply
voltage, current, and temperature. Of the 84 GPIO pins, 8 can be used as
digital monitors (DMONx), 32 to enable the power supply (ENx), 24 for margining
(MARx), 16 for logical GPO, and 32 GPIs for cascading, and system function.
The UCD9090 is a 10-rail PMBus/I2C addressable power-supply sequencer and
monitor. The device integrates a 12-bit ADC for monitoring up to 10 power-supply
voltage inputs. Twenty-three GPIO pins can be used for power supply enables,

View File

@ -209,11 +209,11 @@ config SENSORS_TPS53679
be called tps53679.
config SENSORS_UCD9000
tristate "TI UCD90120, UCD90124, UCD90160, UCD9090, UCD90910"
tristate "TI UCD90120, UCD90124, UCD90160, UCD90320, UCD9090, UCD90910"
help
If you say yes here you get hardware monitoring support for TI
UCD90120, UCD90124, UCD90160, UCD9090, UCD90910, Sequencer and System
Health Controllers.
UCD90120, UCD90124, UCD90160, UCD90320, UCD9090, UCD90910, Sequencer
and System Health Controllers.
This driver can also be built as a module. If so, the module will
be called ucd9000.

View File

@ -18,7 +18,8 @@
#include <linux/gpio/driver.h>
#include "pmbus.h"
enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd9090, ucd90910 };
enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd90320, ucd9090,
ucd90910 };
#define UCD9000_MONITOR_CONFIG 0xd5
#define UCD9000_NUM_PAGES 0xd6
@ -38,7 +39,7 @@ enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd9090, ucd90910 };
#define UCD9000_GPIO_OUTPUT 1
#define UCD9000_MON_TYPE(x) (((x) >> 5) & 0x07)
#define UCD9000_MON_PAGE(x) ((x) & 0x0f)
#define UCD9000_MON_PAGE(x) ((x) & 0x1f)
#define UCD9000_MON_VOLTAGE 1
#define UCD9000_MON_TEMPERATURE 2
@ -50,10 +51,12 @@ enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd9090, ucd90910 };
#define UCD9000_GPIO_NAME_LEN 16
#define UCD9090_NUM_GPIOS 23
#define UCD901XX_NUM_GPIOS 26
#define UCD90320_NUM_GPIOS 84
#define UCD90910_NUM_GPIOS 26
#define UCD9000_DEBUGFS_NAME_LEN 24
#define UCD9000_GPI_COUNT 8
#define UCD90320_GPI_COUNT 32
struct ucd9000_data {
u8 fan_data[UCD9000_NUM_FAN][I2C_SMBUS_BLOCK_MAX];
@ -131,6 +134,7 @@ static const struct i2c_device_id ucd9000_id[] = {
{"ucd90120", ucd90120},
{"ucd90124", ucd90124},
{"ucd90160", ucd90160},
{"ucd90320", ucd90320},
{"ucd9090", ucd9090},
{"ucd90910", ucd90910},
{}
@ -154,6 +158,10 @@ static const struct of_device_id __maybe_unused ucd9000_of_match[] = {
.compatible = "ti,ucd90160",
.data = (void *)ucd90160
},
{
.compatible = "ti,ucd90320",
.data = (void *)ucd90320
},
{
.compatible = "ti,ucd9090",
.data = (void *)ucd9090
@ -322,6 +330,9 @@ static void ucd9000_probe_gpio(struct i2c_client *client,
case ucd90160:
data->gpio.ngpio = UCD901XX_NUM_GPIOS;
break;
case ucd90320:
data->gpio.ngpio = UCD90320_NUM_GPIOS;
break;
case ucd90910:
data->gpio.ngpio = UCD90910_NUM_GPIOS;
break;
@ -372,17 +383,18 @@ static int ucd9000_debugfs_show_mfr_status_bit(void *data, u64 *val)
struct ucd9000_debugfs_entry *entry = data;
struct i2c_client *client = entry->client;
u8 buffer[I2C_SMBUS_BLOCK_MAX];
int ret;
int ret, i;
ret = ucd9000_get_mfr_status(client, buffer);
if (ret < 0)
return ret;
/*
* Attribute only created for devices with gpi fault bits at bits
* 16-23, which is the second byte of the response.
* GPI fault bits are in sets of 8, two bytes from end of response.
*/
*val = !!(buffer[1] & BIT(entry->index));
i = ret - 3 - entry->index / 8;
if (i >= 0)
*val = !!(buffer[i] & BIT(entry->index % 8));
return 0;
}
@ -422,7 +434,7 @@ static int ucd9000_init_debugfs(struct i2c_client *client,
{
struct dentry *debugfs;
struct ucd9000_debugfs_entry *entries;
int i;
int i, gpi_count;
char name[UCD9000_DEBUGFS_NAME_LEN];
debugfs = pmbus_get_debugfs_dir(client);
@ -435,18 +447,21 @@ static int ucd9000_init_debugfs(struct i2c_client *client,
/*
* Of the chips this driver supports, only the UCD9090, UCD90160,
* and UCD90910 report GPI faults in their MFR_STATUS register, so only
* create the GPI fault debugfs attributes for those chips.
* UCD90320, and UCD90910 report GPI faults in their MFR_STATUS
* register, so only create the GPI fault debugfs attributes for those
* chips.
*/
if (mid->driver_data == ucd9090 || mid->driver_data == ucd90160 ||
mid->driver_data == ucd90910) {
mid->driver_data == ucd90320 || mid->driver_data == ucd90910) {
gpi_count = mid->driver_data == ucd90320 ? UCD90320_GPI_COUNT
: UCD9000_GPI_COUNT;
entries = devm_kcalloc(&client->dev,
UCD9000_GPI_COUNT, sizeof(*entries),
gpi_count, sizeof(*entries),
GFP_KERNEL);
if (!entries)
return -ENOMEM;
for (i = 0; i < UCD9000_GPI_COUNT; i++) {
for (i = 0; i < gpi_count; i++) {
entries[i].client = client;
entries[i].index = i;
scnprintf(name, UCD9000_DEBUGFS_NAME_LEN,