Skip to content

Commit

Permalink
regulator: fan53880: Add initial support
Browse files Browse the repository at this point in the history
This patch adds support for ON Semiconductor FAN53880 regulator.

The FAN53880 is an I2C porgrammable power management IC (PMIC)
that contains a BUCK (step-down converter), four LDOs (low dropouts)
and one BOOST (step-up converter).  It is designed for mobile power
applications.

Signed-off-by: Christoph Fritz <chf.fritz@googlemail.com>
Link: https://lore.kernel.org/r/20200702210846.31659-2-chf.fritz@googlemail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
Christoph Fritz authored and Mark Brown committed Jul 3, 2020
1 parent 8cc31dc commit e6dea51
Show file tree
Hide file tree
Showing 3 changed files with 190 additions and 0 deletions.
10 changes: 10 additions & 0 deletions drivers/regulator/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,16 @@ config REGULATOR_FAN53555
input voltage supply of 2.5V to 5.5V. The output voltage is
programmed through an I2C interface.

config REGULATOR_FAN53880
tristate "Fairchild FAN53880 Regulator"
depends on I2C
select REGMAP_I2C
help
This driver supports Fairchild (ON Semiconductor) FAN53880
regulator. The regulator is a programmable power management IC
(PMIC), it is controlled by I2C and provides one BUCK, one BOOST
and four LDO outputs.

config REGULATOR_GPIO
tristate "GPIO regulator support"
depends on GPIOLIB || COMPILE_TEST
Expand Down
1 change: 1 addition & 0 deletions drivers/regulator/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ obj-$(CONFIG_REGULATOR_DA9211) += da9211-regulator.o
obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
obj-$(CONFIG_REGULATOR_FAN53880) += fan53880.o
obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o
obj-$(CONFIG_REGULATOR_HI6421V530) += hi6421v530-regulator.o
Expand Down
179 changes: 179 additions & 0 deletions drivers/regulator/fan53880.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
// SPDX-License-Identifier: GPL-2.0+
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>

enum fan53880_regulator_ids {
FAN53880_LDO1,
FAN53880_LDO2,
FAN53880_LDO3,
FAN53880_LDO4,
FAN53880_BUCK,
FAN53880_BOOST,
};

enum fan53880_registers {
FAN53880_PRODUCT_ID = 0x00,
FAN53880_SILICON_REV,
FAN53880_BUCKVOUT,
FAN53880_BOOSTVOUT,
FAN53880_LDO1VOUT,
FAN53880_LDO2VOUT,
FAN53880_LDO3VOUT,
FAN53880_LDO4VOUT,
FAN53880_IOUT,
FAN53880_ENABLE,
FAN53880_ENABLE_BOOST,
};

#define FAN53880_ID 0x01

static const struct regulator_ops fan53880_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,
};

#define FAN53880_LDO(_num, _supply, _default) \
[FAN53880_LDO ## _num] = { \
.name = "LDO"#_num, \
.of_match = of_match_ptr("LDO"#_num), \
.regulators_node = of_match_ptr("regulators"), \
.type = REGULATOR_VOLTAGE, \
.linear_ranges = (struct linear_range[]) { \
REGULATOR_LINEAR_RANGE(_default, 0x0, 0x0, 0), \
REGULATOR_LINEAR_RANGE(800000, 0xf, 0x73, 25000), \
}, \
.n_linear_ranges = 2, \
.vsel_reg = FAN53880_LDO ## _num ## VOUT, \
.vsel_mask = 0x7f, \
.enable_reg = FAN53880_ENABLE, \
.enable_mask = BIT(_num - 1), \
.enable_time = 150, \
.supply_name = _supply, \
.ops = &fan53880_ops, \
}

static const struct regulator_desc fan53880_regulators[] = {
FAN53880_LDO(1, "VIN12", 2800000),
FAN53880_LDO(2, "VIN12", 2800000),
FAN53880_LDO(3, "VIN3", 1800000),
FAN53880_LDO(4, "VIN4", 1800000),
[FAN53880_BUCK] = {
.name = "BUCK",
.of_match = of_match_ptr("BUCK"),
.regulators_node = of_match_ptr("regulators"),
.type = REGULATOR_VOLTAGE,
.linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(1100000, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(600000, 0x1f, 0xf7, 12500),
},
.n_linear_ranges = 2,
.vsel_reg = FAN53880_BUCKVOUT,
.vsel_mask = 0x7f,
.enable_reg = FAN53880_ENABLE,
.enable_mask = 0x10,
.enable_time = 480,
.supply_name = "PVIN",
.ops = &fan53880_ops,
},
[FAN53880_BOOST] = {
.name = "BOOST",
.of_match = of_match_ptr("BOOST"),
.regulators_node = of_match_ptr("regulators"),
.type = REGULATOR_VOLTAGE,
.linear_ranges = (struct linear_range[]) {
REGULATOR_LINEAR_RANGE(5000000, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(3000000, 0x4, 0x70, 25000),
},
.n_linear_ranges = 2,
.vsel_reg = FAN53880_BOOSTVOUT,
.vsel_mask = 0x7f,
.enable_reg = FAN53880_ENABLE_BOOST,
.enable_mask = 0xff,
.enable_time = 580,
.supply_name = "PVIN",
.ops = &fan53880_ops,
},
};

static const struct regmap_config fan53880_regmap = {
.reg_bits = 8,
.val_bits = 8,
.max_register = FAN53880_ENABLE_BOOST,
};

static int fan53880_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct regulator_config config = { };
struct regulator_dev *rdev;
struct regmap *regmap;
int i, ret;
unsigned int data;

regmap = devm_regmap_init_i2c(i2c, &fan53880_regmap);
if (IS_ERR(regmap)) {
ret = PTR_ERR(regmap);
dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret);
return ret;
}

ret = regmap_read(regmap, FAN53880_PRODUCT_ID, &data);
if (ret < 0) {
dev_err(&i2c->dev, "Failed to read PRODUCT_ID: %d\n", ret);
return ret;
}
if (data != FAN53880_ID) {
dev_err(&i2c->dev, "Unsupported device id: 0x%x.\n", data);
return -ENODEV;
}

config.dev = &i2c->dev;
config.init_data = NULL;

for (i = 0; i < ARRAY_SIZE(fan53880_regulators); i++) {
rdev = devm_regulator_register(&i2c->dev,
&fan53880_regulators[i],
&config);
if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev);
dev_err(&i2c->dev, "Failed to register %s: %d\n",
fan53880_regulators[i].name, ret);
return ret;
}
}

return 0;
}

static const struct of_device_id fan53880_dt_ids[] = {
{ .compatible = "onnn,fan53880", },
{}
};
MODULE_DEVICE_TABLE(of, fan53880_dt_ids);

static const struct i2c_device_id fan53880_i2c_id[] = {
{ "fan53880", },
{}
};
MODULE_DEVICE_TABLE(i2c, fan53880_i2c_id);

static struct i2c_driver fan53880_regulator_driver = {
.driver = {
.name = "fan53880",
.of_match_table = of_match_ptr(fan53880_dt_ids),
},
.probe = fan53880_i2c_probe,
.id_table = fan53880_i2c_id,
};
module_i2c_driver(fan53880_regulator_driver);

MODULE_DESCRIPTION("FAN53880 PMIC voltage regulator driver");
MODULE_AUTHOR("Christoph Fritz <chf.fritz@googlemail.com>");
MODULE_LICENSE("GPL");

0 comments on commit e6dea51

Please sign in to comment.