/* * Firmware is sometimes not ready if we try and read the * data from the page immediately after setting. Maxim * recommends 50us delay due to the chip failing to clock * stretch long enough here.
*/ #define MAX34440_PAGE_CHANGE_DELAY 50
/* * The whole max344* family have IOUT_OC_WARN_LIMIT and IOUT_OC_FAULT_LIMIT * swapped from the standard pmbus spec addresses. * For max34451, version MAX34451ETNA6+ and later has this issue fixed.
*/ #define MAX34440_IOUT_OC_WARN_LIMIT 0x46 #define MAX34440_IOUT_OC_FAULT_LIMIT 0x4A
staticint max34440_read_word_data(struct i2c_client *client, int page, int phase, int reg)
{ int ret; conststruct pmbus_driver_info *info = pmbus_get_driver_info(client); conststruct max34440_data *data = to_max34440_data(info);
switch (reg) { case PMBUS_IOUT_OC_FAULT_LIMIT:
ret = pmbus_read_word_data(client, page, phase,
data->iout_oc_fault_limit); break; case PMBUS_IOUT_OC_WARN_LIMIT:
ret = pmbus_read_word_data(client, page, phase,
data->iout_oc_warn_limit); break; case PMBUS_VIRT_READ_VOUT_MIN:
ret = pmbus_read_word_data(client, page, phase,
MAX34440_MFR_VOUT_MIN); break; case PMBUS_VIRT_READ_VOUT_MAX:
ret = pmbus_read_word_data(client, page, phase,
MAX34440_MFR_VOUT_PEAK); break; case PMBUS_VIRT_READ_IOUT_AVG: if (data->id != max34446 && data->id != max34451 &&
data->id != adpm12160) return -ENXIO;
ret = pmbus_read_word_data(client, page, phase,
MAX34446_MFR_IOUT_AVG); break; case PMBUS_VIRT_READ_IOUT_MAX:
ret = pmbus_read_word_data(client, page, phase,
MAX34440_MFR_IOUT_PEAK); break; case PMBUS_VIRT_READ_POUT_AVG: if (data->id != max34446) return -ENXIO;
ret = pmbus_read_word_data(client, page, phase,
MAX34446_MFR_POUT_AVG); break; case PMBUS_VIRT_READ_POUT_MAX: if (data->id != max34446) return -ENXIO;
ret = pmbus_read_word_data(client, page, phase,
MAX34446_MFR_POUT_PEAK); break; case PMBUS_VIRT_READ_TEMP_AVG: if (data->id != max34446 && data->id != max34460 &&
data->id != max34461) return -ENXIO;
ret = pmbus_read_word_data(client, page, phase,
MAX34446_MFR_TEMPERATURE_AVG); break; case PMBUS_VIRT_READ_TEMP_MAX:
ret = pmbus_read_word_data(client, page, phase,
MAX34440_MFR_TEMPERATURE_PEAK); break; case PMBUS_VIRT_RESET_POUT_HISTORY: if (data->id != max34446) return -ENXIO;
ret = 0; break; case PMBUS_VIRT_RESET_VOUT_HISTORY: case PMBUS_VIRT_RESET_IOUT_HISTORY: case PMBUS_VIRT_RESET_TEMP_HISTORY:
ret = 0; break; default:
ret = -ENODATA; break;
} return ret;
}
staticint max34440_write_word_data(struct i2c_client *client, int page, int reg, u16 word)
{ conststruct pmbus_driver_info *info = pmbus_get_driver_info(client); conststruct max34440_data *data = to_max34440_data(info); int ret;
switch (reg) { case PMBUS_IOUT_OC_FAULT_LIMIT:
ret = pmbus_write_word_data(client, page, data->iout_oc_fault_limit,
word); break; case PMBUS_IOUT_OC_WARN_LIMIT:
ret = pmbus_write_word_data(client, page, data->iout_oc_warn_limit,
word); break; case PMBUS_VIRT_RESET_POUT_HISTORY:
ret = pmbus_write_word_data(client, page,
MAX34446_MFR_POUT_PEAK, 0); if (ret) break;
ret = pmbus_write_word_data(client, page,
MAX34446_MFR_POUT_AVG, 0); break; case PMBUS_VIRT_RESET_VOUT_HISTORY:
ret = pmbus_write_word_data(client, page,
MAX34440_MFR_VOUT_MIN, 0x7fff); if (ret) break;
ret = pmbus_write_word_data(client, page,
MAX34440_MFR_VOUT_PEAK, 0); break; case PMBUS_VIRT_RESET_IOUT_HISTORY:
ret = pmbus_write_word_data(client, page,
MAX34440_MFR_IOUT_PEAK, 0); if (!ret && (data->id == max34446 || data->id == max34451 ||
data->id == adpm12160))
ret = pmbus_write_word_data(client, page,
MAX34446_MFR_IOUT_AVG, 0);
break; case PMBUS_VIRT_RESET_TEMP_HISTORY:
ret = pmbus_write_word_data(client, page,
MAX34440_MFR_TEMPERATURE_PEAK,
0x8000); if (!ret && data->id == max34446)
ret = pmbus_write_word_data(client, page,
MAX34446_MFR_TEMPERATURE_AVG, 0); break; default:
ret = -ENODATA; break;
} return ret;
}
staticint max34440_read_byte_data(struct i2c_client *client, int page, int reg)
{ int ret = 0; int mfg_status;
if (page >= 0) {
ret = pmbus_set_page(client, page, 0xff); if (ret < 0) return ret;
}
switch (reg) { case PMBUS_STATUS_IOUT:
mfg_status = pmbus_read_word_data(client, 0, 0xff,
PMBUS_STATUS_MFR_SPECIFIC); if (mfg_status < 0) return mfg_status; if (mfg_status & MAX34440_STATUS_OC_WARN)
ret |= PB_IOUT_OC_WARNING; if (mfg_status & MAX34440_STATUS_OC_FAULT)
ret |= PB_IOUT_OC_FAULT; break; case PMBUS_STATUS_TEMPERATURE:
mfg_status = pmbus_read_word_data(client, 0, 0xff,
PMBUS_STATUS_MFR_SPECIFIC); if (mfg_status < 0) return mfg_status; if (mfg_status & MAX34440_STATUS_OT_WARN)
ret |= PB_TEMP_OT_WARNING; if (mfg_status & MAX34440_STATUS_OT_FAULT)
ret |= PB_TEMP_OT_FAULT; break; default:
ret = -ENODATA; break;
} return ret;
}
staticint max34451_set_supported_funcs(struct i2c_client *client, struct max34440_data *data)
{ /* * Each of the channel 0-15 can be configured to monitor the following * functions based on MFR_CHANNEL_CONFIG[5:0] * 0x10: Sequencing + voltage monitoring (only valid for PAGES 0–11) * 0x20: Voltage monitoring (no sequencing) * 0x21: Voltage read only * 0x22: Current monitoring * 0x23: Current read only * 0x30: General-purpose input active low * 0x34: General-purpose input active high * 0x00: Disabled
*/
int page, rv; bool max34451_na6 = false;
rv = i2c_smbus_read_word_data(client, PMBUS_MFR_REVISION); if (rv < 0) return rv;
/* This is the driver that will be inserted */ staticstruct i2c_driver max34440_driver = {
.driver = {
.name = "max34440",
},
.probe = max34440_probe,
.id_table = max34440_id,
};
module_i2c_driver(max34440_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS("PMBUS");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.