162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * TI TPS68470 PMIC operation region driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2017 Intel Corporation. All rights reserved.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Author: Rajmohan Mani <rajmohan.mani@intel.com>
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Based on drivers/acpi/pmic/intel_pmic* drivers
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/acpi.h>
1362306a36Sopenharmony_ci#include <linux/init.h>
1462306a36Sopenharmony_ci#include <linux/mfd/tps68470.h>
1562306a36Sopenharmony_ci#include <linux/platform_device.h>
1662306a36Sopenharmony_ci#include <linux/regmap.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistruct tps68470_pmic_table {
1962306a36Sopenharmony_ci	u32 address;		/* operation region address */
2062306a36Sopenharmony_ci	u32 reg;		/* corresponding register */
2162306a36Sopenharmony_ci	u32 bitmask;		/* bit mask for power, clock */
2262306a36Sopenharmony_ci};
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#define TI_PMIC_POWER_OPREGION_ID		0xB0
2562306a36Sopenharmony_ci#define TI_PMIC_VR_VAL_OPREGION_ID		0xB1
2662306a36Sopenharmony_ci#define TI_PMIC_CLOCK_OPREGION_ID		0xB2
2762306a36Sopenharmony_ci#define TI_PMIC_CLKFREQ_OPREGION_ID		0xB3
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistruct tps68470_pmic_opregion {
3062306a36Sopenharmony_ci	struct mutex lock;
3162306a36Sopenharmony_ci	struct regmap *regmap;
3262306a36Sopenharmony_ci};
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define S_IO_I2C_EN	(BIT(0) | BIT(1))
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistatic const struct tps68470_pmic_table power_table[] = {
3762306a36Sopenharmony_ci	{
3862306a36Sopenharmony_ci		.address = 0x00,
3962306a36Sopenharmony_ci		.reg = TPS68470_REG_S_I2C_CTL,
4062306a36Sopenharmony_ci		.bitmask = S_IO_I2C_EN,
4162306a36Sopenharmony_ci		/* S_I2C_CTL */
4262306a36Sopenharmony_ci	},
4362306a36Sopenharmony_ci	{
4462306a36Sopenharmony_ci		.address = 0x04,
4562306a36Sopenharmony_ci		.reg = TPS68470_REG_VCMCTL,
4662306a36Sopenharmony_ci		.bitmask = BIT(0),
4762306a36Sopenharmony_ci		/* VCMCTL */
4862306a36Sopenharmony_ci	},
4962306a36Sopenharmony_ci	{
5062306a36Sopenharmony_ci		.address = 0x08,
5162306a36Sopenharmony_ci		.reg = TPS68470_REG_VAUX1CTL,
5262306a36Sopenharmony_ci		.bitmask = BIT(0),
5362306a36Sopenharmony_ci		/* VAUX1_CTL */
5462306a36Sopenharmony_ci	},
5562306a36Sopenharmony_ci	{
5662306a36Sopenharmony_ci		.address = 0x0C,
5762306a36Sopenharmony_ci		.reg = TPS68470_REG_VAUX2CTL,
5862306a36Sopenharmony_ci		.bitmask = BIT(0),
5962306a36Sopenharmony_ci		/* VAUX2CTL */
6062306a36Sopenharmony_ci	},
6162306a36Sopenharmony_ci	{
6262306a36Sopenharmony_ci		.address = 0x10,
6362306a36Sopenharmony_ci		.reg = TPS68470_REG_VACTL,
6462306a36Sopenharmony_ci		.bitmask = BIT(0),
6562306a36Sopenharmony_ci		/* VACTL */
6662306a36Sopenharmony_ci	},
6762306a36Sopenharmony_ci	{
6862306a36Sopenharmony_ci		.address = 0x14,
6962306a36Sopenharmony_ci		.reg = TPS68470_REG_VDCTL,
7062306a36Sopenharmony_ci		.bitmask = BIT(0),
7162306a36Sopenharmony_ci		/* VDCTL */
7262306a36Sopenharmony_ci	},
7362306a36Sopenharmony_ci};
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci/* Table to set voltage regulator value */
7662306a36Sopenharmony_cistatic const struct tps68470_pmic_table vr_val_table[] = {
7762306a36Sopenharmony_ci	{
7862306a36Sopenharmony_ci		.address = 0x00,
7962306a36Sopenharmony_ci		.reg = TPS68470_REG_VSIOVAL,
8062306a36Sopenharmony_ci		.bitmask = TPS68470_VSIOVAL_IOVOLT_MASK,
8162306a36Sopenharmony_ci		/* TPS68470_REG_VSIOVAL */
8262306a36Sopenharmony_ci	},
8362306a36Sopenharmony_ci	{
8462306a36Sopenharmony_ci		.address = 0x04,
8562306a36Sopenharmony_ci		.reg = TPS68470_REG_VIOVAL,
8662306a36Sopenharmony_ci		.bitmask = TPS68470_VIOVAL_IOVOLT_MASK,
8762306a36Sopenharmony_ci		/* TPS68470_REG_VIOVAL */
8862306a36Sopenharmony_ci	},
8962306a36Sopenharmony_ci	{
9062306a36Sopenharmony_ci		.address = 0x08,
9162306a36Sopenharmony_ci		.reg = TPS68470_REG_VCMVAL,
9262306a36Sopenharmony_ci		.bitmask = TPS68470_VCMVAL_VCVOLT_MASK,
9362306a36Sopenharmony_ci		/* TPS68470_REG_VCMVAL */
9462306a36Sopenharmony_ci	},
9562306a36Sopenharmony_ci	{
9662306a36Sopenharmony_ci		.address = 0x0C,
9762306a36Sopenharmony_ci		.reg = TPS68470_REG_VAUX1VAL,
9862306a36Sopenharmony_ci		.bitmask = TPS68470_VAUX1VAL_AUX1VOLT_MASK,
9962306a36Sopenharmony_ci		/* TPS68470_REG_VAUX1VAL */
10062306a36Sopenharmony_ci	},
10162306a36Sopenharmony_ci	{
10262306a36Sopenharmony_ci		.address = 0x10,
10362306a36Sopenharmony_ci		.reg = TPS68470_REG_VAUX2VAL,
10462306a36Sopenharmony_ci		.bitmask = TPS68470_VAUX2VAL_AUX2VOLT_MASK,
10562306a36Sopenharmony_ci		/* TPS68470_REG_VAUX2VAL */
10662306a36Sopenharmony_ci	},
10762306a36Sopenharmony_ci	{
10862306a36Sopenharmony_ci		.address = 0x14,
10962306a36Sopenharmony_ci		.reg = TPS68470_REG_VAVAL,
11062306a36Sopenharmony_ci		.bitmask = TPS68470_VAVAL_AVOLT_MASK,
11162306a36Sopenharmony_ci		/* TPS68470_REG_VAVAL */
11262306a36Sopenharmony_ci	},
11362306a36Sopenharmony_ci	{
11462306a36Sopenharmony_ci		.address = 0x18,
11562306a36Sopenharmony_ci		.reg = TPS68470_REG_VDVAL,
11662306a36Sopenharmony_ci		.bitmask = TPS68470_VDVAL_DVOLT_MASK,
11762306a36Sopenharmony_ci		/* TPS68470_REG_VDVAL */
11862306a36Sopenharmony_ci	},
11962306a36Sopenharmony_ci};
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci/* Table to configure clock frequency */
12262306a36Sopenharmony_cistatic const struct tps68470_pmic_table clk_freq_table[] = {
12362306a36Sopenharmony_ci	{
12462306a36Sopenharmony_ci		.address = 0x00,
12562306a36Sopenharmony_ci		.reg = TPS68470_REG_POSTDIV2,
12662306a36Sopenharmony_ci		.bitmask = BIT(0) | BIT(1),
12762306a36Sopenharmony_ci		/* TPS68470_REG_POSTDIV2 */
12862306a36Sopenharmony_ci	},
12962306a36Sopenharmony_ci	{
13062306a36Sopenharmony_ci		.address = 0x04,
13162306a36Sopenharmony_ci		.reg = TPS68470_REG_BOOSTDIV,
13262306a36Sopenharmony_ci		.bitmask = 0x1F,
13362306a36Sopenharmony_ci		/* TPS68470_REG_BOOSTDIV */
13462306a36Sopenharmony_ci	},
13562306a36Sopenharmony_ci	{
13662306a36Sopenharmony_ci		.address = 0x08,
13762306a36Sopenharmony_ci		.reg = TPS68470_REG_BUCKDIV,
13862306a36Sopenharmony_ci		.bitmask = 0x0F,
13962306a36Sopenharmony_ci		/* TPS68470_REG_BUCKDIV */
14062306a36Sopenharmony_ci	},
14162306a36Sopenharmony_ci	{
14262306a36Sopenharmony_ci		.address = 0x0C,
14362306a36Sopenharmony_ci		.reg = TPS68470_REG_PLLSWR,
14462306a36Sopenharmony_ci		.bitmask = 0x13,
14562306a36Sopenharmony_ci		/* TPS68470_REG_PLLSWR */
14662306a36Sopenharmony_ci	},
14762306a36Sopenharmony_ci	{
14862306a36Sopenharmony_ci		.address = 0x10,
14962306a36Sopenharmony_ci		.reg = TPS68470_REG_XTALDIV,
15062306a36Sopenharmony_ci		.bitmask = 0xFF,
15162306a36Sopenharmony_ci		/* TPS68470_REG_XTALDIV */
15262306a36Sopenharmony_ci	},
15362306a36Sopenharmony_ci	{
15462306a36Sopenharmony_ci		.address = 0x14,
15562306a36Sopenharmony_ci		.reg = TPS68470_REG_PLLDIV,
15662306a36Sopenharmony_ci		.bitmask = 0xFF,
15762306a36Sopenharmony_ci		/* TPS68470_REG_PLLDIV */
15862306a36Sopenharmony_ci	},
15962306a36Sopenharmony_ci	{
16062306a36Sopenharmony_ci		.address = 0x18,
16162306a36Sopenharmony_ci		.reg = TPS68470_REG_POSTDIV,
16262306a36Sopenharmony_ci		.bitmask = 0x83,
16362306a36Sopenharmony_ci		/* TPS68470_REG_POSTDIV */
16462306a36Sopenharmony_ci	},
16562306a36Sopenharmony_ci};
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci/* Table to configure and enable clocks */
16862306a36Sopenharmony_cistatic const struct tps68470_pmic_table clk_table[] = {
16962306a36Sopenharmony_ci	{
17062306a36Sopenharmony_ci		.address = 0x00,
17162306a36Sopenharmony_ci		.reg = TPS68470_REG_PLLCTL,
17262306a36Sopenharmony_ci		.bitmask = 0xF5,
17362306a36Sopenharmony_ci		/* TPS68470_REG_PLLCTL */
17462306a36Sopenharmony_ci	},
17562306a36Sopenharmony_ci	{
17662306a36Sopenharmony_ci		.address = 0x04,
17762306a36Sopenharmony_ci		.reg = TPS68470_REG_PLLCTL2,
17862306a36Sopenharmony_ci		.bitmask = BIT(0),
17962306a36Sopenharmony_ci		/* TPS68470_REG_PLLCTL2 */
18062306a36Sopenharmony_ci	},
18162306a36Sopenharmony_ci	{
18262306a36Sopenharmony_ci		.address = 0x08,
18362306a36Sopenharmony_ci		.reg = TPS68470_REG_CLKCFG1,
18462306a36Sopenharmony_ci		.bitmask = TPS68470_CLKCFG1_MODE_A_MASK |
18562306a36Sopenharmony_ci			TPS68470_CLKCFG1_MODE_B_MASK,
18662306a36Sopenharmony_ci		/* TPS68470_REG_CLKCFG1 */
18762306a36Sopenharmony_ci	},
18862306a36Sopenharmony_ci	{
18962306a36Sopenharmony_ci		.address = 0x0C,
19062306a36Sopenharmony_ci		.reg = TPS68470_REG_CLKCFG2,
19162306a36Sopenharmony_ci		.bitmask = TPS68470_CLKCFG1_MODE_A_MASK |
19262306a36Sopenharmony_ci			TPS68470_CLKCFG1_MODE_B_MASK,
19362306a36Sopenharmony_ci		/* TPS68470_REG_CLKCFG2 */
19462306a36Sopenharmony_ci	},
19562306a36Sopenharmony_ci};
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic int pmic_get_reg_bit(u64 address,
19862306a36Sopenharmony_ci			    const struct tps68470_pmic_table *table,
19962306a36Sopenharmony_ci			    const unsigned int table_size, int *reg,
20062306a36Sopenharmony_ci			    int *bitmask)
20162306a36Sopenharmony_ci{
20262306a36Sopenharmony_ci	u64 i;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	i = address / 4;
20562306a36Sopenharmony_ci	if (i >= table_size)
20662306a36Sopenharmony_ci		return -ENOENT;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	if (!reg || !bitmask)
20962306a36Sopenharmony_ci		return -EINVAL;
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	*reg = table[i].reg;
21262306a36Sopenharmony_ci	*bitmask = table[i].bitmask;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	return 0;
21562306a36Sopenharmony_ci}
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_cistatic int tps68470_pmic_get_power(struct regmap *regmap, int reg,
21862306a36Sopenharmony_ci				       int bitmask, u64 *value)
21962306a36Sopenharmony_ci{
22062306a36Sopenharmony_ci	unsigned int data;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	if (regmap_read(regmap, reg, &data))
22362306a36Sopenharmony_ci		return -EIO;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	*value = (data & bitmask) ? 1 : 0;
22662306a36Sopenharmony_ci	return 0;
22762306a36Sopenharmony_ci}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_cistatic int tps68470_pmic_get_vr_val(struct regmap *regmap, int reg,
23062306a36Sopenharmony_ci				       int bitmask, u64 *value)
23162306a36Sopenharmony_ci{
23262306a36Sopenharmony_ci	unsigned int data;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	if (regmap_read(regmap, reg, &data))
23562306a36Sopenharmony_ci		return -EIO;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	*value = data & bitmask;
23862306a36Sopenharmony_ci	return 0;
23962306a36Sopenharmony_ci}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_cistatic int tps68470_pmic_get_clk(struct regmap *regmap, int reg,
24262306a36Sopenharmony_ci				       int bitmask, u64 *value)
24362306a36Sopenharmony_ci{
24462306a36Sopenharmony_ci	unsigned int data;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	if (regmap_read(regmap, reg, &data))
24762306a36Sopenharmony_ci		return -EIO;
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	*value = (data & bitmask) ? 1 : 0;
25062306a36Sopenharmony_ci	return 0;
25162306a36Sopenharmony_ci}
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_cistatic int tps68470_pmic_get_clk_freq(struct regmap *regmap, int reg,
25462306a36Sopenharmony_ci				       int bitmask, u64 *value)
25562306a36Sopenharmony_ci{
25662306a36Sopenharmony_ci	unsigned int data;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	if (regmap_read(regmap, reg, &data))
25962306a36Sopenharmony_ci		return -EIO;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	*value = data & bitmask;
26262306a36Sopenharmony_ci	return 0;
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_cistatic int ti_tps68470_regmap_update_bits(struct regmap *regmap, int reg,
26662306a36Sopenharmony_ci					int bitmask, u64 value)
26762306a36Sopenharmony_ci{
26862306a36Sopenharmony_ci	return regmap_update_bits(regmap, reg, bitmask, value);
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_cistatic acpi_status tps68470_pmic_common_handler(u32 function,
27262306a36Sopenharmony_ci					  acpi_physical_address address,
27362306a36Sopenharmony_ci					  u32 bits, u64 *value,
27462306a36Sopenharmony_ci					  void *region_context,
27562306a36Sopenharmony_ci					  int (*get)(struct regmap *,
27662306a36Sopenharmony_ci						     int, int, u64 *),
27762306a36Sopenharmony_ci					  int (*update)(struct regmap *,
27862306a36Sopenharmony_ci							int, int, u64),
27962306a36Sopenharmony_ci					  const struct tps68470_pmic_table *tbl,
28062306a36Sopenharmony_ci					  unsigned int tbl_size)
28162306a36Sopenharmony_ci{
28262306a36Sopenharmony_ci	struct tps68470_pmic_opregion *opregion = region_context;
28362306a36Sopenharmony_ci	struct regmap *regmap = opregion->regmap;
28462306a36Sopenharmony_ci	int reg, ret, bitmask;
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	if (bits != 32)
28762306a36Sopenharmony_ci		return AE_BAD_PARAMETER;
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	ret = pmic_get_reg_bit(address, tbl, tbl_size, &reg, &bitmask);
29062306a36Sopenharmony_ci	if (ret < 0)
29162306a36Sopenharmony_ci		return AE_BAD_PARAMETER;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	if (function == ACPI_WRITE && *value > bitmask)
29462306a36Sopenharmony_ci		return AE_BAD_PARAMETER;
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	mutex_lock(&opregion->lock);
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci	ret = (function == ACPI_READ) ?
29962306a36Sopenharmony_ci		get(regmap, reg, bitmask, value) :
30062306a36Sopenharmony_ci		update(regmap, reg, bitmask, *value);
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	mutex_unlock(&opregion->lock);
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	return ret ? AE_ERROR : AE_OK;
30562306a36Sopenharmony_ci}
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_cistatic acpi_status tps68470_pmic_cfreq_handler(u32 function,
30862306a36Sopenharmony_ci					    acpi_physical_address address,
30962306a36Sopenharmony_ci					    u32 bits, u64 *value,
31062306a36Sopenharmony_ci					    void *handler_context,
31162306a36Sopenharmony_ci					    void *region_context)
31262306a36Sopenharmony_ci{
31362306a36Sopenharmony_ci	return tps68470_pmic_common_handler(function, address, bits, value,
31462306a36Sopenharmony_ci				region_context,
31562306a36Sopenharmony_ci				tps68470_pmic_get_clk_freq,
31662306a36Sopenharmony_ci				ti_tps68470_regmap_update_bits,
31762306a36Sopenharmony_ci				clk_freq_table,
31862306a36Sopenharmony_ci				ARRAY_SIZE(clk_freq_table));
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_cistatic acpi_status tps68470_pmic_clk_handler(u32 function,
32262306a36Sopenharmony_ci				       acpi_physical_address address, u32 bits,
32362306a36Sopenharmony_ci				       u64 *value, void *handler_context,
32462306a36Sopenharmony_ci				       void *region_context)
32562306a36Sopenharmony_ci{
32662306a36Sopenharmony_ci	return tps68470_pmic_common_handler(function, address, bits, value,
32762306a36Sopenharmony_ci				region_context,
32862306a36Sopenharmony_ci				tps68470_pmic_get_clk,
32962306a36Sopenharmony_ci				ti_tps68470_regmap_update_bits,
33062306a36Sopenharmony_ci				clk_table,
33162306a36Sopenharmony_ci				ARRAY_SIZE(clk_table));
33262306a36Sopenharmony_ci}
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_cistatic acpi_status tps68470_pmic_vrval_handler(u32 function,
33562306a36Sopenharmony_ci					  acpi_physical_address address,
33662306a36Sopenharmony_ci					  u32 bits, u64 *value,
33762306a36Sopenharmony_ci					  void *handler_context,
33862306a36Sopenharmony_ci					  void *region_context)
33962306a36Sopenharmony_ci{
34062306a36Sopenharmony_ci	return tps68470_pmic_common_handler(function, address, bits, value,
34162306a36Sopenharmony_ci				region_context,
34262306a36Sopenharmony_ci				tps68470_pmic_get_vr_val,
34362306a36Sopenharmony_ci				ti_tps68470_regmap_update_bits,
34462306a36Sopenharmony_ci				vr_val_table,
34562306a36Sopenharmony_ci				ARRAY_SIZE(vr_val_table));
34662306a36Sopenharmony_ci}
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_cistatic acpi_status tps68470_pmic_pwr_handler(u32 function,
34962306a36Sopenharmony_ci					 acpi_physical_address address,
35062306a36Sopenharmony_ci					 u32 bits, u64 *value,
35162306a36Sopenharmony_ci					 void *handler_context,
35262306a36Sopenharmony_ci					 void *region_context)
35362306a36Sopenharmony_ci{
35462306a36Sopenharmony_ci	if (bits != 32)
35562306a36Sopenharmony_ci		return AE_BAD_PARAMETER;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	/* set/clear for bit 0, bits 0 and 1 together */
35862306a36Sopenharmony_ci	if (function == ACPI_WRITE &&
35962306a36Sopenharmony_ci	    !(*value == 0 || *value == 1 || *value == 3)) {
36062306a36Sopenharmony_ci		return AE_BAD_PARAMETER;
36162306a36Sopenharmony_ci	}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	return tps68470_pmic_common_handler(function, address, bits, value,
36462306a36Sopenharmony_ci				region_context,
36562306a36Sopenharmony_ci				tps68470_pmic_get_power,
36662306a36Sopenharmony_ci				ti_tps68470_regmap_update_bits,
36762306a36Sopenharmony_ci				power_table,
36862306a36Sopenharmony_ci				ARRAY_SIZE(power_table));
36962306a36Sopenharmony_ci}
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_cistatic int tps68470_pmic_opregion_probe(struct platform_device *pdev)
37262306a36Sopenharmony_ci{
37362306a36Sopenharmony_ci	struct regmap *tps68470_regmap = dev_get_drvdata(pdev->dev.parent);
37462306a36Sopenharmony_ci	acpi_handle handle = ACPI_HANDLE(pdev->dev.parent);
37562306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
37662306a36Sopenharmony_ci	struct tps68470_pmic_opregion *opregion;
37762306a36Sopenharmony_ci	acpi_status status;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	if (!dev || !tps68470_regmap) {
38062306a36Sopenharmony_ci		dev_warn(dev, "dev or regmap is NULL\n");
38162306a36Sopenharmony_ci		return -EINVAL;
38262306a36Sopenharmony_ci	}
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci	if (!handle) {
38562306a36Sopenharmony_ci		dev_warn(dev, "acpi handle is NULL\n");
38662306a36Sopenharmony_ci		return -ENODEV;
38762306a36Sopenharmony_ci	}
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	opregion = devm_kzalloc(dev, sizeof(*opregion), GFP_KERNEL);
39062306a36Sopenharmony_ci	if (!opregion)
39162306a36Sopenharmony_ci		return -ENOMEM;
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	mutex_init(&opregion->lock);
39462306a36Sopenharmony_ci	opregion->regmap = tps68470_regmap;
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	status = acpi_install_address_space_handler(handle,
39762306a36Sopenharmony_ci						    TI_PMIC_POWER_OPREGION_ID,
39862306a36Sopenharmony_ci						    tps68470_pmic_pwr_handler,
39962306a36Sopenharmony_ci						    NULL, opregion);
40062306a36Sopenharmony_ci	if (ACPI_FAILURE(status))
40162306a36Sopenharmony_ci		goto out_mutex_destroy;
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	status = acpi_install_address_space_handler(handle,
40462306a36Sopenharmony_ci						    TI_PMIC_VR_VAL_OPREGION_ID,
40562306a36Sopenharmony_ci						    tps68470_pmic_vrval_handler,
40662306a36Sopenharmony_ci						    NULL, opregion);
40762306a36Sopenharmony_ci	if (ACPI_FAILURE(status))
40862306a36Sopenharmony_ci		goto out_remove_power_handler;
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	status = acpi_install_address_space_handler(handle,
41162306a36Sopenharmony_ci						    TI_PMIC_CLOCK_OPREGION_ID,
41262306a36Sopenharmony_ci						    tps68470_pmic_clk_handler,
41362306a36Sopenharmony_ci						    NULL, opregion);
41462306a36Sopenharmony_ci	if (ACPI_FAILURE(status))
41562306a36Sopenharmony_ci		goto out_remove_vr_val_handler;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	status = acpi_install_address_space_handler(handle,
41862306a36Sopenharmony_ci						    TI_PMIC_CLKFREQ_OPREGION_ID,
41962306a36Sopenharmony_ci						    tps68470_pmic_cfreq_handler,
42062306a36Sopenharmony_ci						    NULL, opregion);
42162306a36Sopenharmony_ci	if (ACPI_FAILURE(status))
42262306a36Sopenharmony_ci		goto out_remove_clk_handler;
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	return 0;
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ciout_remove_clk_handler:
42762306a36Sopenharmony_ci	acpi_remove_address_space_handler(handle, TI_PMIC_CLOCK_OPREGION_ID,
42862306a36Sopenharmony_ci					  tps68470_pmic_clk_handler);
42962306a36Sopenharmony_ciout_remove_vr_val_handler:
43062306a36Sopenharmony_ci	acpi_remove_address_space_handler(handle, TI_PMIC_VR_VAL_OPREGION_ID,
43162306a36Sopenharmony_ci					  tps68470_pmic_vrval_handler);
43262306a36Sopenharmony_ciout_remove_power_handler:
43362306a36Sopenharmony_ci	acpi_remove_address_space_handler(handle, TI_PMIC_POWER_OPREGION_ID,
43462306a36Sopenharmony_ci					  tps68470_pmic_pwr_handler);
43562306a36Sopenharmony_ciout_mutex_destroy:
43662306a36Sopenharmony_ci	mutex_destroy(&opregion->lock);
43762306a36Sopenharmony_ci	return -ENODEV;
43862306a36Sopenharmony_ci}
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_cistatic struct platform_driver tps68470_pmic_opregion_driver = {
44162306a36Sopenharmony_ci	.probe = tps68470_pmic_opregion_probe,
44262306a36Sopenharmony_ci	.driver = {
44362306a36Sopenharmony_ci		.name = "tps68470_pmic_opregion",
44462306a36Sopenharmony_ci	},
44562306a36Sopenharmony_ci};
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_cibuiltin_platform_driver(tps68470_pmic_opregion_driver)
448