162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Regulator driver for tps65090 power management chip.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/module.h>
1062306a36Sopenharmony_ci#include <linux/delay.h>
1162306a36Sopenharmony_ci#include <linux/init.h>
1262306a36Sopenharmony_ci#include <linux/of.h>
1362306a36Sopenharmony_ci#include <linux/gpio/consumer.h>
1462306a36Sopenharmony_ci#include <linux/slab.h>
1562306a36Sopenharmony_ci#include <linux/err.h>
1662306a36Sopenharmony_ci#include <linux/platform_device.h>
1762306a36Sopenharmony_ci#include <linux/regulator/driver.h>
1862306a36Sopenharmony_ci#include <linux/regulator/machine.h>
1962306a36Sopenharmony_ci#include <linux/regulator/of_regulator.h>
2062306a36Sopenharmony_ci#include <linux/mfd/tps65090.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define MAX_CTRL_READ_TRIES	5
2362306a36Sopenharmony_ci#define MAX_FET_ENABLE_TRIES	1000
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define CTRL_EN_BIT		0 /* Regulator enable bit, active high */
2662306a36Sopenharmony_ci#define CTRL_WT_BIT		2 /* Regulator wait time 0 bit */
2762306a36Sopenharmony_ci#define CTRL_PG_BIT		4 /* Regulator power good bit, 1=good */
2862306a36Sopenharmony_ci#define CTRL_TO_BIT		7 /* Regulator timeout bit, 1=wait */
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#define MAX_OVERCURRENT_WAIT	3 /* Overcurrent wait must be <= this */
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/**
3362306a36Sopenharmony_ci * struct tps65090_regulator - Per-regulator data for a tps65090 regulator
3462306a36Sopenharmony_ci *
3562306a36Sopenharmony_ci * @dev: Pointer to our device.
3662306a36Sopenharmony_ci * @desc: The struct regulator_desc for the regulator.
3762306a36Sopenharmony_ci * @rdev: The struct regulator_dev for the regulator.
3862306a36Sopenharmony_ci * @overcurrent_wait_valid: True if overcurrent_wait is valid.
3962306a36Sopenharmony_ci * @overcurrent_wait: For FETs, the value to put in the WTFET bitfield.
4062306a36Sopenharmony_ci */
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistruct tps65090_regulator {
4362306a36Sopenharmony_ci	struct device		*dev;
4462306a36Sopenharmony_ci	struct regulator_desc	*desc;
4562306a36Sopenharmony_ci	struct regulator_dev	*rdev;
4662306a36Sopenharmony_ci	bool			overcurrent_wait_valid;
4762306a36Sopenharmony_ci	int			overcurrent_wait;
4862306a36Sopenharmony_ci};
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic const struct regulator_ops tps65090_ext_control_ops = {
5162306a36Sopenharmony_ci};
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci/**
5462306a36Sopenharmony_ci * tps65090_reg_set_overcurrent_wait - Setup overcurrent wait
5562306a36Sopenharmony_ci *
5662306a36Sopenharmony_ci * This will set the overcurrent wait time based on what's in the regulator
5762306a36Sopenharmony_ci * info.
5862306a36Sopenharmony_ci *
5962306a36Sopenharmony_ci * @ri:		Overall regulator data
6062306a36Sopenharmony_ci * @rdev:	Regulator device
6162306a36Sopenharmony_ci *
6262306a36Sopenharmony_ci * Return: 0 if no error, non-zero if there was an error writing the register.
6362306a36Sopenharmony_ci */
6462306a36Sopenharmony_cistatic int tps65090_reg_set_overcurrent_wait(struct tps65090_regulator *ri,
6562306a36Sopenharmony_ci					     struct regulator_dev *rdev)
6662306a36Sopenharmony_ci{
6762306a36Sopenharmony_ci	int ret;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
7062306a36Sopenharmony_ci				 MAX_OVERCURRENT_WAIT << CTRL_WT_BIT,
7162306a36Sopenharmony_ci				 ri->overcurrent_wait << CTRL_WT_BIT);
7262306a36Sopenharmony_ci	if (ret) {
7362306a36Sopenharmony_ci		dev_err(&rdev->dev, "Error updating overcurrent wait %#x\n",
7462306a36Sopenharmony_ci			rdev->desc->enable_reg);
7562306a36Sopenharmony_ci	}
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	return ret;
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci/**
8162306a36Sopenharmony_ci * tps65090_try_enable_fet - Try to enable a FET
8262306a36Sopenharmony_ci *
8362306a36Sopenharmony_ci * @rdev:	Regulator device
8462306a36Sopenharmony_ci *
8562306a36Sopenharmony_ci * Return: 0 if ok, -ENOTRECOVERABLE if the FET power good bit did not get
8662306a36Sopenharmony_ci * set, or some other -ve value if another error occurred (e.g. i2c error)
8762306a36Sopenharmony_ci */
8862306a36Sopenharmony_cistatic int tps65090_try_enable_fet(struct regulator_dev *rdev)
8962306a36Sopenharmony_ci{
9062306a36Sopenharmony_ci	unsigned int control;
9162306a36Sopenharmony_ci	int ret, i;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
9462306a36Sopenharmony_ci				 rdev->desc->enable_mask,
9562306a36Sopenharmony_ci				 rdev->desc->enable_mask);
9662306a36Sopenharmony_ci	if (ret < 0) {
9762306a36Sopenharmony_ci		dev_err(&rdev->dev, "Error in updating reg %#x\n",
9862306a36Sopenharmony_ci			rdev->desc->enable_reg);
9962306a36Sopenharmony_ci		return ret;
10062306a36Sopenharmony_ci	}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	for (i = 0; i < MAX_CTRL_READ_TRIES; i++) {
10362306a36Sopenharmony_ci		ret = regmap_read(rdev->regmap, rdev->desc->enable_reg,
10462306a36Sopenharmony_ci				  &control);
10562306a36Sopenharmony_ci		if (ret < 0)
10662306a36Sopenharmony_ci			return ret;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci		if (!(control & BIT(CTRL_TO_BIT)))
10962306a36Sopenharmony_ci			break;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci		usleep_range(1000, 1500);
11262306a36Sopenharmony_ci	}
11362306a36Sopenharmony_ci	if (!(control & BIT(CTRL_PG_BIT)))
11462306a36Sopenharmony_ci		return -ENOTRECOVERABLE;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	return 0;
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci/**
12062306a36Sopenharmony_ci * tps65090_fet_enable - Enable a FET, trying a few times if it fails
12162306a36Sopenharmony_ci *
12262306a36Sopenharmony_ci * Some versions of the tps65090 have issues when turning on the FETs.
12362306a36Sopenharmony_ci * This function goes through several steps to ensure the best chance of the
12462306a36Sopenharmony_ci * FET going on.  Specifically:
12562306a36Sopenharmony_ci * - We'll make sure that we bump the "overcurrent wait" to the maximum, which
12662306a36Sopenharmony_ci *   increases the chances that we'll turn on properly.
12762306a36Sopenharmony_ci * - We'll retry turning the FET on multiple times (turning off in between).
12862306a36Sopenharmony_ci *
12962306a36Sopenharmony_ci * @rdev:	Regulator device
13062306a36Sopenharmony_ci *
13162306a36Sopenharmony_ci * Return: 0 if ok, non-zero if it fails.
13262306a36Sopenharmony_ci */
13362306a36Sopenharmony_cistatic int tps65090_fet_enable(struct regulator_dev *rdev)
13462306a36Sopenharmony_ci{
13562306a36Sopenharmony_ci	int ret, tries;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	/*
13862306a36Sopenharmony_ci	 * Try enabling multiple times until we succeed since sometimes the
13962306a36Sopenharmony_ci	 * first try times out.
14062306a36Sopenharmony_ci	 */
14162306a36Sopenharmony_ci	tries = 0;
14262306a36Sopenharmony_ci	while (true) {
14362306a36Sopenharmony_ci		ret = tps65090_try_enable_fet(rdev);
14462306a36Sopenharmony_ci		if (!ret)
14562306a36Sopenharmony_ci			break;
14662306a36Sopenharmony_ci		if (ret != -ENOTRECOVERABLE || tries == MAX_FET_ENABLE_TRIES)
14762306a36Sopenharmony_ci			goto err;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci		/* Try turning the FET off (and then on again) */
15062306a36Sopenharmony_ci		ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
15162306a36Sopenharmony_ci					 rdev->desc->enable_mask, 0);
15262306a36Sopenharmony_ci		if (ret)
15362306a36Sopenharmony_ci			goto err;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci		tries++;
15662306a36Sopenharmony_ci	}
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	if (tries)
15962306a36Sopenharmony_ci		dev_warn(&rdev->dev, "reg %#x enable ok after %d tries\n",
16062306a36Sopenharmony_ci			 rdev->desc->enable_reg, tries);
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	return 0;
16362306a36Sopenharmony_cierr:
16462306a36Sopenharmony_ci	dev_warn(&rdev->dev, "reg %#x enable failed\n", rdev->desc->enable_reg);
16562306a36Sopenharmony_ci	WARN_ON(1);
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	return ret;
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic const struct regulator_ops tps65090_reg_control_ops = {
17162306a36Sopenharmony_ci	.enable		= regulator_enable_regmap,
17262306a36Sopenharmony_ci	.disable	= regulator_disable_regmap,
17362306a36Sopenharmony_ci	.is_enabled	= regulator_is_enabled_regmap,
17462306a36Sopenharmony_ci};
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_cistatic const struct regulator_ops tps65090_fet_control_ops = {
17762306a36Sopenharmony_ci	.enable		= tps65090_fet_enable,
17862306a36Sopenharmony_ci	.disable	= regulator_disable_regmap,
17962306a36Sopenharmony_ci	.is_enabled	= regulator_is_enabled_regmap,
18062306a36Sopenharmony_ci};
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_cistatic const struct regulator_ops tps65090_ldo_ops = {
18362306a36Sopenharmony_ci};
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci#define tps65090_REG_DESC(_id, _sname, _en_reg, _en_bits, _nvolt, _volt, _ops) \
18662306a36Sopenharmony_ci{							\
18762306a36Sopenharmony_ci	.name = "TPS65090_RAILS"#_id,			\
18862306a36Sopenharmony_ci	.supply_name = _sname,				\
18962306a36Sopenharmony_ci	.id = TPS65090_REGULATOR_##_id,			\
19062306a36Sopenharmony_ci	.n_voltages = _nvolt,				\
19162306a36Sopenharmony_ci	.ops = &_ops,					\
19262306a36Sopenharmony_ci	.fixed_uV = _volt,				\
19362306a36Sopenharmony_ci	.enable_reg = _en_reg,				\
19462306a36Sopenharmony_ci	.enable_val = _en_bits,				\
19562306a36Sopenharmony_ci	.enable_mask = _en_bits,			\
19662306a36Sopenharmony_ci	.type = REGULATOR_VOLTAGE,			\
19762306a36Sopenharmony_ci	.owner = THIS_MODULE,				\
19862306a36Sopenharmony_ci}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci#define tps65090_REG_FIXEDV(_id, _sname, en_reg, _en_bits, _volt, _ops) \
20162306a36Sopenharmony_ci	tps65090_REG_DESC(_id, _sname, en_reg, _en_bits, 1, _volt, _ops)
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci#define tps65090_REG_SWITCH(_id, _sname, en_reg, _en_bits, _ops) \
20462306a36Sopenharmony_ci	tps65090_REG_DESC(_id, _sname, en_reg, _en_bits, 0, 0, _ops)
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistatic struct regulator_desc tps65090_regulator_desc[] = {
20762306a36Sopenharmony_ci	tps65090_REG_FIXEDV(DCDC1, "vsys1",   0x0C, BIT(CTRL_EN_BIT), 5000000,
20862306a36Sopenharmony_ci			    tps65090_reg_control_ops),
20962306a36Sopenharmony_ci	tps65090_REG_FIXEDV(DCDC2, "vsys2",   0x0D, BIT(CTRL_EN_BIT), 3300000,
21062306a36Sopenharmony_ci			    tps65090_reg_control_ops),
21162306a36Sopenharmony_ci	tps65090_REG_SWITCH(DCDC3, "vsys3",   0x0E, BIT(CTRL_EN_BIT),
21262306a36Sopenharmony_ci			    tps65090_reg_control_ops),
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	tps65090_REG_SWITCH(FET1,  "infet1",  0x0F,
21562306a36Sopenharmony_ci			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
21662306a36Sopenharmony_ci			    tps65090_fet_control_ops),
21762306a36Sopenharmony_ci	tps65090_REG_SWITCH(FET2,  "infet2",  0x10,
21862306a36Sopenharmony_ci			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
21962306a36Sopenharmony_ci			    tps65090_fet_control_ops),
22062306a36Sopenharmony_ci	tps65090_REG_SWITCH(FET3,  "infet3",  0x11,
22162306a36Sopenharmony_ci			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
22262306a36Sopenharmony_ci			    tps65090_fet_control_ops),
22362306a36Sopenharmony_ci	tps65090_REG_SWITCH(FET4,  "infet4",  0x12,
22462306a36Sopenharmony_ci			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
22562306a36Sopenharmony_ci			    tps65090_fet_control_ops),
22662306a36Sopenharmony_ci	tps65090_REG_SWITCH(FET5,  "infet5",  0x13,
22762306a36Sopenharmony_ci			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
22862306a36Sopenharmony_ci			    tps65090_fet_control_ops),
22962306a36Sopenharmony_ci	tps65090_REG_SWITCH(FET6,  "infet6",  0x14,
23062306a36Sopenharmony_ci			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
23162306a36Sopenharmony_ci			    tps65090_fet_control_ops),
23262306a36Sopenharmony_ci	tps65090_REG_SWITCH(FET7,  "infet7",  0x15,
23362306a36Sopenharmony_ci			    BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
23462306a36Sopenharmony_ci			    tps65090_fet_control_ops),
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	tps65090_REG_FIXEDV(LDO1,  "vsys-l1", 0, 0, 5000000,
23762306a36Sopenharmony_ci			    tps65090_ldo_ops),
23862306a36Sopenharmony_ci	tps65090_REG_FIXEDV(LDO2,  "vsys-l2", 0, 0, 3300000,
23962306a36Sopenharmony_ci			    tps65090_ldo_ops),
24062306a36Sopenharmony_ci};
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_cistatic inline bool is_dcdc(int id)
24362306a36Sopenharmony_ci{
24462306a36Sopenharmony_ci	switch (id) {
24562306a36Sopenharmony_ci	case TPS65090_REGULATOR_DCDC1:
24662306a36Sopenharmony_ci	case TPS65090_REGULATOR_DCDC2:
24762306a36Sopenharmony_ci	case TPS65090_REGULATOR_DCDC3:
24862306a36Sopenharmony_ci		return true;
24962306a36Sopenharmony_ci	default:
25062306a36Sopenharmony_ci		return false;
25162306a36Sopenharmony_ci	}
25262306a36Sopenharmony_ci}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_cistatic int tps65090_config_ext_control(
25562306a36Sopenharmony_ci	struct tps65090_regulator *ri, bool enable)
25662306a36Sopenharmony_ci{
25762306a36Sopenharmony_ci	int ret;
25862306a36Sopenharmony_ci	struct device *parent = ri->dev->parent;
25962306a36Sopenharmony_ci	unsigned int reg_en_reg = ri->desc->enable_reg;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	if (enable)
26262306a36Sopenharmony_ci		ret = tps65090_set_bits(parent, reg_en_reg, 1);
26362306a36Sopenharmony_ci	else
26462306a36Sopenharmony_ci		ret =  tps65090_clr_bits(parent, reg_en_reg, 1);
26562306a36Sopenharmony_ci	if (ret < 0)
26662306a36Sopenharmony_ci		dev_err(ri->dev, "Error in updating reg 0x%x\n", reg_en_reg);
26762306a36Sopenharmony_ci	return ret;
26862306a36Sopenharmony_ci}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_cistatic int tps65090_regulator_disable_ext_control(
27162306a36Sopenharmony_ci		struct tps65090_regulator *ri,
27262306a36Sopenharmony_ci		struct tps65090_regulator_plat_data *tps_pdata)
27362306a36Sopenharmony_ci{
27462306a36Sopenharmony_ci	int ret = 0;
27562306a36Sopenharmony_ci	struct device *parent = ri->dev->parent;
27662306a36Sopenharmony_ci	unsigned int reg_en_reg = ri->desc->enable_reg;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	/*
27962306a36Sopenharmony_ci	 * First enable output for internal control if require.
28062306a36Sopenharmony_ci	 * And then disable external control.
28162306a36Sopenharmony_ci	 */
28262306a36Sopenharmony_ci	if (tps_pdata->reg_init_data->constraints.always_on ||
28362306a36Sopenharmony_ci			tps_pdata->reg_init_data->constraints.boot_on) {
28462306a36Sopenharmony_ci		ret =  tps65090_set_bits(parent, reg_en_reg, 0);
28562306a36Sopenharmony_ci		if (ret < 0) {
28662306a36Sopenharmony_ci			dev_err(ri->dev, "Error in set reg 0x%x\n", reg_en_reg);
28762306a36Sopenharmony_ci			return ret;
28862306a36Sopenharmony_ci		}
28962306a36Sopenharmony_ci	}
29062306a36Sopenharmony_ci	return tps65090_config_ext_control(ri, false);
29162306a36Sopenharmony_ci}
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci#ifdef CONFIG_OF
29462306a36Sopenharmony_cistatic struct of_regulator_match tps65090_matches[] = {
29562306a36Sopenharmony_ci	{ .name = "dcdc1", },
29662306a36Sopenharmony_ci	{ .name = "dcdc2", },
29762306a36Sopenharmony_ci	{ .name = "dcdc3", },
29862306a36Sopenharmony_ci	{ .name = "fet1",  },
29962306a36Sopenharmony_ci	{ .name = "fet2",  },
30062306a36Sopenharmony_ci	{ .name = "fet3",  },
30162306a36Sopenharmony_ci	{ .name = "fet4",  },
30262306a36Sopenharmony_ci	{ .name = "fet5",  },
30362306a36Sopenharmony_ci	{ .name = "fet6",  },
30462306a36Sopenharmony_ci	{ .name = "fet7",  },
30562306a36Sopenharmony_ci	{ .name = "ldo1",  },
30662306a36Sopenharmony_ci	{ .name = "ldo2",  },
30762306a36Sopenharmony_ci};
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_cistatic struct tps65090_platform_data *tps65090_parse_dt_reg_data(
31062306a36Sopenharmony_ci		struct platform_device *pdev,
31162306a36Sopenharmony_ci		struct of_regulator_match **tps65090_reg_matches)
31262306a36Sopenharmony_ci{
31362306a36Sopenharmony_ci	struct tps65090_platform_data *tps65090_pdata;
31462306a36Sopenharmony_ci	struct device_node *np = pdev->dev.parent->of_node;
31562306a36Sopenharmony_ci	struct device_node *regulators;
31662306a36Sopenharmony_ci	int idx = 0, ret;
31762306a36Sopenharmony_ci	struct tps65090_regulator_plat_data *reg_pdata;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	tps65090_pdata = devm_kzalloc(&pdev->dev, sizeof(*tps65090_pdata),
32062306a36Sopenharmony_ci				GFP_KERNEL);
32162306a36Sopenharmony_ci	if (!tps65090_pdata)
32262306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	reg_pdata = devm_kcalloc(&pdev->dev,
32562306a36Sopenharmony_ci				 TPS65090_REGULATOR_MAX, sizeof(*reg_pdata),
32662306a36Sopenharmony_ci				 GFP_KERNEL);
32762306a36Sopenharmony_ci	if (!reg_pdata)
32862306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	regulators = of_get_child_by_name(np, "regulators");
33162306a36Sopenharmony_ci	if (!regulators) {
33262306a36Sopenharmony_ci		dev_err(&pdev->dev, "regulator node not found\n");
33362306a36Sopenharmony_ci		return ERR_PTR(-ENODEV);
33462306a36Sopenharmony_ci	}
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	ret = of_regulator_match(&pdev->dev, regulators, tps65090_matches,
33762306a36Sopenharmony_ci			ARRAY_SIZE(tps65090_matches));
33862306a36Sopenharmony_ci	of_node_put(regulators);
33962306a36Sopenharmony_ci	if (ret < 0) {
34062306a36Sopenharmony_ci		dev_err(&pdev->dev,
34162306a36Sopenharmony_ci			"Error parsing regulator init data: %d\n", ret);
34262306a36Sopenharmony_ci		return ERR_PTR(ret);
34362306a36Sopenharmony_ci	}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	*tps65090_reg_matches = tps65090_matches;
34662306a36Sopenharmony_ci	for (idx = 0; idx < ARRAY_SIZE(tps65090_matches); idx++) {
34762306a36Sopenharmony_ci		struct regulator_init_data *ri_data;
34862306a36Sopenharmony_ci		struct tps65090_regulator_plat_data *rpdata;
34962306a36Sopenharmony_ci		struct device_node *np;
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci		rpdata = &reg_pdata[idx];
35262306a36Sopenharmony_ci		ri_data = tps65090_matches[idx].init_data;
35362306a36Sopenharmony_ci		if (!ri_data)
35462306a36Sopenharmony_ci			continue;
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci		np = tps65090_matches[idx].of_node;
35762306a36Sopenharmony_ci		if (!np)
35862306a36Sopenharmony_ci			continue;
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci		rpdata->reg_init_data = ri_data;
36162306a36Sopenharmony_ci		rpdata->enable_ext_control = of_property_read_bool(np,
36262306a36Sopenharmony_ci						"ti,enable-ext-control");
36362306a36Sopenharmony_ci		if (rpdata->enable_ext_control) {
36462306a36Sopenharmony_ci			enum gpiod_flags gflags;
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci			if (ri_data->constraints.always_on ||
36762306a36Sopenharmony_ci			    ri_data->constraints.boot_on)
36862306a36Sopenharmony_ci				gflags = GPIOD_OUT_HIGH;
36962306a36Sopenharmony_ci			else
37062306a36Sopenharmony_ci				gflags = GPIOD_OUT_LOW;
37162306a36Sopenharmony_ci			gflags |= GPIOD_FLAGS_BIT_NONEXCLUSIVE;
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci			rpdata->gpiod = devm_fwnode_gpiod_get(
37462306a36Sopenharmony_ci							&pdev->dev,
37562306a36Sopenharmony_ci							of_fwnode_handle(np),
37662306a36Sopenharmony_ci							"dcdc-ext-control",
37762306a36Sopenharmony_ci							gflags,
37862306a36Sopenharmony_ci							"tps65090");
37962306a36Sopenharmony_ci			if (PTR_ERR(rpdata->gpiod) == -ENOENT) {
38062306a36Sopenharmony_ci				dev_err(&pdev->dev,
38162306a36Sopenharmony_ci					"could not find DCDC external control GPIO\n");
38262306a36Sopenharmony_ci				rpdata->gpiod = NULL;
38362306a36Sopenharmony_ci			} else if (IS_ERR(rpdata->gpiod))
38462306a36Sopenharmony_ci				return ERR_CAST(rpdata->gpiod);
38562306a36Sopenharmony_ci		}
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci		if (of_property_read_u32(np, "ti,overcurrent-wait",
38862306a36Sopenharmony_ci					 &rpdata->overcurrent_wait) == 0)
38962306a36Sopenharmony_ci			rpdata->overcurrent_wait_valid = true;
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci		tps65090_pdata->reg_pdata[idx] = rpdata;
39262306a36Sopenharmony_ci	}
39362306a36Sopenharmony_ci	return tps65090_pdata;
39462306a36Sopenharmony_ci}
39562306a36Sopenharmony_ci#else
39662306a36Sopenharmony_cistatic inline struct tps65090_platform_data *tps65090_parse_dt_reg_data(
39762306a36Sopenharmony_ci			struct platform_device *pdev,
39862306a36Sopenharmony_ci			struct of_regulator_match **tps65090_reg_matches)
39962306a36Sopenharmony_ci{
40062306a36Sopenharmony_ci	*tps65090_reg_matches = NULL;
40162306a36Sopenharmony_ci	return NULL;
40262306a36Sopenharmony_ci}
40362306a36Sopenharmony_ci#endif
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_cistatic int tps65090_regulator_probe(struct platform_device *pdev)
40662306a36Sopenharmony_ci{
40762306a36Sopenharmony_ci	struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent);
40862306a36Sopenharmony_ci	struct tps65090_regulator *ri = NULL;
40962306a36Sopenharmony_ci	struct regulator_config config = { };
41062306a36Sopenharmony_ci	struct regulator_dev *rdev;
41162306a36Sopenharmony_ci	struct tps65090_regulator_plat_data *tps_pdata;
41262306a36Sopenharmony_ci	struct tps65090_regulator *pmic;
41362306a36Sopenharmony_ci	struct tps65090_platform_data *tps65090_pdata;
41462306a36Sopenharmony_ci	struct of_regulator_match *tps65090_reg_matches = NULL;
41562306a36Sopenharmony_ci	int num;
41662306a36Sopenharmony_ci	int ret;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	dev_dbg(&pdev->dev, "Probing regulator\n");
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	tps65090_pdata = dev_get_platdata(pdev->dev.parent);
42162306a36Sopenharmony_ci	if (!tps65090_pdata && tps65090_mfd->dev->of_node)
42262306a36Sopenharmony_ci		tps65090_pdata = tps65090_parse_dt_reg_data(pdev,
42362306a36Sopenharmony_ci					&tps65090_reg_matches);
42462306a36Sopenharmony_ci	if (IS_ERR_OR_NULL(tps65090_pdata)) {
42562306a36Sopenharmony_ci		dev_err(&pdev->dev, "Platform data missing\n");
42662306a36Sopenharmony_ci		return tps65090_pdata ? PTR_ERR(tps65090_pdata) : -EINVAL;
42762306a36Sopenharmony_ci	}
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	pmic = devm_kcalloc(&pdev->dev,
43062306a36Sopenharmony_ci			    TPS65090_REGULATOR_MAX, sizeof(*pmic),
43162306a36Sopenharmony_ci			    GFP_KERNEL);
43262306a36Sopenharmony_ci	if (!pmic)
43362306a36Sopenharmony_ci		return -ENOMEM;
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	for (num = 0; num < TPS65090_REGULATOR_MAX; num++) {
43662306a36Sopenharmony_ci		tps_pdata = tps65090_pdata->reg_pdata[num];
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci		ri = &pmic[num];
43962306a36Sopenharmony_ci		ri->dev = &pdev->dev;
44062306a36Sopenharmony_ci		ri->desc = &tps65090_regulator_desc[num];
44162306a36Sopenharmony_ci		if (tps_pdata) {
44262306a36Sopenharmony_ci			ri->overcurrent_wait_valid =
44362306a36Sopenharmony_ci				tps_pdata->overcurrent_wait_valid;
44462306a36Sopenharmony_ci			ri->overcurrent_wait = tps_pdata->overcurrent_wait;
44562306a36Sopenharmony_ci		}
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci		/*
44862306a36Sopenharmony_ci		 * TPS5090 DCDC support the control from external digital input.
44962306a36Sopenharmony_ci		 * Configure it as per platform data.
45062306a36Sopenharmony_ci		 */
45162306a36Sopenharmony_ci		if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data) {
45262306a36Sopenharmony_ci			if (tps_pdata->enable_ext_control) {
45362306a36Sopenharmony_ci				config.ena_gpiod = tps_pdata->gpiod;
45462306a36Sopenharmony_ci				ri->desc->ops = &tps65090_ext_control_ops;
45562306a36Sopenharmony_ci			} else {
45662306a36Sopenharmony_ci				ret = tps65090_regulator_disable_ext_control(
45762306a36Sopenharmony_ci						ri, tps_pdata);
45862306a36Sopenharmony_ci				if (ret < 0) {
45962306a36Sopenharmony_ci					dev_err(&pdev->dev,
46062306a36Sopenharmony_ci						"failed disable ext control\n");
46162306a36Sopenharmony_ci					return ret;
46262306a36Sopenharmony_ci				}
46362306a36Sopenharmony_ci			}
46462306a36Sopenharmony_ci		}
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci		config.dev = pdev->dev.parent;
46762306a36Sopenharmony_ci		config.driver_data = ri;
46862306a36Sopenharmony_ci		config.regmap = tps65090_mfd->rmap;
46962306a36Sopenharmony_ci		if (tps_pdata)
47062306a36Sopenharmony_ci			config.init_data = tps_pdata->reg_init_data;
47162306a36Sopenharmony_ci		else
47262306a36Sopenharmony_ci			config.init_data = NULL;
47362306a36Sopenharmony_ci		if (tps65090_reg_matches)
47462306a36Sopenharmony_ci			config.of_node = tps65090_reg_matches[num].of_node;
47562306a36Sopenharmony_ci		else
47662306a36Sopenharmony_ci			config.of_node = NULL;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci		/*
47962306a36Sopenharmony_ci		 * Hand the GPIO descriptor management over to the regulator
48062306a36Sopenharmony_ci		 * core, remove it from devres management.
48162306a36Sopenharmony_ci		 */
48262306a36Sopenharmony_ci		if (config.ena_gpiod)
48362306a36Sopenharmony_ci			devm_gpiod_unhinge(&pdev->dev, config.ena_gpiod);
48462306a36Sopenharmony_ci		rdev = devm_regulator_register(&pdev->dev, ri->desc, &config);
48562306a36Sopenharmony_ci		if (IS_ERR(rdev)) {
48662306a36Sopenharmony_ci			dev_err(&pdev->dev, "failed to register regulator %s\n",
48762306a36Sopenharmony_ci				ri->desc->name);
48862306a36Sopenharmony_ci			return PTR_ERR(rdev);
48962306a36Sopenharmony_ci		}
49062306a36Sopenharmony_ci		ri->rdev = rdev;
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci		if (ri->overcurrent_wait_valid) {
49362306a36Sopenharmony_ci			ret = tps65090_reg_set_overcurrent_wait(ri, rdev);
49462306a36Sopenharmony_ci			if (ret < 0)
49562306a36Sopenharmony_ci				return ret;
49662306a36Sopenharmony_ci		}
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci		/* Enable external control if it is require */
49962306a36Sopenharmony_ci		if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data &&
50062306a36Sopenharmony_ci				tps_pdata->enable_ext_control) {
50162306a36Sopenharmony_ci			ret = tps65090_config_ext_control(ri, true);
50262306a36Sopenharmony_ci			if (ret < 0)
50362306a36Sopenharmony_ci				return ret;
50462306a36Sopenharmony_ci		}
50562306a36Sopenharmony_ci	}
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	platform_set_drvdata(pdev, pmic);
50862306a36Sopenharmony_ci	return 0;
50962306a36Sopenharmony_ci}
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_cistatic struct platform_driver tps65090_regulator_driver = {
51262306a36Sopenharmony_ci	.driver	= {
51362306a36Sopenharmony_ci		.name	= "tps65090-pmic",
51462306a36Sopenharmony_ci		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
51562306a36Sopenharmony_ci	},
51662306a36Sopenharmony_ci	.probe		= tps65090_regulator_probe,
51762306a36Sopenharmony_ci};
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_cistatic int __init tps65090_regulator_init(void)
52062306a36Sopenharmony_ci{
52162306a36Sopenharmony_ci	return platform_driver_register(&tps65090_regulator_driver);
52262306a36Sopenharmony_ci}
52362306a36Sopenharmony_cisubsys_initcall(tps65090_regulator_init);
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_cistatic void __exit tps65090_regulator_exit(void)
52662306a36Sopenharmony_ci{
52762306a36Sopenharmony_ci	platform_driver_unregister(&tps65090_regulator_driver);
52862306a36Sopenharmony_ci}
52962306a36Sopenharmony_cimodule_exit(tps65090_regulator_exit);
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ciMODULE_DESCRIPTION("tps65090 regulator driver");
53262306a36Sopenharmony_ciMODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
53362306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
53462306a36Sopenharmony_ciMODULE_ALIAS("platform:tps65090-pmic");
535