|
| 1 | +From 966db1e756443757cf74b7d0ba56a3254e35fd79 Mon Sep 17 00:00:00 2001 |
| 2 | + |
| 3 | +From: Saranpong Chobtrong < [email protected]> |
| 4 | + |
| 5 | +Subject: [PATCH] hwmon: (pmbus/dps200): Support DPS200 PSU module |
| 6 | + |
| 7 | +The generic PMBUS driver does not support the chip that uses direct mode yet. |
| 8 | +This driver supports dps200 which uses coefficients defined in the datasheet. |
| 9 | +Ref: datasheet is DPS200PB184E-ES002.pdf [not public access datasheet] |
| 10 | + |
| 11 | +DP200 does not support pmbus coefficient commands. |
| 12 | +Each field of direct mode has a conversion definition defined by the datasheet. |
| 13 | + |
| 14 | +Add dps200 device to the dps1900 driver. |
| 15 | + |
| 16 | +Signed-off-by: Saranpong Chobtrong < [email protected]> |
| 17 | +--- |
| 18 | + drivers/hwmon/pmbus/dps1900.c | 104 +++++++++++++++++++++++++++++++++++++++-- |
| 19 | + 1 file changed, 98 insertions(+), 6 deletions(-) |
| 20 | + |
| 21 | +diff --git a/drivers/hwmon/pmbus/dps1900.c b/drivers/hwmon/pmbus/dps1900.c |
| 22 | +index f737f6480..d60c48e2c 100644 |
| 23 | +--- a/drivers/hwmon/pmbus/dps1900.c |
| 24 | ++++ b/drivers/hwmon/pmbus/dps1900.c |
| 25 | +@@ -1,3 +1,5 @@ |
| 26 | ++// SPDX-License-Identifier: GPL-2.0-or-later |
| 27 | ++ |
| 28 | + #include <linux/kernel.h> |
| 29 | + #include <linux/module.h> |
| 30 | + #include <linux/init.h> |
| 31 | +@@ -7,6 +9,8 @@ |
| 32 | + #include <linux/pmbus.h> |
| 33 | + #include "pmbus.h" |
| 34 | + |
| 35 | ++enum chips { dps1900, dps200 }; |
| 36 | ++ |
| 37 | + static int dps1900_read_word_data(struct i2c_client *client, int page, int reg) |
| 38 | + { |
| 39 | + if (reg >= PMBUS_VIRT_BASE || |
| 40 | +@@ -30,24 +34,112 @@ static int dps1900_read_word_data(struct i2c_client *client, int page, int reg) |
| 41 | + return pmbus_read_word_data(client, page, reg); |
| 42 | + } |
| 43 | + |
| 44 | ++static int dps200_read_word_data(struct i2c_client *client, int page, int reg) |
| 45 | ++{ |
| 46 | ++ |
| 47 | ++ if (reg >= PMBUS_VIRT_BASE || |
| 48 | ++ reg == PMBUS_VOUT_OV_FAULT_LIMIT || |
| 49 | ++ reg == PMBUS_VOUT_OV_WARN_LIMIT || |
| 50 | ++ reg == PMBUS_VOUT_UV_WARN_LIMIT || |
| 51 | ++ reg == PMBUS_VOUT_UV_FAULT_LIMIT || |
| 52 | ++ reg == PMBUS_IOUT_OC_LV_FAULT_LIMIT || |
| 53 | ++ reg == PMBUS_IOUT_UC_FAULT_LIMIT || |
| 54 | ++ reg == PMBUS_UT_WARN_LIMIT || |
| 55 | ++ reg == PMBUS_UT_FAULT_LIMIT || |
| 56 | ++ reg == PMBUS_VIN_OV_FAULT_LIMIT || |
| 57 | ++ reg == PMBUS_VIN_OV_WARN_LIMIT || |
| 58 | ++ reg == PMBUS_IIN_OC_FAULT_LIMIT || |
| 59 | ++ reg == PMBUS_POUT_MAX) |
| 60 | ++ return -ENXIO; |
| 61 | ++ |
| 62 | ++ /* |
| 63 | ++ * NOTE: The following field have constant driver value. |
| 64 | ++ * If the register are PMBUS_IOUT_OC_WARN_LIMIT or |
| 65 | ++ * PMBUS_IOUT_OC_FAULT_LIMIT convert the constant value from linear |
| 66 | ++ * to direct format. |
| 67 | ++ */ |
| 68 | ++ if (reg == PMBUS_IOUT_OC_WARN_LIMIT) |
| 69 | ++ return 0xb4; |
| 70 | ++ else if (reg == PMBUS_IOUT_OC_FAULT_LIMIT) |
| 71 | ++ return 0xc8; |
| 72 | ++ else |
| 73 | ++ return pmbus_read_word_data(client, page, reg); |
| 74 | ++} |
| 75 | ++ |
| 76 | + static struct pmbus_driver_info dps1900_info = { |
| 77 | + .pages = 1, |
| 78 | + .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
| 79 | +- | PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
| 80 | +- | PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 |
| 81 | +- | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP |
| 82 | +- | PMBUS_HAVE_STATUS_INPUT, |
| 83 | ++ | PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
| 84 | ++ | PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 |
| 85 | ++ | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP |
| 86 | ++ | PMBUS_HAVE_STATUS_INPUT, |
| 87 | + .read_word_data = dps1900_read_word_data, |
| 88 | + }; |
| 89 | + |
| 90 | ++/* |
| 91 | ++ * From DPS-200 datasheet the supported sensors format defined as: |
| 92 | ++ * VOUT: direct mode with one decimal place. |
| 93 | ++ * |
| 94 | ++ * Other sensors: |
| 95 | ++ * IOUT: direct mode with one decimal place. |
| 96 | ++ * IOUT Limits: linear mode, which difference from IOUT. |
| 97 | ++ * VIN, IIN, POWER, TEMP, & FAN: linear mode. |
| 98 | ++ */ |
| 99 | ++static struct pmbus_driver_info dps200_info = { |
| 100 | ++ .pages = 1, |
| 101 | ++ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
| 102 | ++ | PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
| 103 | ++ | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT |
| 104 | ++ | PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 |
| 105 | ++ | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 |
| 106 | ++ | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_STATUS_INPUT, |
| 107 | ++ .format = { |
| 108 | ++ [PSC_VOLTAGE_OUT] = direct, |
| 109 | ++ [PSC_CURRENT_OUT] = direct, |
| 110 | ++ }, |
| 111 | ++ .m = { |
| 112 | ++ [PSC_VOLTAGE_OUT] = 10, |
| 113 | ++ [PSC_CURRENT_OUT] = 10, |
| 114 | ++ }, |
| 115 | ++ .b = { |
| 116 | ++ [PSC_VOLTAGE_OUT] = 0, |
| 117 | ++ [PSC_CURRENT_OUT] = 0, |
| 118 | ++ }, |
| 119 | ++ .R = { |
| 120 | ++ [PSC_VOLTAGE_OUT] = 0, |
| 121 | ++ [PSC_CURRENT_OUT] = 0, |
| 122 | ++ }, |
| 123 | ++ .read_word_data = dps200_read_word_data, |
| 124 | ++}; |
| 125 | ++ |
| 126 | + static int dps1900_probe(struct i2c_client *client, |
| 127 | + const struct i2c_device_id *id) |
| 128 | + { |
| 129 | +- return pmbus_do_probe(client, id, &dps1900_info); |
| 130 | ++ struct pmbus_driver_info *info; |
| 131 | ++ |
| 132 | ++ info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info), |
| 133 | ++ GFP_KERNEL); |
| 134 | ++ if (!info) |
| 135 | ++ return -ENOMEM; |
| 136 | ++ |
| 137 | ++ switch (id->driver_data) { |
| 138 | ++ case dps1900: |
| 139 | ++ info = &dps1900_info; |
| 140 | ++ break; |
| 141 | ++ case dps200: |
| 142 | ++ info = &dps200_info; |
| 143 | ++ break; |
| 144 | ++ default: |
| 145 | ++ dev_err(&client->dev, "Unsupported device\n"); |
| 146 | ++ return -ENODEV; |
| 147 | ++ } |
| 148 | ++ |
| 149 | ++ return pmbus_do_probe(client, id, info); |
| 150 | + } |
| 151 | + |
| 152 | + static const struct i2c_device_id dps1900_id[] = { |
| 153 | +- {"dps1900", 0}, |
| 154 | ++ {"dps1900", dps1900}, |
| 155 | ++ {"dps200", dps200}, |
| 156 | + {} |
| 157 | + }; |
| 158 | + |
0 commit comments