static int axp20x_regulator_probe(struct platform_device *pdev) { struct regulator_dev *rdev; struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); struct regulator_config config = { }; struct regulator_init_data *init_data; int ret, i; u32 workmode; ret = axp20x_regulator_parse_dt(pdev); if (ret) return ret; for (i = 0; i < AXP20X_REG_ID_MAX; i++) { init_data = axp20x_matches[i].init_data; config.dev = pdev->dev.parent; config.init_data = init_data; config.regmap = axp20x->regmap; config.of_node = axp20x_matches[i].of_node; rdev = devm_regulator_register(&pdev->dev, &axp20x_regulators[i], &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "Failed to register %s\n", axp20x_regulators[i].name); return PTR_ERR(rdev); } ret = of_property_read_u32(axp20x_matches[i].of_node, "x-powers,dcdc-workmode", &workmode); if (!ret) { if (axp20x_set_dcdc_workmode(rdev, i, workmode)) dev_err(&pdev->dev, "Failed to set workmode on %s\n", axp20x_regulators[i].name); } } return 0; }
static int axp20x_regulator_probe(struct platform_device *pdev) { struct regulator_dev *rdev; struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); const struct regulator_desc *regulators; struct regulator_config config = { .dev = pdev->dev.parent, .regmap = axp20x->regmap, .driver_data = axp20x, }; int ret, i, nregulators; u32 workmode; switch (axp20x->variant) { case AXP202_ID: case AXP209_ID: regulators = axp20x_regulators; nregulators = AXP20X_REG_ID_MAX; break; case AXP221_ID: regulators = axp22x_regulators; nregulators = AXP22X_REG_ID_MAX; break; default: dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n", axp20x->variant); return -EINVAL; } /* This only sets the dcdc freq. Ignore any errors */ axp20x_regulator_parse_dt(pdev); for (i = 0; i < nregulators; i++) { rdev = devm_regulator_register(&pdev->dev, ®ulators[i], &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "Failed to register %s\n", regulators[i].name); return PTR_ERR(rdev); } ret = of_property_read_u32(rdev->dev.of_node, "x-powers,dcdc-workmode", &workmode); if (!ret) { if (axp20x_set_dcdc_workmode(rdev, i, workmode)) dev_err(&pdev->dev, "Failed to set workmode on %s\n", rdev->desc->name); } } return 0; } static struct platform_driver axp20x_regulator_driver = { .probe = axp20x_regulator_probe, .driver = { .name = "axp20x-regulator", }, }; module_platform_driver(axp20x_regulator_driver); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Carlo Caione <*****@*****.**>"); MODULE_DESCRIPTION("Regulator Driver for AXP20X PMIC"); MODULE_ALIAS("platform:axp20x-regulator");
static int axp20x_regulator_probe(struct platform_device *pdev) { struct regulator_dev *rdev; struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); const struct regulator_desc *regulators; struct regulator_config config = { .dev = pdev->dev.parent, .regmap = axp20x->regmap, .driver_data = axp20x, }; int ret, i, nregulators; u32 workmode; const char *dcdc1_name = axp22x_regulators[AXP22X_DCDC1].name; const char *dcdc5_name = axp22x_regulators[AXP22X_DCDC5].name; bool drivevbus = false; switch (axp20x->variant) { case AXP202_ID: case AXP209_ID: regulators = axp20x_regulators; nregulators = AXP20X_REG_ID_MAX; break; case AXP221_ID: case AXP223_ID: regulators = axp22x_regulators; nregulators = AXP22X_REG_ID_MAX; drivevbus = of_property_read_bool(pdev->dev.parent->of_node, "x-powers,drive-vbus-en"); break; case AXP809_ID: regulators = axp809_regulators; nregulators = AXP809_REG_ID_MAX; break; default: dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n", axp20x->variant); return -EINVAL; } /* This only sets the dcdc freq. Ignore any errors */ axp20x_regulator_parse_dt(pdev); for (i = 0; i < nregulators; i++) { const struct regulator_desc *desc = ®ulators[i]; struct regulator_desc *new_desc; /* * Regulators DC1SW and DC5LDO are connected internally, * so we have to handle their supply names separately. * * We always register the regulators in proper sequence, * so the supply names are correctly read. See the last * part of this loop to see where we save the DT defined * name. */ if ((regulators == axp22x_regulators && i == AXP22X_DC1SW) || (regulators == axp809_regulators && i == AXP809_DC1SW)) { new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL); *new_desc = regulators[i]; new_desc->supply_name = dcdc1_name; desc = new_desc; } if ((regulators == axp22x_regulators && i == AXP22X_DC5LDO) || (regulators == axp809_regulators && i == AXP809_DC5LDO)) { new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL); *new_desc = regulators[i]; new_desc->supply_name = dcdc5_name; desc = new_desc; } rdev = devm_regulator_register(&pdev->dev, desc, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "Failed to register %s\n", regulators[i].name); return PTR_ERR(rdev); } ret = of_property_read_u32(rdev->dev.of_node, "x-powers,dcdc-workmode", &workmode); if (!ret) { if (axp20x_set_dcdc_workmode(rdev, i, workmode)) dev_err(&pdev->dev, "Failed to set workmode on %s\n", rdev->desc->name); } /* * Save AXP22X DCDC1 / DCDC5 regulator names for later. */ if ((regulators == axp22x_regulators && i == AXP22X_DCDC1) || (regulators == axp809_regulators && i == AXP809_DCDC1)) of_property_read_string(rdev->dev.of_node, "regulator-name", &dcdc1_name); if ((regulators == axp22x_regulators && i == AXP22X_DCDC5) || (regulators == axp809_regulators && i == AXP809_DCDC5)) of_property_read_string(rdev->dev.of_node, "regulator-name", &dcdc5_name); } if (drivevbus) { /* Change N_VBUSEN sense pin to DRIVEVBUS output pin */ regmap_update_bits(axp20x->regmap, AXP20X_OVER_TMP, AXP22X_MISC_N_VBUSEN_FUNC, 0); rdev = devm_regulator_register(&pdev->dev, &axp22x_drivevbus_regulator, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "Failed to register drivevbus\n"); return PTR_ERR(rdev); } } return 0; } static struct platform_driver axp20x_regulator_driver = { .probe = axp20x_regulator_probe, .driver = { .name = "axp20x-regulator", }, }; module_platform_driver(axp20x_regulator_driver); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Carlo Caione <*****@*****.**>"); MODULE_DESCRIPTION("Regulator Driver for AXP20X PMIC"); MODULE_ALIAS("platform:axp20x-regulator");