Commit a470f11c authored by Jim Wright's avatar Jim Wright Committed by Guenter Roeck

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: default avatarJim Wright <wrightj@linux.vnet.ibm.com>
Link: https://lore.kernel.org/r/20191205232411.21492-3-wrightj@linux.vnet.ibm.comSigned-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent 8a36e38d
...@@ -3,9 +3,10 @@ Kernel driver ucd9000 ...@@ -3,9 +3,10 @@ Kernel driver ucd9000
Supported chips: 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: - Addresses scanned: -
...@@ -14,6 +15,7 @@ Supported chips: ...@@ -14,6 +15,7 @@ Supported chips:
- http://focus.ti.com/lit/ds/symlink/ucd90120.pdf - 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/ucd90124.pdf
- http://focus.ti.com/lit/ds/symlink/ucd90160.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/ucd9090.pdf
- http://focus.ti.com/lit/ds/symlink/ucd90910.pdf - http://focus.ti.com/lit/ds/symlink/ucd90910.pdf
...@@ -45,6 +47,12 @@ power-on reset signals, external interrupts, cascading, or other system ...@@ -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 functions. Twelve of these pins offer PWM functionality. Using these pins, the
UCD90160 offers support for margining, and general-purpose PWM functions. 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 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 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, voltage inputs. Twenty-three GPIO pins can be used for power supply enables,
......
...@@ -209,11 +209,11 @@ config SENSORS_TPS53679 ...@@ -209,11 +209,11 @@ config SENSORS_TPS53679
be called tps53679. be called tps53679.
config SENSORS_UCD9000 config SENSORS_UCD9000
tristate "TI UCD90120, UCD90124, UCD90160, UCD9090, UCD90910" tristate "TI UCD90120, UCD90124, UCD90160, UCD90320, UCD9090, UCD90910"
help help
If you say yes here you get hardware monitoring support for TI If you say yes here you get hardware monitoring support for TI
UCD90120, UCD90124, UCD90160, UCD9090, UCD90910, Sequencer and System UCD90120, UCD90124, UCD90160, UCD90320, UCD9090, UCD90910, Sequencer
Health Controllers. and System Health Controllers.
This driver can also be built as a module. If so, the module will This driver can also be built as a module. If so, the module will
be called ucd9000. be called ucd9000.
......
...@@ -18,7 +18,8 @@ ...@@ -18,7 +18,8 @@
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
#include "pmbus.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_MONITOR_CONFIG 0xd5
#define UCD9000_NUM_PAGES 0xd6 #define UCD9000_NUM_PAGES 0xd6
...@@ -38,7 +39,7 @@ enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd9090, ucd90910 }; ...@@ -38,7 +39,7 @@ enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd9090, ucd90910 };
#define UCD9000_GPIO_OUTPUT 1 #define UCD9000_GPIO_OUTPUT 1
#define UCD9000_MON_TYPE(x) (((x) >> 5) & 0x07) #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_VOLTAGE 1
#define UCD9000_MON_TEMPERATURE 2 #define UCD9000_MON_TEMPERATURE 2
...@@ -50,10 +51,12 @@ enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd9090, ucd90910 }; ...@@ -50,10 +51,12 @@ enum chips { ucd9000, ucd90120, ucd90124, ucd90160, ucd9090, ucd90910 };
#define UCD9000_GPIO_NAME_LEN 16 #define UCD9000_GPIO_NAME_LEN 16
#define UCD9090_NUM_GPIOS 23 #define UCD9090_NUM_GPIOS 23
#define UCD901XX_NUM_GPIOS 26 #define UCD901XX_NUM_GPIOS 26
#define UCD90320_NUM_GPIOS 84
#define UCD90910_NUM_GPIOS 26 #define UCD90910_NUM_GPIOS 26
#define UCD9000_DEBUGFS_NAME_LEN 24 #define UCD9000_DEBUGFS_NAME_LEN 24
#define UCD9000_GPI_COUNT 8 #define UCD9000_GPI_COUNT 8
#define UCD90320_GPI_COUNT 32
struct ucd9000_data { struct ucd9000_data {
u8 fan_data[UCD9000_NUM_FAN][I2C_SMBUS_BLOCK_MAX]; u8 fan_data[UCD9000_NUM_FAN][I2C_SMBUS_BLOCK_MAX];
...@@ -131,6 +134,7 @@ static const struct i2c_device_id ucd9000_id[] = { ...@@ -131,6 +134,7 @@ static const struct i2c_device_id ucd9000_id[] = {
{"ucd90120", ucd90120}, {"ucd90120", ucd90120},
{"ucd90124", ucd90124}, {"ucd90124", ucd90124},
{"ucd90160", ucd90160}, {"ucd90160", ucd90160},
{"ucd90320", ucd90320},
{"ucd9090", ucd9090}, {"ucd9090", ucd9090},
{"ucd90910", ucd90910}, {"ucd90910", ucd90910},
{} {}
...@@ -154,6 +158,10 @@ static const struct of_device_id __maybe_unused ucd9000_of_match[] = { ...@@ -154,6 +158,10 @@ static const struct of_device_id __maybe_unused ucd9000_of_match[] = {
.compatible = "ti,ucd90160", .compatible = "ti,ucd90160",
.data = (void *)ucd90160 .data = (void *)ucd90160
}, },
{
.compatible = "ti,ucd90320",
.data = (void *)ucd90320
},
{ {
.compatible = "ti,ucd9090", .compatible = "ti,ucd9090",
.data = (void *)ucd9090 .data = (void *)ucd9090
...@@ -322,6 +330,9 @@ static void ucd9000_probe_gpio(struct i2c_client *client, ...@@ -322,6 +330,9 @@ static void ucd9000_probe_gpio(struct i2c_client *client,
case ucd90160: case ucd90160:
data->gpio.ngpio = UCD901XX_NUM_GPIOS; data->gpio.ngpio = UCD901XX_NUM_GPIOS;
break; break;
case ucd90320:
data->gpio.ngpio = UCD90320_NUM_GPIOS;
break;
case ucd90910: case ucd90910:
data->gpio.ngpio = UCD90910_NUM_GPIOS; data->gpio.ngpio = UCD90910_NUM_GPIOS;
break; break;
...@@ -372,17 +383,18 @@ static int ucd9000_debugfs_show_mfr_status_bit(void *data, u64 *val) ...@@ -372,17 +383,18 @@ static int ucd9000_debugfs_show_mfr_status_bit(void *data, u64 *val)
struct ucd9000_debugfs_entry *entry = data; struct ucd9000_debugfs_entry *entry = data;
struct i2c_client *client = entry->client; struct i2c_client *client = entry->client;
u8 buffer[I2C_SMBUS_BLOCK_MAX]; u8 buffer[I2C_SMBUS_BLOCK_MAX];
int ret; int ret, i;
ret = ucd9000_get_mfr_status(client, buffer); ret = ucd9000_get_mfr_status(client, buffer);
if (ret < 0) if (ret < 0)
return ret; return ret;
/* /*
* Attribute only created for devices with gpi fault bits at bits * GPI fault bits are in sets of 8, two bytes from end of response.
* 16-23, which is the second byte of the 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; return 0;
} }
...@@ -422,7 +434,7 @@ static int ucd9000_init_debugfs(struct i2c_client *client, ...@@ -422,7 +434,7 @@ static int ucd9000_init_debugfs(struct i2c_client *client,
{ {
struct dentry *debugfs; struct dentry *debugfs;
struct ucd9000_debugfs_entry *entries; struct ucd9000_debugfs_entry *entries;
int i; int i, gpi_count;
char name[UCD9000_DEBUGFS_NAME_LEN]; char name[UCD9000_DEBUGFS_NAME_LEN];
debugfs = pmbus_get_debugfs_dir(client); debugfs = pmbus_get_debugfs_dir(client);
...@@ -435,18 +447,21 @@ static int ucd9000_init_debugfs(struct i2c_client *client, ...@@ -435,18 +447,21 @@ static int ucd9000_init_debugfs(struct i2c_client *client,
/* /*
* Of the chips this driver supports, only the UCD9090, UCD90160, * Of the chips this driver supports, only the UCD9090, UCD90160,
* and UCD90910 report GPI faults in their MFR_STATUS register, so only * UCD90320, and UCD90910 report GPI faults in their MFR_STATUS
* create the GPI fault debugfs attributes for those chips. * register, so only create the GPI fault debugfs attributes for those
* chips.
*/ */
if (mid->driver_data == ucd9090 || mid->driver_data == ucd90160 || 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, entries = devm_kcalloc(&client->dev,
UCD9000_GPI_COUNT, sizeof(*entries), gpi_count, sizeof(*entries),
GFP_KERNEL); GFP_KERNEL);
if (!entries) if (!entries)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < UCD9000_GPI_COUNT; i++) { for (i = 0; i < gpi_count; i++) {
entries[i].client = client; entries[i].client = client;
entries[i].index = i; entries[i].index = i;
scnprintf(name, UCD9000_DEBUGFS_NAME_LEN, scnprintf(name, UCD9000_DEBUGFS_NAME_LEN,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment