162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2014, Sony Mobile Communications AB.
462306a36Sopenharmony_ci * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/module.h>
862306a36Sopenharmony_ci#include <linux/platform_device.h>
962306a36Sopenharmony_ci#include <linux/of.h>
1062306a36Sopenharmony_ci#include <linux/of_device.h>
1162306a36Sopenharmony_ci#include <linux/regulator/driver.h>
1262306a36Sopenharmony_ci#include <linux/regulator/machine.h>
1362306a36Sopenharmony_ci#include <linux/regulator/of_regulator.h>
1462306a36Sopenharmony_ci#include <linux/mfd/qcom_rpm.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include <dt-bindings/mfd/qcom-rpm.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#define MAX_REQUEST_LEN 2
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistruct request_member {
2162306a36Sopenharmony_ci	int		word;
2262306a36Sopenharmony_ci	unsigned int	mask;
2362306a36Sopenharmony_ci	int		shift;
2462306a36Sopenharmony_ci};
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cistruct rpm_reg_parts {
2762306a36Sopenharmony_ci	struct request_member mV;		/* used if voltage is in mV */
2862306a36Sopenharmony_ci	struct request_member uV;		/* used if voltage is in uV */
2962306a36Sopenharmony_ci	struct request_member ip;		/* peak current in mA */
3062306a36Sopenharmony_ci	struct request_member pd;		/* pull down enable */
3162306a36Sopenharmony_ci	struct request_member ia;		/* average current in mA */
3262306a36Sopenharmony_ci	struct request_member fm;		/* force mode */
3362306a36Sopenharmony_ci	struct request_member pm;		/* power mode */
3462306a36Sopenharmony_ci	struct request_member pc;		/* pin control */
3562306a36Sopenharmony_ci	struct request_member pf;		/* pin function */
3662306a36Sopenharmony_ci	struct request_member enable_state;	/* NCP and switch */
3762306a36Sopenharmony_ci	struct request_member comp_mode;	/* NCP */
3862306a36Sopenharmony_ci	struct request_member freq;		/* frequency: NCP and SMPS */
3962306a36Sopenharmony_ci	struct request_member freq_clk_src;	/* clock source: SMPS */
4062306a36Sopenharmony_ci	struct request_member hpm;		/* switch: control OCP and SS */
4162306a36Sopenharmony_ci	int request_len;
4262306a36Sopenharmony_ci};
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#define FORCE_MODE_IS_2_BITS(reg) \
4562306a36Sopenharmony_ci	(((reg)->parts->fm.mask >> (reg)->parts->fm.shift) == 3)
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistruct qcom_rpm_reg {
4862306a36Sopenharmony_ci	struct qcom_rpm *rpm;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	struct mutex lock;
5162306a36Sopenharmony_ci	struct device *dev;
5262306a36Sopenharmony_ci	struct regulator_desc desc;
5362306a36Sopenharmony_ci	const struct rpm_reg_parts *parts;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	int resource;
5662306a36Sopenharmony_ci	u32 val[MAX_REQUEST_LEN];
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	int uV;
5962306a36Sopenharmony_ci	int is_enabled;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	bool supports_force_mode_auto;
6262306a36Sopenharmony_ci	bool supports_force_mode_bypass;
6362306a36Sopenharmony_ci};
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic const struct rpm_reg_parts rpm8660_ldo_parts = {
6662306a36Sopenharmony_ci	.request_len    = 2,
6762306a36Sopenharmony_ci	.mV             = { 0, 0x00000FFF,  0 },
6862306a36Sopenharmony_ci	.ip             = { 0, 0x00FFF000, 12 },
6962306a36Sopenharmony_ci	.fm             = { 0, 0x03000000, 24 },
7062306a36Sopenharmony_ci	.pc             = { 0, 0x3C000000, 26 },
7162306a36Sopenharmony_ci	.pf             = { 0, 0xC0000000, 30 },
7262306a36Sopenharmony_ci	.pd             = { 1, 0x00000001,  0 },
7362306a36Sopenharmony_ci	.ia             = { 1, 0x00001FFE,  1 },
7462306a36Sopenharmony_ci};
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistatic const struct rpm_reg_parts rpm8660_smps_parts = {
7762306a36Sopenharmony_ci	.request_len    = 2,
7862306a36Sopenharmony_ci	.mV             = { 0, 0x00000FFF,  0 },
7962306a36Sopenharmony_ci	.ip             = { 0, 0x00FFF000, 12 },
8062306a36Sopenharmony_ci	.fm             = { 0, 0x03000000, 24 },
8162306a36Sopenharmony_ci	.pc             = { 0, 0x3C000000, 26 },
8262306a36Sopenharmony_ci	.pf             = { 0, 0xC0000000, 30 },
8362306a36Sopenharmony_ci	.pd             = { 1, 0x00000001,  0 },
8462306a36Sopenharmony_ci	.ia             = { 1, 0x00001FFE,  1 },
8562306a36Sopenharmony_ci	.freq           = { 1, 0x001FE000, 13 },
8662306a36Sopenharmony_ci	.freq_clk_src   = { 1, 0x00600000, 21 },
8762306a36Sopenharmony_ci};
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistatic const struct rpm_reg_parts rpm8660_switch_parts = {
9062306a36Sopenharmony_ci	.request_len    = 1,
9162306a36Sopenharmony_ci	.enable_state   = { 0, 0x00000001,  0 },
9262306a36Sopenharmony_ci	.pd             = { 0, 0x00000002,  1 },
9362306a36Sopenharmony_ci	.pc             = { 0, 0x0000003C,  2 },
9462306a36Sopenharmony_ci	.pf             = { 0, 0x000000C0,  6 },
9562306a36Sopenharmony_ci	.hpm            = { 0, 0x00000300,  8 },
9662306a36Sopenharmony_ci};
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic const struct rpm_reg_parts rpm8660_ncp_parts = {
9962306a36Sopenharmony_ci	.request_len    = 1,
10062306a36Sopenharmony_ci	.mV             = { 0, 0x00000FFF,  0 },
10162306a36Sopenharmony_ci	.enable_state   = { 0, 0x00001000, 12 },
10262306a36Sopenharmony_ci	.comp_mode      = { 0, 0x00002000, 13 },
10362306a36Sopenharmony_ci	.freq           = { 0, 0x003FC000, 14 },
10462306a36Sopenharmony_ci};
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_cistatic const struct rpm_reg_parts rpm8960_ldo_parts = {
10762306a36Sopenharmony_ci	.request_len    = 2,
10862306a36Sopenharmony_ci	.uV             = { 0, 0x007FFFFF,  0 },
10962306a36Sopenharmony_ci	.pd             = { 0, 0x00800000, 23 },
11062306a36Sopenharmony_ci	.pc             = { 0, 0x0F000000, 24 },
11162306a36Sopenharmony_ci	.pf             = { 0, 0xF0000000, 28 },
11262306a36Sopenharmony_ci	.ip             = { 1, 0x000003FF,  0 },
11362306a36Sopenharmony_ci	.ia             = { 1, 0x000FFC00, 10 },
11462306a36Sopenharmony_ci	.fm             = { 1, 0x00700000, 20 },
11562306a36Sopenharmony_ci};
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic const struct rpm_reg_parts rpm8960_smps_parts = {
11862306a36Sopenharmony_ci	.request_len    = 2,
11962306a36Sopenharmony_ci	.uV             = { 0, 0x007FFFFF,  0 },
12062306a36Sopenharmony_ci	.pd             = { 0, 0x00800000, 23 },
12162306a36Sopenharmony_ci	.pc             = { 0, 0x0F000000, 24 },
12262306a36Sopenharmony_ci	.pf             = { 0, 0xF0000000, 28 },
12362306a36Sopenharmony_ci	.ip             = { 1, 0x000003FF,  0 },
12462306a36Sopenharmony_ci	.ia             = { 1, 0x000FFC00, 10 },
12562306a36Sopenharmony_ci	.fm             = { 1, 0x00700000, 20 },
12662306a36Sopenharmony_ci	.pm             = { 1, 0x00800000, 23 },
12762306a36Sopenharmony_ci	.freq           = { 1, 0x1F000000, 24 },
12862306a36Sopenharmony_ci	.freq_clk_src   = { 1, 0x60000000, 29 },
12962306a36Sopenharmony_ci};
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cistatic const struct rpm_reg_parts rpm8960_switch_parts = {
13262306a36Sopenharmony_ci	.request_len    = 1,
13362306a36Sopenharmony_ci	.enable_state   = { 0, 0x00000001,  0 },
13462306a36Sopenharmony_ci	.pd             = { 0, 0x00000002,  1 },
13562306a36Sopenharmony_ci	.pc             = { 0, 0x0000003C,  2 },
13662306a36Sopenharmony_ci	.pf             = { 0, 0x000003C0,  6 },
13762306a36Sopenharmony_ci	.hpm            = { 0, 0x00000C00, 10 },
13862306a36Sopenharmony_ci};
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_cistatic const struct rpm_reg_parts rpm8960_ncp_parts = {
14162306a36Sopenharmony_ci	.request_len    = 1,
14262306a36Sopenharmony_ci	.uV             = { 0, 0x007FFFFF,  0 },
14362306a36Sopenharmony_ci	.enable_state   = { 0, 0x00800000, 23 },
14462306a36Sopenharmony_ci	.comp_mode      = { 0, 0x01000000, 24 },
14562306a36Sopenharmony_ci	.freq           = { 0, 0x3E000000, 25 },
14662306a36Sopenharmony_ci};
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci/*
14962306a36Sopenharmony_ci * Physically available PMIC regulator voltage ranges
15062306a36Sopenharmony_ci */
15162306a36Sopenharmony_cistatic const struct linear_range pldo_ranges[] = {
15262306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE( 750000,   0,  59, 12500),
15362306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1500000,  60, 123, 25000),
15462306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(3100000, 124, 160, 50000),
15562306a36Sopenharmony_ci};
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_cistatic const struct linear_range nldo_ranges[] = {
15862306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE( 750000,   0,  63, 12500),
15962306a36Sopenharmony_ci};
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic const struct linear_range nldo1200_ranges[] = {
16262306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE( 375000,   0,  59,  6250),
16362306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE( 750000,  60, 123, 12500),
16462306a36Sopenharmony_ci};
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_cistatic const struct linear_range smps_ranges[] = {
16762306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE( 375000,   0,  29, 12500),
16862306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE( 750000,  30,  89, 12500),
16962306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1500000,  90, 153, 25000),
17062306a36Sopenharmony_ci};
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_cistatic const struct linear_range ftsmps_ranges[] = {
17362306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE( 350000,   0,   6, 50000),
17462306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE( 700000,   7,  63, 12500),
17562306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1500000,  64, 100, 50000),
17662306a36Sopenharmony_ci};
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_cistatic const struct linear_range smb208_ranges[] = {
17962306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE( 375000,   0,  29, 12500),
18062306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE( 750000,  30,  89, 12500),
18162306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1500000,  90, 153, 25000),
18262306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(3100000, 154, 234, 25000),
18362306a36Sopenharmony_ci};
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_cistatic const struct linear_range ncp_ranges[] = {
18662306a36Sopenharmony_ci	REGULATOR_LINEAR_RANGE(1500000,   0,  31, 50000),
18762306a36Sopenharmony_ci};
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cistatic int rpm_reg_write(struct qcom_rpm_reg *vreg,
19062306a36Sopenharmony_ci			 const struct request_member *req,
19162306a36Sopenharmony_ci			 const int value)
19262306a36Sopenharmony_ci{
19362306a36Sopenharmony_ci	if (WARN_ON((value << req->shift) & ~req->mask))
19462306a36Sopenharmony_ci		return -EINVAL;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	vreg->val[req->word] &= ~req->mask;
19762306a36Sopenharmony_ci	vreg->val[req->word] |= value << req->shift;
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	return qcom_rpm_write(vreg->rpm,
20062306a36Sopenharmony_ci			      QCOM_RPM_ACTIVE_STATE,
20162306a36Sopenharmony_ci			      vreg->resource,
20262306a36Sopenharmony_ci			      vreg->val,
20362306a36Sopenharmony_ci			      vreg->parts->request_len);
20462306a36Sopenharmony_ci}
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistatic int rpm_reg_set_mV_sel(struct regulator_dev *rdev,
20762306a36Sopenharmony_ci			      unsigned selector)
20862306a36Sopenharmony_ci{
20962306a36Sopenharmony_ci	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
21062306a36Sopenharmony_ci	const struct rpm_reg_parts *parts = vreg->parts;
21162306a36Sopenharmony_ci	const struct request_member *req = &parts->mV;
21262306a36Sopenharmony_ci	int ret = 0;
21362306a36Sopenharmony_ci	int uV;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	if (req->mask == 0)
21662306a36Sopenharmony_ci		return -EINVAL;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	uV = regulator_list_voltage_linear_range(rdev, selector);
21962306a36Sopenharmony_ci	if (uV < 0)
22062306a36Sopenharmony_ci		return uV;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	mutex_lock(&vreg->lock);
22362306a36Sopenharmony_ci	if (vreg->is_enabled)
22462306a36Sopenharmony_ci		ret = rpm_reg_write(vreg, req, uV / 1000);
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	if (!ret)
22762306a36Sopenharmony_ci		vreg->uV = uV;
22862306a36Sopenharmony_ci	mutex_unlock(&vreg->lock);
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	return ret;
23162306a36Sopenharmony_ci}
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_cistatic int rpm_reg_set_uV_sel(struct regulator_dev *rdev,
23462306a36Sopenharmony_ci			      unsigned selector)
23562306a36Sopenharmony_ci{
23662306a36Sopenharmony_ci	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
23762306a36Sopenharmony_ci	const struct rpm_reg_parts *parts = vreg->parts;
23862306a36Sopenharmony_ci	const struct request_member *req = &parts->uV;
23962306a36Sopenharmony_ci	int ret = 0;
24062306a36Sopenharmony_ci	int uV;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	if (req->mask == 0)
24362306a36Sopenharmony_ci		return -EINVAL;
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci	uV = regulator_list_voltage_linear_range(rdev, selector);
24662306a36Sopenharmony_ci	if (uV < 0)
24762306a36Sopenharmony_ci		return uV;
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	mutex_lock(&vreg->lock);
25062306a36Sopenharmony_ci	if (vreg->is_enabled)
25162306a36Sopenharmony_ci		ret = rpm_reg_write(vreg, req, uV);
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	if (!ret)
25462306a36Sopenharmony_ci		vreg->uV = uV;
25562306a36Sopenharmony_ci	mutex_unlock(&vreg->lock);
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	return ret;
25862306a36Sopenharmony_ci}
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_cistatic int rpm_reg_get_voltage(struct regulator_dev *rdev)
26162306a36Sopenharmony_ci{
26262306a36Sopenharmony_ci	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	return vreg->uV;
26562306a36Sopenharmony_ci}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_cistatic int rpm_reg_mV_enable(struct regulator_dev *rdev)
26862306a36Sopenharmony_ci{
26962306a36Sopenharmony_ci	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
27062306a36Sopenharmony_ci	const struct rpm_reg_parts *parts = vreg->parts;
27162306a36Sopenharmony_ci	const struct request_member *req = &parts->mV;
27262306a36Sopenharmony_ci	int ret;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	if (req->mask == 0)
27562306a36Sopenharmony_ci		return -EINVAL;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	mutex_lock(&vreg->lock);
27862306a36Sopenharmony_ci	ret = rpm_reg_write(vreg, req, vreg->uV / 1000);
27962306a36Sopenharmony_ci	if (!ret)
28062306a36Sopenharmony_ci		vreg->is_enabled = 1;
28162306a36Sopenharmony_ci	mutex_unlock(&vreg->lock);
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	return ret;
28462306a36Sopenharmony_ci}
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_cistatic int rpm_reg_uV_enable(struct regulator_dev *rdev)
28762306a36Sopenharmony_ci{
28862306a36Sopenharmony_ci	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
28962306a36Sopenharmony_ci	const struct rpm_reg_parts *parts = vreg->parts;
29062306a36Sopenharmony_ci	const struct request_member *req = &parts->uV;
29162306a36Sopenharmony_ci	int ret;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	if (req->mask == 0)
29462306a36Sopenharmony_ci		return -EINVAL;
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	mutex_lock(&vreg->lock);
29762306a36Sopenharmony_ci	ret = rpm_reg_write(vreg, req, vreg->uV);
29862306a36Sopenharmony_ci	if (!ret)
29962306a36Sopenharmony_ci		vreg->is_enabled = 1;
30062306a36Sopenharmony_ci	mutex_unlock(&vreg->lock);
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	return ret;
30362306a36Sopenharmony_ci}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_cistatic int rpm_reg_switch_enable(struct regulator_dev *rdev)
30662306a36Sopenharmony_ci{
30762306a36Sopenharmony_ci	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
30862306a36Sopenharmony_ci	const struct rpm_reg_parts *parts = vreg->parts;
30962306a36Sopenharmony_ci	const struct request_member *req = &parts->enable_state;
31062306a36Sopenharmony_ci	int ret;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	if (req->mask == 0)
31362306a36Sopenharmony_ci		return -EINVAL;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	mutex_lock(&vreg->lock);
31662306a36Sopenharmony_ci	ret = rpm_reg_write(vreg, req, 1);
31762306a36Sopenharmony_ci	if (!ret)
31862306a36Sopenharmony_ci		vreg->is_enabled = 1;
31962306a36Sopenharmony_ci	mutex_unlock(&vreg->lock);
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	return ret;
32262306a36Sopenharmony_ci}
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_cistatic int rpm_reg_mV_disable(struct regulator_dev *rdev)
32562306a36Sopenharmony_ci{
32662306a36Sopenharmony_ci	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
32762306a36Sopenharmony_ci	const struct rpm_reg_parts *parts = vreg->parts;
32862306a36Sopenharmony_ci	const struct request_member *req = &parts->mV;
32962306a36Sopenharmony_ci	int ret;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	if (req->mask == 0)
33262306a36Sopenharmony_ci		return -EINVAL;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	mutex_lock(&vreg->lock);
33562306a36Sopenharmony_ci	ret = rpm_reg_write(vreg, req, 0);
33662306a36Sopenharmony_ci	if (!ret)
33762306a36Sopenharmony_ci		vreg->is_enabled = 0;
33862306a36Sopenharmony_ci	mutex_unlock(&vreg->lock);
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	return ret;
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_cistatic int rpm_reg_uV_disable(struct regulator_dev *rdev)
34462306a36Sopenharmony_ci{
34562306a36Sopenharmony_ci	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
34662306a36Sopenharmony_ci	const struct rpm_reg_parts *parts = vreg->parts;
34762306a36Sopenharmony_ci	const struct request_member *req = &parts->uV;
34862306a36Sopenharmony_ci	int ret;
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	if (req->mask == 0)
35162306a36Sopenharmony_ci		return -EINVAL;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	mutex_lock(&vreg->lock);
35462306a36Sopenharmony_ci	ret = rpm_reg_write(vreg, req, 0);
35562306a36Sopenharmony_ci	if (!ret)
35662306a36Sopenharmony_ci		vreg->is_enabled = 0;
35762306a36Sopenharmony_ci	mutex_unlock(&vreg->lock);
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	return ret;
36062306a36Sopenharmony_ci}
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_cistatic int rpm_reg_switch_disable(struct regulator_dev *rdev)
36362306a36Sopenharmony_ci{
36462306a36Sopenharmony_ci	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
36562306a36Sopenharmony_ci	const struct rpm_reg_parts *parts = vreg->parts;
36662306a36Sopenharmony_ci	const struct request_member *req = &parts->enable_state;
36762306a36Sopenharmony_ci	int ret;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	if (req->mask == 0)
37062306a36Sopenharmony_ci		return -EINVAL;
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci	mutex_lock(&vreg->lock);
37362306a36Sopenharmony_ci	ret = rpm_reg_write(vreg, req, 0);
37462306a36Sopenharmony_ci	if (!ret)
37562306a36Sopenharmony_ci		vreg->is_enabled = 0;
37662306a36Sopenharmony_ci	mutex_unlock(&vreg->lock);
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	return ret;
37962306a36Sopenharmony_ci}
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_cistatic int rpm_reg_is_enabled(struct regulator_dev *rdev)
38262306a36Sopenharmony_ci{
38362306a36Sopenharmony_ci	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	return vreg->is_enabled;
38662306a36Sopenharmony_ci}
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_cistatic int rpm_reg_set_load(struct regulator_dev *rdev, int load_uA)
38962306a36Sopenharmony_ci{
39062306a36Sopenharmony_ci	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
39162306a36Sopenharmony_ci	const struct rpm_reg_parts *parts = vreg->parts;
39262306a36Sopenharmony_ci	const struct request_member *req = &parts->ia;
39362306a36Sopenharmony_ci	int load_mA = load_uA / 1000;
39462306a36Sopenharmony_ci	int max_mA = req->mask >> req->shift;
39562306a36Sopenharmony_ci	int ret;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	if (req->mask == 0)
39862306a36Sopenharmony_ci		return -EINVAL;
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	if (load_mA > max_mA)
40162306a36Sopenharmony_ci		load_mA = max_mA;
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	mutex_lock(&vreg->lock);
40462306a36Sopenharmony_ci	ret = rpm_reg_write(vreg, req, load_mA);
40562306a36Sopenharmony_ci	mutex_unlock(&vreg->lock);
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	return ret;
40862306a36Sopenharmony_ci}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_cistatic const struct regulator_ops uV_ops = {
41162306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_linear_range,
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	.set_voltage_sel = rpm_reg_set_uV_sel,
41462306a36Sopenharmony_ci	.get_voltage = rpm_reg_get_voltage,
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	.enable = rpm_reg_uV_enable,
41762306a36Sopenharmony_ci	.disable = rpm_reg_uV_disable,
41862306a36Sopenharmony_ci	.is_enabled = rpm_reg_is_enabled,
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	.set_load = rpm_reg_set_load,
42162306a36Sopenharmony_ci};
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_cistatic const struct regulator_ops mV_ops = {
42462306a36Sopenharmony_ci	.list_voltage = regulator_list_voltage_linear_range,
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	.set_voltage_sel = rpm_reg_set_mV_sel,
42762306a36Sopenharmony_ci	.get_voltage = rpm_reg_get_voltage,
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	.enable = rpm_reg_mV_enable,
43062306a36Sopenharmony_ci	.disable = rpm_reg_mV_disable,
43162306a36Sopenharmony_ci	.is_enabled = rpm_reg_is_enabled,
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	.set_load = rpm_reg_set_load,
43462306a36Sopenharmony_ci};
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_cistatic const struct regulator_ops switch_ops = {
43762306a36Sopenharmony_ci	.enable = rpm_reg_switch_enable,
43862306a36Sopenharmony_ci	.disable = rpm_reg_switch_disable,
43962306a36Sopenharmony_ci	.is_enabled = rpm_reg_is_enabled,
44062306a36Sopenharmony_ci};
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci/*
44362306a36Sopenharmony_ci * PM8018 regulators
44462306a36Sopenharmony_ci */
44562306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8018_pldo = {
44662306a36Sopenharmony_ci	.desc.linear_ranges = pldo_ranges,
44762306a36Sopenharmony_ci	.desc.n_linear_ranges = ARRAY_SIZE(pldo_ranges),
44862306a36Sopenharmony_ci	.desc.n_voltages = 161,
44962306a36Sopenharmony_ci	.desc.ops = &uV_ops,
45062306a36Sopenharmony_ci	.parts = &rpm8960_ldo_parts,
45162306a36Sopenharmony_ci	.supports_force_mode_auto = false,
45262306a36Sopenharmony_ci	.supports_force_mode_bypass = false,
45362306a36Sopenharmony_ci};
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8018_nldo = {
45662306a36Sopenharmony_ci	.desc.linear_ranges = nldo_ranges,
45762306a36Sopenharmony_ci	.desc.n_linear_ranges = ARRAY_SIZE(nldo_ranges),
45862306a36Sopenharmony_ci	.desc.n_voltages = 64,
45962306a36Sopenharmony_ci	.desc.ops = &uV_ops,
46062306a36Sopenharmony_ci	.parts = &rpm8960_ldo_parts,
46162306a36Sopenharmony_ci	.supports_force_mode_auto = false,
46262306a36Sopenharmony_ci	.supports_force_mode_bypass = false,
46362306a36Sopenharmony_ci};
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8018_smps = {
46662306a36Sopenharmony_ci	.desc.linear_ranges = smps_ranges,
46762306a36Sopenharmony_ci	.desc.n_linear_ranges = ARRAY_SIZE(smps_ranges),
46862306a36Sopenharmony_ci	.desc.n_voltages = 154,
46962306a36Sopenharmony_ci	.desc.ops = &uV_ops,
47062306a36Sopenharmony_ci	.parts = &rpm8960_smps_parts,
47162306a36Sopenharmony_ci	.supports_force_mode_auto = false,
47262306a36Sopenharmony_ci	.supports_force_mode_bypass = false,
47362306a36Sopenharmony_ci};
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8018_switch = {
47662306a36Sopenharmony_ci	.desc.ops = &switch_ops,
47762306a36Sopenharmony_ci	.parts = &rpm8960_switch_parts,
47862306a36Sopenharmony_ci};
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci/*
48162306a36Sopenharmony_ci * PM8058 regulators
48262306a36Sopenharmony_ci */
48362306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8058_pldo = {
48462306a36Sopenharmony_ci	.desc.linear_ranges = pldo_ranges,
48562306a36Sopenharmony_ci	.desc.n_linear_ranges = ARRAY_SIZE(pldo_ranges),
48662306a36Sopenharmony_ci	.desc.n_voltages = 161,
48762306a36Sopenharmony_ci	.desc.ops = &mV_ops,
48862306a36Sopenharmony_ci	.parts = &rpm8660_ldo_parts,
48962306a36Sopenharmony_ci	.supports_force_mode_auto = false,
49062306a36Sopenharmony_ci	.supports_force_mode_bypass = false,
49162306a36Sopenharmony_ci};
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8058_nldo = {
49462306a36Sopenharmony_ci	.desc.linear_ranges = nldo_ranges,
49562306a36Sopenharmony_ci	.desc.n_linear_ranges = ARRAY_SIZE(nldo_ranges),
49662306a36Sopenharmony_ci	.desc.n_voltages = 64,
49762306a36Sopenharmony_ci	.desc.ops = &mV_ops,
49862306a36Sopenharmony_ci	.parts = &rpm8660_ldo_parts,
49962306a36Sopenharmony_ci	.supports_force_mode_auto = false,
50062306a36Sopenharmony_ci	.supports_force_mode_bypass = false,
50162306a36Sopenharmony_ci};
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8058_smps = {
50462306a36Sopenharmony_ci	.desc.linear_ranges = smps_ranges,
50562306a36Sopenharmony_ci	.desc.n_linear_ranges = ARRAY_SIZE(smps_ranges),
50662306a36Sopenharmony_ci	.desc.n_voltages = 154,
50762306a36Sopenharmony_ci	.desc.ops = &mV_ops,
50862306a36Sopenharmony_ci	.parts = &rpm8660_smps_parts,
50962306a36Sopenharmony_ci	.supports_force_mode_auto = false,
51062306a36Sopenharmony_ci	.supports_force_mode_bypass = false,
51162306a36Sopenharmony_ci};
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8058_ncp = {
51462306a36Sopenharmony_ci	.desc.linear_ranges = ncp_ranges,
51562306a36Sopenharmony_ci	.desc.n_linear_ranges = ARRAY_SIZE(ncp_ranges),
51662306a36Sopenharmony_ci	.desc.n_voltages = 32,
51762306a36Sopenharmony_ci	.desc.ops = &mV_ops,
51862306a36Sopenharmony_ci	.parts = &rpm8660_ncp_parts,
51962306a36Sopenharmony_ci};
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8058_switch = {
52262306a36Sopenharmony_ci	.desc.ops = &switch_ops,
52362306a36Sopenharmony_ci	.parts = &rpm8660_switch_parts,
52462306a36Sopenharmony_ci};
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci/*
52762306a36Sopenharmony_ci * PM8901 regulators
52862306a36Sopenharmony_ci */
52962306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8901_pldo = {
53062306a36Sopenharmony_ci	.desc.linear_ranges = pldo_ranges,
53162306a36Sopenharmony_ci	.desc.n_linear_ranges = ARRAY_SIZE(pldo_ranges),
53262306a36Sopenharmony_ci	.desc.n_voltages = 161,
53362306a36Sopenharmony_ci	.desc.ops = &mV_ops,
53462306a36Sopenharmony_ci	.parts = &rpm8660_ldo_parts,
53562306a36Sopenharmony_ci	.supports_force_mode_auto = false,
53662306a36Sopenharmony_ci	.supports_force_mode_bypass = true,
53762306a36Sopenharmony_ci};
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8901_nldo = {
54062306a36Sopenharmony_ci	.desc.linear_ranges = nldo_ranges,
54162306a36Sopenharmony_ci	.desc.n_linear_ranges = ARRAY_SIZE(nldo_ranges),
54262306a36Sopenharmony_ci	.desc.n_voltages = 64,
54362306a36Sopenharmony_ci	.desc.ops = &mV_ops,
54462306a36Sopenharmony_ci	.parts = &rpm8660_ldo_parts,
54562306a36Sopenharmony_ci	.supports_force_mode_auto = false,
54662306a36Sopenharmony_ci	.supports_force_mode_bypass = true,
54762306a36Sopenharmony_ci};
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8901_ftsmps = {
55062306a36Sopenharmony_ci	.desc.linear_ranges = ftsmps_ranges,
55162306a36Sopenharmony_ci	.desc.n_linear_ranges = ARRAY_SIZE(ftsmps_ranges),
55262306a36Sopenharmony_ci	.desc.n_voltages = 101,
55362306a36Sopenharmony_ci	.desc.ops = &mV_ops,
55462306a36Sopenharmony_ci	.parts = &rpm8660_smps_parts,
55562306a36Sopenharmony_ci	.supports_force_mode_auto = true,
55662306a36Sopenharmony_ci	.supports_force_mode_bypass = false,
55762306a36Sopenharmony_ci};
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8901_switch = {
56062306a36Sopenharmony_ci	.desc.ops = &switch_ops,
56162306a36Sopenharmony_ci	.parts = &rpm8660_switch_parts,
56262306a36Sopenharmony_ci};
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci/*
56562306a36Sopenharmony_ci * PM8921 regulators
56662306a36Sopenharmony_ci */
56762306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8921_pldo = {
56862306a36Sopenharmony_ci	.desc.linear_ranges = pldo_ranges,
56962306a36Sopenharmony_ci	.desc.n_linear_ranges = ARRAY_SIZE(pldo_ranges),
57062306a36Sopenharmony_ci	.desc.n_voltages = 161,
57162306a36Sopenharmony_ci	.desc.ops = &uV_ops,
57262306a36Sopenharmony_ci	.parts = &rpm8960_ldo_parts,
57362306a36Sopenharmony_ci	.supports_force_mode_auto = false,
57462306a36Sopenharmony_ci	.supports_force_mode_bypass = true,
57562306a36Sopenharmony_ci};
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8921_nldo = {
57862306a36Sopenharmony_ci	.desc.linear_ranges = nldo_ranges,
57962306a36Sopenharmony_ci	.desc.n_linear_ranges = ARRAY_SIZE(nldo_ranges),
58062306a36Sopenharmony_ci	.desc.n_voltages = 64,
58162306a36Sopenharmony_ci	.desc.ops = &uV_ops,
58262306a36Sopenharmony_ci	.parts = &rpm8960_ldo_parts,
58362306a36Sopenharmony_ci	.supports_force_mode_auto = false,
58462306a36Sopenharmony_ci	.supports_force_mode_bypass = true,
58562306a36Sopenharmony_ci};
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8921_nldo1200 = {
58862306a36Sopenharmony_ci	.desc.linear_ranges = nldo1200_ranges,
58962306a36Sopenharmony_ci	.desc.n_linear_ranges = ARRAY_SIZE(nldo1200_ranges),
59062306a36Sopenharmony_ci	.desc.n_voltages = 124,
59162306a36Sopenharmony_ci	.desc.ops = &uV_ops,
59262306a36Sopenharmony_ci	.parts = &rpm8960_ldo_parts,
59362306a36Sopenharmony_ci	.supports_force_mode_auto = false,
59462306a36Sopenharmony_ci	.supports_force_mode_bypass = true,
59562306a36Sopenharmony_ci};
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8921_smps = {
59862306a36Sopenharmony_ci	.desc.linear_ranges = smps_ranges,
59962306a36Sopenharmony_ci	.desc.n_linear_ranges = ARRAY_SIZE(smps_ranges),
60062306a36Sopenharmony_ci	.desc.n_voltages = 154,
60162306a36Sopenharmony_ci	.desc.ops = &uV_ops,
60262306a36Sopenharmony_ci	.parts = &rpm8960_smps_parts,
60362306a36Sopenharmony_ci	.supports_force_mode_auto = true,
60462306a36Sopenharmony_ci	.supports_force_mode_bypass = false,
60562306a36Sopenharmony_ci};
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8921_ncp = {
60862306a36Sopenharmony_ci	.desc.linear_ranges = ncp_ranges,
60962306a36Sopenharmony_ci	.desc.n_linear_ranges = ARRAY_SIZE(ncp_ranges),
61062306a36Sopenharmony_ci	.desc.n_voltages = 32,
61162306a36Sopenharmony_ci	.desc.ops = &uV_ops,
61262306a36Sopenharmony_ci	.parts = &rpm8960_ncp_parts,
61362306a36Sopenharmony_ci};
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_cistatic const struct qcom_rpm_reg pm8921_switch = {
61662306a36Sopenharmony_ci	.desc.ops = &switch_ops,
61762306a36Sopenharmony_ci	.parts = &rpm8960_switch_parts,
61862306a36Sopenharmony_ci};
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_cistatic const struct qcom_rpm_reg smb208_smps = {
62162306a36Sopenharmony_ci	.desc.linear_ranges = smb208_ranges,
62262306a36Sopenharmony_ci	.desc.n_linear_ranges = ARRAY_SIZE(smb208_ranges),
62362306a36Sopenharmony_ci	.desc.n_voltages = 235,
62462306a36Sopenharmony_ci	.desc.ops = &uV_ops,
62562306a36Sopenharmony_ci	.parts = &rpm8960_smps_parts,
62662306a36Sopenharmony_ci	.supports_force_mode_auto = false,
62762306a36Sopenharmony_ci	.supports_force_mode_bypass = false,
62862306a36Sopenharmony_ci};
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_cistatic int rpm_reg_set(struct qcom_rpm_reg *vreg,
63162306a36Sopenharmony_ci		       const struct request_member *req,
63262306a36Sopenharmony_ci		       const int value)
63362306a36Sopenharmony_ci{
63462306a36Sopenharmony_ci	if (req->mask == 0 || (value << req->shift) & ~req->mask)
63562306a36Sopenharmony_ci		return -EINVAL;
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci	vreg->val[req->word] &= ~req->mask;
63862306a36Sopenharmony_ci	vreg->val[req->word] |= value << req->shift;
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	return 0;
64162306a36Sopenharmony_ci}
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_cistatic int rpm_reg_of_parse_freq(struct device *dev,
64462306a36Sopenharmony_ci				 struct device_node *node,
64562306a36Sopenharmony_ci				 struct qcom_rpm_reg *vreg)
64662306a36Sopenharmony_ci{
64762306a36Sopenharmony_ci	static const int freq_table[] = {
64862306a36Sopenharmony_ci		19200000, 9600000, 6400000, 4800000, 3840000, 3200000, 2740000,
64962306a36Sopenharmony_ci		2400000, 2130000, 1920000, 1750000, 1600000, 1480000, 1370000,
65062306a36Sopenharmony_ci		1280000, 1200000,
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	};
65362306a36Sopenharmony_ci	const char *key;
65462306a36Sopenharmony_ci	u32 freq;
65562306a36Sopenharmony_ci	int ret;
65662306a36Sopenharmony_ci	int i;
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	key = "qcom,switch-mode-frequency";
65962306a36Sopenharmony_ci	ret = of_property_read_u32(node, key, &freq);
66062306a36Sopenharmony_ci	if (ret) {
66162306a36Sopenharmony_ci		dev_err(dev, "regulator requires %s property\n", key);
66262306a36Sopenharmony_ci		return -EINVAL;
66362306a36Sopenharmony_ci	}
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(freq_table); i++) {
66662306a36Sopenharmony_ci		if (freq == freq_table[i]) {
66762306a36Sopenharmony_ci			rpm_reg_set(vreg, &vreg->parts->freq, i + 1);
66862306a36Sopenharmony_ci			return 0;
66962306a36Sopenharmony_ci		}
67062306a36Sopenharmony_ci	}
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	dev_err(dev, "invalid frequency %d\n", freq);
67362306a36Sopenharmony_ci	return -EINVAL;
67462306a36Sopenharmony_ci}
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_cistatic int rpm_reg_of_parse(struct device_node *node,
67762306a36Sopenharmony_ci			    const struct regulator_desc *desc,
67862306a36Sopenharmony_ci			    struct regulator_config *config)
67962306a36Sopenharmony_ci{
68062306a36Sopenharmony_ci	struct qcom_rpm_reg *vreg = config->driver_data;
68162306a36Sopenharmony_ci	struct device *dev = config->dev;
68262306a36Sopenharmony_ci	const char *key;
68362306a36Sopenharmony_ci	u32 force_mode;
68462306a36Sopenharmony_ci	bool pwm;
68562306a36Sopenharmony_ci	u32 val;
68662306a36Sopenharmony_ci	int ret;
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci	key = "bias-pull-down";
68962306a36Sopenharmony_ci	if (of_property_read_bool(node, key)) {
69062306a36Sopenharmony_ci		ret = rpm_reg_set(vreg, &vreg->parts->pd, 1);
69162306a36Sopenharmony_ci		if (ret) {
69262306a36Sopenharmony_ci			dev_err(dev, "%s is invalid", key);
69362306a36Sopenharmony_ci			return ret;
69462306a36Sopenharmony_ci		}
69562306a36Sopenharmony_ci	}
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci	if (vreg->parts->freq.mask) {
69862306a36Sopenharmony_ci		ret = rpm_reg_of_parse_freq(dev, node, vreg);
69962306a36Sopenharmony_ci		if (ret < 0)
70062306a36Sopenharmony_ci			return ret;
70162306a36Sopenharmony_ci	}
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	if (vreg->parts->pm.mask) {
70462306a36Sopenharmony_ci		key = "qcom,power-mode-hysteretic";
70562306a36Sopenharmony_ci		pwm = !of_property_read_bool(node, key);
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci		ret = rpm_reg_set(vreg, &vreg->parts->pm, pwm);
70862306a36Sopenharmony_ci		if (ret) {
70962306a36Sopenharmony_ci			dev_err(dev, "failed to set power mode\n");
71062306a36Sopenharmony_ci			return ret;
71162306a36Sopenharmony_ci		}
71262306a36Sopenharmony_ci	}
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci	if (vreg->parts->fm.mask) {
71562306a36Sopenharmony_ci		force_mode = -1;
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_ci		key = "qcom,force-mode";
71862306a36Sopenharmony_ci		ret = of_property_read_u32(node, key, &val);
71962306a36Sopenharmony_ci		if (ret == -EINVAL) {
72062306a36Sopenharmony_ci			val = QCOM_RPM_FORCE_MODE_NONE;
72162306a36Sopenharmony_ci		} else if (ret < 0) {
72262306a36Sopenharmony_ci			dev_err(dev, "failed to read %s\n", key);
72362306a36Sopenharmony_ci			return ret;
72462306a36Sopenharmony_ci		}
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci		/*
72762306a36Sopenharmony_ci		 * If force-mode is encoded as 2 bits then the
72862306a36Sopenharmony_ci		 * possible register values are:
72962306a36Sopenharmony_ci		 * NONE, LPM, HPM
73062306a36Sopenharmony_ci		 * otherwise:
73162306a36Sopenharmony_ci		 * NONE, LPM, AUTO, HPM, BYPASS
73262306a36Sopenharmony_ci		 */
73362306a36Sopenharmony_ci		switch (val) {
73462306a36Sopenharmony_ci		case QCOM_RPM_FORCE_MODE_NONE:
73562306a36Sopenharmony_ci			force_mode = 0;
73662306a36Sopenharmony_ci			break;
73762306a36Sopenharmony_ci		case QCOM_RPM_FORCE_MODE_LPM:
73862306a36Sopenharmony_ci			force_mode = 1;
73962306a36Sopenharmony_ci			break;
74062306a36Sopenharmony_ci		case QCOM_RPM_FORCE_MODE_HPM:
74162306a36Sopenharmony_ci			if (FORCE_MODE_IS_2_BITS(vreg))
74262306a36Sopenharmony_ci				force_mode = 2;
74362306a36Sopenharmony_ci			else
74462306a36Sopenharmony_ci				force_mode = 3;
74562306a36Sopenharmony_ci			break;
74662306a36Sopenharmony_ci		case QCOM_RPM_FORCE_MODE_AUTO:
74762306a36Sopenharmony_ci			if (vreg->supports_force_mode_auto)
74862306a36Sopenharmony_ci				force_mode = 2;
74962306a36Sopenharmony_ci			break;
75062306a36Sopenharmony_ci		case QCOM_RPM_FORCE_MODE_BYPASS:
75162306a36Sopenharmony_ci			if (vreg->supports_force_mode_bypass)
75262306a36Sopenharmony_ci				force_mode = 4;
75362306a36Sopenharmony_ci			break;
75462306a36Sopenharmony_ci		}
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci		if (force_mode == -1) {
75762306a36Sopenharmony_ci			dev_err(dev, "invalid force mode\n");
75862306a36Sopenharmony_ci			return -EINVAL;
75962306a36Sopenharmony_ci		}
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_ci		ret = rpm_reg_set(vreg, &vreg->parts->fm, force_mode);
76262306a36Sopenharmony_ci		if (ret) {
76362306a36Sopenharmony_ci			dev_err(dev, "failed to set force mode\n");
76462306a36Sopenharmony_ci			return ret;
76562306a36Sopenharmony_ci		}
76662306a36Sopenharmony_ci	}
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci	return 0;
76962306a36Sopenharmony_ci}
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_cistruct rpm_regulator_data {
77262306a36Sopenharmony_ci	const char *name;
77362306a36Sopenharmony_ci	int resource;
77462306a36Sopenharmony_ci	const struct qcom_rpm_reg *template;
77562306a36Sopenharmony_ci	const char *supply;
77662306a36Sopenharmony_ci};
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_cistatic const struct rpm_regulator_data rpm_pm8018_regulators[] = {
77962306a36Sopenharmony_ci	{ "s1",  QCOM_RPM_PM8018_SMPS1, &pm8018_smps, "vdd_s1" },
78062306a36Sopenharmony_ci	{ "s2",  QCOM_RPM_PM8018_SMPS2, &pm8018_smps, "vdd_s2" },
78162306a36Sopenharmony_ci	{ "s3",  QCOM_RPM_PM8018_SMPS3, &pm8018_smps, "vdd_s3" },
78262306a36Sopenharmony_ci	{ "s4",  QCOM_RPM_PM8018_SMPS4, &pm8018_smps, "vdd_s4" },
78362306a36Sopenharmony_ci	{ "s5",  QCOM_RPM_PM8018_SMPS5, &pm8018_smps, "vdd_s5" },
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	{ "l2",  QCOM_RPM_PM8018_LDO2,  &pm8018_pldo, "vdd_l2" },
78662306a36Sopenharmony_ci	{ "l3",  QCOM_RPM_PM8018_LDO3,  &pm8018_pldo, "vdd_l3" },
78762306a36Sopenharmony_ci	{ "l4",  QCOM_RPM_PM8018_LDO4,  &pm8018_pldo, "vdd_l4" },
78862306a36Sopenharmony_ci	{ "l5",  QCOM_RPM_PM8018_LDO5,  &pm8018_pldo, "vdd_l5" },
78962306a36Sopenharmony_ci	{ "l6",  QCOM_RPM_PM8018_LDO6,  &pm8018_pldo, "vdd_l7" },
79062306a36Sopenharmony_ci	{ "l7",  QCOM_RPM_PM8018_LDO7,  &pm8018_pldo, "vdd_l7" },
79162306a36Sopenharmony_ci	{ "l8",  QCOM_RPM_PM8018_LDO8,  &pm8018_nldo, "vdd_l8" },
79262306a36Sopenharmony_ci	{ "l9",  QCOM_RPM_PM8018_LDO9,  &pm8921_nldo1200,
79362306a36Sopenharmony_ci						      "vdd_l9_l10_l11_l12" },
79462306a36Sopenharmony_ci	{ "l10", QCOM_RPM_PM8018_LDO10, &pm8018_nldo, "vdd_l9_l10_l11_l12" },
79562306a36Sopenharmony_ci	{ "l11", QCOM_RPM_PM8018_LDO11, &pm8018_nldo, "vdd_l9_l10_l11_l12" },
79662306a36Sopenharmony_ci	{ "l12", QCOM_RPM_PM8018_LDO12, &pm8018_nldo, "vdd_l9_l10_l11_l12" },
79762306a36Sopenharmony_ci	{ "l14", QCOM_RPM_PM8018_LDO14, &pm8018_pldo, "vdd_l14" },
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci	{ "lvs1", QCOM_RPM_PM8018_LVS1, &pm8018_switch, "lvs1_in" },
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci	{ }
80262306a36Sopenharmony_ci};
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_cistatic const struct rpm_regulator_data rpm_pm8058_regulators[] = {
80562306a36Sopenharmony_ci	{ "s0",   QCOM_RPM_PM8058_SMPS0,  &pm8058_smps, "vdd_s0" },
80662306a36Sopenharmony_ci	{ "s1",   QCOM_RPM_PM8058_SMPS1,  &pm8058_smps, "vdd_s1" },
80762306a36Sopenharmony_ci	{ "s2",   QCOM_RPM_PM8058_SMPS2,  &pm8058_smps, "vdd_s2" },
80862306a36Sopenharmony_ci	{ "s3",   QCOM_RPM_PM8058_SMPS3,  &pm8058_smps, "vdd_s3" },
80962306a36Sopenharmony_ci	{ "s4",   QCOM_RPM_PM8058_SMPS4,  &pm8058_smps, "vdd_s4" },
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci	{ "l0",   QCOM_RPM_PM8058_LDO0,   &pm8058_nldo, "vdd_l0_l1_lvs"	},
81262306a36Sopenharmony_ci	{ "l1",   QCOM_RPM_PM8058_LDO1,   &pm8058_nldo, "vdd_l0_l1_lvs" },
81362306a36Sopenharmony_ci	{ "l2",   QCOM_RPM_PM8058_LDO2,   &pm8058_pldo, "vdd_l2_l11_l12" },
81462306a36Sopenharmony_ci	{ "l3",   QCOM_RPM_PM8058_LDO3,   &pm8058_pldo, "vdd_l3_l4_l5" },
81562306a36Sopenharmony_ci	{ "l4",   QCOM_RPM_PM8058_LDO4,   &pm8058_pldo, "vdd_l3_l4_l5" },
81662306a36Sopenharmony_ci	{ "l5",   QCOM_RPM_PM8058_LDO5,   &pm8058_pldo, "vdd_l3_l4_l5" },
81762306a36Sopenharmony_ci	{ "l6",   QCOM_RPM_PM8058_LDO6,   &pm8058_pldo, "vdd_l6_l7" },
81862306a36Sopenharmony_ci	{ "l7",   QCOM_RPM_PM8058_LDO7,   &pm8058_pldo, "vdd_l6_l7" },
81962306a36Sopenharmony_ci	{ "l8",   QCOM_RPM_PM8058_LDO8,   &pm8058_pldo, "vdd_l8" },
82062306a36Sopenharmony_ci	{ "l9",   QCOM_RPM_PM8058_LDO9,   &pm8058_pldo, "vdd_l9" },
82162306a36Sopenharmony_ci	{ "l10",  QCOM_RPM_PM8058_LDO10,  &pm8058_pldo, "vdd_l10" },
82262306a36Sopenharmony_ci	{ "l11",  QCOM_RPM_PM8058_LDO11,  &pm8058_pldo, "vdd_l2_l11_l12" },
82362306a36Sopenharmony_ci	{ "l12",  QCOM_RPM_PM8058_LDO12,  &pm8058_pldo, "vdd_l2_l11_l12" },
82462306a36Sopenharmony_ci	{ "l13",  QCOM_RPM_PM8058_LDO13,  &pm8058_pldo, "vdd_l13_l16" },
82562306a36Sopenharmony_ci	{ "l14",  QCOM_RPM_PM8058_LDO14,  &pm8058_pldo, "vdd_l14_l15" },
82662306a36Sopenharmony_ci	{ "l15",  QCOM_RPM_PM8058_LDO15,  &pm8058_pldo, "vdd_l14_l15" },
82762306a36Sopenharmony_ci	{ "l16",  QCOM_RPM_PM8058_LDO16,  &pm8058_pldo, "vdd_l13_l16" },
82862306a36Sopenharmony_ci	{ "l17",  QCOM_RPM_PM8058_LDO17,  &pm8058_pldo, "vdd_l17_l18" },
82962306a36Sopenharmony_ci	{ "l18",  QCOM_RPM_PM8058_LDO18,  &pm8058_pldo, "vdd_l17_l18" },
83062306a36Sopenharmony_ci	{ "l19",  QCOM_RPM_PM8058_LDO19,  &pm8058_pldo, "vdd_l19_l20" },
83162306a36Sopenharmony_ci	{ "l20",  QCOM_RPM_PM8058_LDO20,  &pm8058_pldo, "vdd_l19_l20" },
83262306a36Sopenharmony_ci	{ "l21",  QCOM_RPM_PM8058_LDO21,  &pm8058_nldo, "vdd_l21" },
83362306a36Sopenharmony_ci	{ "l22",  QCOM_RPM_PM8058_LDO22,  &pm8058_nldo, "vdd_l22" },
83462306a36Sopenharmony_ci	{ "l23",  QCOM_RPM_PM8058_LDO23,  &pm8058_nldo, "vdd_l23_l24_l25" },
83562306a36Sopenharmony_ci	{ "l24",  QCOM_RPM_PM8058_LDO24,  &pm8058_nldo, "vdd_l23_l24_l25" },
83662306a36Sopenharmony_ci	{ "l25",  QCOM_RPM_PM8058_LDO25,  &pm8058_nldo, "vdd_l23_l24_l25" },
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	{ "lvs0", QCOM_RPM_PM8058_LVS0, &pm8058_switch, "vdd_l0_l1_lvs" },
83962306a36Sopenharmony_ci	{ "lvs1", QCOM_RPM_PM8058_LVS1, &pm8058_switch, "vdd_l0_l1_lvs" },
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci	{ "ncp",  QCOM_RPM_PM8058_NCP, &pm8058_ncp, "vdd_ncp" },
84262306a36Sopenharmony_ci	{ }
84362306a36Sopenharmony_ci};
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_cistatic const struct rpm_regulator_data rpm_pm8901_regulators[] = {
84662306a36Sopenharmony_ci	{ "s0",   QCOM_RPM_PM8901_SMPS0, &pm8901_ftsmps, "vdd_s0" },
84762306a36Sopenharmony_ci	{ "s1",   QCOM_RPM_PM8901_SMPS1, &pm8901_ftsmps, "vdd_s1" },
84862306a36Sopenharmony_ci	{ "s2",   QCOM_RPM_PM8901_SMPS2, &pm8901_ftsmps, "vdd_s2" },
84962306a36Sopenharmony_ci	{ "s3",   QCOM_RPM_PM8901_SMPS3, &pm8901_ftsmps, "vdd_s3" },
85062306a36Sopenharmony_ci	{ "s4",   QCOM_RPM_PM8901_SMPS4, &pm8901_ftsmps, "vdd_s4" },
85162306a36Sopenharmony_ci
85262306a36Sopenharmony_ci	{ "l0",   QCOM_RPM_PM8901_LDO0, &pm8901_nldo, "vdd_l0" },
85362306a36Sopenharmony_ci	{ "l1",   QCOM_RPM_PM8901_LDO1, &pm8901_pldo, "vdd_l1" },
85462306a36Sopenharmony_ci	{ "l2",   QCOM_RPM_PM8901_LDO2, &pm8901_pldo, "vdd_l2" },
85562306a36Sopenharmony_ci	{ "l3",   QCOM_RPM_PM8901_LDO3, &pm8901_pldo, "vdd_l3" },
85662306a36Sopenharmony_ci	{ "l4",   QCOM_RPM_PM8901_LDO4, &pm8901_pldo, "vdd_l4" },
85762306a36Sopenharmony_ci	{ "l5",   QCOM_RPM_PM8901_LDO5, &pm8901_pldo, "vdd_l5" },
85862306a36Sopenharmony_ci	{ "l6",   QCOM_RPM_PM8901_LDO6, &pm8901_pldo, "vdd_l6" },
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci	{ "lvs0", QCOM_RPM_PM8901_LVS0, &pm8901_switch, "lvs0_in" },
86162306a36Sopenharmony_ci	{ "lvs1", QCOM_RPM_PM8901_LVS1, &pm8901_switch, "lvs1_in" },
86262306a36Sopenharmony_ci	{ "lvs2", QCOM_RPM_PM8901_LVS2, &pm8901_switch, "lvs2_in" },
86362306a36Sopenharmony_ci	{ "lvs3", QCOM_RPM_PM8901_LVS3, &pm8901_switch, "lvs3_in" },
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci	{ "mvs", QCOM_RPM_PM8901_MVS, &pm8901_switch, "mvs_in" },
86662306a36Sopenharmony_ci	{ }
86762306a36Sopenharmony_ci};
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_cistatic const struct rpm_regulator_data rpm_pm8921_regulators[] = {
87062306a36Sopenharmony_ci	{ "s1",  QCOM_RPM_PM8921_SMPS1, &pm8921_smps, "vdd_s1" },
87162306a36Sopenharmony_ci	{ "s2",  QCOM_RPM_PM8921_SMPS2, &pm8921_smps, "vdd_s2" },
87262306a36Sopenharmony_ci	{ "s3",  QCOM_RPM_PM8921_SMPS3, &pm8921_smps },
87362306a36Sopenharmony_ci	{ "s4",  QCOM_RPM_PM8921_SMPS4, &pm8921_smps, "vdd_s4" },
87462306a36Sopenharmony_ci	{ "s7",  QCOM_RPM_PM8921_SMPS7, &pm8921_smps, "vdd_s7" },
87562306a36Sopenharmony_ci	{ "s8",  QCOM_RPM_PM8921_SMPS8, &pm8921_smps, "vdd_s8"  },
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci	{ "l1",  QCOM_RPM_PM8921_LDO1, &pm8921_nldo, "vdd_l1_l2_l12_l18" },
87862306a36Sopenharmony_ci	{ "l2",  QCOM_RPM_PM8921_LDO2, &pm8921_nldo, "vdd_l1_l2_l12_l18" },
87962306a36Sopenharmony_ci	{ "l3",  QCOM_RPM_PM8921_LDO3, &pm8921_pldo, "vdd_l3_l15_l17" },
88062306a36Sopenharmony_ci	{ "l4",  QCOM_RPM_PM8921_LDO4, &pm8921_pldo, "vdd_l4_l14" },
88162306a36Sopenharmony_ci	{ "l5",  QCOM_RPM_PM8921_LDO5, &pm8921_pldo, "vdd_l5_l8_l16" },
88262306a36Sopenharmony_ci	{ "l6",  QCOM_RPM_PM8921_LDO6, &pm8921_pldo, "vdd_l6_l7" },
88362306a36Sopenharmony_ci	{ "l7",  QCOM_RPM_PM8921_LDO7, &pm8921_pldo, "vdd_l6_l7" },
88462306a36Sopenharmony_ci	{ "l8",  QCOM_RPM_PM8921_LDO8, &pm8921_pldo, "vdd_l5_l8_l16" },
88562306a36Sopenharmony_ci	{ "l9",  QCOM_RPM_PM8921_LDO9, &pm8921_pldo, "vdd_l9_l11" },
88662306a36Sopenharmony_ci	{ "l10", QCOM_RPM_PM8921_LDO10, &pm8921_pldo, "vdd_l10_l22" },
88762306a36Sopenharmony_ci	{ "l11", QCOM_RPM_PM8921_LDO11, &pm8921_pldo, "vdd_l9_l11" },
88862306a36Sopenharmony_ci	{ "l12", QCOM_RPM_PM8921_LDO12, &pm8921_nldo, "vdd_l1_l2_l12_l18" },
88962306a36Sopenharmony_ci	{ "l14", QCOM_RPM_PM8921_LDO14, &pm8921_pldo, "vdd_l4_l14" },
89062306a36Sopenharmony_ci	{ "l15", QCOM_RPM_PM8921_LDO15, &pm8921_pldo, "vdd_l3_l15_l17" },
89162306a36Sopenharmony_ci	{ "l16", QCOM_RPM_PM8921_LDO16, &pm8921_pldo, "vdd_l5_l8_l16" },
89262306a36Sopenharmony_ci	{ "l17", QCOM_RPM_PM8921_LDO17, &pm8921_pldo, "vdd_l3_l15_l17" },
89362306a36Sopenharmony_ci	{ "l18", QCOM_RPM_PM8921_LDO18, &pm8921_nldo, "vdd_l1_l2_l12_l18" },
89462306a36Sopenharmony_ci	{ "l21", QCOM_RPM_PM8921_LDO21, &pm8921_pldo, "vdd_l21_l23_l29" },
89562306a36Sopenharmony_ci	{ "l22", QCOM_RPM_PM8921_LDO22, &pm8921_pldo, "vdd_l10_l22" },
89662306a36Sopenharmony_ci	{ "l23", QCOM_RPM_PM8921_LDO23, &pm8921_pldo, "vdd_l21_l23_l29" },
89762306a36Sopenharmony_ci	{ "l24", QCOM_RPM_PM8921_LDO24, &pm8921_nldo1200, "vdd_l24" },
89862306a36Sopenharmony_ci	{ "l25", QCOM_RPM_PM8921_LDO25, &pm8921_nldo1200, "vdd_l25" },
89962306a36Sopenharmony_ci	{ "l26", QCOM_RPM_PM8921_LDO26, &pm8921_nldo1200, "vdd_l26" },
90062306a36Sopenharmony_ci	{ "l27", QCOM_RPM_PM8921_LDO27, &pm8921_nldo1200, "vdd_l27" },
90162306a36Sopenharmony_ci	{ "l28", QCOM_RPM_PM8921_LDO28, &pm8921_nldo1200, "vdd_l28" },
90262306a36Sopenharmony_ci	{ "l29", QCOM_RPM_PM8921_LDO29, &pm8921_pldo, "vdd_l21_l23_l29" },
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci	{ "lvs1", QCOM_RPM_PM8921_LVS1, &pm8921_switch, "vin_lvs1_3_6" },
90562306a36Sopenharmony_ci	{ "lvs2", QCOM_RPM_PM8921_LVS2, &pm8921_switch, "vin_lvs2" },
90662306a36Sopenharmony_ci	{ "lvs3", QCOM_RPM_PM8921_LVS3, &pm8921_switch, "vin_lvs1_3_6" },
90762306a36Sopenharmony_ci	{ "lvs4", QCOM_RPM_PM8921_LVS4, &pm8921_switch, "vin_lvs4_5_7" },
90862306a36Sopenharmony_ci	{ "lvs5", QCOM_RPM_PM8921_LVS5, &pm8921_switch, "vin_lvs4_5_7" },
90962306a36Sopenharmony_ci	{ "lvs6", QCOM_RPM_PM8921_LVS6, &pm8921_switch, "vin_lvs1_3_6" },
91062306a36Sopenharmony_ci	{ "lvs7", QCOM_RPM_PM8921_LVS7, &pm8921_switch, "vin_lvs4_5_7" },
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	{ "usb-switch", QCOM_RPM_USB_OTG_SWITCH, &pm8921_switch, "vin_5vs" },
91362306a36Sopenharmony_ci	{ "hdmi-switch", QCOM_RPM_HDMI_SWITCH, &pm8921_switch, "vin_5vs" },
91462306a36Sopenharmony_ci	{ "ncp", QCOM_RPM_PM8921_NCP, &pm8921_ncp, "vdd_ncp" },
91562306a36Sopenharmony_ci	{ }
91662306a36Sopenharmony_ci};
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_cistatic const struct rpm_regulator_data rpm_smb208_regulators[] = {
91962306a36Sopenharmony_ci	{ "s1a",  QCOM_RPM_SMB208_S1a, &smb208_smps, "vin_s1a" },
92062306a36Sopenharmony_ci	{ "s1b",  QCOM_RPM_SMB208_S1b, &smb208_smps, "vin_s1b" },
92162306a36Sopenharmony_ci	{ "s2a",  QCOM_RPM_SMB208_S2a, &smb208_smps, "vin_s2a" },
92262306a36Sopenharmony_ci	{ "s2b",  QCOM_RPM_SMB208_S2b, &smb208_smps, "vin_s2b" },
92362306a36Sopenharmony_ci	{ }
92462306a36Sopenharmony_ci};
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_cistatic const struct of_device_id rpm_of_match[] = {
92762306a36Sopenharmony_ci	{ .compatible = "qcom,rpm-pm8018-regulators",
92862306a36Sopenharmony_ci		.data = &rpm_pm8018_regulators },
92962306a36Sopenharmony_ci	{ .compatible = "qcom,rpm-pm8058-regulators", .data = &rpm_pm8058_regulators },
93062306a36Sopenharmony_ci	{ .compatible = "qcom,rpm-pm8901-regulators", .data = &rpm_pm8901_regulators },
93162306a36Sopenharmony_ci	{ .compatible = "qcom,rpm-pm8921-regulators", .data = &rpm_pm8921_regulators },
93262306a36Sopenharmony_ci	{ .compatible = "qcom,rpm-smb208-regulators", .data = &rpm_smb208_regulators },
93362306a36Sopenharmony_ci	{ }
93462306a36Sopenharmony_ci};
93562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, rpm_of_match);
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_cistatic int rpm_reg_probe(struct platform_device *pdev)
93862306a36Sopenharmony_ci{
93962306a36Sopenharmony_ci	const struct rpm_regulator_data *reg;
94062306a36Sopenharmony_ci	const struct of_device_id *match;
94162306a36Sopenharmony_ci	struct regulator_config config = { };
94262306a36Sopenharmony_ci	struct regulator_dev *rdev;
94362306a36Sopenharmony_ci	struct qcom_rpm_reg *vreg;
94462306a36Sopenharmony_ci	struct qcom_rpm *rpm;
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci	rpm = dev_get_drvdata(pdev->dev.parent);
94762306a36Sopenharmony_ci	if (!rpm) {
94862306a36Sopenharmony_ci		dev_err(&pdev->dev, "unable to retrieve handle to rpm\n");
94962306a36Sopenharmony_ci		return -ENODEV;
95062306a36Sopenharmony_ci	}
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci	match = of_match_device(rpm_of_match, &pdev->dev);
95362306a36Sopenharmony_ci	if (!match) {
95462306a36Sopenharmony_ci		dev_err(&pdev->dev, "failed to match device\n");
95562306a36Sopenharmony_ci		return -ENODEV;
95662306a36Sopenharmony_ci	}
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_ci	for (reg = match->data; reg->name; reg++) {
95962306a36Sopenharmony_ci		vreg = devm_kmemdup(&pdev->dev, reg->template, sizeof(*vreg), GFP_KERNEL);
96062306a36Sopenharmony_ci		if (!vreg)
96162306a36Sopenharmony_ci			return -ENOMEM;
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_ci		mutex_init(&vreg->lock);
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci		vreg->dev = &pdev->dev;
96662306a36Sopenharmony_ci		vreg->resource = reg->resource;
96762306a36Sopenharmony_ci		vreg->rpm = rpm;
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci		vreg->desc.id = -1;
97062306a36Sopenharmony_ci		vreg->desc.owner = THIS_MODULE;
97162306a36Sopenharmony_ci		vreg->desc.type = REGULATOR_VOLTAGE;
97262306a36Sopenharmony_ci		vreg->desc.name = reg->name;
97362306a36Sopenharmony_ci		vreg->desc.supply_name = reg->supply;
97462306a36Sopenharmony_ci		vreg->desc.of_match = reg->name;
97562306a36Sopenharmony_ci		vreg->desc.of_parse_cb = rpm_reg_of_parse;
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci		config.dev = &pdev->dev;
97862306a36Sopenharmony_ci		config.driver_data = vreg;
97962306a36Sopenharmony_ci		rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config);
98062306a36Sopenharmony_ci		if (IS_ERR(rdev)) {
98162306a36Sopenharmony_ci			dev_err(&pdev->dev, "failed to register %s\n", reg->name);
98262306a36Sopenharmony_ci			return PTR_ERR(rdev);
98362306a36Sopenharmony_ci		}
98462306a36Sopenharmony_ci	}
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_ci	return 0;
98762306a36Sopenharmony_ci}
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_cistatic struct platform_driver rpm_reg_driver = {
99062306a36Sopenharmony_ci	.probe          = rpm_reg_probe,
99162306a36Sopenharmony_ci	.driver  = {
99262306a36Sopenharmony_ci		.name  = "qcom_rpm_reg",
99362306a36Sopenharmony_ci		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
99462306a36Sopenharmony_ci		.of_match_table = of_match_ptr(rpm_of_match),
99562306a36Sopenharmony_ci	},
99662306a36Sopenharmony_ci};
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_cistatic int __init rpm_reg_init(void)
99962306a36Sopenharmony_ci{
100062306a36Sopenharmony_ci	return platform_driver_register(&rpm_reg_driver);
100162306a36Sopenharmony_ci}
100262306a36Sopenharmony_cisubsys_initcall(rpm_reg_init);
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_cistatic void __exit rpm_reg_exit(void)
100562306a36Sopenharmony_ci{
100662306a36Sopenharmony_ci	platform_driver_unregister(&rpm_reg_driver);
100762306a36Sopenharmony_ci}
100862306a36Sopenharmony_cimodule_exit(rpm_reg_exit)
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ciMODULE_DESCRIPTION("Qualcomm RPM regulator driver");
101162306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
1012