// SPDX-License-Identifier: GPL-2.0-only #include #include #include #include #include #include static const struct regmap_config pm886_regulator_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = PM886_REG_BUCK5_VOUT, }; static const struct regulator_ops pm886_ldo_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_iterate, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, }; static const struct regulator_ops pm886_buck_ops = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, }; static const unsigned int pm886_ldo_volt_table1[] = { 1700000, 1800000, 1900000, 2500000, 2800000, 2900000, 3100000, 3300000, }; static const unsigned int pm886_ldo_volt_table2[] = { 1200000, 1250000, 1700000, 1800000, 1850000, 1900000, 2500000, 2600000, 2700000, 2750000, 2800000, 2850000, 2900000, 3000000, 3100000, 3300000, }; static const unsigned int pm886_ldo_volt_table3[] = { 1700000, 1800000, 1900000, 2000000, 2100000, 2500000, 2700000, 2800000, }; static const struct linear_range pm886_buck_volt_ranges1[] = { REGULATOR_LINEAR_RANGE(600000, 0, 79, 12500), REGULATOR_LINEAR_RANGE(1600000, 80, 84, 50000), }; static const struct linear_range pm886_buck_volt_ranges2[] = { REGULATOR_LINEAR_RANGE(600000, 0, 79, 12500), REGULATOR_LINEAR_RANGE(1600000, 80, 114, 50000), }; static struct regulator_desc pm886_regulators[] = { { .name = "LDO1", .regulators_node = "regulators", .of_match = "ldo1", .ops = &pm886_ldo_ops, .type = REGULATOR_VOLTAGE, .enable_reg = PM886_REG_LDO_EN1, .enable_mask = BIT(0), .volt_table = pm886_ldo_volt_table1, .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table1), .vsel_reg = PM886_REG_LDO1_VOUT, .vsel_mask = PM886_LDO_VSEL_MASK, }, { .name = "LDO2", .regulators_node = "regulators", .of_match = "ldo2", .ops = &pm886_ldo_ops, .type = REGULATOR_VOLTAGE, .enable_reg = PM886_REG_LDO_EN1, .enable_mask = BIT(1), .volt_table = pm886_ldo_volt_table1, .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table1), .vsel_reg = PM886_REG_LDO2_VOUT, .vsel_mask = PM886_LDO_VSEL_MASK, }, { .name = "LDO3", .regulators_node = "regulators", .of_match = "ldo3", .ops = &pm886_ldo_ops, .type = REGULATOR_VOLTAGE, .enable_reg = PM886_REG_LDO_EN1, .enable_mask = BIT(2), .volt_table = pm886_ldo_volt_table1, .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table1), .vsel_reg = PM886_REG_LDO3_VOUT, .vsel_mask = PM886_LDO_VSEL_MASK, }, { .name = "LDO4", .regulators_node = "regulators", .of_match = "ldo4", .ops = &pm886_ldo_ops, .type = REGULATOR_VOLTAGE, .enable_reg = PM886_REG_LDO_EN1, .enable_mask = BIT(3), .volt_table = pm886_ldo_volt_table2, .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2), .vsel_reg = PM886_REG_LDO4_VOUT, .vsel_mask = PM886_LDO_VSEL_MASK, }, { .name = "LDO5", .regulators_node = "regulators", .of_match = "ldo5", .ops = &pm886_ldo_ops, .type = REGULATOR_VOLTAGE, .enable_reg = PM886_REG_LDO_EN1, .enable_mask = BIT(4), .volt_table = pm886_ldo_volt_table2, .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2), .vsel_reg = PM886_REG_LDO5_VOUT, .vsel_mask = PM886_LDO_VSEL_MASK, }, { .name = "LDO6", .regulators_node = "regulators", .of_match = "ldo6", .ops = &pm886_ldo_ops, .type = REGULATOR_VOLTAGE, .enable_reg = PM886_REG_LDO_EN1, .enable_mask = BIT(5), .volt_table = pm886_ldo_volt_table2, .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2), .vsel_reg = PM886_REG_LDO6_VOUT, .vsel_mask = PM886_LDO_VSEL_MASK, }, { .name = "LDO7", .regulators_node = "regulators", .of_match = "ldo7", .ops = &pm886_ldo_ops, .type = REGULATOR_VOLTAGE, .enable_reg = PM886_REG_LDO_EN1, .enable_mask = BIT(6), .volt_table = pm886_ldo_volt_table2, .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2), .vsel_reg = PM886_REG_LDO7_VOUT, .vsel_mask = PM886_LDO_VSEL_MASK, }, { .name = "LDO8", .regulators_node = "regulators", .of_match = "ldo8", .ops = &pm886_ldo_ops, .type = REGULATOR_VOLTAGE, .enable_reg = PM886_REG_LDO_EN1, .enable_mask = BIT(7), .volt_table = pm886_ldo_volt_table2, .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2), .vsel_reg = PM886_REG_LDO8_VOUT, .vsel_mask = PM886_LDO_VSEL_MASK, }, { .name = "LDO9", .regulators_node = "regulators", .of_match = "ldo9", .ops = &pm886_ldo_ops, .type = REGULATOR_VOLTAGE, .enable_reg = PM886_REG_LDO_EN2, .enable_mask = BIT(0), .volt_table = pm886_ldo_volt_table2, .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2), .vsel_reg = PM886_REG_LDO9_VOUT, .vsel_mask = PM886_LDO_VSEL_MASK, }, { .name = "LDO10", .regulators_node = "regulators", .of_match = "ldo10", .ops = &pm886_ldo_ops, .type = REGULATOR_VOLTAGE, .enable_reg = PM886_REG_LDO_EN2, .enable_mask = BIT(1), .volt_table = pm886_ldo_volt_table2, .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2), .vsel_reg = PM886_REG_LDO10_VOUT, .vsel_mask = PM886_LDO_VSEL_MASK, }, { .name = "LDO11", .regulators_node = "regulators", .of_match = "ldo11", .ops = &pm886_ldo_ops, .type = REGULATOR_VOLTAGE, .enable_reg = PM886_REG_LDO_EN2, .enable_mask = BIT(2), .volt_table = pm886_ldo_volt_table2, .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2), .vsel_reg = PM886_REG_LDO11_VOUT, .vsel_mask = PM886_LDO_VSEL_MASK, }, { .name = "LDO12", .regulators_node = "regulators", .of_match = "ldo12", .ops = &pm886_ldo_ops, .type = REGULATOR_VOLTAGE, .enable_reg = PM886_REG_LDO_EN2, .enable_mask = BIT(3), .volt_table = pm886_ldo_volt_table2, .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2), .vsel_reg = PM886_REG_LDO12_VOUT, .vsel_mask = PM886_LDO_VSEL_MASK, }, { .name = "LDO13", .regulators_node = "regulators", .of_match = "ldo13", .ops = &pm886_ldo_ops, .type = REGULATOR_VOLTAGE, .enable_reg = PM886_REG_LDO_EN2, .enable_mask = BIT(4), .volt_table = pm886_ldo_volt_table2, .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2), .vsel_reg = PM886_REG_LDO13_VOUT, .vsel_mask = PM886_LDO_VSEL_MASK, }, { .name = "LDO14", .regulators_node = "regulators", .of_match = "ldo14", .ops = &pm886_ldo_ops, .type = REGULATOR_VOLTAGE, .enable_reg = PM886_REG_LDO_EN2, .enable_mask = BIT(5), .volt_table = pm886_ldo_volt_table2, .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2), .vsel_reg = PM886_REG_LDO14_VOUT, .vsel_mask = PM886_LDO_VSEL_MASK, }, { .name = "LDO15", .regulators_node = "regulators", .of_match = "ldo15", .ops = &pm886_ldo_ops, .type = REGULATOR_VOLTAGE, .enable_reg = PM886_REG_LDO_EN2, .enable_mask = BIT(6), .volt_table = pm886_ldo_volt_table2, .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table2), .vsel_reg = PM886_REG_LDO15_VOUT, .vsel_mask = PM886_LDO_VSEL_MASK, }, { .name = "LDO16", .regulators_node = "regulators", .of_match = "ldo16", .ops = &pm886_ldo_ops, .type = REGULATOR_VOLTAGE, .enable_reg = PM886_REG_LDO_EN2, .enable_mask = BIT(7), .volt_table = pm886_ldo_volt_table3, .n_voltages = ARRAY_SIZE(pm886_ldo_volt_table3), .vsel_reg = PM886_REG_LDO16_VOUT, .vsel_mask = PM886_LDO_VSEL_MASK, }, { .name = "buck1", .regulators_node = "regulators", .of_match = "buck1", .ops = &pm886_buck_ops, .type = REGULATOR_VOLTAGE, .n_voltages = 85, .linear_ranges = pm886_buck_volt_ranges1, .n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges1), .vsel_reg = PM886_REG_BUCK1_VOUT, .vsel_mask = PM886_BUCK_VSEL_MASK, .enable_reg = PM886_REG_BUCK_EN, .enable_mask = BIT(0), }, { .name = "buck2", .regulators_node = "regulators", .of_match = "buck2", .ops = &pm886_buck_ops, .type = REGULATOR_VOLTAGE, .n_voltages = 115, .linear_ranges = pm886_buck_volt_ranges2, .n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges2), .vsel_reg = PM886_REG_BUCK2_VOUT, .vsel_mask = PM886_BUCK_VSEL_MASK, .enable_reg = PM886_REG_BUCK_EN, .enable_mask = BIT(1), }, { .name = "buck3", .regulators_node = "regulators", .of_match = "buck3", .ops = &pm886_buck_ops, .type = REGULATOR_VOLTAGE, .n_voltages = 115, .linear_ranges = pm886_buck_volt_ranges2, .n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges2), .vsel_reg = PM886_REG_BUCK3_VOUT, .vsel_mask = PM886_BUCK_VSEL_MASK, .enable_reg = PM886_REG_BUCK_EN, .enable_mask = BIT(2), }, { .name = "buck4", .regulators_node = "regulators", .of_match = "buck4", .ops = &pm886_buck_ops, .type = REGULATOR_VOLTAGE, .n_voltages = 115, .linear_ranges = pm886_buck_volt_ranges2, .n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges2), .vsel_reg = PM886_REG_BUCK4_VOUT, .vsel_mask = PM886_BUCK_VSEL_MASK, .enable_reg = PM886_REG_BUCK_EN, .enable_mask = BIT(3), }, { .name = "buck5", .regulators_node = "regulators", .of_match = "buck5", .ops = &pm886_buck_ops, .type = REGULATOR_VOLTAGE, .n_voltages = 115, .linear_ranges = pm886_buck_volt_ranges2, .n_linear_ranges = ARRAY_SIZE(pm886_buck_volt_ranges2), .vsel_reg = PM886_REG_BUCK5_VOUT, .vsel_mask = PM886_BUCK_VSEL_MASK, .enable_reg = PM886_REG_BUCK_EN, .enable_mask = BIT(4), }, }; static int pm886_regulator_probe(struct platform_device *pdev) { struct pm886_chip *chip = dev_get_drvdata(pdev->dev.parent); struct regulator_config rcfg = { }; struct device *dev = &pdev->dev; struct regulator_desc *rdesc; struct regulator_dev *rdev; struct i2c_client *page; struct regmap *regmap; page = devm_i2c_new_dummy_device(dev, chip->client->adapter, chip->client->addr + PM886_PAGE_OFFSET_REGULATORS); if (IS_ERR(page)) return dev_err_probe(dev, PTR_ERR(page), "Failed to initialize regulators client\n"); regmap = devm_regmap_init_i2c(page, &pm886_regulator_regmap_config); if (IS_ERR(regmap)) return dev_err_probe(dev, PTR_ERR(regmap), "Failed to initialize regulators regmap\n"); rcfg.regmap = regmap; rcfg.dev = dev->parent; for (int i = 0; i < ARRAY_SIZE(pm886_regulators); i++) { rdesc = &pm886_regulators[i]; rdev = devm_regulator_register(dev, rdesc, &rcfg); if (IS_ERR(rdev)) return dev_err_probe(dev, PTR_ERR(rdev), "Failed to register %s\n", rdesc->name); } return 0; } static const struct platform_device_id pm886_regulator_id_table[] = { { "88pm886-regulator", }, { } }; MODULE_DEVICE_TABLE(platform, pm886_regulator_id_table); static struct platform_driver pm886_regulator_driver = { .driver = { .name = "88pm886-regulator", }, .probe = pm886_regulator_probe, .id_table = pm886_regulator_id_table, }; module_platform_driver(pm886_regulator_driver); MODULE_DESCRIPTION("Marvell 88PM886 PMIC regulator driver"); MODULE_AUTHOR("Karel Balej "); MODULE_LICENSE("GPL");