diff options
| author | Matti Vaittinen <mazziesaccount@gmail.com> | 2026-06-26 10:26:02 +0300 |
|---|---|---|
| committer | Guenter Roeck <linux@roeck-us.net> | 2026-08-10 08:59:40 -0700 |
| commit | 73a76fa6e865aaf82bea6df26afd3efb06e6ea88 (patch) | |
| tree | d12e2f344bff830607722e7860b23e9399390283 | |
| parent | b66f500d6259c6a8fbdc97588236dcda1ee45215 (diff) | |
hwmon: (pmbus/adm1275) Support ROHM BD12790
Add support for ROHM BD12790 hot-swap controller which is largely
similar to Analog Devices adm1272.
The BD12790 uses the same selectable 60V/100V voltage ranges and
15mV/30mV current-sense ranges as the ADM1272, and the same VRANGE
(bit 5) and IRANGE (bit 0) layout in PMON_CONFIG. It therefore uses
a dedicated coefficient table that mirrors adm1272_coefficients, with
the following differences derived from BD12790 datasheet Table 1 (p.18):
- power 60V/30mV: m=17560 (vs. 17561)
- power 100V/30mV: m=10536 (vs. 10535)
- temperature: b=31880 (vs. 31871, reflecting T[11:0] = 4.2*T + 3188)
Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
Assisted-by: GitHub Copilot:claude-sonnet-4.6
Link: https://lore.kernel.org/r/b209c1b47712b69f17b52cfd7a7a38ed76024ca7.1782458224.git.mazziesaccount@gmail.com
[groeck: Fixed comment describing BD12790 coefficients]
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
| -rw-r--r-- | drivers/hwmon/pmbus/Kconfig | 4 | ||||
| -rw-r--r-- | drivers/hwmon/pmbus/adm1275.c | 79 |
2 files changed, 78 insertions, 5 deletions
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig index 5e3a84416083..ae003a6eac30 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig @@ -52,8 +52,8 @@ config SENSORS_ADM1275 help If you say yes here you get hardware monitoring support for Analog Devices ADM1075, ADM1272, ADM1273, ADM1275, ADM1276, ADM1278, ADM1281, - ADM1293, ADM1294, ROHM BD12780, and SQ24905C Hot-Swap Controller and - Digital Power Monitors. + ADM1293, ADM1294, ROHM BD12780, ROHM BD12790, and SQ24905C + Hot-Swap Controller and Digital Power Monitors. This driver can also be built as a module. If so, the module will be called adm1275. diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c index eecb00371afa..174f9bcba7e2 100644 --- a/drivers/hwmon/pmbus/adm1275.c +++ b/drivers/hwmon/pmbus/adm1275.c @@ -19,7 +19,7 @@ #include "pmbus.h" enum chips { adm1075, adm1272, adm1273, adm1275, adm1276, adm1278, adm1281, - adm1293, adm1294, bd12780, sq24905c }; + adm1293, adm1294, bd12780, bd12790, sq24905c }; #define ADM1275_MFR_STATUS_IOUT_WARN2 BIT(0) #define ADM1293_MFR_STATUS_VAUX_UV_WARN BIT(5) @@ -47,7 +47,7 @@ enum chips { adm1075, adm1272, adm1273, adm1275, adm1276, adm1278, adm1281, #define ADM1278_VOUT_EN BIT(1) #define ADM1278_PMON_DEFCONFIG (ADM1278_VOUT_EN | ADM1278_TEMP1_EN | ADM1278_TSFILT) -/* The BD12780 data sheets mark TSFILT bit as reserved. */ +/* The BD127[89]0 data sheets mark TSFILT bit as reserved. */ #define BD12780_PMON_DEFCONFIG (ADM1278_VOUT_EN | ADM1278_TEMP1_EN) #define ADM1293_IRANGE_25 0 @@ -136,6 +136,30 @@ static const struct coefficients adm1272_coefficients[] = { }; +/* + * BD12790 coefficients derived from preliminary datasheet, Table 1 (p.18) + * and the PMBus direct-format relationship X = (Y * 10^(-R) - b) / m. + * + * Voltage: V[V] = 14.77e-3 * code (60V) / 24.62e-3 * code (100V) + * -> m = 6770, R=-2 / m = 4062, R=-2 + * Current: code = I[A] * RS * 132802.1 + 2048 (15mV) / * 66401.06 + 2048 (30mV) + * -> m = 1328, b = 2048 * 10^(-R) = 20480, R=-1 / m = 664, same b and R + * Power: code = k * RS * PIN, k = 35119.94 / 17559.97 / 21071.44 / 10535.72 + * -> m = round(k * 10^(-3-R)), R=-2 for 60V/15mV, R=-3 for the other three + * Temperature: code = 4.2 * T + 3188 -> m = 42, b = 3188 * 10 = 31880, R=-1 + */ +static const struct coefficients bd12790_coefficients[] = { + [0] = { 6770, 0, -2 }, /* voltage, vrange 60V */ + [1] = { 4062, 0, -2 }, /* voltage, vrange 100V */ + [2] = { 1328, 20480, -1 }, /* current, vsense range 15mV */ + [3] = { 664, 20480, -1 }, /* current, vsense range 30mV */ + [4] = { 3512, 0, -2 }, /* power, vrange 60V, irange 15mV */ + [5] = { 21071, 0, -3 }, /* power, vrange 100V, irange 15mV */ + [6] = { 17560, 0, -3 }, /* power, vrange 60V, irange 30mV */ + [7] = { 10536, 0, -3 }, /* power, vrange 100V, irange 30mV */ + [8] = { 42, 31880, -1 }, /* temperature */ +}; + static const struct coefficients adm1275_coefficients[] = { [0] = { 19199, 0, -2 }, /* voltage, vrange set */ [1] = { 6720, 0, -1 }, /* voltage, vrange not set */ @@ -490,6 +514,7 @@ static const struct i2c_device_id adm1275_id[] = { { .name = "adm1293", .driver_data = adm1293 }, { .name = "adm1294", .driver_data = adm1294 }, { .name = "bd12780", .driver_data = bd12780 }, + { .name = "bd12790", .driver_data = bd12790 }, { .name = "mc09c", .driver_data = sq24905c }, { } }; @@ -567,7 +592,8 @@ static int adm1275_probe(struct i2c_client *client) if (mid->driver_data == adm1272 || mid->driver_data == adm1273 || mid->driver_data == adm1278 || mid->driver_data == adm1281 || mid->driver_data == adm1293 || mid->driver_data == adm1294 || - mid->driver_data == bd12780 || mid->driver_data == sq24905c) + mid->driver_data == bd12780 || mid->driver_data == bd12790 || + mid->driver_data == sq24905c) config_read_fn = i2c_smbus_read_word_data; else config_read_fn = i2c_smbus_read_byte_data; @@ -647,6 +673,7 @@ static int adm1275_probe(struct i2c_client *client) data->have_power_sampling = true; coefficients = adm1272_coefficients; + vindex = (config & ADM1275_VRANGE) ? 1 : 0; cindex = (config & ADM1272_IRANGE) ? 3 : 2; /* pindex depends on the combination of the above */ @@ -679,6 +706,51 @@ static int adm1275_probe(struct i2c_client *client) if (config & ADM1278_VIN_EN) info->func[0] |= PMBUS_HAVE_VIN; break; + + /* + * The BD12790 is almost identical to the adm1272. Only the defconfig + * and coefficients have minor differences. + */ + case bd12790: + data->have_vout = true; + data->have_pin_max = true; + data->have_temp_max = true; + data->have_power_sampling = true; + + coefficients = bd12790_coefficients; + + vindex = (config & ADM1275_VRANGE) ? 1 : 0; + cindex = (config & ADM1272_IRANGE) ? 3 : 2; + /* pindex depends on the combination of the above */ + switch (config & (ADM1275_VRANGE | ADM1272_IRANGE)) { + case 0: + default: + pindex = 4; + break; + case ADM1275_VRANGE: + pindex = 5; + break; + case ADM1272_IRANGE: + pindex = 6; + break; + case ADM1275_VRANGE | ADM1272_IRANGE: + pindex = 7; + break; + } + tindex = 8; + + info->func[0] |= PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | + PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | + PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; + + ret = adm1275_enable_vout_temp(data, client, config, + BD12780_PMON_DEFCONFIG); + if (ret) + return ret; + + if (config & ADM1278_VIN_EN) + info->func[0] |= PMBUS_HAVE_VIN; + break; case adm1275: if (device_config & ADM1275_IOUT_WARN2_SELECT) data->have_oc_fault = true; @@ -919,6 +991,7 @@ static const struct of_device_id adm1275_of_match[] = { { .compatible = "adi,adm1293", }, { .compatible = "adi,adm1294", }, { .compatible = "rohm,bd12780", }, + { .compatible = "rohm,bd12790", }, { .compatible = "silergy,mc09c", }, { } }; |
