174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 29d2ecfb7SGuenter Roeck /* 39d2ecfb7SGuenter Roeck * Hardware monitoring driver for Maxim MAX34440/MAX34441 49d2ecfb7SGuenter Roeck * 59d2ecfb7SGuenter Roeck * Copyright (c) 2011 Ericsson AB. 650115ac9SGuenter Roeck * Copyright (c) 2012 Guenter Roeck 79d2ecfb7SGuenter Roeck */ 89d2ecfb7SGuenter Roeck 92c052d42SGuenter Roeck #include <linux/bitops.h> 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/i2c.h> 159d2ecfb7SGuenter Roeck #include "pmbus.h" 169d2ecfb7SGuenter Roeck 177a001dbaSKun Yi enum chips { max34440, max34441, max34446, max34451, max34460, max34461 }; 189d2ecfb7SGuenter Roeck 1998591dbeSGuenter Roeck #define MAX34440_MFR_VOUT_PEAK 0xd4 2098591dbeSGuenter Roeck #define MAX34440_MFR_IOUT_PEAK 0xd5 2198591dbeSGuenter Roeck #define MAX34440_MFR_TEMPERATURE_PEAK 0xd6 2256aad5d1SGuenter Roeck #define MAX34440_MFR_VOUT_MIN 0xd7 2398591dbeSGuenter Roeck 24590defe5SGuenter Roeck #define MAX34446_MFR_POUT_PEAK 0xe0 25590defe5SGuenter Roeck #define MAX34446_MFR_POUT_AVG 0xe1 26590defe5SGuenter Roeck #define MAX34446_MFR_IOUT_AVG 0xe2 27590defe5SGuenter Roeck #define MAX34446_MFR_TEMPERATURE_AVG 0xe3 28590defe5SGuenter Roeck 292c052d42SGuenter Roeck #define MAX34440_STATUS_OC_WARN BIT(0) 302c052d42SGuenter Roeck #define MAX34440_STATUS_OC_FAULT BIT(1) 312c052d42SGuenter Roeck #define MAX34440_STATUS_OT_FAULT BIT(5) 322c052d42SGuenter Roeck #define MAX34440_STATUS_OT_WARN BIT(6) 339d2ecfb7SGuenter Roeck 347a001dbaSKun Yi #define MAX34451_MFR_CHANNEL_CONFIG 0xe4 357a001dbaSKun Yi #define MAX34451_MFR_CHANNEL_CONFIG_SEL_MASK 0x3f 367a001dbaSKun Yi 37590defe5SGuenter Roeck struct max34440_data { 38590defe5SGuenter Roeck int id; 39590defe5SGuenter Roeck struct pmbus_driver_info info; 40590defe5SGuenter Roeck }; 41590defe5SGuenter Roeck 42590defe5SGuenter Roeck #define to_max34440_data(x) container_of(x, struct max34440_data, info) 43590defe5SGuenter Roeck 44*43f33b6eSGuenter Roeck static int max34440_read_word_data(struct i2c_client *client, int page, 45*43f33b6eSGuenter Roeck int phase, int reg) 4698591dbeSGuenter Roeck { 4798591dbeSGuenter Roeck int ret; 48590defe5SGuenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 49590defe5SGuenter Roeck const struct max34440_data *data = to_max34440_data(info); 5098591dbeSGuenter Roeck 5198591dbeSGuenter Roeck switch (reg) { 5256aad5d1SGuenter Roeck case PMBUS_VIRT_READ_VOUT_MIN: 53*43f33b6eSGuenter Roeck ret = pmbus_read_word_data(client, page, phase, 5456aad5d1SGuenter Roeck MAX34440_MFR_VOUT_MIN); 5556aad5d1SGuenter Roeck break; 5698591dbeSGuenter Roeck case PMBUS_VIRT_READ_VOUT_MAX: 57*43f33b6eSGuenter Roeck ret = pmbus_read_word_data(client, page, phase, 5898591dbeSGuenter Roeck MAX34440_MFR_VOUT_PEAK); 5998591dbeSGuenter Roeck break; 60590defe5SGuenter Roeck case PMBUS_VIRT_READ_IOUT_AVG: 617a001dbaSKun Yi if (data->id != max34446 && data->id != max34451) 62590defe5SGuenter Roeck return -ENXIO; 63*43f33b6eSGuenter Roeck ret = pmbus_read_word_data(client, page, phase, 64590defe5SGuenter Roeck MAX34446_MFR_IOUT_AVG); 65590defe5SGuenter Roeck break; 6698591dbeSGuenter Roeck case PMBUS_VIRT_READ_IOUT_MAX: 67*43f33b6eSGuenter Roeck ret = pmbus_read_word_data(client, page, phase, 6898591dbeSGuenter Roeck MAX34440_MFR_IOUT_PEAK); 6998591dbeSGuenter Roeck break; 70590defe5SGuenter Roeck case PMBUS_VIRT_READ_POUT_AVG: 71590defe5SGuenter Roeck if (data->id != max34446) 72590defe5SGuenter Roeck return -ENXIO; 73*43f33b6eSGuenter Roeck ret = pmbus_read_word_data(client, page, phase, 74590defe5SGuenter Roeck MAX34446_MFR_POUT_AVG); 75590defe5SGuenter Roeck break; 76590defe5SGuenter Roeck case PMBUS_VIRT_READ_POUT_MAX: 77590defe5SGuenter Roeck if (data->id != max34446) 78590defe5SGuenter Roeck return -ENXIO; 79*43f33b6eSGuenter Roeck ret = pmbus_read_word_data(client, page, phase, 80590defe5SGuenter Roeck MAX34446_MFR_POUT_PEAK); 81590defe5SGuenter Roeck break; 82590defe5SGuenter Roeck case PMBUS_VIRT_READ_TEMP_AVG: 8350115ac9SGuenter Roeck if (data->id != max34446 && data->id != max34460 && 8450115ac9SGuenter Roeck data->id != max34461) 85590defe5SGuenter Roeck return -ENXIO; 86*43f33b6eSGuenter Roeck ret = pmbus_read_word_data(client, page, phase, 87590defe5SGuenter Roeck MAX34446_MFR_TEMPERATURE_AVG); 88590defe5SGuenter Roeck break; 8998591dbeSGuenter Roeck case PMBUS_VIRT_READ_TEMP_MAX: 90*43f33b6eSGuenter Roeck ret = pmbus_read_word_data(client, page, phase, 9198591dbeSGuenter Roeck MAX34440_MFR_TEMPERATURE_PEAK); 9298591dbeSGuenter Roeck break; 93590defe5SGuenter Roeck case PMBUS_VIRT_RESET_POUT_HISTORY: 94590defe5SGuenter Roeck if (data->id != max34446) 95590defe5SGuenter Roeck return -ENXIO; 96590defe5SGuenter Roeck ret = 0; 97590defe5SGuenter Roeck break; 9898591dbeSGuenter Roeck case PMBUS_VIRT_RESET_VOUT_HISTORY: 9998591dbeSGuenter Roeck case PMBUS_VIRT_RESET_IOUT_HISTORY: 10098591dbeSGuenter Roeck case PMBUS_VIRT_RESET_TEMP_HISTORY: 10198591dbeSGuenter Roeck ret = 0; 10298591dbeSGuenter Roeck break; 10398591dbeSGuenter Roeck default: 10498591dbeSGuenter Roeck ret = -ENODATA; 10598591dbeSGuenter Roeck break; 10698591dbeSGuenter Roeck } 10798591dbeSGuenter Roeck return ret; 10898591dbeSGuenter Roeck } 10998591dbeSGuenter Roeck 11098591dbeSGuenter Roeck static int max34440_write_word_data(struct i2c_client *client, int page, 11198591dbeSGuenter Roeck int reg, u16 word) 11298591dbeSGuenter Roeck { 113590defe5SGuenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 114590defe5SGuenter Roeck const struct max34440_data *data = to_max34440_data(info); 11598591dbeSGuenter Roeck int ret; 11698591dbeSGuenter Roeck 11798591dbeSGuenter Roeck switch (reg) { 118590defe5SGuenter Roeck case PMBUS_VIRT_RESET_POUT_HISTORY: 119590defe5SGuenter Roeck ret = pmbus_write_word_data(client, page, 120590defe5SGuenter Roeck MAX34446_MFR_POUT_PEAK, 0); 121590defe5SGuenter Roeck if (ret) 122590defe5SGuenter Roeck break; 123590defe5SGuenter Roeck ret = pmbus_write_word_data(client, page, 124590defe5SGuenter Roeck MAX34446_MFR_POUT_AVG, 0); 125590defe5SGuenter Roeck break; 12698591dbeSGuenter Roeck case PMBUS_VIRT_RESET_VOUT_HISTORY: 12798591dbeSGuenter Roeck ret = pmbus_write_word_data(client, page, 12856aad5d1SGuenter Roeck MAX34440_MFR_VOUT_MIN, 0x7fff); 12956aad5d1SGuenter Roeck if (ret) 13056aad5d1SGuenter Roeck break; 13156aad5d1SGuenter Roeck ret = pmbus_write_word_data(client, page, 13298591dbeSGuenter Roeck MAX34440_MFR_VOUT_PEAK, 0); 13398591dbeSGuenter Roeck break; 13498591dbeSGuenter Roeck case PMBUS_VIRT_RESET_IOUT_HISTORY: 13598591dbeSGuenter Roeck ret = pmbus_write_word_data(client, page, 13698591dbeSGuenter Roeck MAX34440_MFR_IOUT_PEAK, 0); 1377a001dbaSKun Yi if (!ret && (data->id == max34446 || data->id == max34451)) 138590defe5SGuenter Roeck ret = pmbus_write_word_data(client, page, 139590defe5SGuenter Roeck MAX34446_MFR_IOUT_AVG, 0); 140590defe5SGuenter Roeck 14198591dbeSGuenter Roeck break; 14298591dbeSGuenter Roeck case PMBUS_VIRT_RESET_TEMP_HISTORY: 14398591dbeSGuenter Roeck ret = pmbus_write_word_data(client, page, 14498591dbeSGuenter Roeck MAX34440_MFR_TEMPERATURE_PEAK, 145dc91ad8eSGuenter Roeck 0x8000); 146590defe5SGuenter Roeck if (!ret && data->id == max34446) 147590defe5SGuenter Roeck ret = pmbus_write_word_data(client, page, 148590defe5SGuenter Roeck MAX34446_MFR_TEMPERATURE_AVG, 0); 14998591dbeSGuenter Roeck break; 15098591dbeSGuenter Roeck default: 15198591dbeSGuenter Roeck ret = -ENODATA; 15298591dbeSGuenter Roeck break; 15398591dbeSGuenter Roeck } 15498591dbeSGuenter Roeck return ret; 15598591dbeSGuenter Roeck } 15698591dbeSGuenter Roeck 1579d2ecfb7SGuenter Roeck static int max34440_read_byte_data(struct i2c_client *client, int page, int reg) 1589d2ecfb7SGuenter Roeck { 159da8e48abSGuenter Roeck int ret = 0; 1609d2ecfb7SGuenter Roeck int mfg_status; 1619d2ecfb7SGuenter Roeck 162da8e48abSGuenter Roeck if (page >= 0) { 163*43f33b6eSGuenter Roeck ret = pmbus_set_page(client, page, 0xff); 1649d2ecfb7SGuenter Roeck if (ret < 0) 1659d2ecfb7SGuenter Roeck return ret; 166da8e48abSGuenter Roeck } 1679d2ecfb7SGuenter Roeck 1689d2ecfb7SGuenter Roeck switch (reg) { 1699d2ecfb7SGuenter Roeck case PMBUS_STATUS_IOUT: 170*43f33b6eSGuenter Roeck mfg_status = pmbus_read_word_data(client, 0, 0xff, 1719d2ecfb7SGuenter Roeck PMBUS_STATUS_MFR_SPECIFIC); 1729d2ecfb7SGuenter Roeck if (mfg_status < 0) 1739d2ecfb7SGuenter Roeck return mfg_status; 1749d2ecfb7SGuenter Roeck if (mfg_status & MAX34440_STATUS_OC_WARN) 1759d2ecfb7SGuenter Roeck ret |= PB_IOUT_OC_WARNING; 1769d2ecfb7SGuenter Roeck if (mfg_status & MAX34440_STATUS_OC_FAULT) 1779d2ecfb7SGuenter Roeck ret |= PB_IOUT_OC_FAULT; 1789d2ecfb7SGuenter Roeck break; 1799d2ecfb7SGuenter Roeck case PMBUS_STATUS_TEMPERATURE: 180*43f33b6eSGuenter Roeck mfg_status = pmbus_read_word_data(client, 0, 0xff, 1819d2ecfb7SGuenter Roeck PMBUS_STATUS_MFR_SPECIFIC); 1829d2ecfb7SGuenter Roeck if (mfg_status < 0) 1839d2ecfb7SGuenter Roeck return mfg_status; 1849d2ecfb7SGuenter Roeck if (mfg_status & MAX34440_STATUS_OT_WARN) 1859d2ecfb7SGuenter Roeck ret |= PB_TEMP_OT_WARNING; 1869d2ecfb7SGuenter Roeck if (mfg_status & MAX34440_STATUS_OT_FAULT) 1879d2ecfb7SGuenter Roeck ret |= PB_TEMP_OT_FAULT; 1889d2ecfb7SGuenter Roeck break; 1899d2ecfb7SGuenter Roeck default: 1909d2ecfb7SGuenter Roeck ret = -ENODATA; 1919d2ecfb7SGuenter Roeck break; 1929d2ecfb7SGuenter Roeck } 1939d2ecfb7SGuenter Roeck return ret; 1949d2ecfb7SGuenter Roeck } 1959d2ecfb7SGuenter Roeck 1967a001dbaSKun Yi static int max34451_set_supported_funcs(struct i2c_client *client, 1977a001dbaSKun Yi struct max34440_data *data) 1987a001dbaSKun Yi { 1997a001dbaSKun Yi /* 2007a001dbaSKun Yi * Each of the channel 0-15 can be configured to monitor the following 2017a001dbaSKun Yi * functions based on MFR_CHANNEL_CONFIG[5:0] 2027a001dbaSKun Yi * 0x10: Sequencing + voltage monitoring (only valid for PAGES 0–11) 2037a001dbaSKun Yi * 0x20: Voltage monitoring (no sequencing) 2047a001dbaSKun Yi * 0x21: Voltage read only 2057a001dbaSKun Yi * 0x22: Current monitoring 2067a001dbaSKun Yi * 0x23: Current read only 2077a001dbaSKun Yi * 0x30: General-purpose input active low 2087a001dbaSKun Yi * 0x34: General-purpose input active high 2097a001dbaSKun Yi * 0x00: Disabled 2107a001dbaSKun Yi */ 2117a001dbaSKun Yi 2127a001dbaSKun Yi int page, rv; 2137a001dbaSKun Yi 2147a001dbaSKun Yi for (page = 0; page < 16; page++) { 2157a001dbaSKun Yi rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); 2167a001dbaSKun Yi if (rv < 0) 2177a001dbaSKun Yi return rv; 2187a001dbaSKun Yi 2197a001dbaSKun Yi rv = i2c_smbus_read_word_data(client, 2207a001dbaSKun Yi MAX34451_MFR_CHANNEL_CONFIG); 2217a001dbaSKun Yi if (rv < 0) 2227a001dbaSKun Yi return rv; 2237a001dbaSKun Yi 2247a001dbaSKun Yi switch (rv & MAX34451_MFR_CHANNEL_CONFIG_SEL_MASK) { 2257a001dbaSKun Yi case 0x10: 2267a001dbaSKun Yi case 0x20: 2277a001dbaSKun Yi data->info.func[page] = PMBUS_HAVE_VOUT | 2287a001dbaSKun Yi PMBUS_HAVE_STATUS_VOUT; 2297a001dbaSKun Yi break; 2307a001dbaSKun Yi case 0x21: 2317a001dbaSKun Yi data->info.func[page] = PMBUS_HAVE_VOUT; 2327a001dbaSKun Yi break; 2337a001dbaSKun Yi case 0x22: 2347a001dbaSKun Yi data->info.func[page] = PMBUS_HAVE_IOUT | 2357a001dbaSKun Yi PMBUS_HAVE_STATUS_IOUT; 2367a001dbaSKun Yi break; 2377a001dbaSKun Yi case 0x23: 2387a001dbaSKun Yi data->info.func[page] = PMBUS_HAVE_IOUT; 2397a001dbaSKun Yi break; 2407a001dbaSKun Yi default: 2417a001dbaSKun Yi break; 2427a001dbaSKun Yi } 2437a001dbaSKun Yi } 2447a001dbaSKun Yi 2457a001dbaSKun Yi return 0; 2467a001dbaSKun Yi } 2477a001dbaSKun Yi 2489d2ecfb7SGuenter Roeck static struct pmbus_driver_info max34440_info[] = { 2499d2ecfb7SGuenter Roeck [max34440] = { 2509d2ecfb7SGuenter Roeck .pages = 14, 2511061d851SGuenter Roeck .format[PSC_VOLTAGE_IN] = direct, 2521061d851SGuenter Roeck .format[PSC_VOLTAGE_OUT] = direct, 2531061d851SGuenter Roeck .format[PSC_TEMPERATURE] = direct, 2541061d851SGuenter Roeck .format[PSC_CURRENT_OUT] = direct, 2559d2ecfb7SGuenter Roeck .m[PSC_VOLTAGE_IN] = 1, 2569d2ecfb7SGuenter Roeck .b[PSC_VOLTAGE_IN] = 0, 2579d2ecfb7SGuenter Roeck .R[PSC_VOLTAGE_IN] = 3, /* R = 0 in datasheet reflects mV */ 2589d2ecfb7SGuenter Roeck .m[PSC_VOLTAGE_OUT] = 1, 2599d2ecfb7SGuenter Roeck .b[PSC_VOLTAGE_OUT] = 0, 2609d2ecfb7SGuenter Roeck .R[PSC_VOLTAGE_OUT] = 3, /* R = 0 in datasheet reflects mV */ 2619d2ecfb7SGuenter Roeck .m[PSC_CURRENT_OUT] = 1, 2629d2ecfb7SGuenter Roeck .b[PSC_CURRENT_OUT] = 0, 2639d2ecfb7SGuenter Roeck .R[PSC_CURRENT_OUT] = 3, /* R = 0 in datasheet reflects mA */ 2649d2ecfb7SGuenter Roeck .m[PSC_TEMPERATURE] = 1, 2659d2ecfb7SGuenter Roeck .b[PSC_TEMPERATURE] = 0, 2669d2ecfb7SGuenter Roeck .R[PSC_TEMPERATURE] = 2, 2679d2ecfb7SGuenter Roeck .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 2689d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 2699d2ecfb7SGuenter Roeck .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 2709d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 2719d2ecfb7SGuenter Roeck .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 2729d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 2739d2ecfb7SGuenter Roeck .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 2749d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 2759d2ecfb7SGuenter Roeck .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 2769d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 2779d2ecfb7SGuenter Roeck .func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 2789d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 2799d2ecfb7SGuenter Roeck .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 2809d2ecfb7SGuenter Roeck .func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 2819d2ecfb7SGuenter Roeck .func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 2829d2ecfb7SGuenter Roeck .func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 2839d2ecfb7SGuenter Roeck .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 2849d2ecfb7SGuenter Roeck .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 2859d2ecfb7SGuenter Roeck .func[12] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 2869d2ecfb7SGuenter Roeck .func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 2879d2ecfb7SGuenter Roeck .read_byte_data = max34440_read_byte_data, 28898591dbeSGuenter Roeck .read_word_data = max34440_read_word_data, 28998591dbeSGuenter Roeck .write_word_data = max34440_write_word_data, 2909d2ecfb7SGuenter Roeck }, 2919d2ecfb7SGuenter Roeck [max34441] = { 2929d2ecfb7SGuenter Roeck .pages = 12, 2931061d851SGuenter Roeck .format[PSC_VOLTAGE_IN] = direct, 2941061d851SGuenter Roeck .format[PSC_VOLTAGE_OUT] = direct, 2951061d851SGuenter Roeck .format[PSC_TEMPERATURE] = direct, 2961061d851SGuenter Roeck .format[PSC_CURRENT_OUT] = direct, 2971061d851SGuenter Roeck .format[PSC_FAN] = direct, 2989d2ecfb7SGuenter Roeck .m[PSC_VOLTAGE_IN] = 1, 2999d2ecfb7SGuenter Roeck .b[PSC_VOLTAGE_IN] = 0, 3009d2ecfb7SGuenter Roeck .R[PSC_VOLTAGE_IN] = 3, 3019d2ecfb7SGuenter Roeck .m[PSC_VOLTAGE_OUT] = 1, 3029d2ecfb7SGuenter Roeck .b[PSC_VOLTAGE_OUT] = 0, 3039d2ecfb7SGuenter Roeck .R[PSC_VOLTAGE_OUT] = 3, 3049d2ecfb7SGuenter Roeck .m[PSC_CURRENT_OUT] = 1, 3059d2ecfb7SGuenter Roeck .b[PSC_CURRENT_OUT] = 0, 3069d2ecfb7SGuenter Roeck .R[PSC_CURRENT_OUT] = 3, 3079d2ecfb7SGuenter Roeck .m[PSC_TEMPERATURE] = 1, 3089d2ecfb7SGuenter Roeck .b[PSC_TEMPERATURE] = 0, 3099d2ecfb7SGuenter Roeck .R[PSC_TEMPERATURE] = 2, 3109d2ecfb7SGuenter Roeck .m[PSC_FAN] = 1, 3119d2ecfb7SGuenter Roeck .b[PSC_FAN] = 0, 3129d2ecfb7SGuenter Roeck .R[PSC_FAN] = 0, 3139d2ecfb7SGuenter Roeck .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 3149d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 3159d2ecfb7SGuenter Roeck .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 3169d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 3179d2ecfb7SGuenter Roeck .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 3189d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 3199d2ecfb7SGuenter Roeck .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 3209d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 3219d2ecfb7SGuenter Roeck .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 3229d2ecfb7SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 3239d2ecfb7SGuenter Roeck .func[5] = PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12, 3249d2ecfb7SGuenter Roeck .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 3259d2ecfb7SGuenter Roeck .func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 3269d2ecfb7SGuenter Roeck .func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 3279d2ecfb7SGuenter Roeck .func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 3289d2ecfb7SGuenter Roeck .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 3299d2ecfb7SGuenter Roeck .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 3309d2ecfb7SGuenter Roeck .read_byte_data = max34440_read_byte_data, 33198591dbeSGuenter Roeck .read_word_data = max34440_read_word_data, 33298591dbeSGuenter Roeck .write_word_data = max34440_write_word_data, 3339d2ecfb7SGuenter Roeck }, 334590defe5SGuenter Roeck [max34446] = { 335590defe5SGuenter Roeck .pages = 7, 336590defe5SGuenter Roeck .format[PSC_VOLTAGE_IN] = direct, 337590defe5SGuenter Roeck .format[PSC_VOLTAGE_OUT] = direct, 338590defe5SGuenter Roeck .format[PSC_TEMPERATURE] = direct, 339590defe5SGuenter Roeck .format[PSC_CURRENT_OUT] = direct, 340590defe5SGuenter Roeck .format[PSC_POWER] = direct, 341590defe5SGuenter Roeck .m[PSC_VOLTAGE_IN] = 1, 342590defe5SGuenter Roeck .b[PSC_VOLTAGE_IN] = 0, 343590defe5SGuenter Roeck .R[PSC_VOLTAGE_IN] = 3, 344590defe5SGuenter Roeck .m[PSC_VOLTAGE_OUT] = 1, 345590defe5SGuenter Roeck .b[PSC_VOLTAGE_OUT] = 0, 346590defe5SGuenter Roeck .R[PSC_VOLTAGE_OUT] = 3, 347590defe5SGuenter Roeck .m[PSC_CURRENT_OUT] = 1, 348590defe5SGuenter Roeck .b[PSC_CURRENT_OUT] = 0, 349590defe5SGuenter Roeck .R[PSC_CURRENT_OUT] = 3, 350590defe5SGuenter Roeck .m[PSC_POWER] = 1, 351590defe5SGuenter Roeck .b[PSC_POWER] = 0, 352590defe5SGuenter Roeck .R[PSC_POWER] = 3, 353590defe5SGuenter Roeck .m[PSC_TEMPERATURE] = 1, 354590defe5SGuenter Roeck .b[PSC_TEMPERATURE] = 0, 355590defe5SGuenter Roeck .R[PSC_TEMPERATURE] = 2, 356590defe5SGuenter Roeck .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 357590defe5SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT, 358590defe5SGuenter Roeck .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 359590defe5SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 360590defe5SGuenter Roeck .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 361590defe5SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT, 362590defe5SGuenter Roeck .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 363590defe5SGuenter Roeck | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 364590defe5SGuenter Roeck .func[4] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 365590defe5SGuenter Roeck .func[5] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 366590defe5SGuenter Roeck .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 367590defe5SGuenter Roeck .read_byte_data = max34440_read_byte_data, 368590defe5SGuenter Roeck .read_word_data = max34440_read_word_data, 369590defe5SGuenter Roeck .write_word_data = max34440_write_word_data, 370590defe5SGuenter Roeck }, 3717a001dbaSKun Yi [max34451] = { 3727a001dbaSKun Yi .pages = 21, 3737a001dbaSKun Yi .format[PSC_VOLTAGE_OUT] = direct, 3747a001dbaSKun Yi .format[PSC_TEMPERATURE] = direct, 3757a001dbaSKun Yi .format[PSC_CURRENT_OUT] = direct, 3767a001dbaSKun Yi .m[PSC_VOLTAGE_OUT] = 1, 3777a001dbaSKun Yi .b[PSC_VOLTAGE_OUT] = 0, 3787a001dbaSKun Yi .R[PSC_VOLTAGE_OUT] = 3, 3797a001dbaSKun Yi .m[PSC_CURRENT_OUT] = 1, 3807a001dbaSKun Yi .b[PSC_CURRENT_OUT] = 0, 3817a001dbaSKun Yi .R[PSC_CURRENT_OUT] = 2, 3827a001dbaSKun Yi .m[PSC_TEMPERATURE] = 1, 3837a001dbaSKun Yi .b[PSC_TEMPERATURE] = 0, 3847a001dbaSKun Yi .R[PSC_TEMPERATURE] = 2, 3857a001dbaSKun Yi /* func 0-15 is set dynamically before probing */ 3867a001dbaSKun Yi .func[16] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 3877a001dbaSKun Yi .func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 3887a001dbaSKun Yi .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 3897a001dbaSKun Yi .func[19] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 3907a001dbaSKun Yi .func[20] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 3917a001dbaSKun Yi .read_byte_data = max34440_read_byte_data, 3927a001dbaSKun Yi .read_word_data = max34440_read_word_data, 3937a001dbaSKun Yi .write_word_data = max34440_write_word_data, 3947a001dbaSKun Yi }, 39550115ac9SGuenter Roeck [max34460] = { 39650115ac9SGuenter Roeck .pages = 18, 39750115ac9SGuenter Roeck .format[PSC_VOLTAGE_OUT] = direct, 39850115ac9SGuenter Roeck .format[PSC_TEMPERATURE] = direct, 39950115ac9SGuenter Roeck .m[PSC_VOLTAGE_OUT] = 1, 40050115ac9SGuenter Roeck .b[PSC_VOLTAGE_OUT] = 0, 40150115ac9SGuenter Roeck .R[PSC_VOLTAGE_OUT] = 3, 40250115ac9SGuenter Roeck .m[PSC_TEMPERATURE] = 1, 40350115ac9SGuenter Roeck .b[PSC_TEMPERATURE] = 0, 40450115ac9SGuenter Roeck .R[PSC_TEMPERATURE] = 2, 40550115ac9SGuenter Roeck .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 40650115ac9SGuenter Roeck .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 40750115ac9SGuenter Roeck .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 40850115ac9SGuenter Roeck .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 40950115ac9SGuenter Roeck .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 41050115ac9SGuenter Roeck .func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 41150115ac9SGuenter Roeck .func[6] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 41250115ac9SGuenter Roeck .func[7] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 41350115ac9SGuenter Roeck .func[8] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 41450115ac9SGuenter Roeck .func[9] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 41550115ac9SGuenter Roeck .func[10] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 41650115ac9SGuenter Roeck .func[11] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 41750115ac9SGuenter Roeck .func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 41850115ac9SGuenter Roeck .func[14] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 41950115ac9SGuenter Roeck .func[15] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 42050115ac9SGuenter Roeck .func[16] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 42150115ac9SGuenter Roeck .func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 42250115ac9SGuenter Roeck .read_byte_data = max34440_read_byte_data, 42350115ac9SGuenter Roeck .read_word_data = max34440_read_word_data, 42450115ac9SGuenter Roeck .write_word_data = max34440_write_word_data, 42550115ac9SGuenter Roeck }, 42650115ac9SGuenter Roeck [max34461] = { 42750115ac9SGuenter Roeck .pages = 23, 42850115ac9SGuenter Roeck .format[PSC_VOLTAGE_OUT] = direct, 42950115ac9SGuenter Roeck .format[PSC_TEMPERATURE] = direct, 43050115ac9SGuenter Roeck .m[PSC_VOLTAGE_OUT] = 1, 43150115ac9SGuenter Roeck .b[PSC_VOLTAGE_OUT] = 0, 43250115ac9SGuenter Roeck .R[PSC_VOLTAGE_OUT] = 3, 43350115ac9SGuenter Roeck .m[PSC_TEMPERATURE] = 1, 43450115ac9SGuenter Roeck .b[PSC_TEMPERATURE] = 0, 43550115ac9SGuenter Roeck .R[PSC_TEMPERATURE] = 2, 43650115ac9SGuenter Roeck .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 43750115ac9SGuenter Roeck .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 43850115ac9SGuenter Roeck .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 43950115ac9SGuenter Roeck .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 44050115ac9SGuenter Roeck .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 44150115ac9SGuenter Roeck .func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 44250115ac9SGuenter Roeck .func[6] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 44350115ac9SGuenter Roeck .func[7] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 44450115ac9SGuenter Roeck .func[8] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 44550115ac9SGuenter Roeck .func[9] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 44650115ac9SGuenter Roeck .func[10] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 44750115ac9SGuenter Roeck .func[11] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 44850115ac9SGuenter Roeck .func[12] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 44950115ac9SGuenter Roeck .func[13] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 45050115ac9SGuenter Roeck .func[14] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 45150115ac9SGuenter Roeck .func[15] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 45250115ac9SGuenter Roeck /* page 16 is reserved */ 45350115ac9SGuenter Roeck .func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 45450115ac9SGuenter Roeck .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 45550115ac9SGuenter Roeck .func[19] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 45650115ac9SGuenter Roeck .func[20] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 45750115ac9SGuenter Roeck .func[21] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 45850115ac9SGuenter Roeck .read_byte_data = max34440_read_byte_data, 45950115ac9SGuenter Roeck .read_word_data = max34440_read_word_data, 46050115ac9SGuenter Roeck .write_word_data = max34440_write_word_data, 46150115ac9SGuenter Roeck }, 4629d2ecfb7SGuenter Roeck }; 4639d2ecfb7SGuenter Roeck 4649d2ecfb7SGuenter Roeck static int max34440_probe(struct i2c_client *client, 4659d2ecfb7SGuenter Roeck const struct i2c_device_id *id) 4669d2ecfb7SGuenter Roeck { 467590defe5SGuenter Roeck struct max34440_data *data; 4687a001dbaSKun Yi int rv; 469590defe5SGuenter Roeck 470590defe5SGuenter Roeck data = devm_kzalloc(&client->dev, sizeof(struct max34440_data), 471590defe5SGuenter Roeck GFP_KERNEL); 472590defe5SGuenter Roeck if (!data) 473590defe5SGuenter Roeck return -ENOMEM; 474590defe5SGuenter Roeck data->id = id->driver_data; 475590defe5SGuenter Roeck data->info = max34440_info[id->driver_data]; 476590defe5SGuenter Roeck 4777a001dbaSKun Yi if (data->id == max34451) { 4787a001dbaSKun Yi rv = max34451_set_supported_funcs(client, data); 4797a001dbaSKun Yi if (rv) 4807a001dbaSKun Yi return rv; 4817a001dbaSKun Yi } 4827a001dbaSKun Yi 483590defe5SGuenter Roeck return pmbus_do_probe(client, id, &data->info); 4849d2ecfb7SGuenter Roeck } 4859d2ecfb7SGuenter Roeck 4869d2ecfb7SGuenter Roeck static const struct i2c_device_id max34440_id[] = { 4879d2ecfb7SGuenter Roeck {"max34440", max34440}, 4889d2ecfb7SGuenter Roeck {"max34441", max34441}, 489590defe5SGuenter Roeck {"max34446", max34446}, 4907a001dbaSKun Yi {"max34451", max34451}, 49150115ac9SGuenter Roeck {"max34460", max34460}, 49250115ac9SGuenter Roeck {"max34461", max34461}, 4939d2ecfb7SGuenter Roeck {} 4949d2ecfb7SGuenter Roeck }; 4959d2ecfb7SGuenter Roeck MODULE_DEVICE_TABLE(i2c, max34440_id); 4969d2ecfb7SGuenter Roeck 4979d2ecfb7SGuenter Roeck /* This is the driver that will be inserted */ 4989d2ecfb7SGuenter Roeck static struct i2c_driver max34440_driver = { 4999d2ecfb7SGuenter Roeck .driver = { 5009d2ecfb7SGuenter Roeck .name = "max34440", 5019d2ecfb7SGuenter Roeck }, 5029d2ecfb7SGuenter Roeck .probe = max34440_probe, 503dd285ad7SGuenter Roeck .remove = pmbus_do_remove, 5049d2ecfb7SGuenter Roeck .id_table = max34440_id, 5059d2ecfb7SGuenter Roeck }; 5069d2ecfb7SGuenter Roeck 507f0967eeaSAxel Lin module_i2c_driver(max34440_driver); 5089d2ecfb7SGuenter Roeck 5099d2ecfb7SGuenter Roeck MODULE_AUTHOR("Guenter Roeck"); 5109d2ecfb7SGuenter Roeck MODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441"); 5119d2ecfb7SGuenter Roeck MODULE_LICENSE("GPL"); 512