1e6dea51eSChristoph Fritz // SPDX-License-Identifier: GPL-2.0+ 2e6dea51eSChristoph Fritz #include <linux/module.h> 3e6dea51eSChristoph Fritz #include <linux/i2c.h> 4e6dea51eSChristoph Fritz #include <linux/regmap.h> 5e6dea51eSChristoph Fritz #include <linux/regulator/driver.h> 6e6dea51eSChristoph Fritz 7e6dea51eSChristoph Fritz enum fan53880_regulator_ids { 8e6dea51eSChristoph Fritz FAN53880_LDO1, 9e6dea51eSChristoph Fritz FAN53880_LDO2, 10e6dea51eSChristoph Fritz FAN53880_LDO3, 11e6dea51eSChristoph Fritz FAN53880_LDO4, 12e6dea51eSChristoph Fritz FAN53880_BUCK, 13e6dea51eSChristoph Fritz FAN53880_BOOST, 14e6dea51eSChristoph Fritz }; 15e6dea51eSChristoph Fritz 16e6dea51eSChristoph Fritz enum fan53880_registers { 17e6dea51eSChristoph Fritz FAN53880_PRODUCT_ID = 0x00, 18e6dea51eSChristoph Fritz FAN53880_SILICON_REV, 19e6dea51eSChristoph Fritz FAN53880_BUCKVOUT, 20e6dea51eSChristoph Fritz FAN53880_BOOSTVOUT, 21e6dea51eSChristoph Fritz FAN53880_LDO1VOUT, 22e6dea51eSChristoph Fritz FAN53880_LDO2VOUT, 23e6dea51eSChristoph Fritz FAN53880_LDO3VOUT, 24e6dea51eSChristoph Fritz FAN53880_LDO4VOUT, 25e6dea51eSChristoph Fritz FAN53880_IOUT, 26e6dea51eSChristoph Fritz FAN53880_ENABLE, 27e6dea51eSChristoph Fritz FAN53880_ENABLE_BOOST, 28e6dea51eSChristoph Fritz }; 29e6dea51eSChristoph Fritz 30e6dea51eSChristoph Fritz #define FAN53880_ID 0x01 31e6dea51eSChristoph Fritz 32e6dea51eSChristoph Fritz static const struct regulator_ops fan53880_ops = { 33e6dea51eSChristoph Fritz .list_voltage = regulator_list_voltage_linear_range, 34e6dea51eSChristoph Fritz .map_voltage = regulator_map_voltage_linear_range, 35e6dea51eSChristoph Fritz .set_voltage_sel = regulator_set_voltage_sel_regmap, 36e6dea51eSChristoph Fritz .get_voltage_sel = regulator_get_voltage_sel_regmap, 37e6dea51eSChristoph Fritz .enable = regulator_enable_regmap, 38e6dea51eSChristoph Fritz .disable = regulator_disable_regmap, 39e6dea51eSChristoph Fritz .is_enabled = regulator_is_enabled_regmap, 40e6dea51eSChristoph Fritz }; 41e6dea51eSChristoph Fritz 42e6dea51eSChristoph Fritz #define FAN53880_LDO(_num, _supply, _default) \ 43e6dea51eSChristoph Fritz [FAN53880_LDO ## _num] = { \ 44e6dea51eSChristoph Fritz .name = "LDO"#_num, \ 45*c4b02c92SJean Delvare .of_match = "LDO"#_num, \ 46*c4b02c92SJean Delvare .regulators_node = "regulators", \ 47e6dea51eSChristoph Fritz .type = REGULATOR_VOLTAGE, \ 486c814b67SAxel Lin .owner = THIS_MODULE, \ 49e6dea51eSChristoph Fritz .linear_ranges = (struct linear_range[]) { \ 50e6dea51eSChristoph Fritz REGULATOR_LINEAR_RANGE(_default, 0x0, 0x0, 0), \ 51e6dea51eSChristoph Fritz REGULATOR_LINEAR_RANGE(800000, 0xf, 0x73, 25000), \ 52e6dea51eSChristoph Fritz }, \ 53e6dea51eSChristoph Fritz .n_linear_ranges = 2, \ 5434991ee9SAxel Lin .n_voltages = 0x74, \ 55e6dea51eSChristoph Fritz .vsel_reg = FAN53880_LDO ## _num ## VOUT, \ 56e6dea51eSChristoph Fritz .vsel_mask = 0x7f, \ 57e6dea51eSChristoph Fritz .enable_reg = FAN53880_ENABLE, \ 58e6dea51eSChristoph Fritz .enable_mask = BIT(_num - 1), \ 59e6dea51eSChristoph Fritz .enable_time = 150, \ 60e6dea51eSChristoph Fritz .supply_name = _supply, \ 61e6dea51eSChristoph Fritz .ops = &fan53880_ops, \ 62e6dea51eSChristoph Fritz } 63e6dea51eSChristoph Fritz 64e6dea51eSChristoph Fritz static const struct regulator_desc fan53880_regulators[] = { 65e6dea51eSChristoph Fritz FAN53880_LDO(1, "VIN12", 2800000), 66e6dea51eSChristoph Fritz FAN53880_LDO(2, "VIN12", 2800000), 67e6dea51eSChristoph Fritz FAN53880_LDO(3, "VIN3", 1800000), 68e6dea51eSChristoph Fritz FAN53880_LDO(4, "VIN4", 1800000), 69e6dea51eSChristoph Fritz [FAN53880_BUCK] = { 70e6dea51eSChristoph Fritz .name = "BUCK", 71*c4b02c92SJean Delvare .of_match = "BUCK", 72*c4b02c92SJean Delvare .regulators_node = "regulators", 73e6dea51eSChristoph Fritz .type = REGULATOR_VOLTAGE, 746c814b67SAxel Lin .owner = THIS_MODULE, 75e6dea51eSChristoph Fritz .linear_ranges = (struct linear_range[]) { 76e6dea51eSChristoph Fritz REGULATOR_LINEAR_RANGE(1100000, 0x0, 0x0, 0), 77e6dea51eSChristoph Fritz REGULATOR_LINEAR_RANGE(600000, 0x1f, 0xf7, 12500), 78e6dea51eSChristoph Fritz }, 79e6dea51eSChristoph Fritz .n_linear_ranges = 2, 8034991ee9SAxel Lin .n_voltages = 0xf8, 81e6dea51eSChristoph Fritz .vsel_reg = FAN53880_BUCKVOUT, 822e11737aSAxel Lin .vsel_mask = 0xff, 83e6dea51eSChristoph Fritz .enable_reg = FAN53880_ENABLE, 84e6dea51eSChristoph Fritz .enable_mask = 0x10, 85e6dea51eSChristoph Fritz .enable_time = 480, 86e6dea51eSChristoph Fritz .supply_name = "PVIN", 87e6dea51eSChristoph Fritz .ops = &fan53880_ops, 88e6dea51eSChristoph Fritz }, 89e6dea51eSChristoph Fritz [FAN53880_BOOST] = { 90e6dea51eSChristoph Fritz .name = "BOOST", 91*c4b02c92SJean Delvare .of_match = "BOOST", 92*c4b02c92SJean Delvare .regulators_node = "regulators", 93e6dea51eSChristoph Fritz .type = REGULATOR_VOLTAGE, 946c814b67SAxel Lin .owner = THIS_MODULE, 95e6dea51eSChristoph Fritz .linear_ranges = (struct linear_range[]) { 96e6dea51eSChristoph Fritz REGULATOR_LINEAR_RANGE(5000000, 0x0, 0x0, 0), 97e6dea51eSChristoph Fritz REGULATOR_LINEAR_RANGE(3000000, 0x4, 0x70, 25000), 98e6dea51eSChristoph Fritz }, 99e6dea51eSChristoph Fritz .n_linear_ranges = 2, 10034991ee9SAxel Lin .n_voltages = 0x71, 101e6dea51eSChristoph Fritz .vsel_reg = FAN53880_BOOSTVOUT, 102e6dea51eSChristoph Fritz .vsel_mask = 0x7f, 103e6dea51eSChristoph Fritz .enable_reg = FAN53880_ENABLE_BOOST, 104e6dea51eSChristoph Fritz .enable_mask = 0xff, 105e6dea51eSChristoph Fritz .enable_time = 580, 106e6dea51eSChristoph Fritz .supply_name = "PVIN", 107e6dea51eSChristoph Fritz .ops = &fan53880_ops, 108e6dea51eSChristoph Fritz }, 109e6dea51eSChristoph Fritz }; 110e6dea51eSChristoph Fritz 111e6dea51eSChristoph Fritz static const struct regmap_config fan53880_regmap = { 112e6dea51eSChristoph Fritz .reg_bits = 8, 113e6dea51eSChristoph Fritz .val_bits = 8, 114e6dea51eSChristoph Fritz .max_register = FAN53880_ENABLE_BOOST, 115e6dea51eSChristoph Fritz }; 116e6dea51eSChristoph Fritz 1177075359cSAxel Lin static int fan53880_i2c_probe(struct i2c_client *i2c) 118e6dea51eSChristoph Fritz { 119e6dea51eSChristoph Fritz struct regulator_config config = { }; 120e6dea51eSChristoph Fritz struct regulator_dev *rdev; 121e6dea51eSChristoph Fritz struct regmap *regmap; 122e6dea51eSChristoph Fritz int i, ret; 123e6dea51eSChristoph Fritz unsigned int data; 124e6dea51eSChristoph Fritz 125e6dea51eSChristoph Fritz regmap = devm_regmap_init_i2c(i2c, &fan53880_regmap); 126e6dea51eSChristoph Fritz if (IS_ERR(regmap)) { 127e6dea51eSChristoph Fritz ret = PTR_ERR(regmap); 128e6dea51eSChristoph Fritz dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret); 129e6dea51eSChristoph Fritz return ret; 130e6dea51eSChristoph Fritz } 131e6dea51eSChristoph Fritz 132e6dea51eSChristoph Fritz ret = regmap_read(regmap, FAN53880_PRODUCT_ID, &data); 133e6dea51eSChristoph Fritz if (ret < 0) { 134e6dea51eSChristoph Fritz dev_err(&i2c->dev, "Failed to read PRODUCT_ID: %d\n", ret); 135e6dea51eSChristoph Fritz return ret; 136e6dea51eSChristoph Fritz } 137e6dea51eSChristoph Fritz if (data != FAN53880_ID) { 138e6dea51eSChristoph Fritz dev_err(&i2c->dev, "Unsupported device id: 0x%x.\n", data); 139e6dea51eSChristoph Fritz return -ENODEV; 140e6dea51eSChristoph Fritz } 141e6dea51eSChristoph Fritz 142e6dea51eSChristoph Fritz config.dev = &i2c->dev; 143e6dea51eSChristoph Fritz config.init_data = NULL; 144e6dea51eSChristoph Fritz 145e6dea51eSChristoph Fritz for (i = 0; i < ARRAY_SIZE(fan53880_regulators); i++) { 146e6dea51eSChristoph Fritz rdev = devm_regulator_register(&i2c->dev, 147e6dea51eSChristoph Fritz &fan53880_regulators[i], 148e6dea51eSChristoph Fritz &config); 149e6dea51eSChristoph Fritz if (IS_ERR(rdev)) { 150e6dea51eSChristoph Fritz ret = PTR_ERR(rdev); 151e6dea51eSChristoph Fritz dev_err(&i2c->dev, "Failed to register %s: %d\n", 152e6dea51eSChristoph Fritz fan53880_regulators[i].name, ret); 153e6dea51eSChristoph Fritz return ret; 154e6dea51eSChristoph Fritz } 155e6dea51eSChristoph Fritz } 156e6dea51eSChristoph Fritz 157e6dea51eSChristoph Fritz return 0; 158e6dea51eSChristoph Fritz } 159e6dea51eSChristoph Fritz 160e6dea51eSChristoph Fritz static const struct of_device_id fan53880_dt_ids[] = { 161e6dea51eSChristoph Fritz { .compatible = "onnn,fan53880", }, 162e6dea51eSChristoph Fritz {} 163e6dea51eSChristoph Fritz }; 164e6dea51eSChristoph Fritz MODULE_DEVICE_TABLE(of, fan53880_dt_ids); 165e6dea51eSChristoph Fritz 166e6dea51eSChristoph Fritz static const struct i2c_device_id fan53880_i2c_id[] = { 167e6dea51eSChristoph Fritz { "fan53880", }, 168e6dea51eSChristoph Fritz {} 169e6dea51eSChristoph Fritz }; 170e6dea51eSChristoph Fritz MODULE_DEVICE_TABLE(i2c, fan53880_i2c_id); 171e6dea51eSChristoph Fritz 172e6dea51eSChristoph Fritz static struct i2c_driver fan53880_regulator_driver = { 173e6dea51eSChristoph Fritz .driver = { 174e6dea51eSChristoph Fritz .name = "fan53880", 175*c4b02c92SJean Delvare .of_match_table = fan53880_dt_ids, 176e6dea51eSChristoph Fritz }, 1777075359cSAxel Lin .probe_new = fan53880_i2c_probe, 178e6dea51eSChristoph Fritz .id_table = fan53880_i2c_id, 179e6dea51eSChristoph Fritz }; 180e6dea51eSChristoph Fritz module_i2c_driver(fan53880_regulator_driver); 181e6dea51eSChristoph Fritz 182e6dea51eSChristoph Fritz MODULE_DESCRIPTION("FAN53880 PMIC voltage regulator driver"); 183e6dea51eSChristoph Fritz MODULE_AUTHOR("Christoph Fritz <chf.fritz@googlemail.com>"); 184e6dea51eSChristoph Fritz MODULE_LICENSE("GPL"); 185