1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 29d2ecfb7SGuenter Roeck /* 39d2ecfb7SGuenter Roeck * Hardware monitoring driver for Analog Devices ADM1275 Hot-Swap Controller 49d2ecfb7SGuenter Roeck * and Digital Power Monitor 59d2ecfb7SGuenter Roeck * 69d2ecfb7SGuenter Roeck * Copyright (c) 2011 Ericsson AB. 74ff0ce22SGuenter Roeck * Copyright (c) 2018 Guenter Roeck 89d2ecfb7SGuenter Roeck */ 99d2ecfb7SGuenter Roeck 109d2ecfb7SGuenter Roeck #include <linux/kernel.h> 119d2ecfb7SGuenter Roeck #include <linux/module.h> 129d2ecfb7SGuenter Roeck #include <linux/init.h> 139d2ecfb7SGuenter Roeck #include <linux/err.h> 149d2ecfb7SGuenter Roeck #include <linux/slab.h> 159d2ecfb7SGuenter Roeck #include <linux/i2c.h> 1699b41608SGuenter Roeck #include <linux/bitops.h> 17c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) #include <linux/bitfield.h> 18c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) #include <linux/log2.h> 199d2ecfb7SGuenter Roeck #include "pmbus.h" 209d2ecfb7SGuenter Roeck 214ff0ce22SGuenter Roeck enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1293, adm1294 }; 2268a40382SGuenter Roeck 2368a40382SGuenter Roeck #define ADM1275_MFR_STATUS_IOUT_WARN2 BIT(0) 2468a40382SGuenter Roeck #define ADM1293_MFR_STATUS_VAUX_UV_WARN BIT(5) 2568a40382SGuenter Roeck #define ADM1293_MFR_STATUS_VAUX_OV_WARN BIT(6) 265cf231a3SGuenter Roeck 27c576e30cSGuenter Roeck #define ADM1275_PEAK_IOUT 0xd0 28c576e30cSGuenter Roeck #define ADM1275_PEAK_VIN 0xd1 29c576e30cSGuenter Roeck #define ADM1275_PEAK_VOUT 0xd2 309d2ecfb7SGuenter Roeck #define ADM1275_PMON_CONFIG 0xd4 319d2ecfb7SGuenter Roeck 3299b41608SGuenter Roeck #define ADM1275_VIN_VOUT_SELECT BIT(6) 3399b41608SGuenter Roeck #define ADM1275_VRANGE BIT(5) 3499b41608SGuenter Roeck #define ADM1075_IRANGE_50 BIT(4) 3599b41608SGuenter Roeck #define ADM1075_IRANGE_25 BIT(3) 3699b41608SGuenter Roeck #define ADM1075_IRANGE_MASK (BIT(3) | BIT(4)) 379d2ecfb7SGuenter Roeck 384ff0ce22SGuenter Roeck #define ADM1272_IRANGE BIT(0) 394ff0ce22SGuenter Roeck 40709066acSGuenter Roeck #define ADM1278_TEMP1_EN BIT(3) 41709066acSGuenter Roeck #define ADM1278_VIN_EN BIT(2) 42709066acSGuenter Roeck #define ADM1278_VOUT_EN BIT(1) 43709066acSGuenter Roeck 4468a40382SGuenter Roeck #define ADM1293_IRANGE_25 0 4568a40382SGuenter Roeck #define ADM1293_IRANGE_50 BIT(6) 4668a40382SGuenter Roeck #define ADM1293_IRANGE_100 BIT(7) 4768a40382SGuenter Roeck #define ADM1293_IRANGE_200 (BIT(6) | BIT(7)) 4868a40382SGuenter Roeck #define ADM1293_IRANGE_MASK (BIT(6) | BIT(7)) 4968a40382SGuenter Roeck 5068a40382SGuenter Roeck #define ADM1293_VIN_SEL_012 BIT(2) 5168a40382SGuenter Roeck #define ADM1293_VIN_SEL_074 BIT(3) 5268a40382SGuenter Roeck #define ADM1293_VIN_SEL_210 (BIT(2) | BIT(3)) 5368a40382SGuenter Roeck #define ADM1293_VIN_SEL_MASK (BIT(2) | BIT(3)) 5468a40382SGuenter Roeck 5568a40382SGuenter Roeck #define ADM1293_VAUX_EN BIT(1) 5668a40382SGuenter Roeck 57709066acSGuenter Roeck #define ADM1278_PEAK_TEMP 0xd7 58c5e67636SGuenter Roeck #define ADM1275_IOUT_WARN2_LIMIT 0xd7 59c5e67636SGuenter Roeck #define ADM1275_DEVICE_CONFIG 0xd8 60c5e67636SGuenter Roeck 6199b41608SGuenter Roeck #define ADM1275_IOUT_WARN2_SELECT BIT(4) 62c5e67636SGuenter Roeck 635cf231a3SGuenter Roeck #define ADM1276_PEAK_PIN 0xda 6492711269SGuenter Roeck #define ADM1075_READ_VAUX 0xdd 6592711269SGuenter Roeck #define ADM1075_VAUX_OV_WARN_LIMIT 0xde 6692711269SGuenter Roeck #define ADM1075_VAUX_UV_WARN_LIMIT 0xdf 6768a40382SGuenter Roeck #define ADM1293_IOUT_MIN 0xe3 6868a40382SGuenter Roeck #define ADM1293_PIN_MIN 0xe4 6992711269SGuenter Roeck #define ADM1075_VAUX_STATUS 0xf6 7092711269SGuenter Roeck 7199b41608SGuenter Roeck #define ADM1075_VAUX_OV_WARN BIT(7) 7299b41608SGuenter Roeck #define ADM1075_VAUX_UV_WARN BIT(6) 7392711269SGuenter Roeck 74*7d45deb3SGuenter Roeck #define ADM1275_VI_AVG_SHIFT 0 75*7d45deb3SGuenter Roeck #define ADM1275_VI_AVG_MASK GENMASK(ADM1275_VI_AVG_SHIFT + 2, \ 76*7d45deb3SGuenter Roeck ADM1275_VI_AVG_SHIFT) 77c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) #define ADM1275_SAMPLES_AVG_MAX 128 78c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) 79*7d45deb3SGuenter Roeck #define ADM1278_PWR_AVG_SHIFT 11 80*7d45deb3SGuenter Roeck #define ADM1278_PWR_AVG_MASK GENMASK(ADM1278_PWR_AVG_SHIFT + 2, \ 81*7d45deb3SGuenter Roeck ADM1278_PWR_AVG_SHIFT) 82*7d45deb3SGuenter Roeck #define ADM1278_VI_AVG_SHIFT 8 83*7d45deb3SGuenter Roeck #define ADM1278_VI_AVG_MASK GENMASK(ADM1278_VI_AVG_SHIFT + 2, \ 84*7d45deb3SGuenter Roeck ADM1278_VI_AVG_SHIFT) 85*7d45deb3SGuenter Roeck 86c5e67636SGuenter Roeck struct adm1275_data { 875cf231a3SGuenter Roeck int id; 88c5e67636SGuenter Roeck bool have_oc_fault; 899048539bSGuenter Roeck bool have_uc_fault; 909048539bSGuenter Roeck bool have_vout; 919048539bSGuenter Roeck bool have_vaux_status; 9268a40382SGuenter Roeck bool have_mfr_vaux_status; 9368a40382SGuenter Roeck bool have_iout_min; 9468a40382SGuenter Roeck bool have_pin_min; 959048539bSGuenter Roeck bool have_pin_max; 96709066acSGuenter Roeck bool have_temp_max; 97*7d45deb3SGuenter Roeck bool have_power_sampling; 98c5e67636SGuenter Roeck struct pmbus_driver_info info; 99c5e67636SGuenter Roeck }; 100c5e67636SGuenter Roeck 101c5e67636SGuenter Roeck #define to_adm1275_data(x) container_of(x, struct adm1275_data, info) 102c5e67636SGuenter Roeck 103904b296fSGuenter Roeck struct coefficients { 104904b296fSGuenter Roeck s16 m; 105904b296fSGuenter Roeck s16 b; 106904b296fSGuenter Roeck s16 R; 107904b296fSGuenter Roeck }; 108904b296fSGuenter Roeck 109904b296fSGuenter Roeck static const struct coefficients adm1075_coefficients[] = { 110904b296fSGuenter Roeck [0] = { 27169, 0, -1 }, /* voltage */ 111904b296fSGuenter Roeck [1] = { 806, 20475, -1 }, /* current, irange25 */ 112904b296fSGuenter Roeck [2] = { 404, 20475, -1 }, /* current, irange50 */ 1136faecba0SShikhar Dogra [3] = { 8549, 0, -1 }, /* power, irange25 */ 1146faecba0SShikhar Dogra [4] = { 4279, 0, -1 }, /* power, irange50 */ 115904b296fSGuenter Roeck }; 116904b296fSGuenter Roeck 1174ff0ce22SGuenter Roeck static const struct coefficients adm1272_coefficients[] = { 1184ff0ce22SGuenter Roeck [0] = { 6770, 0, -2 }, /* voltage, vrange 60V */ 1194ff0ce22SGuenter Roeck [1] = { 4062, 0, -2 }, /* voltage, vrange 100V */ 1204ff0ce22SGuenter Roeck [2] = { 1326, 20480, -1 }, /* current, vsense range 15mV */ 1214ff0ce22SGuenter Roeck [3] = { 663, 20480, -1 }, /* current, vsense range 30mV */ 1224ff0ce22SGuenter Roeck [4] = { 3512, 0, -2 }, /* power, vrange 60V, irange 15mV */ 1234ff0ce22SGuenter Roeck [5] = { 21071, 0, -3 }, /* power, vrange 100V, irange 15mV */ 1244ff0ce22SGuenter Roeck [6] = { 17561, 0, -3 }, /* power, vrange 60V, irange 30mV */ 1254ff0ce22SGuenter Roeck [7] = { 10535, 0, -3 }, /* power, vrange 100V, irange 30mV */ 1264ff0ce22SGuenter Roeck [8] = { 42, 31871, -1 }, /* temperature */ 1274ff0ce22SGuenter Roeck 1284ff0ce22SGuenter Roeck }; 1294ff0ce22SGuenter Roeck 130904b296fSGuenter Roeck static const struct coefficients adm1275_coefficients[] = { 131904b296fSGuenter Roeck [0] = { 19199, 0, -2 }, /* voltage, vrange set */ 132904b296fSGuenter Roeck [1] = { 6720, 0, -1 }, /* voltage, vrange not set */ 133904b296fSGuenter Roeck [2] = { 807, 20475, -1 }, /* current */ 134904b296fSGuenter Roeck }; 135904b296fSGuenter Roeck 136904b296fSGuenter Roeck static const struct coefficients adm1276_coefficients[] = { 137904b296fSGuenter Roeck [0] = { 19199, 0, -2 }, /* voltage, vrange set */ 138904b296fSGuenter Roeck [1] = { 6720, 0, -1 }, /* voltage, vrange not set */ 139904b296fSGuenter Roeck [2] = { 807, 20475, -1 }, /* current */ 140904b296fSGuenter Roeck [3] = { 6043, 0, -2 }, /* power, vrange set */ 141904b296fSGuenter Roeck [4] = { 2115, 0, -1 }, /* power, vrange not set */ 142904b296fSGuenter Roeck }; 143904b296fSGuenter Roeck 144709066acSGuenter Roeck static const struct coefficients adm1278_coefficients[] = { 145709066acSGuenter Roeck [0] = { 19599, 0, -2 }, /* voltage */ 146709066acSGuenter Roeck [1] = { 800, 20475, -1 }, /* current */ 147709066acSGuenter Roeck [2] = { 6123, 0, -2 }, /* power */ 148709066acSGuenter Roeck [3] = { 42, 31880, -1 }, /* temperature */ 149709066acSGuenter Roeck }; 150709066acSGuenter Roeck 15168a40382SGuenter Roeck static const struct coefficients adm1293_coefficients[] = { 15268a40382SGuenter Roeck [0] = { 3333, -1, 0 }, /* voltage, vrange 1.2V */ 15368a40382SGuenter Roeck [1] = { 5552, -5, -1 }, /* voltage, vrange 7.4V */ 15468a40382SGuenter Roeck [2] = { 19604, -50, -2 }, /* voltage, vrange 21V */ 15568a40382SGuenter Roeck [3] = { 8000, -100, -2 }, /* current, irange25 */ 15668a40382SGuenter Roeck [4] = { 4000, -100, -2 }, /* current, irange50 */ 15768a40382SGuenter Roeck [5] = { 20000, -1000, -3 }, /* current, irange100 */ 15868a40382SGuenter Roeck [6] = { 10000, -1000, -3 }, /* current, irange200 */ 15968a40382SGuenter Roeck [7] = { 10417, 0, -1 }, /* power, 1.2V, irange25 */ 16068a40382SGuenter Roeck [8] = { 5208, 0, -1 }, /* power, 1.2V, irange50 */ 16168a40382SGuenter Roeck [9] = { 26042, 0, -2 }, /* power, 1.2V, irange100 */ 16268a40382SGuenter Roeck [10] = { 13021, 0, -2 }, /* power, 1.2V, irange200 */ 16368a40382SGuenter Roeck [11] = { 17351, 0, -2 }, /* power, 7.4V, irange25 */ 16468a40382SGuenter Roeck [12] = { 8676, 0, -2 }, /* power, 7.4V, irange50 */ 16568a40382SGuenter Roeck [13] = { 4338, 0, -2 }, /* power, 7.4V, irange100 */ 16668a40382SGuenter Roeck [14] = { 21689, 0, -3 }, /* power, 7.4V, irange200 */ 16768a40382SGuenter Roeck [15] = { 6126, 0, -2 }, /* power, 21V, irange25 */ 16868a40382SGuenter Roeck [16] = { 30631, 0, -3 }, /* power, 21V, irange50 */ 16968a40382SGuenter Roeck [17] = { 15316, 0, -3 }, /* power, 21V, irange100 */ 17068a40382SGuenter Roeck [18] = { 7658, 0, -3 }, /* power, 21V, irange200 */ 17168a40382SGuenter Roeck }; 17268a40382SGuenter Roeck 173*7d45deb3SGuenter Roeck static int adm1275_read_pmon_config(const struct adm1275_data *data, 174*7d45deb3SGuenter Roeck struct i2c_client *client, bool is_power) 175c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) { 176*7d45deb3SGuenter Roeck int shift, ret; 177*7d45deb3SGuenter Roeck u16 mask; 178c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) 179*7d45deb3SGuenter Roeck /* 180*7d45deb3SGuenter Roeck * The PMON configuration register is a 16-bit register only on chips 181*7d45deb3SGuenter Roeck * supporting power average sampling. On other chips it is an 8-bit 182*7d45deb3SGuenter Roeck * register. 183*7d45deb3SGuenter Roeck */ 184*7d45deb3SGuenter Roeck if (data->have_power_sampling) { 185c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG); 186*7d45deb3SGuenter Roeck mask = is_power ? ADM1278_PWR_AVG_MASK : ADM1278_VI_AVG_MASK; 187*7d45deb3SGuenter Roeck shift = is_power ? ADM1278_PWR_AVG_SHIFT : ADM1278_VI_AVG_SHIFT; 188*7d45deb3SGuenter Roeck } else { 189*7d45deb3SGuenter Roeck ret = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG); 190*7d45deb3SGuenter Roeck mask = ADM1275_VI_AVG_MASK; 191*7d45deb3SGuenter Roeck shift = ADM1275_VI_AVG_SHIFT; 192*7d45deb3SGuenter Roeck } 193c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) if (ret < 0) 194c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) return ret; 195c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) 196*7d45deb3SGuenter Roeck return (ret & mask) >> shift; 197c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) } 198c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) 199*7d45deb3SGuenter Roeck static int adm1275_write_pmon_config(const struct adm1275_data *data, 200*7d45deb3SGuenter Roeck struct i2c_client *client, 201*7d45deb3SGuenter Roeck bool is_power, u16 word) 202c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) { 203*7d45deb3SGuenter Roeck int shift, ret; 204*7d45deb3SGuenter Roeck u16 mask; 205c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) 206*7d45deb3SGuenter Roeck if (data->have_power_sampling) { 207c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG); 208*7d45deb3SGuenter Roeck mask = is_power ? ADM1278_PWR_AVG_MASK : ADM1278_VI_AVG_MASK; 209*7d45deb3SGuenter Roeck shift = is_power ? ADM1278_PWR_AVG_SHIFT : ADM1278_VI_AVG_SHIFT; 210*7d45deb3SGuenter Roeck } else { 211*7d45deb3SGuenter Roeck ret = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG); 212*7d45deb3SGuenter Roeck mask = ADM1275_VI_AVG_MASK; 213*7d45deb3SGuenter Roeck shift = ADM1275_VI_AVG_SHIFT; 214*7d45deb3SGuenter Roeck } 215c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) if (ret < 0) 216c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) return ret; 217c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) 218*7d45deb3SGuenter Roeck word = (ret & ~mask) | ((word << shift) & mask); 219*7d45deb3SGuenter Roeck if (data->have_power_sampling) 220*7d45deb3SGuenter Roeck ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG, 221*7d45deb3SGuenter Roeck word); 222*7d45deb3SGuenter Roeck else 223*7d45deb3SGuenter Roeck ret = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONFIG, 224*7d45deb3SGuenter Roeck word); 225c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) 226c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) return ret; 227c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) } 228c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) 229c576e30cSGuenter Roeck static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) 230c576e30cSGuenter Roeck { 231c5e67636SGuenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 232c5e67636SGuenter Roeck const struct adm1275_data *data = to_adm1275_data(info); 2335cf231a3SGuenter Roeck int ret = 0; 234c576e30cSGuenter Roeck 235ecb29abdSGuenter Roeck if (page > 0) 236c5e67636SGuenter Roeck return -ENXIO; 237c576e30cSGuenter Roeck 238c576e30cSGuenter Roeck switch (reg) { 239c5e67636SGuenter Roeck case PMBUS_IOUT_UC_FAULT_LIMIT: 2409048539bSGuenter Roeck if (!data->have_uc_fault) 2419048539bSGuenter Roeck return -ENXIO; 242c5e67636SGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT); 243c5e67636SGuenter Roeck break; 244c5e67636SGuenter Roeck case PMBUS_IOUT_OC_FAULT_LIMIT: 2459048539bSGuenter Roeck if (!data->have_oc_fault) 2469048539bSGuenter Roeck return -ENXIO; 247c5e67636SGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT); 248c5e67636SGuenter Roeck break; 24992711269SGuenter Roeck case PMBUS_VOUT_OV_WARN_LIMIT: 2509048539bSGuenter Roeck if (data->have_vout) 2519048539bSGuenter Roeck return -ENODATA; 25292711269SGuenter Roeck ret = pmbus_read_word_data(client, 0, 25392711269SGuenter Roeck ADM1075_VAUX_OV_WARN_LIMIT); 25492711269SGuenter Roeck break; 25592711269SGuenter Roeck case PMBUS_VOUT_UV_WARN_LIMIT: 2569048539bSGuenter Roeck if (data->have_vout) 2579048539bSGuenter Roeck return -ENODATA; 25892711269SGuenter Roeck ret = pmbus_read_word_data(client, 0, 25992711269SGuenter Roeck ADM1075_VAUX_UV_WARN_LIMIT); 26092711269SGuenter Roeck break; 26192711269SGuenter Roeck case PMBUS_READ_VOUT: 2629048539bSGuenter Roeck if (data->have_vout) 2639048539bSGuenter Roeck return -ENODATA; 26492711269SGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1075_READ_VAUX); 26592711269SGuenter Roeck break; 26668a40382SGuenter Roeck case PMBUS_VIRT_READ_IOUT_MIN: 26768a40382SGuenter Roeck if (!data->have_iout_min) 26868a40382SGuenter Roeck return -ENXIO; 26968a40382SGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1293_IOUT_MIN); 27068a40382SGuenter Roeck break; 271c576e30cSGuenter Roeck case PMBUS_VIRT_READ_IOUT_MAX: 272c576e30cSGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT); 273c576e30cSGuenter Roeck break; 274c576e30cSGuenter Roeck case PMBUS_VIRT_READ_VOUT_MAX: 275c576e30cSGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VOUT); 276c576e30cSGuenter Roeck break; 277c576e30cSGuenter Roeck case PMBUS_VIRT_READ_VIN_MAX: 278c576e30cSGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN); 279c576e30cSGuenter Roeck break; 28068a40382SGuenter Roeck case PMBUS_VIRT_READ_PIN_MIN: 28168a40382SGuenter Roeck if (!data->have_pin_min) 28268a40382SGuenter Roeck return -ENXIO; 28368a40382SGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1293_PIN_MIN); 28468a40382SGuenter Roeck break; 2855cf231a3SGuenter Roeck case PMBUS_VIRT_READ_PIN_MAX: 2869048539bSGuenter Roeck if (!data->have_pin_max) 2879048539bSGuenter Roeck return -ENXIO; 2885cf231a3SGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN); 2895cf231a3SGuenter Roeck break; 290709066acSGuenter Roeck case PMBUS_VIRT_READ_TEMP_MAX: 291709066acSGuenter Roeck if (!data->have_temp_max) 292709066acSGuenter Roeck return -ENXIO; 293709066acSGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1278_PEAK_TEMP); 294709066acSGuenter Roeck break; 295c576e30cSGuenter Roeck case PMBUS_VIRT_RESET_IOUT_HISTORY: 296c576e30cSGuenter Roeck case PMBUS_VIRT_RESET_VOUT_HISTORY: 297c576e30cSGuenter Roeck case PMBUS_VIRT_RESET_VIN_HISTORY: 2985cf231a3SGuenter Roeck break; 2995cf231a3SGuenter Roeck case PMBUS_VIRT_RESET_PIN_HISTORY: 3009048539bSGuenter Roeck if (!data->have_pin_max) 3019048539bSGuenter Roeck return -ENXIO; 302c576e30cSGuenter Roeck break; 303709066acSGuenter Roeck case PMBUS_VIRT_RESET_TEMP_HISTORY: 304709066acSGuenter Roeck if (!data->have_temp_max) 305709066acSGuenter Roeck return -ENXIO; 306709066acSGuenter Roeck break; 307c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) case PMBUS_VIRT_POWER_SAMPLES: 308*7d45deb3SGuenter Roeck if (!data->have_power_sampling) 309*7d45deb3SGuenter Roeck return -ENXIO; 310*7d45deb3SGuenter Roeck ret = adm1275_read_pmon_config(data, client, true); 311c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) if (ret < 0) 312c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) break; 313c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) ret = BIT(ret); 314c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) break; 315c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) case PMBUS_VIRT_IN_SAMPLES: 316c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) case PMBUS_VIRT_CURR_SAMPLES: 317*7d45deb3SGuenter Roeck ret = adm1275_read_pmon_config(data, client, false); 318c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) if (ret < 0) 319c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) break; 320c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) ret = BIT(ret); 321c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) break; 322c576e30cSGuenter Roeck default: 323c576e30cSGuenter Roeck ret = -ENODATA; 324c576e30cSGuenter Roeck break; 325c576e30cSGuenter Roeck } 326c576e30cSGuenter Roeck return ret; 327c576e30cSGuenter Roeck } 328c576e30cSGuenter Roeck 329c576e30cSGuenter Roeck static int adm1275_write_word_data(struct i2c_client *client, int page, int reg, 330c576e30cSGuenter Roeck u16 word) 331c576e30cSGuenter Roeck { 33268a40382SGuenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 33368a40382SGuenter Roeck const struct adm1275_data *data = to_adm1275_data(info); 334c576e30cSGuenter Roeck int ret; 335c576e30cSGuenter Roeck 336ecb29abdSGuenter Roeck if (page > 0) 337c5e67636SGuenter Roeck return -ENXIO; 338c576e30cSGuenter Roeck 339c576e30cSGuenter Roeck switch (reg) { 340c5e67636SGuenter Roeck case PMBUS_IOUT_UC_FAULT_LIMIT: 341c5e67636SGuenter Roeck case PMBUS_IOUT_OC_FAULT_LIMIT: 342c5e67636SGuenter Roeck ret = pmbus_write_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT, 343c5e67636SGuenter Roeck word); 344c5e67636SGuenter Roeck break; 345c576e30cSGuenter Roeck case PMBUS_VIRT_RESET_IOUT_HISTORY: 346c576e30cSGuenter Roeck ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0); 34768a40382SGuenter Roeck if (!ret && data->have_iout_min) 34868a40382SGuenter Roeck ret = pmbus_write_word_data(client, 0, 34968a40382SGuenter Roeck ADM1293_IOUT_MIN, 0); 350c576e30cSGuenter Roeck break; 351c576e30cSGuenter Roeck case PMBUS_VIRT_RESET_VOUT_HISTORY: 352c576e30cSGuenter Roeck ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VOUT, 0); 353c576e30cSGuenter Roeck break; 354c576e30cSGuenter Roeck case PMBUS_VIRT_RESET_VIN_HISTORY: 355c576e30cSGuenter Roeck ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VIN, 0); 356c576e30cSGuenter Roeck break; 3575cf231a3SGuenter Roeck case PMBUS_VIRT_RESET_PIN_HISTORY: 3585cf231a3SGuenter Roeck ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0); 35968a40382SGuenter Roeck if (!ret && data->have_pin_min) 36068a40382SGuenter Roeck ret = pmbus_write_word_data(client, 0, 36168a40382SGuenter Roeck ADM1293_PIN_MIN, 0); 3625cf231a3SGuenter Roeck break; 363709066acSGuenter Roeck case PMBUS_VIRT_RESET_TEMP_HISTORY: 364709066acSGuenter Roeck ret = pmbus_write_word_data(client, 0, ADM1278_PEAK_TEMP, 0); 365709066acSGuenter Roeck break; 366c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) case PMBUS_VIRT_POWER_SAMPLES: 367*7d45deb3SGuenter Roeck if (!data->have_power_sampling) 368*7d45deb3SGuenter Roeck return -ENXIO; 369c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX); 370*7d45deb3SGuenter Roeck ret = adm1275_write_pmon_config(data, client, true, 371c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) ilog2(word)); 372c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) break; 373c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) case PMBUS_VIRT_IN_SAMPLES: 374c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) case PMBUS_VIRT_CURR_SAMPLES: 375c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX); 376*7d45deb3SGuenter Roeck ret = adm1275_write_pmon_config(data, client, false, 377c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) ilog2(word)); 378c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) break; 379c576e30cSGuenter Roeck default: 380c576e30cSGuenter Roeck ret = -ENODATA; 381c576e30cSGuenter Roeck break; 382c576e30cSGuenter Roeck } 383c576e30cSGuenter Roeck return ret; 384c576e30cSGuenter Roeck } 385c576e30cSGuenter Roeck 386c5e67636SGuenter Roeck static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg) 387c5e67636SGuenter Roeck { 388c5e67636SGuenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 389c5e67636SGuenter Roeck const struct adm1275_data *data = to_adm1275_data(info); 390c5e67636SGuenter Roeck int mfr_status, ret; 391c5e67636SGuenter Roeck 392da8e48abSGuenter Roeck if (page > 0) 393c5e67636SGuenter Roeck return -ENXIO; 394c5e67636SGuenter Roeck 395c5e67636SGuenter Roeck switch (reg) { 396c5e67636SGuenter Roeck case PMBUS_STATUS_IOUT: 397c5e67636SGuenter Roeck ret = pmbus_read_byte_data(client, page, PMBUS_STATUS_IOUT); 398c5e67636SGuenter Roeck if (ret < 0) 399c5e67636SGuenter Roeck break; 4009048539bSGuenter Roeck if (!data->have_oc_fault && !data->have_uc_fault) 4019048539bSGuenter Roeck break; 402c5e67636SGuenter Roeck mfr_status = pmbus_read_byte_data(client, page, 403c5e67636SGuenter Roeck PMBUS_STATUS_MFR_SPECIFIC); 4049048539bSGuenter Roeck if (mfr_status < 0) 4059048539bSGuenter Roeck return mfr_status; 406c5e67636SGuenter Roeck if (mfr_status & ADM1275_MFR_STATUS_IOUT_WARN2) { 407c5e67636SGuenter Roeck ret |= data->have_oc_fault ? 408c5e67636SGuenter Roeck PB_IOUT_OC_FAULT : PB_IOUT_UC_FAULT; 409c5e67636SGuenter Roeck } 410c5e67636SGuenter Roeck break; 41192711269SGuenter Roeck case PMBUS_STATUS_VOUT: 4129048539bSGuenter Roeck if (data->have_vout) 4139048539bSGuenter Roeck return -ENODATA; 41492711269SGuenter Roeck ret = 0; 4159048539bSGuenter Roeck if (data->have_vaux_status) { 41692711269SGuenter Roeck mfr_status = pmbus_read_byte_data(client, 0, 41792711269SGuenter Roeck ADM1075_VAUX_STATUS); 4189048539bSGuenter Roeck if (mfr_status < 0) 4199048539bSGuenter Roeck return mfr_status; 42092711269SGuenter Roeck if (mfr_status & ADM1075_VAUX_OV_WARN) 42192711269SGuenter Roeck ret |= PB_VOLTAGE_OV_WARNING; 42292711269SGuenter Roeck if (mfr_status & ADM1075_VAUX_UV_WARN) 42392711269SGuenter Roeck ret |= PB_VOLTAGE_UV_WARNING; 42468a40382SGuenter Roeck } else if (data->have_mfr_vaux_status) { 42568a40382SGuenter Roeck mfr_status = pmbus_read_byte_data(client, page, 42668a40382SGuenter Roeck PMBUS_STATUS_MFR_SPECIFIC); 42768a40382SGuenter Roeck if (mfr_status < 0) 42868a40382SGuenter Roeck return mfr_status; 42968a40382SGuenter Roeck if (mfr_status & ADM1293_MFR_STATUS_VAUX_OV_WARN) 43068a40382SGuenter Roeck ret |= PB_VOLTAGE_OV_WARNING; 43168a40382SGuenter Roeck if (mfr_status & ADM1293_MFR_STATUS_VAUX_UV_WARN) 43268a40382SGuenter Roeck ret |= PB_VOLTAGE_UV_WARNING; 4339048539bSGuenter Roeck } 43492711269SGuenter Roeck break; 435c5e67636SGuenter Roeck default: 436c5e67636SGuenter Roeck ret = -ENODATA; 437c5e67636SGuenter Roeck break; 438c5e67636SGuenter Roeck } 439c5e67636SGuenter Roeck return ret; 440c5e67636SGuenter Roeck } 441c5e67636SGuenter Roeck 44287102808SGuenter Roeck static const struct i2c_device_id adm1275_id[] = { 44392711269SGuenter Roeck { "adm1075", adm1075 }, 4444ff0ce22SGuenter Roeck { "adm1272", adm1272 }, 44587102808SGuenter Roeck { "adm1275", adm1275 }, 44687102808SGuenter Roeck { "adm1276", adm1276 }, 447709066acSGuenter Roeck { "adm1278", adm1278 }, 44868a40382SGuenter Roeck { "adm1293", adm1293 }, 44968a40382SGuenter Roeck { "adm1294", adm1294 }, 45087102808SGuenter Roeck { } 45187102808SGuenter Roeck }; 45287102808SGuenter Roeck MODULE_DEVICE_TABLE(i2c, adm1275_id); 45387102808SGuenter Roeck 4549d2ecfb7SGuenter Roeck static int adm1275_probe(struct i2c_client *client, 4559d2ecfb7SGuenter Roeck const struct i2c_device_id *id) 4569d2ecfb7SGuenter Roeck { 45787102808SGuenter Roeck u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1]; 458c5e67636SGuenter Roeck int config, device_config; 4599d2ecfb7SGuenter Roeck int ret; 4609d2ecfb7SGuenter Roeck struct pmbus_driver_info *info; 461c5e67636SGuenter Roeck struct adm1275_data *data; 46287102808SGuenter Roeck const struct i2c_device_id *mid; 463904b296fSGuenter Roeck const struct coefficients *coefficients; 46468a40382SGuenter Roeck int vindex = -1, voindex = -1, cindex = -1, pindex = -1; 465709066acSGuenter Roeck int tindex = -1; 4666e5c06adSKun Yi u32 shunt; 4679d2ecfb7SGuenter Roeck 4689d2ecfb7SGuenter Roeck if (!i2c_check_functionality(client->adapter, 46987102808SGuenter Roeck I2C_FUNC_SMBUS_READ_BYTE_DATA 47087102808SGuenter Roeck | I2C_FUNC_SMBUS_BLOCK_DATA)) 4719d2ecfb7SGuenter Roeck return -ENODEV; 4729d2ecfb7SGuenter Roeck 47387102808SGuenter Roeck ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, block_buffer); 47487102808SGuenter Roeck if (ret < 0) { 47587102808SGuenter Roeck dev_err(&client->dev, "Failed to read Manufacturer ID\n"); 47687102808SGuenter Roeck return ret; 47787102808SGuenter Roeck } 47887102808SGuenter Roeck if (ret != 3 || strncmp(block_buffer, "ADI", 3)) { 47987102808SGuenter Roeck dev_err(&client->dev, "Unsupported Manufacturer ID\n"); 48087102808SGuenter Roeck return -ENODEV; 48187102808SGuenter Roeck } 48287102808SGuenter Roeck 48387102808SGuenter Roeck ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, block_buffer); 48487102808SGuenter Roeck if (ret < 0) { 48587102808SGuenter Roeck dev_err(&client->dev, "Failed to read Manufacturer Model\n"); 48687102808SGuenter Roeck return ret; 48787102808SGuenter Roeck } 48887102808SGuenter Roeck for (mid = adm1275_id; mid->name[0]; mid++) { 48987102808SGuenter Roeck if (!strncasecmp(mid->name, block_buffer, strlen(mid->name))) 49087102808SGuenter Roeck break; 49187102808SGuenter Roeck } 49287102808SGuenter Roeck if (!mid->name[0]) { 49387102808SGuenter Roeck dev_err(&client->dev, "Unsupported device\n"); 49487102808SGuenter Roeck return -ENODEV; 49587102808SGuenter Roeck } 49687102808SGuenter Roeck 49787102808SGuenter Roeck if (id->driver_data != mid->driver_data) 49887102808SGuenter Roeck dev_notice(&client->dev, 49987102808SGuenter Roeck "Device mismatch: Configured %s, detected %s\n", 50087102808SGuenter Roeck id->name, mid->name); 50187102808SGuenter Roeck 50287102808SGuenter Roeck config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG); 50387102808SGuenter Roeck if (config < 0) 50487102808SGuenter Roeck return config; 50587102808SGuenter Roeck 50687102808SGuenter Roeck device_config = i2c_smbus_read_byte_data(client, ADM1275_DEVICE_CONFIG); 50787102808SGuenter Roeck if (device_config < 0) 50887102808SGuenter Roeck return device_config; 50987102808SGuenter Roeck 5108b313ca7SGuenter Roeck data = devm_kzalloc(&client->dev, sizeof(struct adm1275_data), 5118b313ca7SGuenter Roeck GFP_KERNEL); 512c5e67636SGuenter Roeck if (!data) 5139d2ecfb7SGuenter Roeck return -ENOMEM; 5149d2ecfb7SGuenter Roeck 5156e5c06adSKun Yi if (of_property_read_u32(client->dev.of_node, 5166e5c06adSKun Yi "shunt-resistor-micro-ohms", &shunt)) 5176e5c06adSKun Yi shunt = 1000; /* 1 mOhm if not set via DT */ 5186e5c06adSKun Yi 5196e5c06adSKun Yi if (shunt == 0) 5206e5c06adSKun Yi return -EINVAL; 5216e5c06adSKun Yi 52287102808SGuenter Roeck data->id = mid->driver_data; 5239d2ecfb7SGuenter Roeck 524c5e67636SGuenter Roeck info = &data->info; 525c5e67636SGuenter Roeck 5269d2ecfb7SGuenter Roeck info->pages = 1; 5271061d851SGuenter Roeck info->format[PSC_VOLTAGE_IN] = direct; 5281061d851SGuenter Roeck info->format[PSC_VOLTAGE_OUT] = direct; 5291061d851SGuenter Roeck info->format[PSC_CURRENT_OUT] = direct; 530904b296fSGuenter Roeck info->format[PSC_POWER] = direct; 531709066acSGuenter Roeck info->format[PSC_TEMPERATURE] = direct; 532c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | 533c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) PMBUS_HAVE_SAMPLES; 5349d2ecfb7SGuenter Roeck 535c576e30cSGuenter Roeck info->read_word_data = adm1275_read_word_data; 536c5e67636SGuenter Roeck info->read_byte_data = adm1275_read_byte_data; 537c576e30cSGuenter Roeck info->write_word_data = adm1275_write_word_data; 538c576e30cSGuenter Roeck 53987102808SGuenter Roeck switch (data->id) { 54092711269SGuenter Roeck case adm1075: 5419048539bSGuenter Roeck if (device_config & ADM1275_IOUT_WARN2_SELECT) 5429048539bSGuenter Roeck data->have_oc_fault = true; 5439048539bSGuenter Roeck else 5449048539bSGuenter Roeck data->have_uc_fault = true; 5459048539bSGuenter Roeck data->have_pin_max = true; 5469048539bSGuenter Roeck data->have_vaux_status = true; 5479048539bSGuenter Roeck 548904b296fSGuenter Roeck coefficients = adm1075_coefficients; 549904b296fSGuenter Roeck vindex = 0; 55092711269SGuenter Roeck switch (config & ADM1075_IRANGE_MASK) { 55192711269SGuenter Roeck case ADM1075_IRANGE_25: 552904b296fSGuenter Roeck cindex = 1; 553904b296fSGuenter Roeck pindex = 3; 55492711269SGuenter Roeck break; 55592711269SGuenter Roeck case ADM1075_IRANGE_50: 556904b296fSGuenter Roeck cindex = 2; 557904b296fSGuenter Roeck pindex = 4; 55892711269SGuenter Roeck break; 55992711269SGuenter Roeck default: 56092711269SGuenter Roeck dev_err(&client->dev, "Invalid input current range"); 56192711269SGuenter Roeck break; 56292711269SGuenter Roeck } 563904b296fSGuenter Roeck 56492711269SGuenter Roeck info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN 56592711269SGuenter Roeck | PMBUS_HAVE_STATUS_INPUT; 56692711269SGuenter Roeck if (config & ADM1275_VIN_VOUT_SELECT) 56792711269SGuenter Roeck info->func[0] |= 56892711269SGuenter Roeck PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 56992711269SGuenter Roeck break; 5704ff0ce22SGuenter Roeck case adm1272: 5714ff0ce22SGuenter Roeck data->have_vout = true; 5724ff0ce22SGuenter Roeck data->have_pin_max = true; 5734ff0ce22SGuenter Roeck data->have_temp_max = true; 574*7d45deb3SGuenter Roeck data->have_power_sampling = true; 5754ff0ce22SGuenter Roeck 5764ff0ce22SGuenter Roeck coefficients = adm1272_coefficients; 5774ff0ce22SGuenter Roeck vindex = (config & ADM1275_VRANGE) ? 1 : 0; 5784ff0ce22SGuenter Roeck cindex = (config & ADM1272_IRANGE) ? 3 : 2; 5794ff0ce22SGuenter Roeck /* pindex depends on the combination of the above */ 5804ff0ce22SGuenter Roeck switch (config & (ADM1275_VRANGE | ADM1272_IRANGE)) { 5814ff0ce22SGuenter Roeck case 0: 5824ff0ce22SGuenter Roeck default: 5834ff0ce22SGuenter Roeck pindex = 4; 5844ff0ce22SGuenter Roeck break; 5854ff0ce22SGuenter Roeck case ADM1275_VRANGE: 5864ff0ce22SGuenter Roeck pindex = 5; 5874ff0ce22SGuenter Roeck break; 5884ff0ce22SGuenter Roeck case ADM1272_IRANGE: 5894ff0ce22SGuenter Roeck pindex = 6; 5904ff0ce22SGuenter Roeck break; 5914ff0ce22SGuenter Roeck case ADM1275_VRANGE | ADM1272_IRANGE: 5924ff0ce22SGuenter Roeck pindex = 7; 5934ff0ce22SGuenter Roeck break; 5944ff0ce22SGuenter Roeck } 5954ff0ce22SGuenter Roeck tindex = 8; 5964ff0ce22SGuenter Roeck 5974ff0ce22SGuenter Roeck info->func[0] |= PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | 5984ff0ce22SGuenter Roeck PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 5994ff0ce22SGuenter Roeck 6004ff0ce22SGuenter Roeck /* Enable VOUT if not enabled (it is disabled by default) */ 6014ff0ce22SGuenter Roeck if (!(config & ADM1278_VOUT_EN)) { 6024ff0ce22SGuenter Roeck config |= ADM1278_VOUT_EN; 6034ff0ce22SGuenter Roeck ret = i2c_smbus_write_byte_data(client, 6044ff0ce22SGuenter Roeck ADM1275_PMON_CONFIG, 6054ff0ce22SGuenter Roeck config); 6064ff0ce22SGuenter Roeck if (ret < 0) { 6074ff0ce22SGuenter Roeck dev_err(&client->dev, 6084ff0ce22SGuenter Roeck "Failed to enable VOUT monitoring\n"); 6094ff0ce22SGuenter Roeck return -ENODEV; 6104ff0ce22SGuenter Roeck } 6114ff0ce22SGuenter Roeck } 6124ff0ce22SGuenter Roeck 6134ff0ce22SGuenter Roeck if (config & ADM1278_TEMP1_EN) 6144ff0ce22SGuenter Roeck info->func[0] |= 6154ff0ce22SGuenter Roeck PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; 6164ff0ce22SGuenter Roeck if (config & ADM1278_VIN_EN) 6174ff0ce22SGuenter Roeck info->func[0] |= PMBUS_HAVE_VIN; 6184ff0ce22SGuenter Roeck break; 6195cf231a3SGuenter Roeck case adm1275: 6209048539bSGuenter Roeck if (device_config & ADM1275_IOUT_WARN2_SELECT) 6219048539bSGuenter Roeck data->have_oc_fault = true; 6229048539bSGuenter Roeck else 6239048539bSGuenter Roeck data->have_uc_fault = true; 6249048539bSGuenter Roeck data->have_vout = true; 6259048539bSGuenter Roeck 626904b296fSGuenter Roeck coefficients = adm1275_coefficients; 627904b296fSGuenter Roeck vindex = (config & ADM1275_VRANGE) ? 0 : 1; 628904b296fSGuenter Roeck cindex = 2; 629904b296fSGuenter Roeck 6309d2ecfb7SGuenter Roeck if (config & ADM1275_VIN_VOUT_SELECT) 6315cf231a3SGuenter Roeck info->func[0] |= 6325cf231a3SGuenter Roeck PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 6339d2ecfb7SGuenter Roeck else 6345cf231a3SGuenter Roeck info->func[0] |= 6355cf231a3SGuenter Roeck PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT; 6365cf231a3SGuenter Roeck break; 6375cf231a3SGuenter Roeck case adm1276: 6389048539bSGuenter Roeck if (device_config & ADM1275_IOUT_WARN2_SELECT) 6399048539bSGuenter Roeck data->have_oc_fault = true; 6409048539bSGuenter Roeck else 6419048539bSGuenter Roeck data->have_uc_fault = true; 6429048539bSGuenter Roeck data->have_vout = true; 6439048539bSGuenter Roeck data->have_pin_max = true; 6449048539bSGuenter Roeck 645904b296fSGuenter Roeck coefficients = adm1276_coefficients; 646904b296fSGuenter Roeck vindex = (config & ADM1275_VRANGE) ? 0 : 1; 647904b296fSGuenter Roeck cindex = 2; 648904b296fSGuenter Roeck pindex = (config & ADM1275_VRANGE) ? 3 : 4; 649904b296fSGuenter Roeck 6505cf231a3SGuenter Roeck info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN 6515cf231a3SGuenter Roeck | PMBUS_HAVE_STATUS_INPUT; 6525cf231a3SGuenter Roeck if (config & ADM1275_VIN_VOUT_SELECT) 6535cf231a3SGuenter Roeck info->func[0] |= 6545cf231a3SGuenter Roeck PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 6555cf231a3SGuenter Roeck break; 656709066acSGuenter Roeck case adm1278: 657709066acSGuenter Roeck data->have_vout = true; 658709066acSGuenter Roeck data->have_pin_max = true; 659709066acSGuenter Roeck data->have_temp_max = true; 660*7d45deb3SGuenter Roeck data->have_power_sampling = true; 661709066acSGuenter Roeck 662709066acSGuenter Roeck coefficients = adm1278_coefficients; 663709066acSGuenter Roeck vindex = 0; 664709066acSGuenter Roeck cindex = 1; 665709066acSGuenter Roeck pindex = 2; 666709066acSGuenter Roeck tindex = 3; 667709066acSGuenter Roeck 6682b3d0c19SYi Li info->func[0] |= PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | 6692b3d0c19SYi Li PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 6702b3d0c19SYi Li 6712b3d0c19SYi Li /* Enable VOUT if not enabled (it is disabled by default) */ 6722b3d0c19SYi Li if (!(config & ADM1278_VOUT_EN)) { 6732b3d0c19SYi Li config |= ADM1278_VOUT_EN; 6742b3d0c19SYi Li ret = i2c_smbus_write_byte_data(client, 6752b3d0c19SYi Li ADM1275_PMON_CONFIG, 6762b3d0c19SYi Li config); 6772b3d0c19SYi Li if (ret < 0) { 6782b3d0c19SYi Li dev_err(&client->dev, 6792b3d0c19SYi Li "Failed to enable VOUT monitoring\n"); 6802b3d0c19SYi Li return -ENODEV; 6812b3d0c19SYi Li } 6822b3d0c19SYi Li } 6832b3d0c19SYi Li 684709066acSGuenter Roeck if (config & ADM1278_TEMP1_EN) 685709066acSGuenter Roeck info->func[0] |= 686709066acSGuenter Roeck PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; 687709066acSGuenter Roeck if (config & ADM1278_VIN_EN) 688709066acSGuenter Roeck info->func[0] |= PMBUS_HAVE_VIN; 689709066acSGuenter Roeck break; 69068a40382SGuenter Roeck case adm1293: 69168a40382SGuenter Roeck case adm1294: 69268a40382SGuenter Roeck data->have_iout_min = true; 69368a40382SGuenter Roeck data->have_pin_min = true; 69468a40382SGuenter Roeck data->have_pin_max = true; 69568a40382SGuenter Roeck data->have_mfr_vaux_status = true; 696*7d45deb3SGuenter Roeck data->have_power_sampling = true; 69768a40382SGuenter Roeck 69868a40382SGuenter Roeck coefficients = adm1293_coefficients; 69968a40382SGuenter Roeck 70068a40382SGuenter Roeck voindex = 0; 70168a40382SGuenter Roeck switch (config & ADM1293_VIN_SEL_MASK) { 70268a40382SGuenter Roeck case ADM1293_VIN_SEL_012: /* 1.2V */ 70368a40382SGuenter Roeck vindex = 0; 70468a40382SGuenter Roeck break; 70568a40382SGuenter Roeck case ADM1293_VIN_SEL_074: /* 7.4V */ 70668a40382SGuenter Roeck vindex = 1; 70768a40382SGuenter Roeck break; 70868a40382SGuenter Roeck case ADM1293_VIN_SEL_210: /* 21V */ 70968a40382SGuenter Roeck vindex = 2; 71068a40382SGuenter Roeck break; 71168a40382SGuenter Roeck default: /* disabled */ 71268a40382SGuenter Roeck break; 71368a40382SGuenter Roeck } 71468a40382SGuenter Roeck 71568a40382SGuenter Roeck switch (config & ADM1293_IRANGE_MASK) { 71668a40382SGuenter Roeck case ADM1293_IRANGE_25: 71768a40382SGuenter Roeck cindex = 3; 71868a40382SGuenter Roeck break; 71968a40382SGuenter Roeck case ADM1293_IRANGE_50: 72068a40382SGuenter Roeck cindex = 4; 72168a40382SGuenter Roeck break; 72268a40382SGuenter Roeck case ADM1293_IRANGE_100: 72368a40382SGuenter Roeck cindex = 5; 72468a40382SGuenter Roeck break; 72568a40382SGuenter Roeck case ADM1293_IRANGE_200: 72668a40382SGuenter Roeck cindex = 6; 72768a40382SGuenter Roeck break; 72868a40382SGuenter Roeck } 72968a40382SGuenter Roeck 73068a40382SGuenter Roeck if (vindex >= 0) 73168a40382SGuenter Roeck pindex = 7 + vindex * 4 + (cindex - 3); 73268a40382SGuenter Roeck 73368a40382SGuenter Roeck if (config & ADM1293_VAUX_EN) 73468a40382SGuenter Roeck info->func[0] |= 73568a40382SGuenter Roeck PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 73668a40382SGuenter Roeck 73768a40382SGuenter Roeck info->func[0] |= PMBUS_HAVE_PIN | 73868a40382SGuenter Roeck PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT; 73968a40382SGuenter Roeck 74068a40382SGuenter Roeck break; 741904b296fSGuenter Roeck default: 742904b296fSGuenter Roeck dev_err(&client->dev, "Unsupported device\n"); 743904b296fSGuenter Roeck return -ENODEV; 744904b296fSGuenter Roeck } 74568a40382SGuenter Roeck 74668a40382SGuenter Roeck if (voindex < 0) 74768a40382SGuenter Roeck voindex = vindex; 748904b296fSGuenter Roeck if (vindex >= 0) { 749904b296fSGuenter Roeck info->m[PSC_VOLTAGE_IN] = coefficients[vindex].m; 750904b296fSGuenter Roeck info->b[PSC_VOLTAGE_IN] = coefficients[vindex].b; 751904b296fSGuenter Roeck info->R[PSC_VOLTAGE_IN] = coefficients[vindex].R; 75268a40382SGuenter Roeck } 75368a40382SGuenter Roeck if (voindex >= 0) { 75468a40382SGuenter Roeck info->m[PSC_VOLTAGE_OUT] = coefficients[voindex].m; 75568a40382SGuenter Roeck info->b[PSC_VOLTAGE_OUT] = coefficients[voindex].b; 75668a40382SGuenter Roeck info->R[PSC_VOLTAGE_OUT] = coefficients[voindex].R; 757904b296fSGuenter Roeck } 758904b296fSGuenter Roeck if (cindex >= 0) { 7596e5c06adSKun Yi /* Scale current with sense resistor value */ 7606e5c06adSKun Yi info->m[PSC_CURRENT_OUT] = 7616e5c06adSKun Yi coefficients[cindex].m * shunt / 1000; 762904b296fSGuenter Roeck info->b[PSC_CURRENT_OUT] = coefficients[cindex].b; 763904b296fSGuenter Roeck info->R[PSC_CURRENT_OUT] = coefficients[cindex].R; 764904b296fSGuenter Roeck } 765904b296fSGuenter Roeck if (pindex >= 0) { 7666e5c06adSKun Yi info->m[PSC_POWER] = 7676e5c06adSKun Yi coefficients[pindex].m * shunt / 1000; 768904b296fSGuenter Roeck info->b[PSC_POWER] = coefficients[pindex].b; 769904b296fSGuenter Roeck info->R[PSC_POWER] = coefficients[pindex].R; 7705cf231a3SGuenter Roeck } 771709066acSGuenter Roeck if (tindex >= 0) { 772709066acSGuenter Roeck info->m[PSC_TEMPERATURE] = coefficients[tindex].m; 773709066acSGuenter Roeck info->b[PSC_TEMPERATURE] = coefficients[tindex].b; 774709066acSGuenter Roeck info->R[PSC_TEMPERATURE] = coefficients[tindex].R; 775709066acSGuenter Roeck } 7769d2ecfb7SGuenter Roeck 7778b313ca7SGuenter Roeck return pmbus_do_probe(client, id, info); 7789d2ecfb7SGuenter Roeck } 7799d2ecfb7SGuenter Roeck 7809d2ecfb7SGuenter Roeck static struct i2c_driver adm1275_driver = { 7819d2ecfb7SGuenter Roeck .driver = { 7829d2ecfb7SGuenter Roeck .name = "adm1275", 7839d2ecfb7SGuenter Roeck }, 7849d2ecfb7SGuenter Roeck .probe = adm1275_probe, 785dd285ad7SGuenter Roeck .remove = pmbus_do_remove, 7869d2ecfb7SGuenter Roeck .id_table = adm1275_id, 7879d2ecfb7SGuenter Roeck }; 7889d2ecfb7SGuenter Roeck 789f0967eeaSAxel Lin module_i2c_driver(adm1275_driver); 7909d2ecfb7SGuenter Roeck 7919d2ecfb7SGuenter Roeck MODULE_AUTHOR("Guenter Roeck"); 7925cf231a3SGuenter Roeck MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275 and compatibles"); 7939d2ecfb7SGuenter Roeck MODULE_LICENSE("GPL"); 794