1*97c1723aSGeorgi Vlaev // SPDX-License-Identifier: GPL-2.0-or-later 2*97c1723aSGeorgi Vlaev /* 3*97c1723aSGeorgi Vlaev * Hardware monitoring driver for Analog Devices MAX16545/MAX16550 and 4*97c1723aSGeorgi Vlaev * Volterra VT7505 PMBus controllers. 5*97c1723aSGeorgi Vlaev * 6*97c1723aSGeorgi Vlaev * Copyright 2026 Hewlett Packard Enterprise Development LP 7*97c1723aSGeorgi Vlaev */ 8*97c1723aSGeorgi Vlaev 9*97c1723aSGeorgi Vlaev #include <linux/bitfield.h> 10*97c1723aSGeorgi Vlaev #include <linux/i2c.h> 11*97c1723aSGeorgi Vlaev #include <linux/kernel.h> 12*97c1723aSGeorgi Vlaev #include <linux/module.h> 13*97c1723aSGeorgi Vlaev #include <linux/of.h> 14*97c1723aSGeorgi Vlaev #include <linux/pmbus.h> 15*97c1723aSGeorgi Vlaev 16*97c1723aSGeorgi Vlaev #include "pmbus.h" 17*97c1723aSGeorgi Vlaev 18*97c1723aSGeorgi Vlaev #define VT7505_MFR_CONFIG 0xd0 19*97c1723aSGeorgi Vlaev #define VT7505_CFG_OCP_S_FILT_MASK GENMASK(15, 14) 20*97c1723aSGeorgi Vlaev 21*97c1723aSGeorgi Vlaev #define VT7505_MFR_PEAK_VIN 0xd1 22*97c1723aSGeorgi Vlaev #define VT7505_MFR_PEAK_IOUT 0xd2 23*97c1723aSGeorgi Vlaev #define VT7505_MFR_PEAK_PIN 0xd3 24*97c1723aSGeorgi Vlaev #define VT7505_MFR_PEAK_TEMP 0xd4 25*97c1723aSGeorgi Vlaev #define VT7505_MFR_CLEAR_PEAKS 0xd5 26*97c1723aSGeorgi Vlaev #define VT7505_MFR_PEAK_VOUT 0xfd 27*97c1723aSGeorgi Vlaev 28*97c1723aSGeorgi Vlaev #define VT7505_RLOAD_DEFAULT 4750 29*97c1723aSGeorgi Vlaev /* Largest RLOAD for which coeff * rload / 1000 still fits in s32. */ 30*97c1723aSGeorgi Vlaev #define VT7505_RLOAD_MAX 283383959U 31*97c1723aSGeorgi Vlaev 32*97c1723aSGeorgi Vlaev struct vt7505_chip_data { 33*97c1723aSGeorgi Vlaev int temp_m; 34*97c1723aSGeorgi Vlaev int temp_b; 35*97c1723aSGeorgi Vlaev bool has_ocp_filter; 36*97c1723aSGeorgi Vlaev }; 37*97c1723aSGeorgi Vlaev 38*97c1723aSGeorgi Vlaev static const struct vt7505_chip_data max16545_data = { 39*97c1723aSGeorgi Vlaev .temp_m = 205, 40*97c1723aSGeorgi Vlaev .temp_b = 6545, 41*97c1723aSGeorgi Vlaev }; 42*97c1723aSGeorgi Vlaev 43*97c1723aSGeorgi Vlaev static const struct vt7505_chip_data max16550_data = { 44*97c1723aSGeorgi Vlaev .temp_m = 199, 45*97c1723aSGeorgi Vlaev .temp_b = 7046, 46*97c1723aSGeorgi Vlaev .has_ocp_filter = true, 47*97c1723aSGeorgi Vlaev }; 48*97c1723aSGeorgi Vlaev 49*97c1723aSGeorgi Vlaev static const struct vt7505_chip_data vt7505_data = { 50*97c1723aSGeorgi Vlaev .temp_m = 205, 51*97c1723aSGeorgi Vlaev .temp_b = 6545, 52*97c1723aSGeorgi Vlaev .has_ocp_filter = true, 53*97c1723aSGeorgi Vlaev }; 54*97c1723aSGeorgi Vlaev 55*97c1723aSGeorgi Vlaev static int vt7505_read_word_data(struct i2c_client *client, int page, 56*97c1723aSGeorgi Vlaev int phase, int reg) 57*97c1723aSGeorgi Vlaev { 58*97c1723aSGeorgi Vlaev switch (reg) { 59*97c1723aSGeorgi Vlaev case PMBUS_VIRT_READ_VIN_MAX: 60*97c1723aSGeorgi Vlaev return pmbus_read_word_data(client, page, phase, 61*97c1723aSGeorgi Vlaev VT7505_MFR_PEAK_VIN); 62*97c1723aSGeorgi Vlaev case PMBUS_VIRT_READ_IOUT_MAX: 63*97c1723aSGeorgi Vlaev return pmbus_read_word_data(client, page, phase, 64*97c1723aSGeorgi Vlaev VT7505_MFR_PEAK_IOUT); 65*97c1723aSGeorgi Vlaev case PMBUS_VIRT_READ_PIN_MAX: 66*97c1723aSGeorgi Vlaev return pmbus_read_word_data(client, page, phase, 67*97c1723aSGeorgi Vlaev VT7505_MFR_PEAK_PIN); 68*97c1723aSGeorgi Vlaev case PMBUS_VIRT_READ_TEMP_MAX: 69*97c1723aSGeorgi Vlaev return pmbus_read_word_data(client, page, phase, 70*97c1723aSGeorgi Vlaev VT7505_MFR_PEAK_TEMP); 71*97c1723aSGeorgi Vlaev case PMBUS_VIRT_READ_VOUT_MAX: 72*97c1723aSGeorgi Vlaev return pmbus_read_word_data(client, page, phase, 73*97c1723aSGeorgi Vlaev VT7505_MFR_PEAK_VOUT); 74*97c1723aSGeorgi Vlaev case PMBUS_VIRT_RESET_VIN_HISTORY: 75*97c1723aSGeorgi Vlaev case PMBUS_VIRT_RESET_IOUT_HISTORY: 76*97c1723aSGeorgi Vlaev case PMBUS_VIRT_RESET_PIN_HISTORY: 77*97c1723aSGeorgi Vlaev case PMBUS_VIRT_RESET_TEMP_HISTORY: 78*97c1723aSGeorgi Vlaev case PMBUS_VIRT_RESET_VOUT_HISTORY: 79*97c1723aSGeorgi Vlaev return 0; 80*97c1723aSGeorgi Vlaev default: 81*97c1723aSGeorgi Vlaev return -ENODATA; 82*97c1723aSGeorgi Vlaev } 83*97c1723aSGeorgi Vlaev } 84*97c1723aSGeorgi Vlaev 85*97c1723aSGeorgi Vlaev static int vt7505_write_word_data(struct i2c_client *client, int page, 86*97c1723aSGeorgi Vlaev int reg, u16 word) 87*97c1723aSGeorgi Vlaev { 88*97c1723aSGeorgi Vlaev switch (reg) { 89*97c1723aSGeorgi Vlaev /* 90*97c1723aSGeorgi Vlaev * A single reset command clears all peak values. CLEAR_PEAKS is a 91*97c1723aSGeorgi Vlaev * send-byte command; the device NAKs a word or byte-data write to it. 92*97c1723aSGeorgi Vlaev */ 93*97c1723aSGeorgi Vlaev case PMBUS_VIRT_RESET_VIN_HISTORY: 94*97c1723aSGeorgi Vlaev case PMBUS_VIRT_RESET_IOUT_HISTORY: 95*97c1723aSGeorgi Vlaev case PMBUS_VIRT_RESET_PIN_HISTORY: 96*97c1723aSGeorgi Vlaev case PMBUS_VIRT_RESET_TEMP_HISTORY: 97*97c1723aSGeorgi Vlaev case PMBUS_VIRT_RESET_VOUT_HISTORY: 98*97c1723aSGeorgi Vlaev return pmbus_write_byte(client, page, 99*97c1723aSGeorgi Vlaev VT7505_MFR_CLEAR_PEAKS); 100*97c1723aSGeorgi Vlaev default: 101*97c1723aSGeorgi Vlaev return -ENODATA; 102*97c1723aSGeorgi Vlaev } 103*97c1723aSGeorgi Vlaev } 104*97c1723aSGeorgi Vlaev 105*97c1723aSGeorgi Vlaev /* 106*97c1723aSGeorgi Vlaev * None of these controllers implement the standard PMBus WRITE_PROTECT 107*97c1723aSGeorgi Vlaev * (0x10) register, so tell the core not to access it. 108*97c1723aSGeorgi Vlaev */ 109*97c1723aSGeorgi Vlaev static struct pmbus_platform_data vt7505_pdata = { 110*97c1723aSGeorgi Vlaev .flags = PMBUS_NO_WRITE_PROTECT, 111*97c1723aSGeorgi Vlaev }; 112*97c1723aSGeorgi Vlaev 113*97c1723aSGeorgi Vlaev static int vt7505_set_ocp_filter(struct i2c_client *client) 114*97c1723aSGeorgi Vlaev { 115*97c1723aSGeorgi Vlaev u32 ocp_us; 116*97c1723aSGeorgi Vlaev u8 field; 117*97c1723aSGeorgi Vlaev int ret; 118*97c1723aSGeorgi Vlaev u16 word; 119*97c1723aSGeorgi Vlaev 120*97c1723aSGeorgi Vlaev if (of_property_read_u32(client->dev.of_node, "adi,ocp-severe-filter-us", 121*97c1723aSGeorgi Vlaev &ocp_us)) 122*97c1723aSGeorgi Vlaev return 0; 123*97c1723aSGeorgi Vlaev 124*97c1723aSGeorgi Vlaev switch (ocp_us) { 125*97c1723aSGeorgi Vlaev case 0: 126*97c1723aSGeorgi Vlaev field = 0; 127*97c1723aSGeorgi Vlaev break; 128*97c1723aSGeorgi Vlaev case 1: 129*97c1723aSGeorgi Vlaev field = 1; 130*97c1723aSGeorgi Vlaev break; 131*97c1723aSGeorgi Vlaev case 2: 132*97c1723aSGeorgi Vlaev field = 2; 133*97c1723aSGeorgi Vlaev break; 134*97c1723aSGeorgi Vlaev case 10: 135*97c1723aSGeorgi Vlaev field = 3; 136*97c1723aSGeorgi Vlaev break; 137*97c1723aSGeorgi Vlaev default: 138*97c1723aSGeorgi Vlaev return dev_err_probe(&client->dev, -EINVAL, 139*97c1723aSGeorgi Vlaev "invalid adi,ocp-severe-filter-us value %u\n", 140*97c1723aSGeorgi Vlaev ocp_us); 141*97c1723aSGeorgi Vlaev } 142*97c1723aSGeorgi Vlaev 143*97c1723aSGeorgi Vlaev ret = i2c_smbus_read_word_data(client, VT7505_MFR_CONFIG); 144*97c1723aSGeorgi Vlaev if (ret < 0) 145*97c1723aSGeorgi Vlaev return dev_err_probe(&client->dev, ret, 146*97c1723aSGeorgi Vlaev "failed to read MFR_CONFIG\n"); 147*97c1723aSGeorgi Vlaev 148*97c1723aSGeorgi Vlaev word = ret & ~VT7505_CFG_OCP_S_FILT_MASK; 149*97c1723aSGeorgi Vlaev word |= FIELD_PREP(VT7505_CFG_OCP_S_FILT_MASK, field); 150*97c1723aSGeorgi Vlaev 151*97c1723aSGeorgi Vlaev ret = i2c_smbus_write_word_data(client, VT7505_MFR_CONFIG, word); 152*97c1723aSGeorgi Vlaev if (ret < 0) 153*97c1723aSGeorgi Vlaev return dev_err_probe(&client->dev, ret, 154*97c1723aSGeorgi Vlaev "failed to write MFR_CONFIG\n"); 155*97c1723aSGeorgi Vlaev 156*97c1723aSGeorgi Vlaev return 0; 157*97c1723aSGeorgi Vlaev } 158*97c1723aSGeorgi Vlaev 159*97c1723aSGeorgi Vlaev static void vt7505_set_m(int *m, u32 rload) 160*97c1723aSGeorgi Vlaev { 161*97c1723aSGeorgi Vlaev u64 val = (u64)*m * rload; 162*97c1723aSGeorgi Vlaev 163*97c1723aSGeorgi Vlaev /* rload is range-checked in probe, so the result fits in int. */ 164*97c1723aSGeorgi Vlaev *m = DIV_ROUND_CLOSEST_ULL(val, 1000); 165*97c1723aSGeorgi Vlaev } 166*97c1723aSGeorgi Vlaev 167*97c1723aSGeorgi Vlaev static int vt7505_probe(struct i2c_client *client) 168*97c1723aSGeorgi Vlaev { 169*97c1723aSGeorgi Vlaev struct device *dev = &client->dev; 170*97c1723aSGeorgi Vlaev const struct vt7505_chip_data *chip; 171*97c1723aSGeorgi Vlaev struct pmbus_driver_info *info; 172*97c1723aSGeorgi Vlaev u32 rload; 173*97c1723aSGeorgi Vlaev int ret; 174*97c1723aSGeorgi Vlaev 175*97c1723aSGeorgi Vlaev chip = i2c_get_match_data(client); 176*97c1723aSGeorgi Vlaev if (!chip) 177*97c1723aSGeorgi Vlaev return -ENODEV; 178*97c1723aSGeorgi Vlaev 179*97c1723aSGeorgi Vlaev info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL); 180*97c1723aSGeorgi Vlaev if (!info) 181*97c1723aSGeorgi Vlaev return -ENOMEM; 182*97c1723aSGeorgi Vlaev 183*97c1723aSGeorgi Vlaev dev->platform_data = &vt7505_pdata; 184*97c1723aSGeorgi Vlaev 185*97c1723aSGeorgi Vlaev /* 186*97c1723aSGeorgi Vlaev * The m coefficient used in the direct-format current and power 187*97c1723aSGeorgi Vlaev * calculations depends on RLOAD, the external current-report resistor 188*97c1723aSGeorgi Vlaev * connected between the ILOAD pin and ground. Use the default value if 189*97c1723aSGeorgi Vlaev * none is specified. 190*97c1723aSGeorgi Vlaev */ 191*97c1723aSGeorgi Vlaev if (of_property_read_u32(dev->of_node, "adi,rload-ohms", &rload)) 192*97c1723aSGeorgi Vlaev rload = VT7505_RLOAD_DEFAULT; 193*97c1723aSGeorgi Vlaev 194*97c1723aSGeorgi Vlaev if (!rload || rload > VT7505_RLOAD_MAX) 195*97c1723aSGeorgi Vlaev return dev_err_probe(dev, -EINVAL, 196*97c1723aSGeorgi Vlaev "adi,rload-ohms must be 1-%u\n", 197*97c1723aSGeorgi Vlaev VT7505_RLOAD_MAX); 198*97c1723aSGeorgi Vlaev 199*97c1723aSGeorgi Vlaev info->pages = 1; 200*97c1723aSGeorgi Vlaev info->read_word_data = vt7505_read_word_data; 201*97c1723aSGeorgi Vlaev info->write_word_data = vt7505_write_word_data; 202*97c1723aSGeorgi Vlaev 203*97c1723aSGeorgi Vlaev info->format[PSC_VOLTAGE_IN] = direct; 204*97c1723aSGeorgi Vlaev info->format[PSC_VOLTAGE_OUT] = direct; 205*97c1723aSGeorgi Vlaev info->format[PSC_CURRENT_IN] = direct; 206*97c1723aSGeorgi Vlaev info->format[PSC_CURRENT_OUT] = direct; 207*97c1723aSGeorgi Vlaev info->format[PSC_POWER] = direct; 208*97c1723aSGeorgi Vlaev info->format[PSC_TEMPERATURE] = direct; 209*97c1723aSGeorgi Vlaev 210*97c1723aSGeorgi Vlaev /* 211*97c1723aSGeorgi Vlaev * Direct data format coefficients from the device datasheet ("PMBus 212*97c1723aSGeorgi Vlaev * Equation Parameters"). The current and power m coefficients scale 213*97c1723aSGeorgi Vlaev * with RLOAD; vt7505_set_m() applies the 1/1000 factor below, giving 214*97c1723aSGeorgi Vlaev * m = 3.824 * RLOAD for current and 0.895 * RLOAD for power. The 215*97c1723aSGeorgi Vlaev * temperature coefficients are chip specific (see the chip data). 216*97c1723aSGeorgi Vlaev */ 217*97c1723aSGeorgi Vlaev info->m[PSC_VOLTAGE_IN] = 7578; 218*97c1723aSGeorgi Vlaev info->R[PSC_VOLTAGE_IN] = -2; 219*97c1723aSGeorgi Vlaev info->m[PSC_VOLTAGE_OUT] = 7578; 220*97c1723aSGeorgi Vlaev info->R[PSC_VOLTAGE_OUT] = -2; 221*97c1723aSGeorgi Vlaev info->m[PSC_CURRENT_IN] = 3824; 222*97c1723aSGeorgi Vlaev info->b[PSC_CURRENT_IN] = -4300; 223*97c1723aSGeorgi Vlaev info->R[PSC_CURRENT_IN] = -3; 224*97c1723aSGeorgi Vlaev info->m[PSC_CURRENT_OUT] = 3824; 225*97c1723aSGeorgi Vlaev info->b[PSC_CURRENT_OUT] = -4300; 226*97c1723aSGeorgi Vlaev info->R[PSC_CURRENT_OUT] = -3; 227*97c1723aSGeorgi Vlaev info->m[PSC_POWER] = 895; 228*97c1723aSGeorgi Vlaev info->b[PSC_POWER] = -9100; 229*97c1723aSGeorgi Vlaev info->R[PSC_POWER] = -2; 230*97c1723aSGeorgi Vlaev 231*97c1723aSGeorgi Vlaev vt7505_set_m(&info->m[PSC_CURRENT_IN], rload); 232*97c1723aSGeorgi Vlaev vt7505_set_m(&info->m[PSC_CURRENT_OUT], rload); 233*97c1723aSGeorgi Vlaev vt7505_set_m(&info->m[PSC_POWER], rload); 234*97c1723aSGeorgi Vlaev 235*97c1723aSGeorgi Vlaev info->m[PSC_TEMPERATURE] = chip->temp_m; 236*97c1723aSGeorgi Vlaev info->b[PSC_TEMPERATURE] = chip->temp_b; 237*97c1723aSGeorgi Vlaev info->R[PSC_TEMPERATURE] = -2; 238*97c1723aSGeorgi Vlaev 239*97c1723aSGeorgi Vlaev info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT | 240*97c1723aSGeorgi Vlaev PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | 241*97c1723aSGeorgi Vlaev PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | 242*97c1723aSGeorgi Vlaev PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | 243*97c1723aSGeorgi Vlaev PMBUS_HAVE_IIN | PMBUS_HAVE_PIN; 244*97c1723aSGeorgi Vlaev 245*97c1723aSGeorgi Vlaev /* 246*97c1723aSGeorgi Vlaev * The severe OCP deglitch filter is programmable on the MAX16550 and 247*97c1723aSGeorgi Vlaev * the VT7505, but fixed on the MAX16545. 248*97c1723aSGeorgi Vlaev */ 249*97c1723aSGeorgi Vlaev if (chip->has_ocp_filter) { 250*97c1723aSGeorgi Vlaev ret = vt7505_set_ocp_filter(client); 251*97c1723aSGeorgi Vlaev if (ret) 252*97c1723aSGeorgi Vlaev return ret; 253*97c1723aSGeorgi Vlaev } 254*97c1723aSGeorgi Vlaev 255*97c1723aSGeorgi Vlaev return pmbus_do_probe(client, info); 256*97c1723aSGeorgi Vlaev } 257*97c1723aSGeorgi Vlaev 258*97c1723aSGeorgi Vlaev static const struct i2c_device_id vt7505_id[] = { 259*97c1723aSGeorgi Vlaev { .name = "max16545", .driver_data = (kernel_ulong_t)&max16545_data }, 260*97c1723aSGeorgi Vlaev { .name = "max16550", .driver_data = (kernel_ulong_t)&max16550_data }, 261*97c1723aSGeorgi Vlaev { .name = "vt7505", .driver_data = (kernel_ulong_t)&vt7505_data }, 262*97c1723aSGeorgi Vlaev { } 263*97c1723aSGeorgi Vlaev }; 264*97c1723aSGeorgi Vlaev MODULE_DEVICE_TABLE(i2c, vt7505_id); 265*97c1723aSGeorgi Vlaev 266*97c1723aSGeorgi Vlaev static const struct of_device_id vt7505_of_match[] = { 267*97c1723aSGeorgi Vlaev { .compatible = "adi,max16545", .data = &max16545_data }, 268*97c1723aSGeorgi Vlaev { .compatible = "adi,max16550", .data = &max16550_data }, 269*97c1723aSGeorgi Vlaev { .compatible = "adi,vt7505", .data = &vt7505_data }, 270*97c1723aSGeorgi Vlaev { } 271*97c1723aSGeorgi Vlaev }; 272*97c1723aSGeorgi Vlaev MODULE_DEVICE_TABLE(of, vt7505_of_match); 273*97c1723aSGeorgi Vlaev 274*97c1723aSGeorgi Vlaev static struct i2c_driver vt7505_driver = { 275*97c1723aSGeorgi Vlaev .driver = { 276*97c1723aSGeorgi Vlaev .name = "vt7505", 277*97c1723aSGeorgi Vlaev .of_match_table = vt7505_of_match, 278*97c1723aSGeorgi Vlaev }, 279*97c1723aSGeorgi Vlaev .probe = vt7505_probe, 280*97c1723aSGeorgi Vlaev .id_table = vt7505_id, 281*97c1723aSGeorgi Vlaev }; 282*97c1723aSGeorgi Vlaev module_i2c_driver(vt7505_driver); 283*97c1723aSGeorgi Vlaev 284*97c1723aSGeorgi Vlaev MODULE_AUTHOR("Georgi Vlaev <gvlaev@juniper.net>"); 285*97c1723aSGeorgi Vlaev MODULE_DESCRIPTION("PMBus driver for Analog Devices MAX16545/MAX16550 and Volterra VT7505"); 286*97c1723aSGeorgi Vlaev MODULE_LICENSE("GPL"); 287*97c1723aSGeorgi Vlaev MODULE_IMPORT_NS("PMBUS"); 288