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> 17*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) #include <linux/bitfield.h> 18*c83529c1SAdamski, 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*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) #define ADM1275_PWR_AVG_MASK GENMASK(13, 11) 75*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) #define ADM1275_VI_AVG_MASK GENMASK(10, 8) 76*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) #define ADM1275_SAMPLES_AVG_MAX 128 77*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) 78c5e67636SGuenter Roeck struct adm1275_data { 795cf231a3SGuenter Roeck int id; 80c5e67636SGuenter Roeck bool have_oc_fault; 819048539bSGuenter Roeck bool have_uc_fault; 829048539bSGuenter Roeck bool have_vout; 839048539bSGuenter Roeck bool have_vaux_status; 8468a40382SGuenter Roeck bool have_mfr_vaux_status; 8568a40382SGuenter Roeck bool have_iout_min; 8668a40382SGuenter Roeck bool have_pin_min; 879048539bSGuenter Roeck bool have_pin_max; 88709066acSGuenter Roeck bool have_temp_max; 89c5e67636SGuenter Roeck struct pmbus_driver_info info; 90c5e67636SGuenter Roeck }; 91c5e67636SGuenter Roeck 92c5e67636SGuenter Roeck #define to_adm1275_data(x) container_of(x, struct adm1275_data, info) 93c5e67636SGuenter Roeck 94904b296fSGuenter Roeck struct coefficients { 95904b296fSGuenter Roeck s16 m; 96904b296fSGuenter Roeck s16 b; 97904b296fSGuenter Roeck s16 R; 98904b296fSGuenter Roeck }; 99904b296fSGuenter Roeck 100904b296fSGuenter Roeck static const struct coefficients adm1075_coefficients[] = { 101904b296fSGuenter Roeck [0] = { 27169, 0, -1 }, /* voltage */ 102904b296fSGuenter Roeck [1] = { 806, 20475, -1 }, /* current, irange25 */ 103904b296fSGuenter Roeck [2] = { 404, 20475, -1 }, /* current, irange50 */ 1046faecba0SShikhar Dogra [3] = { 8549, 0, -1 }, /* power, irange25 */ 1056faecba0SShikhar Dogra [4] = { 4279, 0, -1 }, /* power, irange50 */ 106904b296fSGuenter Roeck }; 107904b296fSGuenter Roeck 1084ff0ce22SGuenter Roeck static const struct coefficients adm1272_coefficients[] = { 1094ff0ce22SGuenter Roeck [0] = { 6770, 0, -2 }, /* voltage, vrange 60V */ 1104ff0ce22SGuenter Roeck [1] = { 4062, 0, -2 }, /* voltage, vrange 100V */ 1114ff0ce22SGuenter Roeck [2] = { 1326, 20480, -1 }, /* current, vsense range 15mV */ 1124ff0ce22SGuenter Roeck [3] = { 663, 20480, -1 }, /* current, vsense range 30mV */ 1134ff0ce22SGuenter Roeck [4] = { 3512, 0, -2 }, /* power, vrange 60V, irange 15mV */ 1144ff0ce22SGuenter Roeck [5] = { 21071, 0, -3 }, /* power, vrange 100V, irange 15mV */ 1154ff0ce22SGuenter Roeck [6] = { 17561, 0, -3 }, /* power, vrange 60V, irange 30mV */ 1164ff0ce22SGuenter Roeck [7] = { 10535, 0, -3 }, /* power, vrange 100V, irange 30mV */ 1174ff0ce22SGuenter Roeck [8] = { 42, 31871, -1 }, /* temperature */ 1184ff0ce22SGuenter Roeck 1194ff0ce22SGuenter Roeck }; 1204ff0ce22SGuenter Roeck 121904b296fSGuenter Roeck static const struct coefficients adm1275_coefficients[] = { 122904b296fSGuenter Roeck [0] = { 19199, 0, -2 }, /* voltage, vrange set */ 123904b296fSGuenter Roeck [1] = { 6720, 0, -1 }, /* voltage, vrange not set */ 124904b296fSGuenter Roeck [2] = { 807, 20475, -1 }, /* current */ 125904b296fSGuenter Roeck }; 126904b296fSGuenter Roeck 127904b296fSGuenter Roeck static const struct coefficients adm1276_coefficients[] = { 128904b296fSGuenter Roeck [0] = { 19199, 0, -2 }, /* voltage, vrange set */ 129904b296fSGuenter Roeck [1] = { 6720, 0, -1 }, /* voltage, vrange not set */ 130904b296fSGuenter Roeck [2] = { 807, 20475, -1 }, /* current */ 131904b296fSGuenter Roeck [3] = { 6043, 0, -2 }, /* power, vrange set */ 132904b296fSGuenter Roeck [4] = { 2115, 0, -1 }, /* power, vrange not set */ 133904b296fSGuenter Roeck }; 134904b296fSGuenter Roeck 135709066acSGuenter Roeck static const struct coefficients adm1278_coefficients[] = { 136709066acSGuenter Roeck [0] = { 19599, 0, -2 }, /* voltage */ 137709066acSGuenter Roeck [1] = { 800, 20475, -1 }, /* current */ 138709066acSGuenter Roeck [2] = { 6123, 0, -2 }, /* power */ 139709066acSGuenter Roeck [3] = { 42, 31880, -1 }, /* temperature */ 140709066acSGuenter Roeck }; 141709066acSGuenter Roeck 14268a40382SGuenter Roeck static const struct coefficients adm1293_coefficients[] = { 14368a40382SGuenter Roeck [0] = { 3333, -1, 0 }, /* voltage, vrange 1.2V */ 14468a40382SGuenter Roeck [1] = { 5552, -5, -1 }, /* voltage, vrange 7.4V */ 14568a40382SGuenter Roeck [2] = { 19604, -50, -2 }, /* voltage, vrange 21V */ 14668a40382SGuenter Roeck [3] = { 8000, -100, -2 }, /* current, irange25 */ 14768a40382SGuenter Roeck [4] = { 4000, -100, -2 }, /* current, irange50 */ 14868a40382SGuenter Roeck [5] = { 20000, -1000, -3 }, /* current, irange100 */ 14968a40382SGuenter Roeck [6] = { 10000, -1000, -3 }, /* current, irange200 */ 15068a40382SGuenter Roeck [7] = { 10417, 0, -1 }, /* power, 1.2V, irange25 */ 15168a40382SGuenter Roeck [8] = { 5208, 0, -1 }, /* power, 1.2V, irange50 */ 15268a40382SGuenter Roeck [9] = { 26042, 0, -2 }, /* power, 1.2V, irange100 */ 15368a40382SGuenter Roeck [10] = { 13021, 0, -2 }, /* power, 1.2V, irange200 */ 15468a40382SGuenter Roeck [11] = { 17351, 0, -2 }, /* power, 7.4V, irange25 */ 15568a40382SGuenter Roeck [12] = { 8676, 0, -2 }, /* power, 7.4V, irange50 */ 15668a40382SGuenter Roeck [13] = { 4338, 0, -2 }, /* power, 7.4V, irange100 */ 15768a40382SGuenter Roeck [14] = { 21689, 0, -3 }, /* power, 7.4V, irange200 */ 15868a40382SGuenter Roeck [15] = { 6126, 0, -2 }, /* power, 21V, irange25 */ 15968a40382SGuenter Roeck [16] = { 30631, 0, -3 }, /* power, 21V, irange50 */ 16068a40382SGuenter Roeck [17] = { 15316, 0, -3 }, /* power, 21V, irange100 */ 16168a40382SGuenter Roeck [18] = { 7658, 0, -3 }, /* power, 21V, irange200 */ 16268a40382SGuenter Roeck }; 16368a40382SGuenter Roeck 164*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) static inline int adm1275_read_pmon_config(struct i2c_client *client, u16 mask) 165*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) { 166*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) int ret; 167*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) 168*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG); 169*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) if (ret < 0) 170*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) return ret; 171*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) 172*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) return FIELD_GET(mask, (u16)ret); 173*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) } 174*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) 175*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) static inline int adm1275_write_pmon_config(struct i2c_client *client, u16 mask, 176*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) u16 word) 177*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) { 178*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) int ret; 179*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) 180*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) ret = i2c_smbus_read_word_data(client, ADM1275_PMON_CONFIG); 181*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) if (ret < 0) 182*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) return ret; 183*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) 184*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) word = FIELD_PREP(mask, word) | (ret & ~mask); 185*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG, word); 186*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) 187*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) return ret; 188*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) } 189*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) 190c576e30cSGuenter Roeck static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) 191c576e30cSGuenter Roeck { 192c5e67636SGuenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 193c5e67636SGuenter Roeck const struct adm1275_data *data = to_adm1275_data(info); 1945cf231a3SGuenter Roeck int ret = 0; 195c576e30cSGuenter Roeck 196ecb29abdSGuenter Roeck if (page > 0) 197c5e67636SGuenter Roeck return -ENXIO; 198c576e30cSGuenter Roeck 199c576e30cSGuenter Roeck switch (reg) { 200c5e67636SGuenter Roeck case PMBUS_IOUT_UC_FAULT_LIMIT: 2019048539bSGuenter Roeck if (!data->have_uc_fault) 2029048539bSGuenter Roeck return -ENXIO; 203c5e67636SGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT); 204c5e67636SGuenter Roeck break; 205c5e67636SGuenter Roeck case PMBUS_IOUT_OC_FAULT_LIMIT: 2069048539bSGuenter Roeck if (!data->have_oc_fault) 2079048539bSGuenter Roeck return -ENXIO; 208c5e67636SGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT); 209c5e67636SGuenter Roeck break; 21092711269SGuenter Roeck case PMBUS_VOUT_OV_WARN_LIMIT: 2119048539bSGuenter Roeck if (data->have_vout) 2129048539bSGuenter Roeck return -ENODATA; 21392711269SGuenter Roeck ret = pmbus_read_word_data(client, 0, 21492711269SGuenter Roeck ADM1075_VAUX_OV_WARN_LIMIT); 21592711269SGuenter Roeck break; 21692711269SGuenter Roeck case PMBUS_VOUT_UV_WARN_LIMIT: 2179048539bSGuenter Roeck if (data->have_vout) 2189048539bSGuenter Roeck return -ENODATA; 21992711269SGuenter Roeck ret = pmbus_read_word_data(client, 0, 22092711269SGuenter Roeck ADM1075_VAUX_UV_WARN_LIMIT); 22192711269SGuenter Roeck break; 22292711269SGuenter Roeck case PMBUS_READ_VOUT: 2239048539bSGuenter Roeck if (data->have_vout) 2249048539bSGuenter Roeck return -ENODATA; 22592711269SGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1075_READ_VAUX); 22692711269SGuenter Roeck break; 22768a40382SGuenter Roeck case PMBUS_VIRT_READ_IOUT_MIN: 22868a40382SGuenter Roeck if (!data->have_iout_min) 22968a40382SGuenter Roeck return -ENXIO; 23068a40382SGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1293_IOUT_MIN); 23168a40382SGuenter Roeck break; 232c576e30cSGuenter Roeck case PMBUS_VIRT_READ_IOUT_MAX: 233c576e30cSGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT); 234c576e30cSGuenter Roeck break; 235c576e30cSGuenter Roeck case PMBUS_VIRT_READ_VOUT_MAX: 236c576e30cSGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VOUT); 237c576e30cSGuenter Roeck break; 238c576e30cSGuenter Roeck case PMBUS_VIRT_READ_VIN_MAX: 239c576e30cSGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN); 240c576e30cSGuenter Roeck break; 24168a40382SGuenter Roeck case PMBUS_VIRT_READ_PIN_MIN: 24268a40382SGuenter Roeck if (!data->have_pin_min) 24368a40382SGuenter Roeck return -ENXIO; 24468a40382SGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1293_PIN_MIN); 24568a40382SGuenter Roeck break; 2465cf231a3SGuenter Roeck case PMBUS_VIRT_READ_PIN_MAX: 2479048539bSGuenter Roeck if (!data->have_pin_max) 2489048539bSGuenter Roeck return -ENXIO; 2495cf231a3SGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN); 2505cf231a3SGuenter Roeck break; 251709066acSGuenter Roeck case PMBUS_VIRT_READ_TEMP_MAX: 252709066acSGuenter Roeck if (!data->have_temp_max) 253709066acSGuenter Roeck return -ENXIO; 254709066acSGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1278_PEAK_TEMP); 255709066acSGuenter Roeck break; 256c576e30cSGuenter Roeck case PMBUS_VIRT_RESET_IOUT_HISTORY: 257c576e30cSGuenter Roeck case PMBUS_VIRT_RESET_VOUT_HISTORY: 258c576e30cSGuenter Roeck case PMBUS_VIRT_RESET_VIN_HISTORY: 2595cf231a3SGuenter Roeck break; 2605cf231a3SGuenter Roeck case PMBUS_VIRT_RESET_PIN_HISTORY: 2619048539bSGuenter Roeck if (!data->have_pin_max) 2629048539bSGuenter Roeck return -ENXIO; 263c576e30cSGuenter Roeck break; 264709066acSGuenter Roeck case PMBUS_VIRT_RESET_TEMP_HISTORY: 265709066acSGuenter Roeck if (!data->have_temp_max) 266709066acSGuenter Roeck return -ENXIO; 267709066acSGuenter Roeck break; 268*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) case PMBUS_VIRT_POWER_SAMPLES: 269*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) ret = adm1275_read_pmon_config(client, ADM1275_PWR_AVG_MASK); 270*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) if (ret < 0) 271*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) break; 272*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) ret = BIT(ret); 273*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) break; 274*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) case PMBUS_VIRT_IN_SAMPLES: 275*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) case PMBUS_VIRT_CURR_SAMPLES: 276*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) ret = adm1275_read_pmon_config(client, ADM1275_VI_AVG_MASK); 277*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) if (ret < 0) 278*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) break; 279*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) ret = BIT(ret); 280*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) break; 281c576e30cSGuenter Roeck default: 282c576e30cSGuenter Roeck ret = -ENODATA; 283c576e30cSGuenter Roeck break; 284c576e30cSGuenter Roeck } 285c576e30cSGuenter Roeck return ret; 286c576e30cSGuenter Roeck } 287c576e30cSGuenter Roeck 288c576e30cSGuenter Roeck static int adm1275_write_word_data(struct i2c_client *client, int page, int reg, 289c576e30cSGuenter Roeck u16 word) 290c576e30cSGuenter Roeck { 29168a40382SGuenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 29268a40382SGuenter Roeck const struct adm1275_data *data = to_adm1275_data(info); 293c576e30cSGuenter Roeck int ret; 294c576e30cSGuenter Roeck 295ecb29abdSGuenter Roeck if (page > 0) 296c5e67636SGuenter Roeck return -ENXIO; 297c576e30cSGuenter Roeck 298c576e30cSGuenter Roeck switch (reg) { 299c5e67636SGuenter Roeck case PMBUS_IOUT_UC_FAULT_LIMIT: 300c5e67636SGuenter Roeck case PMBUS_IOUT_OC_FAULT_LIMIT: 301c5e67636SGuenter Roeck ret = pmbus_write_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT, 302c5e67636SGuenter Roeck word); 303c5e67636SGuenter Roeck break; 304c576e30cSGuenter Roeck case PMBUS_VIRT_RESET_IOUT_HISTORY: 305c576e30cSGuenter Roeck ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0); 30668a40382SGuenter Roeck if (!ret && data->have_iout_min) 30768a40382SGuenter Roeck ret = pmbus_write_word_data(client, 0, 30868a40382SGuenter Roeck ADM1293_IOUT_MIN, 0); 309c576e30cSGuenter Roeck break; 310c576e30cSGuenter Roeck case PMBUS_VIRT_RESET_VOUT_HISTORY: 311c576e30cSGuenter Roeck ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VOUT, 0); 312c576e30cSGuenter Roeck break; 313c576e30cSGuenter Roeck case PMBUS_VIRT_RESET_VIN_HISTORY: 314c576e30cSGuenter Roeck ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VIN, 0); 315c576e30cSGuenter Roeck break; 3165cf231a3SGuenter Roeck case PMBUS_VIRT_RESET_PIN_HISTORY: 3175cf231a3SGuenter Roeck ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0); 31868a40382SGuenter Roeck if (!ret && data->have_pin_min) 31968a40382SGuenter Roeck ret = pmbus_write_word_data(client, 0, 32068a40382SGuenter Roeck ADM1293_PIN_MIN, 0); 3215cf231a3SGuenter Roeck break; 322709066acSGuenter Roeck case PMBUS_VIRT_RESET_TEMP_HISTORY: 323709066acSGuenter Roeck ret = pmbus_write_word_data(client, 0, ADM1278_PEAK_TEMP, 0); 324709066acSGuenter Roeck break; 325*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) case PMBUS_VIRT_POWER_SAMPLES: 326*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX); 327*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) ret = adm1275_write_pmon_config(client, ADM1275_PWR_AVG_MASK, 328*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) ilog2(word)); 329*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) break; 330*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) case PMBUS_VIRT_IN_SAMPLES: 331*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) case PMBUS_VIRT_CURR_SAMPLES: 332*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX); 333*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) ret = adm1275_write_pmon_config(client, ADM1275_VI_AVG_MASK, 334*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) ilog2(word)); 335*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) break; 336c576e30cSGuenter Roeck default: 337c576e30cSGuenter Roeck ret = -ENODATA; 338c576e30cSGuenter Roeck break; 339c576e30cSGuenter Roeck } 340c576e30cSGuenter Roeck return ret; 341c576e30cSGuenter Roeck } 342c576e30cSGuenter Roeck 343c5e67636SGuenter Roeck static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg) 344c5e67636SGuenter Roeck { 345c5e67636SGuenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 346c5e67636SGuenter Roeck const struct adm1275_data *data = to_adm1275_data(info); 347c5e67636SGuenter Roeck int mfr_status, ret; 348c5e67636SGuenter Roeck 349da8e48abSGuenter Roeck if (page > 0) 350c5e67636SGuenter Roeck return -ENXIO; 351c5e67636SGuenter Roeck 352c5e67636SGuenter Roeck switch (reg) { 353c5e67636SGuenter Roeck case PMBUS_STATUS_IOUT: 354c5e67636SGuenter Roeck ret = pmbus_read_byte_data(client, page, PMBUS_STATUS_IOUT); 355c5e67636SGuenter Roeck if (ret < 0) 356c5e67636SGuenter Roeck break; 3579048539bSGuenter Roeck if (!data->have_oc_fault && !data->have_uc_fault) 3589048539bSGuenter Roeck break; 359c5e67636SGuenter Roeck mfr_status = pmbus_read_byte_data(client, page, 360c5e67636SGuenter Roeck PMBUS_STATUS_MFR_SPECIFIC); 3619048539bSGuenter Roeck if (mfr_status < 0) 3629048539bSGuenter Roeck return mfr_status; 363c5e67636SGuenter Roeck if (mfr_status & ADM1275_MFR_STATUS_IOUT_WARN2) { 364c5e67636SGuenter Roeck ret |= data->have_oc_fault ? 365c5e67636SGuenter Roeck PB_IOUT_OC_FAULT : PB_IOUT_UC_FAULT; 366c5e67636SGuenter Roeck } 367c5e67636SGuenter Roeck break; 36892711269SGuenter Roeck case PMBUS_STATUS_VOUT: 3699048539bSGuenter Roeck if (data->have_vout) 3709048539bSGuenter Roeck return -ENODATA; 37192711269SGuenter Roeck ret = 0; 3729048539bSGuenter Roeck if (data->have_vaux_status) { 37392711269SGuenter Roeck mfr_status = pmbus_read_byte_data(client, 0, 37492711269SGuenter Roeck ADM1075_VAUX_STATUS); 3759048539bSGuenter Roeck if (mfr_status < 0) 3769048539bSGuenter Roeck return mfr_status; 37792711269SGuenter Roeck if (mfr_status & ADM1075_VAUX_OV_WARN) 37892711269SGuenter Roeck ret |= PB_VOLTAGE_OV_WARNING; 37992711269SGuenter Roeck if (mfr_status & ADM1075_VAUX_UV_WARN) 38092711269SGuenter Roeck ret |= PB_VOLTAGE_UV_WARNING; 38168a40382SGuenter Roeck } else if (data->have_mfr_vaux_status) { 38268a40382SGuenter Roeck mfr_status = pmbus_read_byte_data(client, page, 38368a40382SGuenter Roeck PMBUS_STATUS_MFR_SPECIFIC); 38468a40382SGuenter Roeck if (mfr_status < 0) 38568a40382SGuenter Roeck return mfr_status; 38668a40382SGuenter Roeck if (mfr_status & ADM1293_MFR_STATUS_VAUX_OV_WARN) 38768a40382SGuenter Roeck ret |= PB_VOLTAGE_OV_WARNING; 38868a40382SGuenter Roeck if (mfr_status & ADM1293_MFR_STATUS_VAUX_UV_WARN) 38968a40382SGuenter Roeck ret |= PB_VOLTAGE_UV_WARNING; 3909048539bSGuenter Roeck } 39192711269SGuenter Roeck break; 392c5e67636SGuenter Roeck default: 393c5e67636SGuenter Roeck ret = -ENODATA; 394c5e67636SGuenter Roeck break; 395c5e67636SGuenter Roeck } 396c5e67636SGuenter Roeck return ret; 397c5e67636SGuenter Roeck } 398c5e67636SGuenter Roeck 39987102808SGuenter Roeck static const struct i2c_device_id adm1275_id[] = { 40092711269SGuenter Roeck { "adm1075", adm1075 }, 4014ff0ce22SGuenter Roeck { "adm1272", adm1272 }, 40287102808SGuenter Roeck { "adm1275", adm1275 }, 40387102808SGuenter Roeck { "adm1276", adm1276 }, 404709066acSGuenter Roeck { "adm1278", adm1278 }, 40568a40382SGuenter Roeck { "adm1293", adm1293 }, 40668a40382SGuenter Roeck { "adm1294", adm1294 }, 40787102808SGuenter Roeck { } 40887102808SGuenter Roeck }; 40987102808SGuenter Roeck MODULE_DEVICE_TABLE(i2c, adm1275_id); 41087102808SGuenter Roeck 4119d2ecfb7SGuenter Roeck static int adm1275_probe(struct i2c_client *client, 4129d2ecfb7SGuenter Roeck const struct i2c_device_id *id) 4139d2ecfb7SGuenter Roeck { 41487102808SGuenter Roeck u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1]; 415c5e67636SGuenter Roeck int config, device_config; 4169d2ecfb7SGuenter Roeck int ret; 4179d2ecfb7SGuenter Roeck struct pmbus_driver_info *info; 418c5e67636SGuenter Roeck struct adm1275_data *data; 41987102808SGuenter Roeck const struct i2c_device_id *mid; 420904b296fSGuenter Roeck const struct coefficients *coefficients; 42168a40382SGuenter Roeck int vindex = -1, voindex = -1, cindex = -1, pindex = -1; 422709066acSGuenter Roeck int tindex = -1; 4236e5c06adSKun Yi u32 shunt; 4249d2ecfb7SGuenter Roeck 4259d2ecfb7SGuenter Roeck if (!i2c_check_functionality(client->adapter, 42687102808SGuenter Roeck I2C_FUNC_SMBUS_READ_BYTE_DATA 42787102808SGuenter Roeck | I2C_FUNC_SMBUS_BLOCK_DATA)) 4289d2ecfb7SGuenter Roeck return -ENODEV; 4299d2ecfb7SGuenter Roeck 43087102808SGuenter Roeck ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, block_buffer); 43187102808SGuenter Roeck if (ret < 0) { 43287102808SGuenter Roeck dev_err(&client->dev, "Failed to read Manufacturer ID\n"); 43387102808SGuenter Roeck return ret; 43487102808SGuenter Roeck } 43587102808SGuenter Roeck if (ret != 3 || strncmp(block_buffer, "ADI", 3)) { 43687102808SGuenter Roeck dev_err(&client->dev, "Unsupported Manufacturer ID\n"); 43787102808SGuenter Roeck return -ENODEV; 43887102808SGuenter Roeck } 43987102808SGuenter Roeck 44087102808SGuenter Roeck ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, block_buffer); 44187102808SGuenter Roeck if (ret < 0) { 44287102808SGuenter Roeck dev_err(&client->dev, "Failed to read Manufacturer Model\n"); 44387102808SGuenter Roeck return ret; 44487102808SGuenter Roeck } 44587102808SGuenter Roeck for (mid = adm1275_id; mid->name[0]; mid++) { 44687102808SGuenter Roeck if (!strncasecmp(mid->name, block_buffer, strlen(mid->name))) 44787102808SGuenter Roeck break; 44887102808SGuenter Roeck } 44987102808SGuenter Roeck if (!mid->name[0]) { 45087102808SGuenter Roeck dev_err(&client->dev, "Unsupported device\n"); 45187102808SGuenter Roeck return -ENODEV; 45287102808SGuenter Roeck } 45387102808SGuenter Roeck 45487102808SGuenter Roeck if (id->driver_data != mid->driver_data) 45587102808SGuenter Roeck dev_notice(&client->dev, 45687102808SGuenter Roeck "Device mismatch: Configured %s, detected %s\n", 45787102808SGuenter Roeck id->name, mid->name); 45887102808SGuenter Roeck 45987102808SGuenter Roeck config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG); 46087102808SGuenter Roeck if (config < 0) 46187102808SGuenter Roeck return config; 46287102808SGuenter Roeck 46387102808SGuenter Roeck device_config = i2c_smbus_read_byte_data(client, ADM1275_DEVICE_CONFIG); 46487102808SGuenter Roeck if (device_config < 0) 46587102808SGuenter Roeck return device_config; 46687102808SGuenter Roeck 4678b313ca7SGuenter Roeck data = devm_kzalloc(&client->dev, sizeof(struct adm1275_data), 4688b313ca7SGuenter Roeck GFP_KERNEL); 469c5e67636SGuenter Roeck if (!data) 4709d2ecfb7SGuenter Roeck return -ENOMEM; 4719d2ecfb7SGuenter Roeck 4726e5c06adSKun Yi if (of_property_read_u32(client->dev.of_node, 4736e5c06adSKun Yi "shunt-resistor-micro-ohms", &shunt)) 4746e5c06adSKun Yi shunt = 1000; /* 1 mOhm if not set via DT */ 4756e5c06adSKun Yi 4766e5c06adSKun Yi if (shunt == 0) 4776e5c06adSKun Yi return -EINVAL; 4786e5c06adSKun Yi 47987102808SGuenter Roeck data->id = mid->driver_data; 4809d2ecfb7SGuenter Roeck 481c5e67636SGuenter Roeck info = &data->info; 482c5e67636SGuenter Roeck 4839d2ecfb7SGuenter Roeck info->pages = 1; 4841061d851SGuenter Roeck info->format[PSC_VOLTAGE_IN] = direct; 4851061d851SGuenter Roeck info->format[PSC_VOLTAGE_OUT] = direct; 4861061d851SGuenter Roeck info->format[PSC_CURRENT_OUT] = direct; 487904b296fSGuenter Roeck info->format[PSC_POWER] = direct; 488709066acSGuenter Roeck info->format[PSC_TEMPERATURE] = direct; 489*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | 490*c83529c1SAdamski, Krzysztof (Nokia - PL/Wroclaw) PMBUS_HAVE_SAMPLES; 4919d2ecfb7SGuenter Roeck 492c576e30cSGuenter Roeck info->read_word_data = adm1275_read_word_data; 493c5e67636SGuenter Roeck info->read_byte_data = adm1275_read_byte_data; 494c576e30cSGuenter Roeck info->write_word_data = adm1275_write_word_data; 495c576e30cSGuenter Roeck 49687102808SGuenter Roeck switch (data->id) { 49792711269SGuenter Roeck case adm1075: 4989048539bSGuenter Roeck if (device_config & ADM1275_IOUT_WARN2_SELECT) 4999048539bSGuenter Roeck data->have_oc_fault = true; 5009048539bSGuenter Roeck else 5019048539bSGuenter Roeck data->have_uc_fault = true; 5029048539bSGuenter Roeck data->have_pin_max = true; 5039048539bSGuenter Roeck data->have_vaux_status = true; 5049048539bSGuenter Roeck 505904b296fSGuenter Roeck coefficients = adm1075_coefficients; 506904b296fSGuenter Roeck vindex = 0; 50792711269SGuenter Roeck switch (config & ADM1075_IRANGE_MASK) { 50892711269SGuenter Roeck case ADM1075_IRANGE_25: 509904b296fSGuenter Roeck cindex = 1; 510904b296fSGuenter Roeck pindex = 3; 51192711269SGuenter Roeck break; 51292711269SGuenter Roeck case ADM1075_IRANGE_50: 513904b296fSGuenter Roeck cindex = 2; 514904b296fSGuenter Roeck pindex = 4; 51592711269SGuenter Roeck break; 51692711269SGuenter Roeck default: 51792711269SGuenter Roeck dev_err(&client->dev, "Invalid input current range"); 51892711269SGuenter Roeck break; 51992711269SGuenter Roeck } 520904b296fSGuenter Roeck 52192711269SGuenter Roeck info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN 52292711269SGuenter Roeck | PMBUS_HAVE_STATUS_INPUT; 52392711269SGuenter Roeck if (config & ADM1275_VIN_VOUT_SELECT) 52492711269SGuenter Roeck info->func[0] |= 52592711269SGuenter Roeck PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 52692711269SGuenter Roeck break; 5274ff0ce22SGuenter Roeck case adm1272: 5284ff0ce22SGuenter Roeck data->have_vout = true; 5294ff0ce22SGuenter Roeck data->have_pin_max = true; 5304ff0ce22SGuenter Roeck data->have_temp_max = true; 5314ff0ce22SGuenter Roeck 5324ff0ce22SGuenter Roeck coefficients = adm1272_coefficients; 5334ff0ce22SGuenter Roeck vindex = (config & ADM1275_VRANGE) ? 1 : 0; 5344ff0ce22SGuenter Roeck cindex = (config & ADM1272_IRANGE) ? 3 : 2; 5354ff0ce22SGuenter Roeck /* pindex depends on the combination of the above */ 5364ff0ce22SGuenter Roeck switch (config & (ADM1275_VRANGE | ADM1272_IRANGE)) { 5374ff0ce22SGuenter Roeck case 0: 5384ff0ce22SGuenter Roeck default: 5394ff0ce22SGuenter Roeck pindex = 4; 5404ff0ce22SGuenter Roeck break; 5414ff0ce22SGuenter Roeck case ADM1275_VRANGE: 5424ff0ce22SGuenter Roeck pindex = 5; 5434ff0ce22SGuenter Roeck break; 5444ff0ce22SGuenter Roeck case ADM1272_IRANGE: 5454ff0ce22SGuenter Roeck pindex = 6; 5464ff0ce22SGuenter Roeck break; 5474ff0ce22SGuenter Roeck case ADM1275_VRANGE | ADM1272_IRANGE: 5484ff0ce22SGuenter Roeck pindex = 7; 5494ff0ce22SGuenter Roeck break; 5504ff0ce22SGuenter Roeck } 5514ff0ce22SGuenter Roeck tindex = 8; 5524ff0ce22SGuenter Roeck 5534ff0ce22SGuenter Roeck info->func[0] |= PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | 5544ff0ce22SGuenter Roeck PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 5554ff0ce22SGuenter Roeck 5564ff0ce22SGuenter Roeck /* Enable VOUT if not enabled (it is disabled by default) */ 5574ff0ce22SGuenter Roeck if (!(config & ADM1278_VOUT_EN)) { 5584ff0ce22SGuenter Roeck config |= ADM1278_VOUT_EN; 5594ff0ce22SGuenter Roeck ret = i2c_smbus_write_byte_data(client, 5604ff0ce22SGuenter Roeck ADM1275_PMON_CONFIG, 5614ff0ce22SGuenter Roeck config); 5624ff0ce22SGuenter Roeck if (ret < 0) { 5634ff0ce22SGuenter Roeck dev_err(&client->dev, 5644ff0ce22SGuenter Roeck "Failed to enable VOUT monitoring\n"); 5654ff0ce22SGuenter Roeck return -ENODEV; 5664ff0ce22SGuenter Roeck } 5674ff0ce22SGuenter Roeck } 5684ff0ce22SGuenter Roeck 5694ff0ce22SGuenter Roeck if (config & ADM1278_TEMP1_EN) 5704ff0ce22SGuenter Roeck info->func[0] |= 5714ff0ce22SGuenter Roeck PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; 5724ff0ce22SGuenter Roeck if (config & ADM1278_VIN_EN) 5734ff0ce22SGuenter Roeck info->func[0] |= PMBUS_HAVE_VIN; 5744ff0ce22SGuenter Roeck break; 5755cf231a3SGuenter Roeck case adm1275: 5769048539bSGuenter Roeck if (device_config & ADM1275_IOUT_WARN2_SELECT) 5779048539bSGuenter Roeck data->have_oc_fault = true; 5789048539bSGuenter Roeck else 5799048539bSGuenter Roeck data->have_uc_fault = true; 5809048539bSGuenter Roeck data->have_vout = true; 5819048539bSGuenter Roeck 582904b296fSGuenter Roeck coefficients = adm1275_coefficients; 583904b296fSGuenter Roeck vindex = (config & ADM1275_VRANGE) ? 0 : 1; 584904b296fSGuenter Roeck cindex = 2; 585904b296fSGuenter Roeck 5869d2ecfb7SGuenter Roeck if (config & ADM1275_VIN_VOUT_SELECT) 5875cf231a3SGuenter Roeck info->func[0] |= 5885cf231a3SGuenter Roeck PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 5899d2ecfb7SGuenter Roeck else 5905cf231a3SGuenter Roeck info->func[0] |= 5915cf231a3SGuenter Roeck PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT; 5925cf231a3SGuenter Roeck break; 5935cf231a3SGuenter Roeck case adm1276: 5949048539bSGuenter Roeck if (device_config & ADM1275_IOUT_WARN2_SELECT) 5959048539bSGuenter Roeck data->have_oc_fault = true; 5969048539bSGuenter Roeck else 5979048539bSGuenter Roeck data->have_uc_fault = true; 5989048539bSGuenter Roeck data->have_vout = true; 5999048539bSGuenter Roeck data->have_pin_max = true; 6009048539bSGuenter Roeck 601904b296fSGuenter Roeck coefficients = adm1276_coefficients; 602904b296fSGuenter Roeck vindex = (config & ADM1275_VRANGE) ? 0 : 1; 603904b296fSGuenter Roeck cindex = 2; 604904b296fSGuenter Roeck pindex = (config & ADM1275_VRANGE) ? 3 : 4; 605904b296fSGuenter Roeck 6065cf231a3SGuenter Roeck info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN 6075cf231a3SGuenter Roeck | PMBUS_HAVE_STATUS_INPUT; 6085cf231a3SGuenter Roeck if (config & ADM1275_VIN_VOUT_SELECT) 6095cf231a3SGuenter Roeck info->func[0] |= 6105cf231a3SGuenter Roeck PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 6115cf231a3SGuenter Roeck break; 612709066acSGuenter Roeck case adm1278: 613709066acSGuenter Roeck data->have_vout = true; 614709066acSGuenter Roeck data->have_pin_max = true; 615709066acSGuenter Roeck data->have_temp_max = true; 616709066acSGuenter Roeck 617709066acSGuenter Roeck coefficients = adm1278_coefficients; 618709066acSGuenter Roeck vindex = 0; 619709066acSGuenter Roeck cindex = 1; 620709066acSGuenter Roeck pindex = 2; 621709066acSGuenter Roeck tindex = 3; 622709066acSGuenter Roeck 6232b3d0c19SYi Li info->func[0] |= PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | 6242b3d0c19SYi Li PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 6252b3d0c19SYi Li 6262b3d0c19SYi Li /* Enable VOUT if not enabled (it is disabled by default) */ 6272b3d0c19SYi Li if (!(config & ADM1278_VOUT_EN)) { 6282b3d0c19SYi Li config |= ADM1278_VOUT_EN; 6292b3d0c19SYi Li ret = i2c_smbus_write_byte_data(client, 6302b3d0c19SYi Li ADM1275_PMON_CONFIG, 6312b3d0c19SYi Li config); 6322b3d0c19SYi Li if (ret < 0) { 6332b3d0c19SYi Li dev_err(&client->dev, 6342b3d0c19SYi Li "Failed to enable VOUT monitoring\n"); 6352b3d0c19SYi Li return -ENODEV; 6362b3d0c19SYi Li } 6372b3d0c19SYi Li } 6382b3d0c19SYi Li 639709066acSGuenter Roeck if (config & ADM1278_TEMP1_EN) 640709066acSGuenter Roeck info->func[0] |= 641709066acSGuenter Roeck PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; 642709066acSGuenter Roeck if (config & ADM1278_VIN_EN) 643709066acSGuenter Roeck info->func[0] |= PMBUS_HAVE_VIN; 644709066acSGuenter Roeck break; 64568a40382SGuenter Roeck case adm1293: 64668a40382SGuenter Roeck case adm1294: 64768a40382SGuenter Roeck data->have_iout_min = true; 64868a40382SGuenter Roeck data->have_pin_min = true; 64968a40382SGuenter Roeck data->have_pin_max = true; 65068a40382SGuenter Roeck data->have_mfr_vaux_status = true; 65168a40382SGuenter Roeck 65268a40382SGuenter Roeck coefficients = adm1293_coefficients; 65368a40382SGuenter Roeck 65468a40382SGuenter Roeck voindex = 0; 65568a40382SGuenter Roeck switch (config & ADM1293_VIN_SEL_MASK) { 65668a40382SGuenter Roeck case ADM1293_VIN_SEL_012: /* 1.2V */ 65768a40382SGuenter Roeck vindex = 0; 65868a40382SGuenter Roeck break; 65968a40382SGuenter Roeck case ADM1293_VIN_SEL_074: /* 7.4V */ 66068a40382SGuenter Roeck vindex = 1; 66168a40382SGuenter Roeck break; 66268a40382SGuenter Roeck case ADM1293_VIN_SEL_210: /* 21V */ 66368a40382SGuenter Roeck vindex = 2; 66468a40382SGuenter Roeck break; 66568a40382SGuenter Roeck default: /* disabled */ 66668a40382SGuenter Roeck break; 66768a40382SGuenter Roeck } 66868a40382SGuenter Roeck 66968a40382SGuenter Roeck switch (config & ADM1293_IRANGE_MASK) { 67068a40382SGuenter Roeck case ADM1293_IRANGE_25: 67168a40382SGuenter Roeck cindex = 3; 67268a40382SGuenter Roeck break; 67368a40382SGuenter Roeck case ADM1293_IRANGE_50: 67468a40382SGuenter Roeck cindex = 4; 67568a40382SGuenter Roeck break; 67668a40382SGuenter Roeck case ADM1293_IRANGE_100: 67768a40382SGuenter Roeck cindex = 5; 67868a40382SGuenter Roeck break; 67968a40382SGuenter Roeck case ADM1293_IRANGE_200: 68068a40382SGuenter Roeck cindex = 6; 68168a40382SGuenter Roeck break; 68268a40382SGuenter Roeck } 68368a40382SGuenter Roeck 68468a40382SGuenter Roeck if (vindex >= 0) 68568a40382SGuenter Roeck pindex = 7 + vindex * 4 + (cindex - 3); 68668a40382SGuenter Roeck 68768a40382SGuenter Roeck if (config & ADM1293_VAUX_EN) 68868a40382SGuenter Roeck info->func[0] |= 68968a40382SGuenter Roeck PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 69068a40382SGuenter Roeck 69168a40382SGuenter Roeck info->func[0] |= PMBUS_HAVE_PIN | 69268a40382SGuenter Roeck PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT; 69368a40382SGuenter Roeck 69468a40382SGuenter Roeck break; 695904b296fSGuenter Roeck default: 696904b296fSGuenter Roeck dev_err(&client->dev, "Unsupported device\n"); 697904b296fSGuenter Roeck return -ENODEV; 698904b296fSGuenter Roeck } 69968a40382SGuenter Roeck 70068a40382SGuenter Roeck if (voindex < 0) 70168a40382SGuenter Roeck voindex = vindex; 702904b296fSGuenter Roeck if (vindex >= 0) { 703904b296fSGuenter Roeck info->m[PSC_VOLTAGE_IN] = coefficients[vindex].m; 704904b296fSGuenter Roeck info->b[PSC_VOLTAGE_IN] = coefficients[vindex].b; 705904b296fSGuenter Roeck info->R[PSC_VOLTAGE_IN] = coefficients[vindex].R; 70668a40382SGuenter Roeck } 70768a40382SGuenter Roeck if (voindex >= 0) { 70868a40382SGuenter Roeck info->m[PSC_VOLTAGE_OUT] = coefficients[voindex].m; 70968a40382SGuenter Roeck info->b[PSC_VOLTAGE_OUT] = coefficients[voindex].b; 71068a40382SGuenter Roeck info->R[PSC_VOLTAGE_OUT] = coefficients[voindex].R; 711904b296fSGuenter Roeck } 712904b296fSGuenter Roeck if (cindex >= 0) { 7136e5c06adSKun Yi /* Scale current with sense resistor value */ 7146e5c06adSKun Yi info->m[PSC_CURRENT_OUT] = 7156e5c06adSKun Yi coefficients[cindex].m * shunt / 1000; 716904b296fSGuenter Roeck info->b[PSC_CURRENT_OUT] = coefficients[cindex].b; 717904b296fSGuenter Roeck info->R[PSC_CURRENT_OUT] = coefficients[cindex].R; 718904b296fSGuenter Roeck } 719904b296fSGuenter Roeck if (pindex >= 0) { 7206e5c06adSKun Yi info->m[PSC_POWER] = 7216e5c06adSKun Yi coefficients[pindex].m * shunt / 1000; 722904b296fSGuenter Roeck info->b[PSC_POWER] = coefficients[pindex].b; 723904b296fSGuenter Roeck info->R[PSC_POWER] = coefficients[pindex].R; 7245cf231a3SGuenter Roeck } 725709066acSGuenter Roeck if (tindex >= 0) { 726709066acSGuenter Roeck info->m[PSC_TEMPERATURE] = coefficients[tindex].m; 727709066acSGuenter Roeck info->b[PSC_TEMPERATURE] = coefficients[tindex].b; 728709066acSGuenter Roeck info->R[PSC_TEMPERATURE] = coefficients[tindex].R; 729709066acSGuenter Roeck } 7309d2ecfb7SGuenter Roeck 7318b313ca7SGuenter Roeck return pmbus_do_probe(client, id, info); 7329d2ecfb7SGuenter Roeck } 7339d2ecfb7SGuenter Roeck 7349d2ecfb7SGuenter Roeck static struct i2c_driver adm1275_driver = { 7359d2ecfb7SGuenter Roeck .driver = { 7369d2ecfb7SGuenter Roeck .name = "adm1275", 7379d2ecfb7SGuenter Roeck }, 7389d2ecfb7SGuenter Roeck .probe = adm1275_probe, 739dd285ad7SGuenter Roeck .remove = pmbus_do_remove, 7409d2ecfb7SGuenter Roeck .id_table = adm1275_id, 7419d2ecfb7SGuenter Roeck }; 7429d2ecfb7SGuenter Roeck 743f0967eeaSAxel Lin module_i2c_driver(adm1275_driver); 7449d2ecfb7SGuenter Roeck 7459d2ecfb7SGuenter Roeck MODULE_AUTHOR("Guenter Roeck"); 7465cf231a3SGuenter Roeck MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275 and compatibles"); 7479d2ecfb7SGuenter Roeck MODULE_LICENSE("GPL"); 748