/* * A PMIC can be represented by multiple SPMI devices, but * only the base PMIC device will contain a reference to * the revision information. * * This function takes a pointer to a pmic device and * returns a pointer to the base PMIC device. * * This only supports PMICs with 1 or 2 USIDs.
*/ staticstruct spmi_device *qcom_pmic_get_base_usid(struct spmi_device *sdev, struct qcom_spmi_dev *ctx)
{ struct device_node *spmi_bus; int function_parent_usid, ret;
u32 pmic_addr;
/* * Quick return if the function device is already in the base * USID. This will always be hit for PMICs with only 1 USID.
*/ if (sdev->usid % ctx->num_usids == 0) {
get_device(&sdev->dev); return sdev;
}
function_parent_usid = sdev->usid;
/* * Walk through the list of PMICs until we find the sibling USID. * The goal is to find the first USID which is less than the * number of USIDs in the PMIC array, e.g. for a PMIC with 2 USIDs * where the function device is under USID 3, we want to find the * device for USID 2.
*/
spmi_bus = of_get_parent(sdev->dev.of_node);
sdev = ERR_PTR(-ENODATA);
for_each_child_of_node_scoped(spmi_bus, child) {
ret = of_property_read_u32_index(child, "reg", 0, &pmic_addr); if (ret) {
sdev = ERR_PTR(ret); break;
}
if (pmic_addr == function_parent_usid - (ctx->num_usids - 1)) {
sdev = spmi_find_device_by_of_node(child); if (!sdev) { /* * If the base USID for this PMIC hasn't been * registered yet then we need to defer.
*/
sdev = ERR_PTR(-EPROBE_DEFER);
} break;
}
}
of_node_put(spmi_bus);
return sdev;
}
staticint pmic_spmi_get_base_revid(struct spmi_device *sdev, struct qcom_spmi_dev *ctx)
{ struct qcom_spmi_dev *base_ctx; struct spmi_device *base; int ret = 0;
base = qcom_pmic_get_base_usid(sdev, ctx); if (IS_ERR(base)) return PTR_ERR(base);
/* * Copy revid info from base device if it has probed and is still * bound to its driver.
*/
mutex_lock(&pmic_spmi_revid_lock);
base_ctx = spmi_device_get_drvdata(base); if (!base_ctx) {
ret = -EPROBE_DEFER; goto out_unlock;
}
memcpy(&ctx->pmic, &base_ctx->pmic, sizeof(ctx->pmic));
out_unlock:
mutex_unlock(&pmic_spmi_revid_lock);
ret = regmap_read(map, PMIC_REV2, &pmic->rev2); if (ret < 0) return ret;
ret = regmap_read(map, PMIC_REV3, &pmic->minor); if (ret < 0) return ret;
ret = regmap_read(map, PMIC_REV4, &pmic->major); if (ret < 0) return ret;
if (pmic->subtype == PMI8998_SUBTYPE || pmic->subtype == PM660_SUBTYPE) {
ret = regmap_read(map, PMIC_FAB_ID, &pmic->fab_id); if (ret < 0) return ret;
}
/* * In early versions of PM8941 and PM8226, the major revision number * started incrementing from 0 (eg 0 = v1.0, 1 = v2.0). * Increment the major revision number here if the chip is an early * version of PM8941 or PM8226.
*/ if ((pmic->subtype == PM8941_SUBTYPE || pmic->subtype == PM8226_SUBTYPE) &&
pmic->major < PMIC_REV4_V2)
pmic->major++;
if (pmic->subtype == PM8110_SUBTYPE)
pmic->minor = pmic->rev2;
/** * qcom_pmic_get() - Get a pointer to the base PMIC device * * This function takes a struct device for a driver which is a child of a PMIC. * And locates the PMIC revision information for it. * * @dev: the pmic function device * @return: the struct qcom_spmi_pmic* pointer associated with the function device
*/ conststruct qcom_spmi_pmic *qcom_pmic_get(struct device *dev)
{ struct spmi_device *sdev; struct qcom_spmi_dev *spmi;
/* * Make sure the device is actually a child of a PMIC
*/ if (!of_match_device(pmic_spmi_id_table, dev->parent)) return ERR_PTR(-EINVAL);
/* Only the first slave id for a PMIC contains this information */ if (sdev->usid % ctx->num_usids == 0) {
ret = pmic_spmi_load_revid(regmap, &sdev->dev, &ctx->pmic); if (ret < 0) return ret;
} else {
ret = pmic_spmi_get_base_revid(sdev, ctx); 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.