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