19d2ecfb7SGuenter Roeck /* 29d2ecfb7SGuenter Roeck * Hardware monitoring driver for Maxim MAX34440/MAX34441 39d2ecfb7SGuenter Roeck * 49d2ecfb7SGuenter Roeck * Copyright (c) 2011 Ericsson AB. 550115ac9SGuenter Roeck * Copyright (c) 2012 Guenter Roeck 69d2ecfb7SGuenter Roeck * 79d2ecfb7SGuenter Roeck * This program is free software; you can redistribute it and/or modify 89d2ecfb7SGuenter Roeck * it under the terms of the GNU General Public License as published by 99d2ecfb7SGuenter Roeck * the Free Software Foundation; either version 2 of the License, or 109d2ecfb7SGuenter Roeck * (at your option) any later version. 119d2ecfb7SGuenter Roeck * 129d2ecfb7SGuenter Roeck * This program is distributed in the hope that it will be useful, 139d2ecfb7SGuenter Roeck * but WITHOUT ANY WARRANTY; without even the implied warranty of 149d2ecfb7SGuenter Roeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 159d2ecfb7SGuenter Roeck * GNU General Public License for more details. 169d2ecfb7SGuenter Roeck * 179d2ecfb7SGuenter Roeck * You should have received a copy of the GNU General Public License 189d2ecfb7SGuenter Roeck * along with this program; if not, write to the Free Software 199d2ecfb7SGuenter Roeck * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 209d2ecfb7SGuenter Roeck */ 219d2ecfb7SGuenter Roeck 222c052d42SGuenter Roeck #include <linux/bitops.h> 239d2ecfb7SGuenter Roeck #include <linux/kernel.h> 249d2ecfb7SGuenter Roeck #include <linux/module.h> 259d2ecfb7SGuenter Roeck #include <linux/init.h> 269d2ecfb7SGuenter Roeck #include <linux/err.h> 279d2ecfb7SGuenter Roeck #include <linux/i2c.h> 289d2ecfb7SGuenter Roeck #include "pmbus.h" 299d2ecfb7SGuenter Roeck 30*7a001dbaSKun Yi enum chips { max34440, max34441, max34446, max34451, max34460, max34461 }; 319d2ecfb7SGuenter Roeck 3298591dbeSGuenter Roeck #define MAX34440_MFR_VOUT_PEAK 0xd4 3398591dbeSGuenter Roeck #define MAX34440_MFR_IOUT_PEAK 0xd5 3498591dbeSGuenter Roeck #define MAX34440_MFR_TEMPERATURE_PEAK 0xd6 3556aad5d1SGuenter Roeck #define MAX34440_MFR_VOUT_MIN 0xd7 3698591dbeSGuenter Roeck 37590defe5SGuenter Roeck #define MAX34446_MFR_POUT_PEAK 0xe0 38590defe5SGuenter Roeck #define MAX34446_MFR_POUT_AVG 0xe1 39590defe5SGuenter Roeck #define MAX34446_MFR_IOUT_AVG 0xe2 40590defe5SGuenter Roeck #define MAX34446_MFR_TEMPERATURE_AVG 0xe3 41590defe5SGuenter Roeck 422c052d42SGuenter Roeck #define MAX34440_STATUS_OC_WARN BIT(0) 432c052d42SGuenter Roeck #define MAX34440_STATUS_OC_FAULT BIT(1) 442c052d42SGuenter Roeck #define MAX34440_STATUS_OT_FAULT BIT(5) 452c052d42SGuenter Roeck #define MAX34440_STATUS_OT_WARN BIT(6) 469d2ecfb7SGuenter Roeck 47*7a001dbaSKun Yi #define MAX34451_MFR_CHANNEL_CONFIG 0xe4 48*7a001dbaSKun Yi #define MAX34451_MFR_CHANNEL_CONFIG_SEL_MASK 0x3f 49*7a001dbaSKun Yi 50590defe5SGuenter Roeck struct max34440_data { 51590defe5SGuenter Roeck int id; 52590defe5SGuenter Roeck struct pmbus_driver_info info; 53590defe5SGuenter Roeck }; 54590defe5SGuenter Roeck 55590defe5SGuenter Roeck #define to_max34440_data(x) container_of(x, struct max34440_data, info) 56590defe5SGuenter Roeck 5798591dbeSGuenter Roeck static int max34440_read_word_data(struct i2c_client *client, int page, int reg) 5898591dbeSGuenter Roeck { 5998591dbeSGuenter Roeck int ret; 60590defe5SGuenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 61590defe5SGuenter Roeck const struct max34440_data *data = to_max34440_data(info); 6298591dbeSGuenter Roeck 6398591dbeSGuenter Roeck switch (reg) { 6456aad5d1SGuenter Roeck case PMBUS_VIRT_READ_VOUT_MIN: 6556aad5d1SGuenter Roeck ret = pmbus_read_word_data(client, page, 6656aad5d1SGuenter Roeck MAX34440_MFR_VOUT_MIN); 6756aad5d1SGuenter Roeck break; 6898591dbeSGuenter Roeck case PMBUS_VIRT_READ_VOUT_MAX: 6998591dbeSGuenter Roeck ret = pmbus_read_word_data(client, page, 7098591dbeSGuenter Roeck MAX34440_MFR_VOUT_PEAK); 7198591dbeSGuenter Roeck break; 72590defe5SGuenter Roeck case PMBUS_VIRT_READ_IOUT_AVG: 73*7a001dbaSKun Yi if (data->id != max34446 && data->id != max34451) 74590defe5SGuenter Roeck return -ENXIO; 75590defe5SGuenter Roeck ret = pmbus_read_word_data(client, page, 76590defe5SGuenter Roeck MAX34446_MFR_IOUT_AVG); 77590defe5SGuenter Roeck break; 7898591dbeSGuenter Roeck case PMBUS_VIRT_READ_IOUT_MAX: 7998591dbeSGuenter Roeck ret = pmbus_read_word_data(client, page, 8098591dbeSGuenter Roeck MAX34440_MFR_IOUT_PEAK); 8198591dbeSGuenter Roeck break; 82590defe5SGuenter Roeck case PMBUS_VIRT_READ_POUT_AVG: 83590defe5SGuenter Roeck if (data->id != max34446) 84590defe5SGuenter Roeck return -ENXIO; 85590defe5SGuenter Roeck ret = pmbus_read_word_data(client, page, 86590defe5SGuenter Roeck MAX34446_MFR_POUT_AVG); 87590defe5SGuenter Roeck break; 88590defe5SGuenter Roeck case PMBUS_VIRT_READ_POUT_MAX: 89590defe5SGuenter Roeck if (data->id != max34446) 90590defe5SGuenter Roeck return -ENXIO; 91590defe5SGuenter Roeck ret = pmbus_read_word_data(client, page, 92590defe5SGuenter Roeck MAX34446_MFR_POUT_PEAK); 93590defe5SGuenter Roeck break; 94590defe5SGuenter Roeck case PMBUS_VIRT_READ_TEMP_AVG: 9550115ac9SGuenter Roeck if (data->id != max34446 && data->id != max34460 && 9650115ac9SGuenter Roeck data->id != max34461) 97590defe5SGuenter Roeck return -ENXIO; 98590defe5SGuenter Roeck ret = pmbus_read_word_data(client, page, 99590defe5SGuenter Roeck MAX34446_MFR_TEMPERATURE_AVG); 100590defe5SGuenter Roeck break; 10198591dbeSGuenter Roeck case PMBUS_VIRT_READ_TEMP_MAX: 10298591dbeSGuenter Roeck ret = pmbus_read_word_data(client, page, 10398591dbeSGuenter Roeck MAX34440_MFR_TEMPERATURE_PEAK); 10498591dbeSGuenter Roeck break; 105590defe5SGuenter Roeck case PMBUS_VIRT_RESET_POUT_HISTORY: 106590defe5SGuenter Roeck if (data->id != max34446) 107590defe5SGuenter Roeck return -ENXIO; 108590defe5SGuenter Roeck ret = 0; 109590defe5SGuenter Roeck break; 11098591dbeSGuenter Roeck case PMBUS_VIRT_RESET_VOUT_HISTORY: 11198591dbeSGuenter Roeck case PMBUS_VIRT_RESET_IOUT_HISTORY: 11298591dbeSGuenter Roeck case PMBUS_VIRT_RESET_TEMP_HISTORY: 11398591dbeSGuenter Roeck ret = 0; 11498591dbeSGuenter Roeck break; 11598591dbeSGuenter Roeck default: 11698591dbeSGuenter Roeck ret = -ENODATA; 11798591dbeSGuenter Roeck break; 11898591dbeSGuenter Roeck } 11998591dbeSGuenter Roeck return ret; 12098591dbeSGuenter Roeck } 12198591dbeSGuenter Roeck 12298591dbeSGuenter Roeck static int max34440_write_word_data(struct i2c_client *client, int page, 12398591dbeSGuenter Roeck int reg, u16 word) 12498591dbeSGuenter Roeck { 125590defe5SGuenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 126590defe5SGuenter Roeck const struct max34440_data *data = to_max34440_data(info); 12798591dbeSGuenter Roeck int ret; 12898591dbeSGuenter Roeck 12998591dbeSGuenter Roeck switch (reg) { 130590defe5SGuenter Roeck case PMBUS_VIRT_RESET_POUT_HISTORY: 131590defe5SGuenter Roeck ret = pmbus_write_word_data(client, page, 132590defe5SGuenter Roeck MAX34446_MFR_POUT_PEAK, 0); 133590defe5SGuenter Roeck if (ret) 134590defe5SGuenter Roeck break; 135590defe5SGuenter Roeck ret = pmbus_write_word_data(client, page, 136590defe5SGuenter Roeck MAX34446_MFR_POUT_AVG, 0); 137590defe5SGuenter Roeck break; 13898591dbeSGuenter Roeck case PMBUS_VIRT_RESET_VOUT_HISTORY: 13998591dbeSGuenter Roeck ret = pmbus_write_word_data(client, page, 14056aad5d1SGuenter Roeck MAX34440_MFR_VOUT_MIN, 0x7fff); 14156aad5d1SGuenter Roeck if (ret) 14256aad5d1SGuenter Roeck break; 14356aad5d1SGuenter Roeck ret = pmbus_write_word_data(client, page, 14498591dbeSGuenter Roeck MAX34440_MFR_VOUT_PEAK, 0); 14598591dbeSGuenter Roeck break; 14698591dbeSGuenter Roeck case PMBUS_VIRT_RESET_IOUT_HISTORY: 14798591dbeSGuenter Roeck ret = pmbus_write_word_data(client, page, 14898591dbeSGuenter Roeck MAX34440_MFR_IOUT_PEAK, 0); 149*7a001dbaSKun Yi if (!ret && (data->id == max34446 || data->id == max34451)) 150590defe5SGuenter Roeck ret = pmbus_write_word_data(client, page, 151590defe5SGuenter Roeck MAX34446_MFR_IOUT_AVG, 0); 152590defe5SGuenter Roeck 15398591dbeSGuenter Roeck break; 15498591dbeSGuenter Roeck case PMBUS_VIRT_RESET_TEMP_HISTORY: 15598591dbeSGuenter Roeck ret = pmbus_write_word_data(client, page, 15698591dbeSGuenter Roeck MAX34440_MFR_TEMPERATURE_PEAK, 157dc91ad8eSGuenter Roeck 0x8000); 158590defe5SGuenter Roeck if (!ret && data->id == max34446) 159590defe5SGuenter Roeck ret = pmbus_write_word_data(client, page, 160590defe5SGuenter Roeck MAX34446_MFR_TEMPERATURE_AVG, 0); 16198591dbeSGuenter Roeck break; 16298591dbeSGuenter Roeck default: 16398591dbeSGuenter Roeck ret = -ENODATA; 16498591dbeSGuenter Roeck break; 16598591dbeSGuenter Roeck } 16698591dbeSGuenter Roeck return ret; 16798591dbeSGuenter Roeck } 16898591dbeSGuenter Roeck 1699d2ecfb7SGuenter Roeck static int max34440_read_byte_data(struct i2c_client *client, int page, int reg) 1709d2ecfb7SGuenter Roeck { 171da8e48abSGuenter Roeck int ret = 0; 1729d2ecfb7SGuenter Roeck int mfg_status; 1739d2ecfb7SGuenter Roeck 174da8e48abSGuenter Roeck if (page >= 0) { 1759d2ecfb7SGuenter Roeck ret = pmbus_set_page(client, page); 1769d2ecfb7SGuenter Roeck if (ret < 0) 1779d2ecfb7SGuenter Roeck return ret; 178da8e48abSGuenter Roeck } 1799d2ecfb7SGuenter Roeck 1809d2ecfb7SGuenter Roeck switch (reg) { 1819d2ecfb7SGuenter Roeck case PMBUS_STATUS_IOUT: 1829d2ecfb7SGuenter Roeck mfg_status = pmbus_read_word_data(client, 0, 1839d2ecfb7SGuenter Roeck PMBUS_STATUS_MFR_SPECIFIC); 1849d2ecfb7SGuenter Roeck if (mfg_status < 0) 1859d2ecfb7SGuenter Roeck return mfg_status; 1869d2ecfb7SGuenter Roeck if (mfg_status & MAX34440_STATUS_OC_WARN) 1879d2ecfb7SGuenter Roeck ret |= PB_IOUT_OC_WARNING; 1889d2ecfb7SGuenter Roeck if (mfg_status & MAX34440_STATUS_OC_FAULT) 1899d2ecfb7SGuenter Roeck ret |= PB_IOUT_OC_FAULT; 1909d2ecfb7SGuenter Roeck break; 1919d2ecfb7SGuenter Roeck case PMBUS_STATUS_TEMPERATURE: 1929d2ecfb7SGuenter Roeck mfg_status = pmbus_read_word_data(client, 0, 1939d2ecfb7SGuenter Roeck PMBUS_STATUS_MFR_SPECIFIC); 1949d2ecfb7SGuenter Roeck if (mfg_status < 0) 1959d2ecfb7SGuenter Roeck return mfg_status; 1969d2ecfb7SGuenter Roeck if (mfg_status & MAX34440_STATUS_OT_WARN) 1979d2ecfb7SGuenter Roeck ret |= PB_TEMP_OT_WARNING; 1989d2ecfb7SGuenter Roeck if (mfg_status & MAX34440_STATUS_OT_FAULT) 1999d2ecfb7SGuenter Roeck ret |= PB_TEMP_OT_FAULT; 2009d2ecfb7SGuenter Roeck break; 2019d2ecfb7SGuenter Roeck default: 2029d2ecfb7SGuenter Roeck ret = -ENODATA; 2039d2ecfb7SGuenter Roeck break; 2049d2ecfb7SGuenter Roeck } 2059d2ecfb7SGuenter Roeck return ret; 2069d2ecfb7SGuenter Roeck } 2079d2ecfb7SGuenter Roeck 208*7a001dbaSKun Yi static int max34451_set_supported_funcs(struct i2c_client *client, 209*7a001dbaSKun Yi struct max34440_data *data) 210*7a001dbaSKun Yi { 211*7a001dbaSKun Yi /* 212*7a001dbaSKun Yi * Each of the channel 0-15 can be configured to monitor the following 213*7a001dbaSKun Yi * functions based on MFR_CHANNEL_CONFIG[5:0] 214*7a001dbaSKun Yi * 0x10: Sequencing + voltage monitoring (only valid for PAGES 0–11) 215*7a001dbaSKun Yi * 0x20: Voltage monitoring (no sequencing) 216*7a001dbaSKun Yi * 0x21: Voltage read only 217*7a001dbaSKun Yi * 0x22: Current monitoring 218*7a001dbaSKun Yi * 0x23: Current read only 219*7a001dbaSKun Yi * 0x30: General-purpose input active low 220*7a001dbaSKun Yi * 0x34: General-purpose input active high 221*7a001dbaSKun Yi * 0x00: Disabled 222*7a001dbaSKun Yi */ 223*7a001dbaSKun Yi 224*7a001dbaSKun Yi int page, rv; 225*7a001dbaSKun Yi 226*7a001dbaSKun Yi for (page = 0; page < 16; page++) { 227*7a001dbaSKun Yi rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); 228*7a001dbaSKun Yi if (rv < 0) 229*7a001dbaSKun Yi return rv; 230*7a001dbaSKun Yi 231*7a001dbaSKun Yi rv = i2c_smbus_read_word_data(client, 232*7a001dbaSKun Yi MAX34451_MFR_CHANNEL_CONFIG); 233*7a001dbaSKun Yi if (rv < 0) 234*7a001dbaSKun Yi return rv; 235*7a001dbaSKun Yi 236*7a001dbaSKun Yi switch (rv & MAX34451_MFR_CHANNEL_CONFIG_SEL_MASK) { 237*7a001dbaSKun Yi case 0x10: 238*7a001dbaSKun Yi case 0x20: 239*7a001dbaSKun Yi data->info.func[page] = PMBUS_HAVE_VOUT | 240*7a001dbaSKun Yi PMBUS_HAVE_STATUS_VOUT; 241*7a001dbaSKun Yi break; 242*7a001dbaSKun Yi case 0x21: 243*7a001dbaSKun Yi data->info.func[page] = PMBUS_HAVE_VOUT; 244*7a001dbaSKun Yi break; 245*7a001dbaSKun Yi case 0x22: 246*7a001dbaSKun Yi data->info.func[page] = PMBUS_HAVE_IOUT | 247*7a001dbaSKun Yi PMBUS_HAVE_STATUS_IOUT; 248*7a001dbaSKun Yi break; 249*7a001dbaSKun Yi case 0x23: 250*7a001dbaSKun Yi data->info.func[page] = PMBUS_HAVE_IOUT; 251*7a001dbaSKun Yi break; 252*7a001dbaSKun Yi default: 253*7a001dbaSKun Yi break; 254*7a001dbaSKun Yi } 255*7a001dbaSKun Yi } 256*7a001dbaSKun Yi 257*7a001dbaSKun Yi return 0; 258*7a001dbaSKun Yi } 259*7a001dbaSKun Yi 2609d2ecfb7SGuenter Roeck static struct pmbus_driver_info max34440_info[] = { 2619d2ecfb7SGuenter Roeck [max34440] = { 2629d2ecfb7SGuenter Roeck .pages = 14, 2631061d851SGuenter Roeck .format[PSC_VOLTAGE_IN] = direct, 2641061d851SGuenter Roeck .format[PSC_VOLTAGE_OUT] = direct, 2651061d851SGuenter Roeck .format[PSC_TEMPERATURE] = direct, 2661061d851SGuenter Roeck .format[PSC_CURRENT_OUT] = direct, 2679d2ecfb7SGuenter Roeck .m[PSC_VOLTAGE_IN] = 1, 2689d2ecfb7SGuenter Roeck .b[PSC_VOLTAGE_IN] = 0, 2699d2ecfb7SGuenter Roeck .R[PSC_VOLTAGE_IN] = 3, /* R = 0 in datasheet reflects mV */ 2709d2ecfb7SGuenter Roeck .m[PSC_VOLTAGE_OUT] = 1, 2719d2ecfb7SGuenter Roeck .b[PSC_VOLTAGE_OUT] = 0, 2729d2ecfb7SGuenter Roeck .R[PSC_VOLTAGE_OUT] = 3, /* R = 0 in datasheet reflects mV */ 2739d2ecfb7SGuenter Roeck .m[PSC_CURRENT_OUT] = 1, 2749d2ecfb7SGuenter Roeck .b[PSC_CURRENT_OUT] = 0, 2759d2ecfb7SGuenter Roeck .R[PSC_CURRENT_OUT] = 3, /* R = 0 in datasheet reflects mA */ 2769d2ecfb7SGuenter Roeck .m[PSC_TEMPERATURE] = 1, 2779d2ecfb7SGuenter Roeck .b[PSC_TEMPERATURE] = 0, 2789d2ecfb7SGuenter Roeck .R[PSC_TEMPERATURE] = 2, 2799d2ecfb7SGuenter Roeck .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 2809d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 2819d2ecfb7SGuenter Roeck .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 2829d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 2839d2ecfb7SGuenter Roeck .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 2849d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 2859d2ecfb7SGuenter Roeck .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 2869d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 2879d2ecfb7SGuenter Roeck .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 2889d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 2899d2ecfb7SGuenter Roeck .func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 2909d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 2919d2ecfb7SGuenter Roeck .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 2929d2ecfb7SGuenter Roeck .func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 2939d2ecfb7SGuenter Roeck .func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 2949d2ecfb7SGuenter Roeck .func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 2959d2ecfb7SGuenter Roeck .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 2969d2ecfb7SGuenter Roeck .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 2979d2ecfb7SGuenter Roeck .func[12] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 2989d2ecfb7SGuenter Roeck .func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 2999d2ecfb7SGuenter Roeck .read_byte_data = max34440_read_byte_data, 30098591dbeSGuenter Roeck .read_word_data = max34440_read_word_data, 30198591dbeSGuenter Roeck .write_word_data = max34440_write_word_data, 3029d2ecfb7SGuenter Roeck }, 3039d2ecfb7SGuenter Roeck [max34441] = { 3049d2ecfb7SGuenter Roeck .pages = 12, 3051061d851SGuenter Roeck .format[PSC_VOLTAGE_IN] = direct, 3061061d851SGuenter Roeck .format[PSC_VOLTAGE_OUT] = direct, 3071061d851SGuenter Roeck .format[PSC_TEMPERATURE] = direct, 3081061d851SGuenter Roeck .format[PSC_CURRENT_OUT] = direct, 3091061d851SGuenter Roeck .format[PSC_FAN] = direct, 3109d2ecfb7SGuenter Roeck .m[PSC_VOLTAGE_IN] = 1, 3119d2ecfb7SGuenter Roeck .b[PSC_VOLTAGE_IN] = 0, 3129d2ecfb7SGuenter Roeck .R[PSC_VOLTAGE_IN] = 3, 3139d2ecfb7SGuenter Roeck .m[PSC_VOLTAGE_OUT] = 1, 3149d2ecfb7SGuenter Roeck .b[PSC_VOLTAGE_OUT] = 0, 3159d2ecfb7SGuenter Roeck .R[PSC_VOLTAGE_OUT] = 3, 3169d2ecfb7SGuenter Roeck .m[PSC_CURRENT_OUT] = 1, 3179d2ecfb7SGuenter Roeck .b[PSC_CURRENT_OUT] = 0, 3189d2ecfb7SGuenter Roeck .R[PSC_CURRENT_OUT] = 3, 3199d2ecfb7SGuenter Roeck .m[PSC_TEMPERATURE] = 1, 3209d2ecfb7SGuenter Roeck .b[PSC_TEMPERATURE] = 0, 3219d2ecfb7SGuenter Roeck .R[PSC_TEMPERATURE] = 2, 3229d2ecfb7SGuenter Roeck .m[PSC_FAN] = 1, 3239d2ecfb7SGuenter Roeck .b[PSC_FAN] = 0, 3249d2ecfb7SGuenter Roeck .R[PSC_FAN] = 0, 3259d2ecfb7SGuenter Roeck .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 3269d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 3279d2ecfb7SGuenter Roeck .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 3289d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 3299d2ecfb7SGuenter Roeck .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 3309d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 3319d2ecfb7SGuenter Roeck .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 3329d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 3339d2ecfb7SGuenter Roeck .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 3349d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 3359d2ecfb7SGuenter Roeck .func[5] = PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12, 3369d2ecfb7SGuenter Roeck .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 3379d2ecfb7SGuenter Roeck .func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 3389d2ecfb7SGuenter Roeck .func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 3399d2ecfb7SGuenter Roeck .func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 3409d2ecfb7SGuenter Roeck .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 3419d2ecfb7SGuenter Roeck .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 3429d2ecfb7SGuenter Roeck .read_byte_data = max34440_read_byte_data, 34398591dbeSGuenter Roeck .read_word_data = max34440_read_word_data, 34498591dbeSGuenter Roeck .write_word_data = max34440_write_word_data, 3459d2ecfb7SGuenter Roeck }, 346590defe5SGuenter Roeck [max34446] = { 347590defe5SGuenter Roeck .pages = 7, 348590defe5SGuenter Roeck .format[PSC_VOLTAGE_IN] = direct, 349590defe5SGuenter Roeck .format[PSC_VOLTAGE_OUT] = direct, 350590defe5SGuenter Roeck .format[PSC_TEMPERATURE] = direct, 351590defe5SGuenter Roeck .format[PSC_CURRENT_OUT] = direct, 352590defe5SGuenter Roeck .format[PSC_POWER] = direct, 353590defe5SGuenter Roeck .m[PSC_VOLTAGE_IN] = 1, 354590defe5SGuenter Roeck .b[PSC_VOLTAGE_IN] = 0, 355590defe5SGuenter Roeck .R[PSC_VOLTAGE_IN] = 3, 356590defe5SGuenter Roeck .m[PSC_VOLTAGE_OUT] = 1, 357590defe5SGuenter Roeck .b[PSC_VOLTAGE_OUT] = 0, 358590defe5SGuenter Roeck .R[PSC_VOLTAGE_OUT] = 3, 359590defe5SGuenter Roeck .m[PSC_CURRENT_OUT] = 1, 360590defe5SGuenter Roeck .b[PSC_CURRENT_OUT] = 0, 361590defe5SGuenter Roeck .R[PSC_CURRENT_OUT] = 3, 362590defe5SGuenter Roeck .m[PSC_POWER] = 1, 363590defe5SGuenter Roeck .b[PSC_POWER] = 0, 364590defe5SGuenter Roeck .R[PSC_POWER] = 3, 365590defe5SGuenter Roeck .m[PSC_TEMPERATURE] = 1, 366590defe5SGuenter Roeck .b[PSC_TEMPERATURE] = 0, 367590defe5SGuenter Roeck .R[PSC_TEMPERATURE] = 2, 368590defe5SGuenter Roeck .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 369590defe5SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT, 370590defe5SGuenter Roeck .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 371590defe5SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 372590defe5SGuenter Roeck .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 373590defe5SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT, 374590defe5SGuenter Roeck .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 375590defe5SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 376590defe5SGuenter Roeck .func[4] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 377590defe5SGuenter Roeck .func[5] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 378590defe5SGuenter Roeck .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 379590defe5SGuenter Roeck .read_byte_data = max34440_read_byte_data, 380590defe5SGuenter Roeck .read_word_data = max34440_read_word_data, 381590defe5SGuenter Roeck .write_word_data = max34440_write_word_data, 382590defe5SGuenter Roeck }, 383*7a001dbaSKun Yi [max34451] = { 384*7a001dbaSKun Yi .pages = 21, 385*7a001dbaSKun Yi .format[PSC_VOLTAGE_OUT] = direct, 386*7a001dbaSKun Yi .format[PSC_TEMPERATURE] = direct, 387*7a001dbaSKun Yi .format[PSC_CURRENT_OUT] = direct, 388*7a001dbaSKun Yi .m[PSC_VOLTAGE_OUT] = 1, 389*7a001dbaSKun Yi .b[PSC_VOLTAGE_OUT] = 0, 390*7a001dbaSKun Yi .R[PSC_VOLTAGE_OUT] = 3, 391*7a001dbaSKun Yi .m[PSC_CURRENT_OUT] = 1, 392*7a001dbaSKun Yi .b[PSC_CURRENT_OUT] = 0, 393*7a001dbaSKun Yi .R[PSC_CURRENT_OUT] = 2, 394*7a001dbaSKun Yi .m[PSC_TEMPERATURE] = 1, 395*7a001dbaSKun Yi .b[PSC_TEMPERATURE] = 0, 396*7a001dbaSKun Yi .R[PSC_TEMPERATURE] = 2, 397*7a001dbaSKun Yi /* func 0-15 is set dynamically before probing */ 398*7a001dbaSKun Yi .func[16] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 399*7a001dbaSKun Yi .func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 400*7a001dbaSKun Yi .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 401*7a001dbaSKun Yi .func[19] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 402*7a001dbaSKun Yi .func[20] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 403*7a001dbaSKun Yi .read_byte_data = max34440_read_byte_data, 404*7a001dbaSKun Yi .read_word_data = max34440_read_word_data, 405*7a001dbaSKun Yi .write_word_data = max34440_write_word_data, 406*7a001dbaSKun Yi }, 40750115ac9SGuenter Roeck [max34460] = { 40850115ac9SGuenter Roeck .pages = 18, 40950115ac9SGuenter Roeck .format[PSC_VOLTAGE_OUT] = direct, 41050115ac9SGuenter Roeck .format[PSC_TEMPERATURE] = direct, 41150115ac9SGuenter Roeck .m[PSC_VOLTAGE_OUT] = 1, 41250115ac9SGuenter Roeck .b[PSC_VOLTAGE_OUT] = 0, 41350115ac9SGuenter Roeck .R[PSC_VOLTAGE_OUT] = 3, 41450115ac9SGuenter Roeck .m[PSC_TEMPERATURE] = 1, 41550115ac9SGuenter Roeck .b[PSC_TEMPERATURE] = 0, 41650115ac9SGuenter Roeck .R[PSC_TEMPERATURE] = 2, 41750115ac9SGuenter Roeck .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 41850115ac9SGuenter Roeck .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 41950115ac9SGuenter Roeck .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 42050115ac9SGuenter Roeck .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 42150115ac9SGuenter Roeck .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 42250115ac9SGuenter Roeck .func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 42350115ac9SGuenter Roeck .func[6] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 42450115ac9SGuenter Roeck .func[7] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 42550115ac9SGuenter Roeck .func[8] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 42650115ac9SGuenter Roeck .func[9] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 42750115ac9SGuenter Roeck .func[10] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 42850115ac9SGuenter Roeck .func[11] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 42950115ac9SGuenter Roeck .func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 43050115ac9SGuenter Roeck .func[14] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 43150115ac9SGuenter Roeck .func[15] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 43250115ac9SGuenter Roeck .func[16] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 43350115ac9SGuenter Roeck .func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 43450115ac9SGuenter Roeck .read_byte_data = max34440_read_byte_data, 43550115ac9SGuenter Roeck .read_word_data = max34440_read_word_data, 43650115ac9SGuenter Roeck .write_word_data = max34440_write_word_data, 43750115ac9SGuenter Roeck }, 43850115ac9SGuenter Roeck [max34461] = { 43950115ac9SGuenter Roeck .pages = 23, 44050115ac9SGuenter Roeck .format[PSC_VOLTAGE_OUT] = direct, 44150115ac9SGuenter Roeck .format[PSC_TEMPERATURE] = direct, 44250115ac9SGuenter Roeck .m[PSC_VOLTAGE_OUT] = 1, 44350115ac9SGuenter Roeck .b[PSC_VOLTAGE_OUT] = 0, 44450115ac9SGuenter Roeck .R[PSC_VOLTAGE_OUT] = 3, 44550115ac9SGuenter Roeck .m[PSC_TEMPERATURE] = 1, 44650115ac9SGuenter Roeck .b[PSC_TEMPERATURE] = 0, 44750115ac9SGuenter Roeck .R[PSC_TEMPERATURE] = 2, 44850115ac9SGuenter Roeck .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 44950115ac9SGuenter Roeck .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 45050115ac9SGuenter Roeck .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 45150115ac9SGuenter Roeck .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 45250115ac9SGuenter Roeck .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 45350115ac9SGuenter Roeck .func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 45450115ac9SGuenter Roeck .func[6] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 45550115ac9SGuenter Roeck .func[7] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 45650115ac9SGuenter Roeck .func[8] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 45750115ac9SGuenter Roeck .func[9] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 45850115ac9SGuenter Roeck .func[10] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 45950115ac9SGuenter Roeck .func[11] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 46050115ac9SGuenter Roeck .func[12] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 46150115ac9SGuenter Roeck .func[13] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 46250115ac9SGuenter Roeck .func[14] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 46350115ac9SGuenter Roeck .func[15] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 46450115ac9SGuenter Roeck /* page 16 is reserved */ 46550115ac9SGuenter Roeck .func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 46650115ac9SGuenter Roeck .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 46750115ac9SGuenter Roeck .func[19] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 46850115ac9SGuenter Roeck .func[20] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 46950115ac9SGuenter Roeck .func[21] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 47050115ac9SGuenter Roeck .read_byte_data = max34440_read_byte_data, 47150115ac9SGuenter Roeck .read_word_data = max34440_read_word_data, 47250115ac9SGuenter Roeck .write_word_data = max34440_write_word_data, 47350115ac9SGuenter Roeck }, 4749d2ecfb7SGuenter Roeck }; 4759d2ecfb7SGuenter Roeck 4769d2ecfb7SGuenter Roeck static int max34440_probe(struct i2c_client *client, 4779d2ecfb7SGuenter Roeck const struct i2c_device_id *id) 4789d2ecfb7SGuenter Roeck { 479590defe5SGuenter Roeck struct max34440_data *data; 480*7a001dbaSKun Yi int rv; 481590defe5SGuenter Roeck 482590defe5SGuenter Roeck data = devm_kzalloc(&client->dev, sizeof(struct max34440_data), 483590defe5SGuenter Roeck GFP_KERNEL); 484590defe5SGuenter Roeck if (!data) 485590defe5SGuenter Roeck return -ENOMEM; 486590defe5SGuenter Roeck data->id = id->driver_data; 487590defe5SGuenter Roeck data->info = max34440_info[id->driver_data]; 488590defe5SGuenter Roeck 489*7a001dbaSKun Yi if (data->id == max34451) { 490*7a001dbaSKun Yi rv = max34451_set_supported_funcs(client, data); 491*7a001dbaSKun Yi if (rv) 492*7a001dbaSKun Yi return rv; 493*7a001dbaSKun Yi } 494*7a001dbaSKun Yi 495590defe5SGuenter Roeck return pmbus_do_probe(client, id, &data->info); 4969d2ecfb7SGuenter Roeck } 4979d2ecfb7SGuenter Roeck 4989d2ecfb7SGuenter Roeck static const struct i2c_device_id max34440_id[] = { 4999d2ecfb7SGuenter Roeck {"max34440", max34440}, 5009d2ecfb7SGuenter Roeck {"max34441", max34441}, 501590defe5SGuenter Roeck {"max34446", max34446}, 502*7a001dbaSKun Yi {"max34451", max34451}, 50350115ac9SGuenter Roeck {"max34460", max34460}, 50450115ac9SGuenter Roeck {"max34461", max34461}, 5059d2ecfb7SGuenter Roeck {} 5069d2ecfb7SGuenter Roeck }; 5079d2ecfb7SGuenter Roeck MODULE_DEVICE_TABLE(i2c, max34440_id); 5089d2ecfb7SGuenter Roeck 5099d2ecfb7SGuenter Roeck /* This is the driver that will be inserted */ 5109d2ecfb7SGuenter Roeck static struct i2c_driver max34440_driver = { 5119d2ecfb7SGuenter Roeck .driver = { 5129d2ecfb7SGuenter Roeck .name = "max34440", 5139d2ecfb7SGuenter Roeck }, 5149d2ecfb7SGuenter Roeck .probe = max34440_probe, 515dd285ad7SGuenter Roeck .remove = pmbus_do_remove, 5169d2ecfb7SGuenter Roeck .id_table = max34440_id, 5179d2ecfb7SGuenter Roeck }; 5189d2ecfb7SGuenter Roeck 519f0967eeaSAxel Lin module_i2c_driver(max34440_driver); 5209d2ecfb7SGuenter Roeck 5219d2ecfb7SGuenter Roeck MODULE_AUTHOR("Guenter Roeck"); 5229d2ecfb7SGuenter Roeck MODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441"); 5239d2ecfb7SGuenter Roeck MODULE_LICENSE("GPL"); 524