Skip to content

Commit 14e2976

Browse files
Konrad Dybciobroonie
authored andcommitted
regulator: qcom_smd: Align probe function with rpmh-regulator
The RPMh regulator driver is much newer and gets more attention, which in consequence makes it do a few things better. Update qcom_smd-regulator's probe function to mimic what rpmh-regulator does to address a couple of issues: - Probe defer now works correctly, before it used to, well, kinda just die.. This fixes reliable probing on (at least) PM8994, because Linux apparently cannot deal with supply map dependencies yet.. - Regulator data is now matched more sanely: regulator data is matched against each individual regulator node name and throwing an -EINVAL if data is missing, instead of just assuming everything is fine and iterating over all subsequent array members. - status = "disabled" will now work for disabling individual regulators in DT. Previously it didn't seem to do much if anything at all. Signed-off-by: Konrad Dybcio <konrad.dybcio@somainline.org> Link: https://lore.kernel.org/r/20211230023442.1123424-1-konrad.dybcio@somainline.org Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 1f156b4 commit 14e2976

File tree

1 file changed

+70
-30
lines changed

1 file changed

+70
-30
lines changed

drivers/regulator/qcom_smd-regulator.c

Lines changed: 70 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/of_device.h>
1010
#include <linux/platform_device.h>
1111
#include <linux/regulator/driver.h>
12+
#include <linux/regulator/of_regulator.h>
1213
#include <linux/soc/qcom/smd-rpm.h>
1314

1415
struct qcom_rpm_reg {
@@ -1239,52 +1240,91 @@ static const struct of_device_id rpm_of_match[] = {
12391240
};
12401241
MODULE_DEVICE_TABLE(of, rpm_of_match);
12411242

1242-
static int rpm_reg_probe(struct platform_device *pdev)
1243+
/**
1244+
* rpm_regulator_init_vreg() - initialize all attributes of a qcom_smd-regulator
1245+
* @vreg: Pointer to the individual qcom_smd-regulator resource
1246+
* @dev: Pointer to the top level qcom_smd-regulator PMIC device
1247+
* @node: Pointer to the individual qcom_smd-regulator resource
1248+
* device node
1249+
* @rpm: Pointer to the rpm bus node
1250+
* @pmic_rpm_data: Pointer to a null-terminated array of qcom_smd-regulator
1251+
* resources defined for the top level PMIC device
1252+
*
1253+
* Return: 0 on success, errno on failure
1254+
*/
1255+
static int rpm_regulator_init_vreg(struct qcom_rpm_reg *vreg, struct device *dev,
1256+
struct device_node *node, struct qcom_smd_rpm *rpm,
1257+
const struct rpm_regulator_data *pmic_rpm_data)
12431258
{
1244-
const struct rpm_regulator_data *reg;
1245-
const struct of_device_id *match;
1246-
struct regulator_config config = { };
1259+
struct regulator_config config = {};
1260+
const struct rpm_regulator_data *rpm_data;
12471261
struct regulator_dev *rdev;
1262+
int ret;
1263+
1264+
for (rpm_data = pmic_rpm_data; rpm_data->name; rpm_data++)
1265+
if (of_node_name_eq(node, rpm_data->name))
1266+
break;
1267+
1268+
if (!rpm_data->name) {
1269+
dev_err(dev, "Unknown regulator %pOFn\n", node);
1270+
return -EINVAL;
1271+
}
1272+
1273+
vreg->dev = dev;
1274+
vreg->rpm = rpm;
1275+
vreg->type = rpm_data->type;
1276+
vreg->id = rpm_data->id;
1277+
1278+
memcpy(&vreg->desc, rpm_data->desc, sizeof(vreg->desc));
1279+
vreg->desc.name = rpm_data->name;
1280+
vreg->desc.supply_name = rpm_data->supply;
1281+
vreg->desc.owner = THIS_MODULE;
1282+
vreg->desc.type = REGULATOR_VOLTAGE;
1283+
vreg->desc.of_match = rpm_data->name;
1284+
1285+
config.dev = dev;
1286+
config.of_node = node;
1287+
config.driver_data = vreg;
1288+
1289+
rdev = devm_regulator_register(dev, &vreg->desc, &config);
1290+
if (IS_ERR(rdev)) {
1291+
ret = PTR_ERR(rdev);
1292+
dev_err(dev, "%pOFn: devm_regulator_register() failed, ret=%d\n", node, ret);
1293+
return ret;
1294+
}
1295+
1296+
return 0;
1297+
}
1298+
1299+
static int rpm_reg_probe(struct platform_device *pdev)
1300+
{
1301+
struct device *dev = &pdev->dev;
1302+
const struct rpm_regulator_data *vreg_data;
1303+
struct device_node *node;
12481304
struct qcom_rpm_reg *vreg;
12491305
struct qcom_smd_rpm *rpm;
1306+
int ret;
12501307

12511308
rpm = dev_get_drvdata(pdev->dev.parent);
12521309
if (!rpm) {
1253-
dev_err(&pdev->dev, "unable to retrieve handle to rpm\n");
1310+
dev_err(&pdev->dev, "Unable to retrieve handle to rpm\n");
12541311
return -ENODEV;
12551312
}
12561313

1257-
match = of_match_device(rpm_of_match, &pdev->dev);
1258-
if (!match) {
1259-
dev_err(&pdev->dev, "failed to match device\n");
1314+
vreg_data = of_device_get_match_data(dev);
1315+
if (!vreg_data)
12601316
return -ENODEV;
1261-
}
12621317

1263-
for (reg = match->data; reg->name; reg++) {
1318+
for_each_available_child_of_node(dev->of_node, node) {
12641319
vreg = devm_kzalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
12651320
if (!vreg)
12661321
return -ENOMEM;
12671322

1268-
vreg->dev = &pdev->dev;
1269-
vreg->type = reg->type;
1270-
vreg->id = reg->id;
1271-
vreg->rpm = rpm;
1272-
1273-
memcpy(&vreg->desc, reg->desc, sizeof(vreg->desc));
1274-
1275-
vreg->desc.id = -1;
1276-
vreg->desc.owner = THIS_MODULE;
1277-
vreg->desc.type = REGULATOR_VOLTAGE;
1278-
vreg->desc.name = reg->name;
1279-
vreg->desc.supply_name = reg->supply;
1280-
vreg->desc.of_match = reg->name;
1281-
1282-
config.dev = &pdev->dev;
1283-
config.driver_data = vreg;
1284-
rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config);
1285-
if (IS_ERR(rdev)) {
1286-
dev_err(&pdev->dev, "failed to register %s\n", reg->name);
1287-
return PTR_ERR(rdev);
1323+
ret = rpm_regulator_init_vreg(vreg, dev, node, rpm, vreg_data);
1324+
1325+
if (ret < 0) {
1326+
of_node_put(node);
1327+
return ret;
12881328
}
12891329
}
12901330

0 commit comments

Comments
 (0)