18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci#include <linux/module.h> 38c2ecf20Sopenharmony_ci#include <linux/i2c.h> 48c2ecf20Sopenharmony_ci#include <linux/regmap.h> 58c2ecf20Sopenharmony_ci#include <linux/regulator/driver.h> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_cienum fan53880_regulator_ids { 88c2ecf20Sopenharmony_ci FAN53880_LDO1, 98c2ecf20Sopenharmony_ci FAN53880_LDO2, 108c2ecf20Sopenharmony_ci FAN53880_LDO3, 118c2ecf20Sopenharmony_ci FAN53880_LDO4, 128c2ecf20Sopenharmony_ci FAN53880_BUCK, 138c2ecf20Sopenharmony_ci FAN53880_BOOST, 148c2ecf20Sopenharmony_ci}; 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cienum fan53880_registers { 178c2ecf20Sopenharmony_ci FAN53880_PRODUCT_ID = 0x00, 188c2ecf20Sopenharmony_ci FAN53880_SILICON_REV, 198c2ecf20Sopenharmony_ci FAN53880_BUCKVOUT, 208c2ecf20Sopenharmony_ci FAN53880_BOOSTVOUT, 218c2ecf20Sopenharmony_ci FAN53880_LDO1VOUT, 228c2ecf20Sopenharmony_ci FAN53880_LDO2VOUT, 238c2ecf20Sopenharmony_ci FAN53880_LDO3VOUT, 248c2ecf20Sopenharmony_ci FAN53880_LDO4VOUT, 258c2ecf20Sopenharmony_ci FAN53880_IOUT, 268c2ecf20Sopenharmony_ci FAN53880_ENABLE, 278c2ecf20Sopenharmony_ci FAN53880_ENABLE_BOOST, 288c2ecf20Sopenharmony_ci}; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define FAN53880_ID 0x01 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic const struct regulator_ops fan53880_ops = { 338c2ecf20Sopenharmony_ci .list_voltage = regulator_list_voltage_linear_range, 348c2ecf20Sopenharmony_ci .map_voltage = regulator_map_voltage_linear_range, 358c2ecf20Sopenharmony_ci .set_voltage_sel = regulator_set_voltage_sel_regmap, 368c2ecf20Sopenharmony_ci .get_voltage_sel = regulator_get_voltage_sel_regmap, 378c2ecf20Sopenharmony_ci .enable = regulator_enable_regmap, 388c2ecf20Sopenharmony_ci .disable = regulator_disable_regmap, 398c2ecf20Sopenharmony_ci .is_enabled = regulator_is_enabled_regmap, 408c2ecf20Sopenharmony_ci}; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#define FAN53880_LDO(_num, _supply, _default) \ 438c2ecf20Sopenharmony_ci [FAN53880_LDO ## _num] = { \ 448c2ecf20Sopenharmony_ci .name = "LDO"#_num, \ 458c2ecf20Sopenharmony_ci .of_match = of_match_ptr("LDO"#_num), \ 468c2ecf20Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), \ 478c2ecf20Sopenharmony_ci .type = REGULATOR_VOLTAGE, \ 488c2ecf20Sopenharmony_ci .owner = THIS_MODULE, \ 498c2ecf20Sopenharmony_ci .linear_ranges = (struct linear_range[]) { \ 508c2ecf20Sopenharmony_ci REGULATOR_LINEAR_RANGE(_default, 0x0, 0x0, 0), \ 518c2ecf20Sopenharmony_ci REGULATOR_LINEAR_RANGE(800000, 0xf, 0x73, 25000), \ 528c2ecf20Sopenharmony_ci }, \ 538c2ecf20Sopenharmony_ci .n_linear_ranges = 2, \ 548c2ecf20Sopenharmony_ci .n_voltages = 0x74, \ 558c2ecf20Sopenharmony_ci .vsel_reg = FAN53880_LDO ## _num ## VOUT, \ 568c2ecf20Sopenharmony_ci .vsel_mask = 0x7f, \ 578c2ecf20Sopenharmony_ci .enable_reg = FAN53880_ENABLE, \ 588c2ecf20Sopenharmony_ci .enable_mask = BIT(_num - 1), \ 598c2ecf20Sopenharmony_ci .enable_time = 150, \ 608c2ecf20Sopenharmony_ci .supply_name = _supply, \ 618c2ecf20Sopenharmony_ci .ops = &fan53880_ops, \ 628c2ecf20Sopenharmony_ci } 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic const struct regulator_desc fan53880_regulators[] = { 658c2ecf20Sopenharmony_ci FAN53880_LDO(1, "VIN12", 2800000), 668c2ecf20Sopenharmony_ci FAN53880_LDO(2, "VIN12", 2800000), 678c2ecf20Sopenharmony_ci FAN53880_LDO(3, "VIN3", 1800000), 688c2ecf20Sopenharmony_ci FAN53880_LDO(4, "VIN4", 1800000), 698c2ecf20Sopenharmony_ci [FAN53880_BUCK] = { 708c2ecf20Sopenharmony_ci .name = "BUCK", 718c2ecf20Sopenharmony_ci .of_match = of_match_ptr("BUCK"), 728c2ecf20Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), 738c2ecf20Sopenharmony_ci .type = REGULATOR_VOLTAGE, 748c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 758c2ecf20Sopenharmony_ci .linear_ranges = (struct linear_range[]) { 768c2ecf20Sopenharmony_ci REGULATOR_LINEAR_RANGE(1100000, 0x0, 0x0, 0), 778c2ecf20Sopenharmony_ci REGULATOR_LINEAR_RANGE(600000, 0x1f, 0xf7, 12500), 788c2ecf20Sopenharmony_ci }, 798c2ecf20Sopenharmony_ci .n_linear_ranges = 2, 808c2ecf20Sopenharmony_ci .n_voltages = 0xf8, 818c2ecf20Sopenharmony_ci .vsel_reg = FAN53880_BUCKVOUT, 828c2ecf20Sopenharmony_ci .vsel_mask = 0xff, 838c2ecf20Sopenharmony_ci .enable_reg = FAN53880_ENABLE, 848c2ecf20Sopenharmony_ci .enable_mask = 0x10, 858c2ecf20Sopenharmony_ci .enable_time = 480, 868c2ecf20Sopenharmony_ci .supply_name = "PVIN", 878c2ecf20Sopenharmony_ci .ops = &fan53880_ops, 888c2ecf20Sopenharmony_ci }, 898c2ecf20Sopenharmony_ci [FAN53880_BOOST] = { 908c2ecf20Sopenharmony_ci .name = "BOOST", 918c2ecf20Sopenharmony_ci .of_match = of_match_ptr("BOOST"), 928c2ecf20Sopenharmony_ci .regulators_node = of_match_ptr("regulators"), 938c2ecf20Sopenharmony_ci .type = REGULATOR_VOLTAGE, 948c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 958c2ecf20Sopenharmony_ci .linear_ranges = (struct linear_range[]) { 968c2ecf20Sopenharmony_ci REGULATOR_LINEAR_RANGE(5000000, 0x0, 0x0, 0), 978c2ecf20Sopenharmony_ci REGULATOR_LINEAR_RANGE(3000000, 0x4, 0x70, 25000), 988c2ecf20Sopenharmony_ci }, 998c2ecf20Sopenharmony_ci .n_linear_ranges = 2, 1008c2ecf20Sopenharmony_ci .n_voltages = 0x71, 1018c2ecf20Sopenharmony_ci .vsel_reg = FAN53880_BOOSTVOUT, 1028c2ecf20Sopenharmony_ci .vsel_mask = 0x7f, 1038c2ecf20Sopenharmony_ci .enable_reg = FAN53880_ENABLE_BOOST, 1048c2ecf20Sopenharmony_ci .enable_mask = 0xff, 1058c2ecf20Sopenharmony_ci .enable_time = 580, 1068c2ecf20Sopenharmony_ci .supply_name = "PVIN", 1078c2ecf20Sopenharmony_ci .ops = &fan53880_ops, 1088c2ecf20Sopenharmony_ci }, 1098c2ecf20Sopenharmony_ci}; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_cistatic const struct regmap_config fan53880_regmap = { 1128c2ecf20Sopenharmony_ci .reg_bits = 8, 1138c2ecf20Sopenharmony_ci .val_bits = 8, 1148c2ecf20Sopenharmony_ci .max_register = FAN53880_ENABLE_BOOST, 1158c2ecf20Sopenharmony_ci}; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic int fan53880_i2c_probe(struct i2c_client *i2c, 1188c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci struct regulator_config config = { }; 1218c2ecf20Sopenharmony_ci struct regulator_dev *rdev; 1228c2ecf20Sopenharmony_ci struct regmap *regmap; 1238c2ecf20Sopenharmony_ci int i, ret; 1248c2ecf20Sopenharmony_ci unsigned int data; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci regmap = devm_regmap_init_i2c(i2c, &fan53880_regmap); 1278c2ecf20Sopenharmony_ci if (IS_ERR(regmap)) { 1288c2ecf20Sopenharmony_ci ret = PTR_ERR(regmap); 1298c2ecf20Sopenharmony_ci dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret); 1308c2ecf20Sopenharmony_ci return ret; 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci ret = regmap_read(regmap, FAN53880_PRODUCT_ID, &data); 1348c2ecf20Sopenharmony_ci if (ret < 0) { 1358c2ecf20Sopenharmony_ci dev_err(&i2c->dev, "Failed to read PRODUCT_ID: %d\n", ret); 1368c2ecf20Sopenharmony_ci return ret; 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci if (data != FAN53880_ID) { 1398c2ecf20Sopenharmony_ci dev_err(&i2c->dev, "Unsupported device id: 0x%x.\n", data); 1408c2ecf20Sopenharmony_ci return -ENODEV; 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci config.dev = &i2c->dev; 1448c2ecf20Sopenharmony_ci config.init_data = NULL; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(fan53880_regulators); i++) { 1478c2ecf20Sopenharmony_ci rdev = devm_regulator_register(&i2c->dev, 1488c2ecf20Sopenharmony_ci &fan53880_regulators[i], 1498c2ecf20Sopenharmony_ci &config); 1508c2ecf20Sopenharmony_ci if (IS_ERR(rdev)) { 1518c2ecf20Sopenharmony_ci ret = PTR_ERR(rdev); 1528c2ecf20Sopenharmony_ci dev_err(&i2c->dev, "Failed to register %s: %d\n", 1538c2ecf20Sopenharmony_ci fan53880_regulators[i].name, ret); 1548c2ecf20Sopenharmony_ci return ret; 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci return 0; 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 1628c2ecf20Sopenharmony_cistatic const struct of_device_id fan53880_dt_ids[] = { 1638c2ecf20Sopenharmony_ci { .compatible = "onnn,fan53880", }, 1648c2ecf20Sopenharmony_ci {} 1658c2ecf20Sopenharmony_ci}; 1668c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, fan53880_dt_ids); 1678c2ecf20Sopenharmony_ci#endif 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic const struct i2c_device_id fan53880_i2c_id[] = { 1708c2ecf20Sopenharmony_ci { "fan53880", }, 1718c2ecf20Sopenharmony_ci {} 1728c2ecf20Sopenharmony_ci}; 1738c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, fan53880_i2c_id); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_cistatic struct i2c_driver fan53880_regulator_driver = { 1768c2ecf20Sopenharmony_ci .driver = { 1778c2ecf20Sopenharmony_ci .name = "fan53880", 1788c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(fan53880_dt_ids), 1798c2ecf20Sopenharmony_ci }, 1808c2ecf20Sopenharmony_ci .probe = fan53880_i2c_probe, 1818c2ecf20Sopenharmony_ci .id_table = fan53880_i2c_id, 1828c2ecf20Sopenharmony_ci}; 1838c2ecf20Sopenharmony_cimodule_i2c_driver(fan53880_regulator_driver); 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("FAN53880 PMIC voltage regulator driver"); 1868c2ecf20Sopenharmony_ciMODULE_AUTHOR("Christoph Fritz <chf.fritz@googlemail.com>"); 1878c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 188