162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Hardware monitoring driver for Maxim MAX34440/MAX34441 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2011 Ericsson AB. 662306a36Sopenharmony_ci * Copyright (c) 2012 Guenter Roeck 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/bitops.h> 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <linux/init.h> 1362306a36Sopenharmony_ci#include <linux/err.h> 1462306a36Sopenharmony_ci#include <linux/i2c.h> 1562306a36Sopenharmony_ci#include "pmbus.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cienum chips { max34440, max34441, max34446, max34451, max34460, max34461 }; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define MAX34440_MFR_VOUT_PEAK 0xd4 2062306a36Sopenharmony_ci#define MAX34440_MFR_IOUT_PEAK 0xd5 2162306a36Sopenharmony_ci#define MAX34440_MFR_TEMPERATURE_PEAK 0xd6 2262306a36Sopenharmony_ci#define MAX34440_MFR_VOUT_MIN 0xd7 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define MAX34446_MFR_POUT_PEAK 0xe0 2562306a36Sopenharmony_ci#define MAX34446_MFR_POUT_AVG 0xe1 2662306a36Sopenharmony_ci#define MAX34446_MFR_IOUT_AVG 0xe2 2762306a36Sopenharmony_ci#define MAX34446_MFR_TEMPERATURE_AVG 0xe3 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#define MAX34440_STATUS_OC_WARN BIT(0) 3062306a36Sopenharmony_ci#define MAX34440_STATUS_OC_FAULT BIT(1) 3162306a36Sopenharmony_ci#define MAX34440_STATUS_OT_FAULT BIT(5) 3262306a36Sopenharmony_ci#define MAX34440_STATUS_OT_WARN BIT(6) 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/* 3562306a36Sopenharmony_ci * The whole max344* family have IOUT_OC_WARN_LIMIT and IOUT_OC_FAULT_LIMIT 3662306a36Sopenharmony_ci * swapped from the standard pmbus spec addresses. 3762306a36Sopenharmony_ci */ 3862306a36Sopenharmony_ci#define MAX34440_IOUT_OC_WARN_LIMIT 0x46 3962306a36Sopenharmony_ci#define MAX34440_IOUT_OC_FAULT_LIMIT 0x4A 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#define MAX34451_MFR_CHANNEL_CONFIG 0xe4 4262306a36Sopenharmony_ci#define MAX34451_MFR_CHANNEL_CONFIG_SEL_MASK 0x3f 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistruct max34440_data { 4562306a36Sopenharmony_ci int id; 4662306a36Sopenharmony_ci struct pmbus_driver_info info; 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define to_max34440_data(x) container_of(x, struct max34440_data, info) 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic const struct i2c_device_id max34440_id[]; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistatic int max34440_read_word_data(struct i2c_client *client, int page, 5462306a36Sopenharmony_ci int phase, int reg) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci int ret; 5762306a36Sopenharmony_ci const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 5862306a36Sopenharmony_ci const struct max34440_data *data = to_max34440_data(info); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci switch (reg) { 6162306a36Sopenharmony_ci case PMBUS_IOUT_OC_FAULT_LIMIT: 6262306a36Sopenharmony_ci ret = pmbus_read_word_data(client, page, phase, 6362306a36Sopenharmony_ci MAX34440_IOUT_OC_FAULT_LIMIT); 6462306a36Sopenharmony_ci break; 6562306a36Sopenharmony_ci case PMBUS_IOUT_OC_WARN_LIMIT: 6662306a36Sopenharmony_ci ret = pmbus_read_word_data(client, page, phase, 6762306a36Sopenharmony_ci MAX34440_IOUT_OC_WARN_LIMIT); 6862306a36Sopenharmony_ci break; 6962306a36Sopenharmony_ci case PMBUS_VIRT_READ_VOUT_MIN: 7062306a36Sopenharmony_ci ret = pmbus_read_word_data(client, page, phase, 7162306a36Sopenharmony_ci MAX34440_MFR_VOUT_MIN); 7262306a36Sopenharmony_ci break; 7362306a36Sopenharmony_ci case PMBUS_VIRT_READ_VOUT_MAX: 7462306a36Sopenharmony_ci ret = pmbus_read_word_data(client, page, phase, 7562306a36Sopenharmony_ci MAX34440_MFR_VOUT_PEAK); 7662306a36Sopenharmony_ci break; 7762306a36Sopenharmony_ci case PMBUS_VIRT_READ_IOUT_AVG: 7862306a36Sopenharmony_ci if (data->id != max34446 && data->id != max34451) 7962306a36Sopenharmony_ci return -ENXIO; 8062306a36Sopenharmony_ci ret = pmbus_read_word_data(client, page, phase, 8162306a36Sopenharmony_ci MAX34446_MFR_IOUT_AVG); 8262306a36Sopenharmony_ci break; 8362306a36Sopenharmony_ci case PMBUS_VIRT_READ_IOUT_MAX: 8462306a36Sopenharmony_ci ret = pmbus_read_word_data(client, page, phase, 8562306a36Sopenharmony_ci MAX34440_MFR_IOUT_PEAK); 8662306a36Sopenharmony_ci break; 8762306a36Sopenharmony_ci case PMBUS_VIRT_READ_POUT_AVG: 8862306a36Sopenharmony_ci if (data->id != max34446) 8962306a36Sopenharmony_ci return -ENXIO; 9062306a36Sopenharmony_ci ret = pmbus_read_word_data(client, page, phase, 9162306a36Sopenharmony_ci MAX34446_MFR_POUT_AVG); 9262306a36Sopenharmony_ci break; 9362306a36Sopenharmony_ci case PMBUS_VIRT_READ_POUT_MAX: 9462306a36Sopenharmony_ci if (data->id != max34446) 9562306a36Sopenharmony_ci return -ENXIO; 9662306a36Sopenharmony_ci ret = pmbus_read_word_data(client, page, phase, 9762306a36Sopenharmony_ci MAX34446_MFR_POUT_PEAK); 9862306a36Sopenharmony_ci break; 9962306a36Sopenharmony_ci case PMBUS_VIRT_READ_TEMP_AVG: 10062306a36Sopenharmony_ci if (data->id != max34446 && data->id != max34460 && 10162306a36Sopenharmony_ci data->id != max34461) 10262306a36Sopenharmony_ci return -ENXIO; 10362306a36Sopenharmony_ci ret = pmbus_read_word_data(client, page, phase, 10462306a36Sopenharmony_ci MAX34446_MFR_TEMPERATURE_AVG); 10562306a36Sopenharmony_ci break; 10662306a36Sopenharmony_ci case PMBUS_VIRT_READ_TEMP_MAX: 10762306a36Sopenharmony_ci ret = pmbus_read_word_data(client, page, phase, 10862306a36Sopenharmony_ci MAX34440_MFR_TEMPERATURE_PEAK); 10962306a36Sopenharmony_ci break; 11062306a36Sopenharmony_ci case PMBUS_VIRT_RESET_POUT_HISTORY: 11162306a36Sopenharmony_ci if (data->id != max34446) 11262306a36Sopenharmony_ci return -ENXIO; 11362306a36Sopenharmony_ci ret = 0; 11462306a36Sopenharmony_ci break; 11562306a36Sopenharmony_ci case PMBUS_VIRT_RESET_VOUT_HISTORY: 11662306a36Sopenharmony_ci case PMBUS_VIRT_RESET_IOUT_HISTORY: 11762306a36Sopenharmony_ci case PMBUS_VIRT_RESET_TEMP_HISTORY: 11862306a36Sopenharmony_ci ret = 0; 11962306a36Sopenharmony_ci break; 12062306a36Sopenharmony_ci default: 12162306a36Sopenharmony_ci ret = -ENODATA; 12262306a36Sopenharmony_ci break; 12362306a36Sopenharmony_ci } 12462306a36Sopenharmony_ci return ret; 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic int max34440_write_word_data(struct i2c_client *client, int page, 12862306a36Sopenharmony_ci int reg, u16 word) 12962306a36Sopenharmony_ci{ 13062306a36Sopenharmony_ci const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 13162306a36Sopenharmony_ci const struct max34440_data *data = to_max34440_data(info); 13262306a36Sopenharmony_ci int ret; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci switch (reg) { 13562306a36Sopenharmony_ci case PMBUS_IOUT_OC_FAULT_LIMIT: 13662306a36Sopenharmony_ci ret = pmbus_write_word_data(client, page, MAX34440_IOUT_OC_FAULT_LIMIT, 13762306a36Sopenharmony_ci word); 13862306a36Sopenharmony_ci break; 13962306a36Sopenharmony_ci case PMBUS_IOUT_OC_WARN_LIMIT: 14062306a36Sopenharmony_ci ret = pmbus_write_word_data(client, page, MAX34440_IOUT_OC_WARN_LIMIT, 14162306a36Sopenharmony_ci word); 14262306a36Sopenharmony_ci break; 14362306a36Sopenharmony_ci case PMBUS_VIRT_RESET_POUT_HISTORY: 14462306a36Sopenharmony_ci ret = pmbus_write_word_data(client, page, 14562306a36Sopenharmony_ci MAX34446_MFR_POUT_PEAK, 0); 14662306a36Sopenharmony_ci if (ret) 14762306a36Sopenharmony_ci break; 14862306a36Sopenharmony_ci ret = pmbus_write_word_data(client, page, 14962306a36Sopenharmony_ci MAX34446_MFR_POUT_AVG, 0); 15062306a36Sopenharmony_ci break; 15162306a36Sopenharmony_ci case PMBUS_VIRT_RESET_VOUT_HISTORY: 15262306a36Sopenharmony_ci ret = pmbus_write_word_data(client, page, 15362306a36Sopenharmony_ci MAX34440_MFR_VOUT_MIN, 0x7fff); 15462306a36Sopenharmony_ci if (ret) 15562306a36Sopenharmony_ci break; 15662306a36Sopenharmony_ci ret = pmbus_write_word_data(client, page, 15762306a36Sopenharmony_ci MAX34440_MFR_VOUT_PEAK, 0); 15862306a36Sopenharmony_ci break; 15962306a36Sopenharmony_ci case PMBUS_VIRT_RESET_IOUT_HISTORY: 16062306a36Sopenharmony_ci ret = pmbus_write_word_data(client, page, 16162306a36Sopenharmony_ci MAX34440_MFR_IOUT_PEAK, 0); 16262306a36Sopenharmony_ci if (!ret && (data->id == max34446 || data->id == max34451)) 16362306a36Sopenharmony_ci ret = pmbus_write_word_data(client, page, 16462306a36Sopenharmony_ci MAX34446_MFR_IOUT_AVG, 0); 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci break; 16762306a36Sopenharmony_ci case PMBUS_VIRT_RESET_TEMP_HISTORY: 16862306a36Sopenharmony_ci ret = pmbus_write_word_data(client, page, 16962306a36Sopenharmony_ci MAX34440_MFR_TEMPERATURE_PEAK, 17062306a36Sopenharmony_ci 0x8000); 17162306a36Sopenharmony_ci if (!ret && data->id == max34446) 17262306a36Sopenharmony_ci ret = pmbus_write_word_data(client, page, 17362306a36Sopenharmony_ci MAX34446_MFR_TEMPERATURE_AVG, 0); 17462306a36Sopenharmony_ci break; 17562306a36Sopenharmony_ci default: 17662306a36Sopenharmony_ci ret = -ENODATA; 17762306a36Sopenharmony_ci break; 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci return ret; 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic int max34440_read_byte_data(struct i2c_client *client, int page, int reg) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci int ret = 0; 18562306a36Sopenharmony_ci int mfg_status; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci if (page >= 0) { 18862306a36Sopenharmony_ci ret = pmbus_set_page(client, page, 0xff); 18962306a36Sopenharmony_ci if (ret < 0) 19062306a36Sopenharmony_ci return ret; 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci switch (reg) { 19462306a36Sopenharmony_ci case PMBUS_STATUS_IOUT: 19562306a36Sopenharmony_ci mfg_status = pmbus_read_word_data(client, 0, 0xff, 19662306a36Sopenharmony_ci PMBUS_STATUS_MFR_SPECIFIC); 19762306a36Sopenharmony_ci if (mfg_status < 0) 19862306a36Sopenharmony_ci return mfg_status; 19962306a36Sopenharmony_ci if (mfg_status & MAX34440_STATUS_OC_WARN) 20062306a36Sopenharmony_ci ret |= PB_IOUT_OC_WARNING; 20162306a36Sopenharmony_ci if (mfg_status & MAX34440_STATUS_OC_FAULT) 20262306a36Sopenharmony_ci ret |= PB_IOUT_OC_FAULT; 20362306a36Sopenharmony_ci break; 20462306a36Sopenharmony_ci case PMBUS_STATUS_TEMPERATURE: 20562306a36Sopenharmony_ci mfg_status = pmbus_read_word_data(client, 0, 0xff, 20662306a36Sopenharmony_ci PMBUS_STATUS_MFR_SPECIFIC); 20762306a36Sopenharmony_ci if (mfg_status < 0) 20862306a36Sopenharmony_ci return mfg_status; 20962306a36Sopenharmony_ci if (mfg_status & MAX34440_STATUS_OT_WARN) 21062306a36Sopenharmony_ci ret |= PB_TEMP_OT_WARNING; 21162306a36Sopenharmony_ci if (mfg_status & MAX34440_STATUS_OT_FAULT) 21262306a36Sopenharmony_ci ret |= PB_TEMP_OT_FAULT; 21362306a36Sopenharmony_ci break; 21462306a36Sopenharmony_ci default: 21562306a36Sopenharmony_ci ret = -ENODATA; 21662306a36Sopenharmony_ci break; 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci return ret; 21962306a36Sopenharmony_ci} 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_cistatic int max34451_set_supported_funcs(struct i2c_client *client, 22262306a36Sopenharmony_ci struct max34440_data *data) 22362306a36Sopenharmony_ci{ 22462306a36Sopenharmony_ci /* 22562306a36Sopenharmony_ci * Each of the channel 0-15 can be configured to monitor the following 22662306a36Sopenharmony_ci * functions based on MFR_CHANNEL_CONFIG[5:0] 22762306a36Sopenharmony_ci * 0x10: Sequencing + voltage monitoring (only valid for PAGES 0–11) 22862306a36Sopenharmony_ci * 0x20: Voltage monitoring (no sequencing) 22962306a36Sopenharmony_ci * 0x21: Voltage read only 23062306a36Sopenharmony_ci * 0x22: Current monitoring 23162306a36Sopenharmony_ci * 0x23: Current read only 23262306a36Sopenharmony_ci * 0x30: General-purpose input active low 23362306a36Sopenharmony_ci * 0x34: General-purpose input active high 23462306a36Sopenharmony_ci * 0x00: Disabled 23562306a36Sopenharmony_ci */ 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci int page, rv; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci for (page = 0; page < 16; page++) { 24062306a36Sopenharmony_ci rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); 24162306a36Sopenharmony_ci if (rv < 0) 24262306a36Sopenharmony_ci return rv; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci rv = i2c_smbus_read_word_data(client, 24562306a36Sopenharmony_ci MAX34451_MFR_CHANNEL_CONFIG); 24662306a36Sopenharmony_ci if (rv < 0) 24762306a36Sopenharmony_ci return rv; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci switch (rv & MAX34451_MFR_CHANNEL_CONFIG_SEL_MASK) { 25062306a36Sopenharmony_ci case 0x10: 25162306a36Sopenharmony_ci case 0x20: 25262306a36Sopenharmony_ci data->info.func[page] = PMBUS_HAVE_VOUT | 25362306a36Sopenharmony_ci PMBUS_HAVE_STATUS_VOUT; 25462306a36Sopenharmony_ci break; 25562306a36Sopenharmony_ci case 0x21: 25662306a36Sopenharmony_ci data->info.func[page] = PMBUS_HAVE_VOUT; 25762306a36Sopenharmony_ci break; 25862306a36Sopenharmony_ci case 0x22: 25962306a36Sopenharmony_ci data->info.func[page] = PMBUS_HAVE_IOUT | 26062306a36Sopenharmony_ci PMBUS_HAVE_STATUS_IOUT; 26162306a36Sopenharmony_ci break; 26262306a36Sopenharmony_ci case 0x23: 26362306a36Sopenharmony_ci data->info.func[page] = PMBUS_HAVE_IOUT; 26462306a36Sopenharmony_ci break; 26562306a36Sopenharmony_ci default: 26662306a36Sopenharmony_ci break; 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci } 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci return 0; 27162306a36Sopenharmony_ci} 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_cistatic struct pmbus_driver_info max34440_info[] = { 27462306a36Sopenharmony_ci [max34440] = { 27562306a36Sopenharmony_ci .pages = 14, 27662306a36Sopenharmony_ci .format[PSC_VOLTAGE_IN] = direct, 27762306a36Sopenharmony_ci .format[PSC_VOLTAGE_OUT] = direct, 27862306a36Sopenharmony_ci .format[PSC_TEMPERATURE] = direct, 27962306a36Sopenharmony_ci .format[PSC_CURRENT_OUT] = direct, 28062306a36Sopenharmony_ci .m[PSC_VOLTAGE_IN] = 1, 28162306a36Sopenharmony_ci .b[PSC_VOLTAGE_IN] = 0, 28262306a36Sopenharmony_ci .R[PSC_VOLTAGE_IN] = 3, /* R = 0 in datasheet reflects mV */ 28362306a36Sopenharmony_ci .m[PSC_VOLTAGE_OUT] = 1, 28462306a36Sopenharmony_ci .b[PSC_VOLTAGE_OUT] = 0, 28562306a36Sopenharmony_ci .R[PSC_VOLTAGE_OUT] = 3, /* R = 0 in datasheet reflects mV */ 28662306a36Sopenharmony_ci .m[PSC_CURRENT_OUT] = 1, 28762306a36Sopenharmony_ci .b[PSC_CURRENT_OUT] = 0, 28862306a36Sopenharmony_ci .R[PSC_CURRENT_OUT] = 3, /* R = 0 in datasheet reflects mA */ 28962306a36Sopenharmony_ci .m[PSC_TEMPERATURE] = 1, 29062306a36Sopenharmony_ci .b[PSC_TEMPERATURE] = 0, 29162306a36Sopenharmony_ci .R[PSC_TEMPERATURE] = 2, 29262306a36Sopenharmony_ci .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 29362306a36Sopenharmony_ci | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 29462306a36Sopenharmony_ci .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 29562306a36Sopenharmony_ci | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 29662306a36Sopenharmony_ci .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 29762306a36Sopenharmony_ci | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 29862306a36Sopenharmony_ci .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 29962306a36Sopenharmony_ci | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 30062306a36Sopenharmony_ci .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 30162306a36Sopenharmony_ci | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 30262306a36Sopenharmony_ci .func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 30362306a36Sopenharmony_ci | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 30462306a36Sopenharmony_ci .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 30562306a36Sopenharmony_ci .func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 30662306a36Sopenharmony_ci .func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 30762306a36Sopenharmony_ci .func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 30862306a36Sopenharmony_ci .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 30962306a36Sopenharmony_ci .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 31062306a36Sopenharmony_ci .func[12] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 31162306a36Sopenharmony_ci .func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 31262306a36Sopenharmony_ci .read_byte_data = max34440_read_byte_data, 31362306a36Sopenharmony_ci .read_word_data = max34440_read_word_data, 31462306a36Sopenharmony_ci .write_word_data = max34440_write_word_data, 31562306a36Sopenharmony_ci }, 31662306a36Sopenharmony_ci [max34441] = { 31762306a36Sopenharmony_ci .pages = 12, 31862306a36Sopenharmony_ci .format[PSC_VOLTAGE_IN] = direct, 31962306a36Sopenharmony_ci .format[PSC_VOLTAGE_OUT] = direct, 32062306a36Sopenharmony_ci .format[PSC_TEMPERATURE] = direct, 32162306a36Sopenharmony_ci .format[PSC_CURRENT_OUT] = direct, 32262306a36Sopenharmony_ci .format[PSC_FAN] = direct, 32362306a36Sopenharmony_ci .m[PSC_VOLTAGE_IN] = 1, 32462306a36Sopenharmony_ci .b[PSC_VOLTAGE_IN] = 0, 32562306a36Sopenharmony_ci .R[PSC_VOLTAGE_IN] = 3, 32662306a36Sopenharmony_ci .m[PSC_VOLTAGE_OUT] = 1, 32762306a36Sopenharmony_ci .b[PSC_VOLTAGE_OUT] = 0, 32862306a36Sopenharmony_ci .R[PSC_VOLTAGE_OUT] = 3, 32962306a36Sopenharmony_ci .m[PSC_CURRENT_OUT] = 1, 33062306a36Sopenharmony_ci .b[PSC_CURRENT_OUT] = 0, 33162306a36Sopenharmony_ci .R[PSC_CURRENT_OUT] = 3, 33262306a36Sopenharmony_ci .m[PSC_TEMPERATURE] = 1, 33362306a36Sopenharmony_ci .b[PSC_TEMPERATURE] = 0, 33462306a36Sopenharmony_ci .R[PSC_TEMPERATURE] = 2, 33562306a36Sopenharmony_ci .m[PSC_FAN] = 1, 33662306a36Sopenharmony_ci .b[PSC_FAN] = 0, 33762306a36Sopenharmony_ci .R[PSC_FAN] = 0, 33862306a36Sopenharmony_ci .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 33962306a36Sopenharmony_ci | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 34062306a36Sopenharmony_ci .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 34162306a36Sopenharmony_ci | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 34262306a36Sopenharmony_ci .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 34362306a36Sopenharmony_ci | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 34462306a36Sopenharmony_ci .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 34562306a36Sopenharmony_ci | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 34662306a36Sopenharmony_ci .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 34762306a36Sopenharmony_ci | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 34862306a36Sopenharmony_ci .func[5] = PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12, 34962306a36Sopenharmony_ci .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 35062306a36Sopenharmony_ci .func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 35162306a36Sopenharmony_ci .func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 35262306a36Sopenharmony_ci .func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 35362306a36Sopenharmony_ci .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 35462306a36Sopenharmony_ci .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 35562306a36Sopenharmony_ci .read_byte_data = max34440_read_byte_data, 35662306a36Sopenharmony_ci .read_word_data = max34440_read_word_data, 35762306a36Sopenharmony_ci .write_word_data = max34440_write_word_data, 35862306a36Sopenharmony_ci }, 35962306a36Sopenharmony_ci [max34446] = { 36062306a36Sopenharmony_ci .pages = 7, 36162306a36Sopenharmony_ci .format[PSC_VOLTAGE_IN] = direct, 36262306a36Sopenharmony_ci .format[PSC_VOLTAGE_OUT] = direct, 36362306a36Sopenharmony_ci .format[PSC_TEMPERATURE] = direct, 36462306a36Sopenharmony_ci .format[PSC_CURRENT_OUT] = direct, 36562306a36Sopenharmony_ci .format[PSC_POWER] = direct, 36662306a36Sopenharmony_ci .m[PSC_VOLTAGE_IN] = 1, 36762306a36Sopenharmony_ci .b[PSC_VOLTAGE_IN] = 0, 36862306a36Sopenharmony_ci .R[PSC_VOLTAGE_IN] = 3, 36962306a36Sopenharmony_ci .m[PSC_VOLTAGE_OUT] = 1, 37062306a36Sopenharmony_ci .b[PSC_VOLTAGE_OUT] = 0, 37162306a36Sopenharmony_ci .R[PSC_VOLTAGE_OUT] = 3, 37262306a36Sopenharmony_ci .m[PSC_CURRENT_OUT] = 1, 37362306a36Sopenharmony_ci .b[PSC_CURRENT_OUT] = 0, 37462306a36Sopenharmony_ci .R[PSC_CURRENT_OUT] = 3, 37562306a36Sopenharmony_ci .m[PSC_POWER] = 1, 37662306a36Sopenharmony_ci .b[PSC_POWER] = 0, 37762306a36Sopenharmony_ci .R[PSC_POWER] = 3, 37862306a36Sopenharmony_ci .m[PSC_TEMPERATURE] = 1, 37962306a36Sopenharmony_ci .b[PSC_TEMPERATURE] = 0, 38062306a36Sopenharmony_ci .R[PSC_TEMPERATURE] = 2, 38162306a36Sopenharmony_ci .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 38262306a36Sopenharmony_ci | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT, 38362306a36Sopenharmony_ci .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 38462306a36Sopenharmony_ci | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 38562306a36Sopenharmony_ci .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 38662306a36Sopenharmony_ci | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT, 38762306a36Sopenharmony_ci .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT 38862306a36Sopenharmony_ci | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, 38962306a36Sopenharmony_ci .func[4] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 39062306a36Sopenharmony_ci .func[5] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 39162306a36Sopenharmony_ci .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 39262306a36Sopenharmony_ci .read_byte_data = max34440_read_byte_data, 39362306a36Sopenharmony_ci .read_word_data = max34440_read_word_data, 39462306a36Sopenharmony_ci .write_word_data = max34440_write_word_data, 39562306a36Sopenharmony_ci }, 39662306a36Sopenharmony_ci [max34451] = { 39762306a36Sopenharmony_ci .pages = 21, 39862306a36Sopenharmony_ci .format[PSC_VOLTAGE_OUT] = direct, 39962306a36Sopenharmony_ci .format[PSC_TEMPERATURE] = direct, 40062306a36Sopenharmony_ci .format[PSC_CURRENT_OUT] = direct, 40162306a36Sopenharmony_ci .m[PSC_VOLTAGE_OUT] = 1, 40262306a36Sopenharmony_ci .b[PSC_VOLTAGE_OUT] = 0, 40362306a36Sopenharmony_ci .R[PSC_VOLTAGE_OUT] = 3, 40462306a36Sopenharmony_ci .m[PSC_CURRENT_OUT] = 1, 40562306a36Sopenharmony_ci .b[PSC_CURRENT_OUT] = 0, 40662306a36Sopenharmony_ci .R[PSC_CURRENT_OUT] = 2, 40762306a36Sopenharmony_ci .m[PSC_TEMPERATURE] = 1, 40862306a36Sopenharmony_ci .b[PSC_TEMPERATURE] = 0, 40962306a36Sopenharmony_ci .R[PSC_TEMPERATURE] = 2, 41062306a36Sopenharmony_ci /* func 0-15 is set dynamically before probing */ 41162306a36Sopenharmony_ci .func[16] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 41262306a36Sopenharmony_ci .func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 41362306a36Sopenharmony_ci .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 41462306a36Sopenharmony_ci .func[19] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 41562306a36Sopenharmony_ci .func[20] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 41662306a36Sopenharmony_ci .read_word_data = max34440_read_word_data, 41762306a36Sopenharmony_ci .write_word_data = max34440_write_word_data, 41862306a36Sopenharmony_ci }, 41962306a36Sopenharmony_ci [max34460] = { 42062306a36Sopenharmony_ci .pages = 18, 42162306a36Sopenharmony_ci .format[PSC_VOLTAGE_OUT] = direct, 42262306a36Sopenharmony_ci .format[PSC_TEMPERATURE] = direct, 42362306a36Sopenharmony_ci .m[PSC_VOLTAGE_OUT] = 1, 42462306a36Sopenharmony_ci .b[PSC_VOLTAGE_OUT] = 0, 42562306a36Sopenharmony_ci .R[PSC_VOLTAGE_OUT] = 3, 42662306a36Sopenharmony_ci .m[PSC_TEMPERATURE] = 1, 42762306a36Sopenharmony_ci .b[PSC_TEMPERATURE] = 0, 42862306a36Sopenharmony_ci .R[PSC_TEMPERATURE] = 2, 42962306a36Sopenharmony_ci .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 43062306a36Sopenharmony_ci .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 43162306a36Sopenharmony_ci .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 43262306a36Sopenharmony_ci .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 43362306a36Sopenharmony_ci .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 43462306a36Sopenharmony_ci .func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 43562306a36Sopenharmony_ci .func[6] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 43662306a36Sopenharmony_ci .func[7] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 43762306a36Sopenharmony_ci .func[8] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 43862306a36Sopenharmony_ci .func[9] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 43962306a36Sopenharmony_ci .func[10] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 44062306a36Sopenharmony_ci .func[11] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 44162306a36Sopenharmony_ci .func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 44262306a36Sopenharmony_ci .func[14] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 44362306a36Sopenharmony_ci .func[15] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 44462306a36Sopenharmony_ci .func[16] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 44562306a36Sopenharmony_ci .func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 44662306a36Sopenharmony_ci .read_word_data = max34440_read_word_data, 44762306a36Sopenharmony_ci .write_word_data = max34440_write_word_data, 44862306a36Sopenharmony_ci }, 44962306a36Sopenharmony_ci [max34461] = { 45062306a36Sopenharmony_ci .pages = 23, 45162306a36Sopenharmony_ci .format[PSC_VOLTAGE_OUT] = direct, 45262306a36Sopenharmony_ci .format[PSC_TEMPERATURE] = direct, 45362306a36Sopenharmony_ci .m[PSC_VOLTAGE_OUT] = 1, 45462306a36Sopenharmony_ci .b[PSC_VOLTAGE_OUT] = 0, 45562306a36Sopenharmony_ci .R[PSC_VOLTAGE_OUT] = 3, 45662306a36Sopenharmony_ci .m[PSC_TEMPERATURE] = 1, 45762306a36Sopenharmony_ci .b[PSC_TEMPERATURE] = 0, 45862306a36Sopenharmony_ci .R[PSC_TEMPERATURE] = 2, 45962306a36Sopenharmony_ci .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 46062306a36Sopenharmony_ci .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 46162306a36Sopenharmony_ci .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 46262306a36Sopenharmony_ci .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 46362306a36Sopenharmony_ci .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 46462306a36Sopenharmony_ci .func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 46562306a36Sopenharmony_ci .func[6] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 46662306a36Sopenharmony_ci .func[7] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 46762306a36Sopenharmony_ci .func[8] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 46862306a36Sopenharmony_ci .func[9] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 46962306a36Sopenharmony_ci .func[10] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 47062306a36Sopenharmony_ci .func[11] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 47162306a36Sopenharmony_ci .func[12] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 47262306a36Sopenharmony_ci .func[13] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 47362306a36Sopenharmony_ci .func[14] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 47462306a36Sopenharmony_ci .func[15] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, 47562306a36Sopenharmony_ci /* page 16 is reserved */ 47662306a36Sopenharmony_ci .func[17] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 47762306a36Sopenharmony_ci .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 47862306a36Sopenharmony_ci .func[19] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 47962306a36Sopenharmony_ci .func[20] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 48062306a36Sopenharmony_ci .func[21] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, 48162306a36Sopenharmony_ci .read_word_data = max34440_read_word_data, 48262306a36Sopenharmony_ci .write_word_data = max34440_write_word_data, 48362306a36Sopenharmony_ci }, 48462306a36Sopenharmony_ci}; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_cistatic int max34440_probe(struct i2c_client *client) 48762306a36Sopenharmony_ci{ 48862306a36Sopenharmony_ci struct max34440_data *data; 48962306a36Sopenharmony_ci int rv; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci data = devm_kzalloc(&client->dev, sizeof(struct max34440_data), 49262306a36Sopenharmony_ci GFP_KERNEL); 49362306a36Sopenharmony_ci if (!data) 49462306a36Sopenharmony_ci return -ENOMEM; 49562306a36Sopenharmony_ci data->id = i2c_match_id(max34440_id, client)->driver_data; 49662306a36Sopenharmony_ci data->info = max34440_info[data->id]; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci if (data->id == max34451) { 49962306a36Sopenharmony_ci rv = max34451_set_supported_funcs(client, data); 50062306a36Sopenharmony_ci if (rv) 50162306a36Sopenharmony_ci return rv; 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci return pmbus_do_probe(client, &data->info); 50562306a36Sopenharmony_ci} 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_cistatic const struct i2c_device_id max34440_id[] = { 50862306a36Sopenharmony_ci {"max34440", max34440}, 50962306a36Sopenharmony_ci {"max34441", max34441}, 51062306a36Sopenharmony_ci {"max34446", max34446}, 51162306a36Sopenharmony_ci {"max34451", max34451}, 51262306a36Sopenharmony_ci {"max34460", max34460}, 51362306a36Sopenharmony_ci {"max34461", max34461}, 51462306a36Sopenharmony_ci {} 51562306a36Sopenharmony_ci}; 51662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, max34440_id); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci/* This is the driver that will be inserted */ 51962306a36Sopenharmony_cistatic struct i2c_driver max34440_driver = { 52062306a36Sopenharmony_ci .driver = { 52162306a36Sopenharmony_ci .name = "max34440", 52262306a36Sopenharmony_ci }, 52362306a36Sopenharmony_ci .probe = max34440_probe, 52462306a36Sopenharmony_ci .id_table = max34440_id, 52562306a36Sopenharmony_ci}; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_cimodule_i2c_driver(max34440_driver); 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ciMODULE_AUTHOR("Guenter Roeck"); 53062306a36Sopenharmony_ciMODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441"); 53162306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 53262306a36Sopenharmony_ciMODULE_IMPORT_NS(PMBUS); 533