in rockchip/io-domain.c [551:668]
static int rockchip_iodomain_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
const struct of_device_id *match;
struct rockchip_iodomain *iod;
struct device *parent;
int i, ret = 0;
if (!np)
return -ENODEV;
iod = devm_kzalloc(&pdev->dev, sizeof(*iod), GFP_KERNEL);
if (!iod)
return -ENOMEM;
iod->dev = &pdev->dev;
platform_set_drvdata(pdev, iod);
match = of_match_node(rockchip_iodomain_match, np);
iod->soc_data = match->data;
if (iod->soc_data->write)
iod->write = iod->soc_data->write;
else
iod->write = rockchip_iodomain_write;
parent = pdev->dev.parent;
if (parent && parent->of_node) {
iod->grf = syscon_node_to_regmap(parent->of_node);
} else {
dev_dbg(&pdev->dev, "falling back to old binding\n");
iod->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
}
if (IS_ERR(iod->grf)) {
dev_err(&pdev->dev, "couldn't find grf regmap\n");
return PTR_ERR(iod->grf);
}
for (i = 0; i < MAX_SUPPLIES; i++) {
const char *supply_name = iod->soc_data->supply_names[i];
struct rockchip_iodomain_supply *supply = &iod->supplies[i];
struct regulator *reg;
int uV;
if (!supply_name)
continue;
reg = devm_regulator_get_optional(iod->dev, supply_name);
if (IS_ERR(reg)) {
ret = PTR_ERR(reg);
/* If a supply wasn't specified, that's OK */
if (ret == -ENODEV)
continue;
else if (ret != -EPROBE_DEFER)
dev_err(iod->dev, "couldn't get regulator %s\n",
supply_name);
goto unreg_notify;
}
/* set initial correct value */
uV = regulator_get_voltage(reg);
/* must be a regulator we can get the voltage of */
if (uV < 0) {
dev_err(iod->dev, "Can't determine voltage: %s\n",
supply_name);
ret = uV;
goto unreg_notify;
}
if (uV > MAX_VOLTAGE_3_3) {
dev_crit(iod->dev,
"%d uV is too high. May damage SoC!\n",
uV);
ret = -EINVAL;
goto unreg_notify;
}
/* setup our supply */
supply->idx = i;
supply->iod = iod;
supply->reg = reg;
supply->nb.notifier_call = rockchip_iodomain_notify;
ret = iod->write(supply, uV);
if (ret) {
supply->reg = NULL;
goto unreg_notify;
}
/* register regulator notifier */
ret = regulator_register_notifier(reg, &supply->nb);
if (ret) {
dev_err(&pdev->dev,
"regulator notifier request failed\n");
supply->reg = NULL;
goto unreg_notify;
}
}
if (iod->soc_data->init)
iod->soc_data->init(iod);
return 0;
unreg_notify:
for (i = MAX_SUPPLIES - 1; i >= 0; i--) {
struct rockchip_iodomain_supply *io_supply = &iod->supplies[i];
if (io_supply->reg)
regulator_unregister_notifier(io_supply->reg,
&io_supply->nb);
}
return ret;
}