// SPDX-License-Identifier: GPL-2.0 /* * Hardware monitoring driver for Maxim MAX16508, MAX16600, MAX16601, * and MAX16602. * * Implementation notes: * * This chip series supports two rails, VCORE and VSA. Telemetry information * for the two rails is reported in two subsequent I2C addresses. The driver * instantiates a dummy I2C client at the second I2C address to report * information for the VSA rail in a single instance of the driver. * Telemetry for the VSA rail is reported to the PMBus core in PMBus page 2. * * The chip reports input current using two separate methods. The input current * reported with the standard READ_IIN command is derived from the output * current. The first method is reported to the PMBus core with PMBus page 0, * the second method is reported with PMBus page 1. * * The chip supports reading per-phase temperatures and per-phase input/output * currents for VCORE. Telemetry is reported in vendor specific registers. * The driver translates the vendor specific register values to PMBus standard * register values and reports per-phase information in PMBus page 0. * * Copyright 2019, 2020 Google LLC.
*/
switch (page) { case 0: /* VCORE */ return -ENODATA; case 1: /* VCORE IIN/PIN from sensor element */ default: return -EOPNOTSUPP; case 2: /* VSA */ switch (reg) { case PMBUS_VIRT_RESET_IOUT_HISTORY:
data->iout_avg_pkg = 0xfc00; return 0; case PMBUS_IOUT_OC_FAULT_LIMIT: case PMBUS_IOUT_OC_WARN_LIMIT: case PMBUS_OT_FAULT_LIMIT: case PMBUS_OT_WARN_LIMIT: return i2c_smbus_write_word_data(data->vsa, reg, value); default: return -EOPNOTSUPP;
}
}
}
reg = i2c_smbus_read_byte_data(client, REG_DEFAULT_NUM_POP); if (reg < 0) return reg;
/* * If REG_DEFAULT_NUM_POP returns 0, we don't know how many phases * are populated. Stick with the default in that case.
*/
reg &= 0x0f; if (reg && reg <= MAX16601_NUM_PHASES)
info->phases[0] = reg;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_BYTE_DATA |
I2C_FUNC_SMBUS_READ_BLOCK_DATA)) return -ENODEV;
chip_id = max16601_get_id(client); if (chip_id < 0) return chip_id;
id = i2c_match_id(max16601_id, client); if (chip_id != id->driver_data)
dev_warn(&client->dev, "Device mismatch: Configured %s (%d), detected %d\n",
id->name, (int) id->driver_data, chip_id);
ret = i2c_smbus_read_byte_data(client, REG_PHASE_ID); if (ret < 0) return ret; if (!(ret & CORE_RAIL_INDICATOR)) {
dev_err(dev, "Driver must be instantiated on CORE rail I2C address\n"); return -ENODEV;
}
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM;
data->id = chip_id;
data->iout_avg_pkg = 0xfc00;
data->vsa = i2c_new_dummy_device(client->adapter, client->addr + 1); if (IS_ERR(data->vsa)) {
dev_err(dev, "Failed to register VSA client\n"); return PTR_ERR(data->vsa);
}
ret = devm_add_action_or_reset(dev, max16601_remove, data); if (ret) return ret;
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.