162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Core, IRQ and I2C device driver for DA9061 and DA9062 PMICs
462306a36Sopenharmony_ci * Copyright (C) 2015-2017  Dialog Semiconductor
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/kernel.h>
862306a36Sopenharmony_ci#include <linux/module.h>
962306a36Sopenharmony_ci#include <linux/init.h>
1062306a36Sopenharmony_ci#include <linux/device.h>
1162306a36Sopenharmony_ci#include <linux/interrupt.h>
1262306a36Sopenharmony_ci#include <linux/of.h>
1362306a36Sopenharmony_ci#include <linux/regmap.h>
1462306a36Sopenharmony_ci#include <linux/irq.h>
1562306a36Sopenharmony_ci#include <linux/mfd/core.h>
1662306a36Sopenharmony_ci#include <linux/i2c.h>
1762306a36Sopenharmony_ci#include <linux/mfd/da9062/core.h>
1862306a36Sopenharmony_ci#include <linux/mfd/da9062/registers.h>
1962306a36Sopenharmony_ci#include <linux/regulator/of_regulator.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define	DA9062_REG_EVENT_A_OFFSET	0
2262306a36Sopenharmony_ci#define	DA9062_REG_EVENT_B_OFFSET	1
2362306a36Sopenharmony_ci#define	DA9062_REG_EVENT_C_OFFSET	2
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define	DA9062_IRQ_LOW	0
2662306a36Sopenharmony_ci#define	DA9062_IRQ_HIGH	1
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic struct regmap_irq da9061_irqs[] = {
2962306a36Sopenharmony_ci	/* EVENT A */
3062306a36Sopenharmony_ci	[DA9061_IRQ_ONKEY] = {
3162306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_A_OFFSET,
3262306a36Sopenharmony_ci		.mask = DA9062AA_M_NONKEY_MASK,
3362306a36Sopenharmony_ci	},
3462306a36Sopenharmony_ci	[DA9061_IRQ_WDG_WARN] = {
3562306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_A_OFFSET,
3662306a36Sopenharmony_ci		.mask = DA9062AA_M_WDG_WARN_MASK,
3762306a36Sopenharmony_ci	},
3862306a36Sopenharmony_ci	[DA9061_IRQ_SEQ_RDY] = {
3962306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_A_OFFSET,
4062306a36Sopenharmony_ci		.mask = DA9062AA_M_SEQ_RDY_MASK,
4162306a36Sopenharmony_ci	},
4262306a36Sopenharmony_ci	/* EVENT B */
4362306a36Sopenharmony_ci	[DA9061_IRQ_TEMP] = {
4462306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_B_OFFSET,
4562306a36Sopenharmony_ci		.mask = DA9062AA_M_TEMP_MASK,
4662306a36Sopenharmony_ci	},
4762306a36Sopenharmony_ci	[DA9061_IRQ_LDO_LIM] = {
4862306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_B_OFFSET,
4962306a36Sopenharmony_ci		.mask = DA9062AA_M_LDO_LIM_MASK,
5062306a36Sopenharmony_ci	},
5162306a36Sopenharmony_ci	[DA9061_IRQ_DVC_RDY] = {
5262306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_B_OFFSET,
5362306a36Sopenharmony_ci		.mask = DA9062AA_M_DVC_RDY_MASK,
5462306a36Sopenharmony_ci	},
5562306a36Sopenharmony_ci	[DA9061_IRQ_VDD_WARN] = {
5662306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_B_OFFSET,
5762306a36Sopenharmony_ci		.mask = DA9062AA_M_VDD_WARN_MASK,
5862306a36Sopenharmony_ci	},
5962306a36Sopenharmony_ci	/* EVENT C */
6062306a36Sopenharmony_ci	[DA9061_IRQ_GPI0] = {
6162306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
6262306a36Sopenharmony_ci		.mask = DA9062AA_M_GPI0_MASK,
6362306a36Sopenharmony_ci	},
6462306a36Sopenharmony_ci	[DA9061_IRQ_GPI1] = {
6562306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
6662306a36Sopenharmony_ci		.mask = DA9062AA_M_GPI1_MASK,
6762306a36Sopenharmony_ci	},
6862306a36Sopenharmony_ci	[DA9061_IRQ_GPI2] = {
6962306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
7062306a36Sopenharmony_ci		.mask = DA9062AA_M_GPI2_MASK,
7162306a36Sopenharmony_ci	},
7262306a36Sopenharmony_ci	[DA9061_IRQ_GPI3] = {
7362306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
7462306a36Sopenharmony_ci		.mask = DA9062AA_M_GPI3_MASK,
7562306a36Sopenharmony_ci	},
7662306a36Sopenharmony_ci	[DA9061_IRQ_GPI4] = {
7762306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
7862306a36Sopenharmony_ci		.mask = DA9062AA_M_GPI4_MASK,
7962306a36Sopenharmony_ci	},
8062306a36Sopenharmony_ci};
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic struct regmap_irq_chip da9061_irq_chip = {
8362306a36Sopenharmony_ci	.name = "da9061-irq",
8462306a36Sopenharmony_ci	.irqs = da9061_irqs,
8562306a36Sopenharmony_ci	.num_irqs = DA9061_NUM_IRQ,
8662306a36Sopenharmony_ci	.num_regs = 3,
8762306a36Sopenharmony_ci	.status_base = DA9062AA_EVENT_A,
8862306a36Sopenharmony_ci	.mask_base = DA9062AA_IRQ_MASK_A,
8962306a36Sopenharmony_ci	.ack_base = DA9062AA_EVENT_A,
9062306a36Sopenharmony_ci};
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cistatic struct regmap_irq da9062_irqs[] = {
9362306a36Sopenharmony_ci	/* EVENT A */
9462306a36Sopenharmony_ci	[DA9062_IRQ_ONKEY] = {
9562306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_A_OFFSET,
9662306a36Sopenharmony_ci		.mask = DA9062AA_M_NONKEY_MASK,
9762306a36Sopenharmony_ci	},
9862306a36Sopenharmony_ci	[DA9062_IRQ_ALARM] = {
9962306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_A_OFFSET,
10062306a36Sopenharmony_ci		.mask = DA9062AA_M_ALARM_MASK,
10162306a36Sopenharmony_ci	},
10262306a36Sopenharmony_ci	[DA9062_IRQ_TICK] = {
10362306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_A_OFFSET,
10462306a36Sopenharmony_ci		.mask = DA9062AA_M_TICK_MASK,
10562306a36Sopenharmony_ci	},
10662306a36Sopenharmony_ci	[DA9062_IRQ_WDG_WARN] = {
10762306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_A_OFFSET,
10862306a36Sopenharmony_ci		.mask = DA9062AA_M_WDG_WARN_MASK,
10962306a36Sopenharmony_ci	},
11062306a36Sopenharmony_ci	[DA9062_IRQ_SEQ_RDY] = {
11162306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_A_OFFSET,
11262306a36Sopenharmony_ci		.mask = DA9062AA_M_SEQ_RDY_MASK,
11362306a36Sopenharmony_ci	},
11462306a36Sopenharmony_ci	/* EVENT B */
11562306a36Sopenharmony_ci	[DA9062_IRQ_TEMP] = {
11662306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_B_OFFSET,
11762306a36Sopenharmony_ci		.mask = DA9062AA_M_TEMP_MASK,
11862306a36Sopenharmony_ci	},
11962306a36Sopenharmony_ci	[DA9062_IRQ_LDO_LIM] = {
12062306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_B_OFFSET,
12162306a36Sopenharmony_ci		.mask = DA9062AA_M_LDO_LIM_MASK,
12262306a36Sopenharmony_ci	},
12362306a36Sopenharmony_ci	[DA9062_IRQ_DVC_RDY] = {
12462306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_B_OFFSET,
12562306a36Sopenharmony_ci		.mask = DA9062AA_M_DVC_RDY_MASK,
12662306a36Sopenharmony_ci	},
12762306a36Sopenharmony_ci	[DA9062_IRQ_VDD_WARN] = {
12862306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_B_OFFSET,
12962306a36Sopenharmony_ci		.mask = DA9062AA_M_VDD_WARN_MASK,
13062306a36Sopenharmony_ci	},
13162306a36Sopenharmony_ci	/* EVENT C */
13262306a36Sopenharmony_ci	[DA9062_IRQ_GPI0] = {
13362306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
13462306a36Sopenharmony_ci		.mask = DA9062AA_M_GPI0_MASK,
13562306a36Sopenharmony_ci	},
13662306a36Sopenharmony_ci	[DA9062_IRQ_GPI1] = {
13762306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
13862306a36Sopenharmony_ci		.mask = DA9062AA_M_GPI1_MASK,
13962306a36Sopenharmony_ci	},
14062306a36Sopenharmony_ci	[DA9062_IRQ_GPI2] = {
14162306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
14262306a36Sopenharmony_ci		.mask = DA9062AA_M_GPI2_MASK,
14362306a36Sopenharmony_ci	},
14462306a36Sopenharmony_ci	[DA9062_IRQ_GPI3] = {
14562306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
14662306a36Sopenharmony_ci		.mask = DA9062AA_M_GPI3_MASK,
14762306a36Sopenharmony_ci	},
14862306a36Sopenharmony_ci	[DA9062_IRQ_GPI4] = {
14962306a36Sopenharmony_ci		.reg_offset = DA9062_REG_EVENT_C_OFFSET,
15062306a36Sopenharmony_ci		.mask = DA9062AA_M_GPI4_MASK,
15162306a36Sopenharmony_ci	},
15262306a36Sopenharmony_ci};
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cistatic struct regmap_irq_chip da9062_irq_chip = {
15562306a36Sopenharmony_ci	.name = "da9062-irq",
15662306a36Sopenharmony_ci	.irqs = da9062_irqs,
15762306a36Sopenharmony_ci	.num_irqs = DA9062_NUM_IRQ,
15862306a36Sopenharmony_ci	.num_regs = 3,
15962306a36Sopenharmony_ci	.status_base = DA9062AA_EVENT_A,
16062306a36Sopenharmony_ci	.mask_base = DA9062AA_IRQ_MASK_A,
16162306a36Sopenharmony_ci	.ack_base = DA9062AA_EVENT_A,
16262306a36Sopenharmony_ci};
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_cistatic const struct resource da9061_core_resources[] = {
16562306a36Sopenharmony_ci	DEFINE_RES_IRQ_NAMED(DA9061_IRQ_VDD_WARN, "VDD_WARN"),
16662306a36Sopenharmony_ci};
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cistatic const struct resource da9061_regulators_resources[] = {
16962306a36Sopenharmony_ci	DEFINE_RES_IRQ_NAMED(DA9061_IRQ_LDO_LIM, "LDO_LIM"),
17062306a36Sopenharmony_ci};
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_cistatic const struct resource da9061_thermal_resources[] = {
17362306a36Sopenharmony_ci	DEFINE_RES_IRQ_NAMED(DA9061_IRQ_TEMP, "THERMAL"),
17462306a36Sopenharmony_ci};
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_cistatic const struct resource da9061_wdt_resources[] = {
17762306a36Sopenharmony_ci	DEFINE_RES_IRQ_NAMED(DA9061_IRQ_WDG_WARN, "WD_WARN"),
17862306a36Sopenharmony_ci};
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_cistatic const struct resource da9061_onkey_resources[] = {
18162306a36Sopenharmony_ci	DEFINE_RES_IRQ_NAMED(DA9061_IRQ_ONKEY, "ONKEY"),
18262306a36Sopenharmony_ci};
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_cistatic const struct mfd_cell da9061_devs_irq[] = {
18562306a36Sopenharmony_ci	MFD_CELL_OF("da9061-core", da9061_core_resources, NULL, 0, 0,
18662306a36Sopenharmony_ci		    NULL),
18762306a36Sopenharmony_ci	MFD_CELL_OF("da9062-regulators", da9061_regulators_resources, NULL, 0, 0,
18862306a36Sopenharmony_ci		    NULL),
18962306a36Sopenharmony_ci	MFD_CELL_OF("da9061-watchdog", da9061_wdt_resources, NULL, 0, 0,
19062306a36Sopenharmony_ci		    "dlg,da9061-watchdog"),
19162306a36Sopenharmony_ci	MFD_CELL_OF("da9061-thermal", da9061_thermal_resources, NULL, 0, 0,
19262306a36Sopenharmony_ci		    "dlg,da9061-thermal"),
19362306a36Sopenharmony_ci	MFD_CELL_OF("da9061-onkey", da9061_onkey_resources, NULL, 0, 0,
19462306a36Sopenharmony_ci		    "dlg,da9061-onkey"),
19562306a36Sopenharmony_ci};
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic const struct mfd_cell da9061_devs_noirq[] = {
19862306a36Sopenharmony_ci	MFD_CELL_OF("da9061-core", NULL, NULL, 0, 0, NULL),
19962306a36Sopenharmony_ci	MFD_CELL_OF("da9062-regulators", NULL, NULL, 0, 0, NULL),
20062306a36Sopenharmony_ci	MFD_CELL_OF("da9061-watchdog", NULL, NULL, 0, 0, "dlg,da9061-watchdog"),
20162306a36Sopenharmony_ci	MFD_CELL_OF("da9061-thermal", NULL, NULL, 0, 0, "dlg,da9061-thermal"),
20262306a36Sopenharmony_ci	MFD_CELL_OF("da9061-onkey", NULL, NULL, 0, 0, "dlg,da9061-onkey"),
20362306a36Sopenharmony_ci};
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_cistatic const struct resource da9062_core_resources[] = {
20662306a36Sopenharmony_ci	DEFINE_RES_NAMED(DA9062_IRQ_VDD_WARN, 1, "VDD_WARN", IORESOURCE_IRQ),
20762306a36Sopenharmony_ci};
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistatic const struct resource da9062_regulators_resources[] = {
21062306a36Sopenharmony_ci	DEFINE_RES_NAMED(DA9062_IRQ_LDO_LIM, 1, "LDO_LIM", IORESOURCE_IRQ),
21162306a36Sopenharmony_ci};
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_cistatic const struct resource da9062_thermal_resources[] = {
21462306a36Sopenharmony_ci	DEFINE_RES_NAMED(DA9062_IRQ_TEMP, 1, "THERMAL", IORESOURCE_IRQ),
21562306a36Sopenharmony_ci};
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_cistatic const struct resource da9062_wdt_resources[] = {
21862306a36Sopenharmony_ci	DEFINE_RES_NAMED(DA9062_IRQ_WDG_WARN, 1, "WD_WARN", IORESOURCE_IRQ),
21962306a36Sopenharmony_ci};
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cistatic const struct resource da9062_rtc_resources[] = {
22262306a36Sopenharmony_ci	DEFINE_RES_NAMED(DA9062_IRQ_ALARM, 1, "ALARM", IORESOURCE_IRQ),
22362306a36Sopenharmony_ci	DEFINE_RES_NAMED(DA9062_IRQ_TICK, 1, "TICK", IORESOURCE_IRQ),
22462306a36Sopenharmony_ci};
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_cistatic const struct resource da9062_onkey_resources[] = {
22762306a36Sopenharmony_ci	DEFINE_RES_NAMED(DA9062_IRQ_ONKEY, 1, "ONKEY", IORESOURCE_IRQ),
22862306a36Sopenharmony_ci};
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_cistatic const struct resource da9062_gpio_resources[] = {
23162306a36Sopenharmony_ci	DEFINE_RES_NAMED(DA9062_IRQ_GPI0, 1, "GPI0", IORESOURCE_IRQ),
23262306a36Sopenharmony_ci	DEFINE_RES_NAMED(DA9062_IRQ_GPI1, 1, "GPI1", IORESOURCE_IRQ),
23362306a36Sopenharmony_ci	DEFINE_RES_NAMED(DA9062_IRQ_GPI2, 1, "GPI2", IORESOURCE_IRQ),
23462306a36Sopenharmony_ci	DEFINE_RES_NAMED(DA9062_IRQ_GPI3, 1, "GPI3", IORESOURCE_IRQ),
23562306a36Sopenharmony_ci	DEFINE_RES_NAMED(DA9062_IRQ_GPI4, 1, "GPI4", IORESOURCE_IRQ),
23662306a36Sopenharmony_ci};
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistatic const struct mfd_cell da9062_devs_irq[] = {
23962306a36Sopenharmony_ci	MFD_CELL_OF("da9062-core", da9062_core_resources, NULL, 0, 0,
24062306a36Sopenharmony_ci		    NULL),
24162306a36Sopenharmony_ci	MFD_CELL_OF("da9062-regulators", da9062_regulators_resources, NULL, 0, 0,
24262306a36Sopenharmony_ci		    NULL),
24362306a36Sopenharmony_ci	MFD_CELL_OF("da9062-watchdog", da9062_wdt_resources, NULL, 0, 0,
24462306a36Sopenharmony_ci		    "dlg,da9062-watchdog"),
24562306a36Sopenharmony_ci	MFD_CELL_OF("da9062-thermal", da9062_thermal_resources, NULL, 0, 0,
24662306a36Sopenharmony_ci		    "dlg,da9062-thermal"),
24762306a36Sopenharmony_ci	MFD_CELL_OF("da9062-rtc", da9062_rtc_resources, NULL, 0, 0,
24862306a36Sopenharmony_ci		    "dlg,da9062-rtc"),
24962306a36Sopenharmony_ci	MFD_CELL_OF("da9062-onkey", da9062_onkey_resources, NULL, 0, 0,
25062306a36Sopenharmony_ci		    "dlg,da9062-onkey"),
25162306a36Sopenharmony_ci	MFD_CELL_OF("da9062-gpio", da9062_gpio_resources, NULL, 0, 0,
25262306a36Sopenharmony_ci		    "dlg,da9062-gpio"),
25362306a36Sopenharmony_ci};
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_cistatic const struct mfd_cell da9062_devs_noirq[] = {
25662306a36Sopenharmony_ci	MFD_CELL_OF("da9062-core", NULL, NULL, 0, 0, NULL),
25762306a36Sopenharmony_ci	MFD_CELL_OF("da9062-regulators", NULL, NULL, 0, 0, NULL),
25862306a36Sopenharmony_ci	MFD_CELL_OF("da9062-watchdog", NULL, NULL, 0, 0, "dlg,da9062-watchdog"),
25962306a36Sopenharmony_ci	MFD_CELL_OF("da9062-thermal", NULL, NULL, 0, 0, "dlg,da9062-thermal"),
26062306a36Sopenharmony_ci	MFD_CELL_OF("da9062-rtc", NULL, NULL, 0, 0, "dlg,da9062-rtc"),
26162306a36Sopenharmony_ci	MFD_CELL_OF("da9062-onkey", NULL, NULL, 0, 0, "dlg,da9062-onkey"),
26262306a36Sopenharmony_ci	MFD_CELL_OF("da9062-gpio", NULL, NULL, 0, 0, "dlg,da9062-gpio"),
26362306a36Sopenharmony_ci};
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_cistatic int da9062_clear_fault_log(struct da9062 *chip)
26662306a36Sopenharmony_ci{
26762306a36Sopenharmony_ci	int ret;
26862306a36Sopenharmony_ci	int fault_log;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	ret = regmap_read(chip->regmap, DA9062AA_FAULT_LOG, &fault_log);
27162306a36Sopenharmony_ci	if (ret < 0)
27262306a36Sopenharmony_ci		return ret;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	if (fault_log) {
27562306a36Sopenharmony_ci		if (fault_log & DA9062AA_TWD_ERROR_MASK)
27662306a36Sopenharmony_ci			dev_dbg(chip->dev, "Fault log entry detected: TWD_ERROR\n");
27762306a36Sopenharmony_ci		if (fault_log & DA9062AA_POR_MASK)
27862306a36Sopenharmony_ci			dev_dbg(chip->dev, "Fault log entry detected: POR\n");
27962306a36Sopenharmony_ci		if (fault_log & DA9062AA_VDD_FAULT_MASK)
28062306a36Sopenharmony_ci			dev_dbg(chip->dev, "Fault log entry detected: VDD_FAULT\n");
28162306a36Sopenharmony_ci		if (fault_log & DA9062AA_VDD_START_MASK)
28262306a36Sopenharmony_ci			dev_dbg(chip->dev, "Fault log entry detected: VDD_START\n");
28362306a36Sopenharmony_ci		if (fault_log & DA9062AA_TEMP_CRIT_MASK)
28462306a36Sopenharmony_ci			dev_dbg(chip->dev, "Fault log entry detected: TEMP_CRIT\n");
28562306a36Sopenharmony_ci		if (fault_log & DA9062AA_KEY_RESET_MASK)
28662306a36Sopenharmony_ci			dev_dbg(chip->dev, "Fault log entry detected: KEY_RESET\n");
28762306a36Sopenharmony_ci		if (fault_log & DA9062AA_NSHUTDOWN_MASK)
28862306a36Sopenharmony_ci			dev_dbg(chip->dev, "Fault log entry detected: NSHUTDOWN\n");
28962306a36Sopenharmony_ci		if (fault_log & DA9062AA_WAIT_SHUT_MASK)
29062306a36Sopenharmony_ci			dev_dbg(chip->dev, "Fault log entry detected: WAIT_SHUT\n");
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci		ret = regmap_write(chip->regmap, DA9062AA_FAULT_LOG,
29362306a36Sopenharmony_ci				   fault_log);
29462306a36Sopenharmony_ci	}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	return ret;
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_cistatic int da9062_get_device_type(struct da9062 *chip)
30062306a36Sopenharmony_ci{
30162306a36Sopenharmony_ci	int device_id, variant_id, variant_mrc, variant_vrc;
30262306a36Sopenharmony_ci	char *type;
30362306a36Sopenharmony_ci	int ret;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	ret = regmap_read(chip->regmap, DA9062AA_DEVICE_ID, &device_id);
30662306a36Sopenharmony_ci	if (ret < 0) {
30762306a36Sopenharmony_ci		dev_err(chip->dev, "Cannot read chip ID.\n");
30862306a36Sopenharmony_ci		return -EIO;
30962306a36Sopenharmony_ci	}
31062306a36Sopenharmony_ci	if (device_id != DA9062_PMIC_DEVICE_ID) {
31162306a36Sopenharmony_ci		dev_err(chip->dev, "Invalid device ID: 0x%02x\n", device_id);
31262306a36Sopenharmony_ci		return -ENODEV;
31362306a36Sopenharmony_ci	}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	ret = regmap_read(chip->regmap, DA9062AA_VARIANT_ID, &variant_id);
31662306a36Sopenharmony_ci	if (ret < 0) {
31762306a36Sopenharmony_ci		dev_err(chip->dev, "Cannot read chip variant id.\n");
31862306a36Sopenharmony_ci		return -EIO;
31962306a36Sopenharmony_ci	}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	variant_vrc = (variant_id & DA9062AA_VRC_MASK) >> DA9062AA_VRC_SHIFT;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	switch (variant_vrc) {
32462306a36Sopenharmony_ci	case DA9062_PMIC_VARIANT_VRC_DA9061:
32562306a36Sopenharmony_ci		type = "DA9061";
32662306a36Sopenharmony_ci		break;
32762306a36Sopenharmony_ci	case DA9062_PMIC_VARIANT_VRC_DA9062:
32862306a36Sopenharmony_ci		type = "DA9062";
32962306a36Sopenharmony_ci		break;
33062306a36Sopenharmony_ci	default:
33162306a36Sopenharmony_ci		type = "Unknown";
33262306a36Sopenharmony_ci		break;
33362306a36Sopenharmony_ci	}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	dev_info(chip->dev,
33662306a36Sopenharmony_ci		 "Device detected (device-ID: 0x%02X, var-ID: 0x%02X, %s)\n",
33762306a36Sopenharmony_ci		 device_id, variant_id, type);
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	variant_mrc = (variant_id & DA9062AA_MRC_MASK) >> DA9062AA_MRC_SHIFT;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	if (variant_mrc < DA9062_PMIC_VARIANT_MRC_AA) {
34262306a36Sopenharmony_ci		dev_err(chip->dev,
34362306a36Sopenharmony_ci			"Cannot support variant MRC: 0x%02X\n", variant_mrc);
34462306a36Sopenharmony_ci		return -ENODEV;
34562306a36Sopenharmony_ci	}
34662306a36Sopenharmony_ci
34762306a36Sopenharmony_ci	return ret;
34862306a36Sopenharmony_ci}
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_cistatic u32 da9062_configure_irq_type(struct da9062 *chip, int irq, u32 *trigger)
35162306a36Sopenharmony_ci{
35262306a36Sopenharmony_ci	u32 irq_type = 0;
35362306a36Sopenharmony_ci	struct irq_data *irq_data = irq_get_irq_data(irq);
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	if (!irq_data) {
35662306a36Sopenharmony_ci		dev_err(chip->dev, "Invalid IRQ: %d\n", irq);
35762306a36Sopenharmony_ci		return -EINVAL;
35862306a36Sopenharmony_ci	}
35962306a36Sopenharmony_ci	*trigger = irqd_get_trigger_type(irq_data);
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	switch (*trigger) {
36262306a36Sopenharmony_ci	case IRQ_TYPE_LEVEL_HIGH:
36362306a36Sopenharmony_ci		irq_type = DA9062_IRQ_HIGH;
36462306a36Sopenharmony_ci		break;
36562306a36Sopenharmony_ci	case IRQ_TYPE_LEVEL_LOW:
36662306a36Sopenharmony_ci		irq_type = DA9062_IRQ_LOW;
36762306a36Sopenharmony_ci		break;
36862306a36Sopenharmony_ci	default:
36962306a36Sopenharmony_ci		dev_warn(chip->dev, "Unsupported IRQ type: %d\n", *trigger);
37062306a36Sopenharmony_ci		return -EINVAL;
37162306a36Sopenharmony_ci	}
37262306a36Sopenharmony_ci	return regmap_update_bits(chip->regmap, DA9062AA_CONFIG_A,
37362306a36Sopenharmony_ci			DA9062AA_IRQ_TYPE_MASK,
37462306a36Sopenharmony_ci			irq_type << DA9062AA_IRQ_TYPE_SHIFT);
37562306a36Sopenharmony_ci}
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_cistatic const struct regmap_range da9061_aa_readable_ranges[] = {
37862306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
37962306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
38062306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
38162306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
38262306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_GPIO_OUT3_4),
38362306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),
38462306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
38562306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
38662306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
38762306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
38862306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
38962306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
39062306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_WAIT),
39162306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_RESET, DA9062AA_BUCK_ILIM_C),
39262306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_BUCK1_CFG, DA9062AA_BUCK3_CFG),
39362306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VBUCK1_A, DA9062AA_VBUCK4_A),
39462306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
39562306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
39662306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_CONFIG_A, DA9062AA_CONFIG_A),
39762306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B),
39862306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
39962306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
40062306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_INTERFACE, DA9062AA_CONFIG_E),
40162306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_CONFIG_G, DA9062AA_CONFIG_K),
40262306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_CONFIG_M, DA9062AA_CONFIG_M),
40362306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),
40462306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_DEVICE_ID, DA9062AA_CONFIG_ID),
40562306a36Sopenharmony_ci};
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_cistatic const struct regmap_range da9061_aa_writeable_ranges[] = {
40862306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_PAGE_CON),
40962306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_FAULT_LOG, DA9062AA_EVENT_C),
41062306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
41162306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
41262306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_GPIO_OUT3_4),
41362306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),
41462306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
41562306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
41662306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
41762306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
41862306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
41962306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
42062306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_WAIT),
42162306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_RESET, DA9062AA_BUCK_ILIM_C),
42262306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_BUCK1_CFG, DA9062AA_BUCK3_CFG),
42362306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VBUCK1_A, DA9062AA_VBUCK4_A),
42462306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
42562306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
42662306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_CONFIG_A, DA9062AA_CONFIG_A),
42762306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B),
42862306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
42962306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
43062306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_CONFIG_J, DA9062AA_CONFIG_J),
43162306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),
43262306a36Sopenharmony_ci};
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_cistatic const struct regmap_range da9061_aa_volatile_ranges[] = {
43562306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
43662306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
43762306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_CONTROL_B),
43862306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_CONTROL_E, DA9062AA_CONTROL_F),
43962306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),
44062306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
44162306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
44262306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
44362306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_SEQ, DA9062AA_SEQ),
44462306a36Sopenharmony_ci};
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_cistatic const struct regmap_access_table da9061_aa_readable_table = {
44762306a36Sopenharmony_ci	.yes_ranges = da9061_aa_readable_ranges,
44862306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9061_aa_readable_ranges),
44962306a36Sopenharmony_ci};
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_cistatic const struct regmap_access_table da9061_aa_writeable_table = {
45262306a36Sopenharmony_ci	.yes_ranges = da9061_aa_writeable_ranges,
45362306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9061_aa_writeable_ranges),
45462306a36Sopenharmony_ci};
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_cistatic const struct regmap_access_table da9061_aa_volatile_table = {
45762306a36Sopenharmony_ci	.yes_ranges = da9061_aa_volatile_ranges,
45862306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9061_aa_volatile_ranges),
45962306a36Sopenharmony_ci};
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_cistatic const struct regmap_range_cfg da9061_range_cfg[] = {
46262306a36Sopenharmony_ci	{
46362306a36Sopenharmony_ci		.range_min = DA9062AA_PAGE_CON,
46462306a36Sopenharmony_ci		.range_max = DA9062AA_CONFIG_ID,
46562306a36Sopenharmony_ci		.selector_reg = DA9062AA_PAGE_CON,
46662306a36Sopenharmony_ci		.selector_mask = 1 << DA9062_I2C_PAGE_SEL_SHIFT,
46762306a36Sopenharmony_ci		.selector_shift = DA9062_I2C_PAGE_SEL_SHIFT,
46862306a36Sopenharmony_ci		.window_start = 0,
46962306a36Sopenharmony_ci		.window_len = 256,
47062306a36Sopenharmony_ci	}
47162306a36Sopenharmony_ci};
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_cistatic struct regmap_config da9061_regmap_config = {
47462306a36Sopenharmony_ci	.reg_bits = 8,
47562306a36Sopenharmony_ci	.val_bits = 8,
47662306a36Sopenharmony_ci	.ranges = da9061_range_cfg,
47762306a36Sopenharmony_ci	.num_ranges = ARRAY_SIZE(da9061_range_cfg),
47862306a36Sopenharmony_ci	.max_register = DA9062AA_CONFIG_ID,
47962306a36Sopenharmony_ci	.cache_type = REGCACHE_RBTREE,
48062306a36Sopenharmony_ci	.rd_table = &da9061_aa_readable_table,
48162306a36Sopenharmony_ci	.wr_table = &da9061_aa_writeable_table,
48262306a36Sopenharmony_ci	.volatile_table = &da9061_aa_volatile_table,
48362306a36Sopenharmony_ci};
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_cistatic const struct regmap_range da9062_aa_readable_ranges[] = {
48662306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
48762306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
48862306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
48962306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
49062306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_BUCK4_CONT),
49162306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
49262306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
49362306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
49462306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_SECOND_D),
49562306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
49662306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
49762306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
49862306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_BUCK3_CFG),
49962306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VBUCK2_A, DA9062AA_VBUCK4_A),
50062306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
50162306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
50262306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VBUCK2_B, DA9062AA_VBUCK4_B),
50362306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
50462306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
50562306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_BBAT_CONT, DA9062AA_BBAT_CONT),
50662306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_INTERFACE, DA9062AA_CONFIG_E),
50762306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_CONFIG_G, DA9062AA_CONFIG_K),
50862306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_CONFIG_M, DA9062AA_CONFIG_M),
50962306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_TRIM_CLDR, DA9062AA_GP_ID_19),
51062306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_DEVICE_ID, DA9062AA_CONFIG_ID),
51162306a36Sopenharmony_ci};
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_cistatic const struct regmap_range da9062_aa_writeable_ranges[] = {
51462306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_PAGE_CON),
51562306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_FAULT_LOG, DA9062AA_EVENT_C),
51662306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
51762306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
51862306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_BUCK4_CONT),
51962306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
52062306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
52162306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
52262306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_ALARM_Y),
52362306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
52462306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
52562306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
52662306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_BUCK3_CFG),
52762306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VBUCK2_A, DA9062AA_VBUCK4_A),
52862306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
52962306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
53062306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VBUCK2_B, DA9062AA_VBUCK4_B),
53162306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
53262306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
53362306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_BBAT_CONT, DA9062AA_BBAT_CONT),
53462306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_CONFIG_J, DA9062AA_CONFIG_J),
53562306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),
53662306a36Sopenharmony_ci};
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_cistatic const struct regmap_range da9062_aa_volatile_ranges[] = {
53962306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
54062306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
54162306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_CONTROL_B),
54262306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_CONTROL_E, DA9062AA_CONTROL_F),
54362306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_BUCK2_CONT, DA9062AA_BUCK4_CONT),
54462306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
54562306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
54662306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
54762306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_SECOND_D),
54862306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_SEQ, DA9062AA_SEQ),
54962306a36Sopenharmony_ci	regmap_reg_range(DA9062AA_EN_32K, DA9062AA_EN_32K),
55062306a36Sopenharmony_ci};
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_cistatic const struct regmap_access_table da9062_aa_readable_table = {
55362306a36Sopenharmony_ci	.yes_ranges = da9062_aa_readable_ranges,
55462306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9062_aa_readable_ranges),
55562306a36Sopenharmony_ci};
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_cistatic const struct regmap_access_table da9062_aa_writeable_table = {
55862306a36Sopenharmony_ci	.yes_ranges = da9062_aa_writeable_ranges,
55962306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9062_aa_writeable_ranges),
56062306a36Sopenharmony_ci};
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_cistatic const struct regmap_access_table da9062_aa_volatile_table = {
56362306a36Sopenharmony_ci	.yes_ranges = da9062_aa_volatile_ranges,
56462306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9062_aa_volatile_ranges),
56562306a36Sopenharmony_ci};
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_cistatic const struct regmap_range_cfg da9062_range_cfg[] = {
56862306a36Sopenharmony_ci	{
56962306a36Sopenharmony_ci		.range_min = DA9062AA_PAGE_CON,
57062306a36Sopenharmony_ci		.range_max = DA9062AA_CONFIG_ID,
57162306a36Sopenharmony_ci		.selector_reg = DA9062AA_PAGE_CON,
57262306a36Sopenharmony_ci		.selector_mask = 1 << DA9062_I2C_PAGE_SEL_SHIFT,
57362306a36Sopenharmony_ci		.selector_shift = DA9062_I2C_PAGE_SEL_SHIFT,
57462306a36Sopenharmony_ci		.window_start = 0,
57562306a36Sopenharmony_ci		.window_len = 256,
57662306a36Sopenharmony_ci	}
57762306a36Sopenharmony_ci};
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_cistatic struct regmap_config da9062_regmap_config = {
58062306a36Sopenharmony_ci	.reg_bits = 8,
58162306a36Sopenharmony_ci	.val_bits = 8,
58262306a36Sopenharmony_ci	.ranges = da9062_range_cfg,
58362306a36Sopenharmony_ci	.num_ranges = ARRAY_SIZE(da9062_range_cfg),
58462306a36Sopenharmony_ci	.max_register = DA9062AA_CONFIG_ID,
58562306a36Sopenharmony_ci	.cache_type = REGCACHE_RBTREE,
58662306a36Sopenharmony_ci	.rd_table = &da9062_aa_readable_table,
58762306a36Sopenharmony_ci	.wr_table = &da9062_aa_writeable_table,
58862306a36Sopenharmony_ci	.volatile_table = &da9062_aa_volatile_table,
58962306a36Sopenharmony_ci};
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_cistatic const struct of_device_id da9062_dt_ids[] = {
59262306a36Sopenharmony_ci	{ .compatible = "dlg,da9061", .data = (void *)COMPAT_TYPE_DA9061, },
59362306a36Sopenharmony_ci	{ .compatible = "dlg,da9062", .data = (void *)COMPAT_TYPE_DA9062, },
59462306a36Sopenharmony_ci	{ }
59562306a36Sopenharmony_ci};
59662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, da9062_dt_ids);
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_cistatic int da9062_i2c_probe(struct i2c_client *i2c)
59962306a36Sopenharmony_ci{
60062306a36Sopenharmony_ci	const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
60162306a36Sopenharmony_ci	struct da9062 *chip;
60262306a36Sopenharmony_ci	unsigned int irq_base = 0;
60362306a36Sopenharmony_ci	const struct mfd_cell *cell;
60462306a36Sopenharmony_ci	const struct regmap_irq_chip *irq_chip;
60562306a36Sopenharmony_ci	const struct regmap_config *config;
60662306a36Sopenharmony_ci	int cell_num;
60762306a36Sopenharmony_ci	u32 trigger_type = 0;
60862306a36Sopenharmony_ci	int ret;
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	chip = devm_kzalloc(&i2c->dev, sizeof(*chip), GFP_KERNEL);
61162306a36Sopenharmony_ci	if (!chip)
61262306a36Sopenharmony_ci		return -ENOMEM;
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	if (i2c->dev.of_node)
61562306a36Sopenharmony_ci		chip->chip_type = (uintptr_t)of_device_get_match_data(&i2c->dev);
61662306a36Sopenharmony_ci	else
61762306a36Sopenharmony_ci		chip->chip_type = id->driver_data;
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	i2c_set_clientdata(i2c, chip);
62062306a36Sopenharmony_ci	chip->dev = &i2c->dev;
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci	/* Start with a base configuration without IRQ */
62362306a36Sopenharmony_ci	switch (chip->chip_type) {
62462306a36Sopenharmony_ci	case COMPAT_TYPE_DA9061:
62562306a36Sopenharmony_ci		cell = da9061_devs_noirq;
62662306a36Sopenharmony_ci		cell_num = ARRAY_SIZE(da9061_devs_noirq);
62762306a36Sopenharmony_ci		config = &da9061_regmap_config;
62862306a36Sopenharmony_ci		break;
62962306a36Sopenharmony_ci	case COMPAT_TYPE_DA9062:
63062306a36Sopenharmony_ci		cell = da9062_devs_noirq;
63162306a36Sopenharmony_ci		cell_num = ARRAY_SIZE(da9062_devs_noirq);
63262306a36Sopenharmony_ci		config = &da9062_regmap_config;
63362306a36Sopenharmony_ci		break;
63462306a36Sopenharmony_ci	default:
63562306a36Sopenharmony_ci		dev_err(chip->dev, "Unrecognised chip type\n");
63662306a36Sopenharmony_ci		return -ENODEV;
63762306a36Sopenharmony_ci	}
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci	chip->regmap = devm_regmap_init_i2c(i2c, config);
64062306a36Sopenharmony_ci	if (IS_ERR(chip->regmap)) {
64162306a36Sopenharmony_ci		ret = PTR_ERR(chip->regmap);
64262306a36Sopenharmony_ci		dev_err(chip->dev, "Failed to allocate register map: %d\n",
64362306a36Sopenharmony_ci			ret);
64462306a36Sopenharmony_ci		return ret;
64562306a36Sopenharmony_ci	}
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	/* If SMBus is not available and only I2C is possible, enter I2C mode */
64862306a36Sopenharmony_ci	if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) {
64962306a36Sopenharmony_ci		dev_info(chip->dev, "Entering I2C mode!\n");
65062306a36Sopenharmony_ci		ret = regmap_clear_bits(chip->regmap, DA9062AA_CONFIG_J,
65162306a36Sopenharmony_ci					DA9062AA_TWOWIRE_TO_MASK);
65262306a36Sopenharmony_ci		if (ret < 0) {
65362306a36Sopenharmony_ci			dev_err(chip->dev, "Failed to set Two-Wire Bus Mode.\n");
65462306a36Sopenharmony_ci			return ret;
65562306a36Sopenharmony_ci		}
65662306a36Sopenharmony_ci	}
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	ret = da9062_clear_fault_log(chip);
65962306a36Sopenharmony_ci	if (ret < 0)
66062306a36Sopenharmony_ci		dev_warn(chip->dev, "Cannot clear fault log\n");
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci	ret = da9062_get_device_type(chip);
66362306a36Sopenharmony_ci	if (ret)
66462306a36Sopenharmony_ci		return ret;
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci	/* If IRQ is available, reconfigure it accordingly */
66762306a36Sopenharmony_ci	if (i2c->irq) {
66862306a36Sopenharmony_ci		if (chip->chip_type == COMPAT_TYPE_DA9061) {
66962306a36Sopenharmony_ci			cell = da9061_devs_irq;
67062306a36Sopenharmony_ci			cell_num = ARRAY_SIZE(da9061_devs_irq);
67162306a36Sopenharmony_ci			irq_chip = &da9061_irq_chip;
67262306a36Sopenharmony_ci		} else {
67362306a36Sopenharmony_ci			cell = da9062_devs_irq;
67462306a36Sopenharmony_ci			cell_num = ARRAY_SIZE(da9062_devs_irq);
67562306a36Sopenharmony_ci			irq_chip = &da9062_irq_chip;
67662306a36Sopenharmony_ci		}
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci		ret = da9062_configure_irq_type(chip, i2c->irq, &trigger_type);
67962306a36Sopenharmony_ci		if (ret < 0) {
68062306a36Sopenharmony_ci			dev_err(chip->dev, "Failed to configure IRQ type\n");
68162306a36Sopenharmony_ci			return ret;
68262306a36Sopenharmony_ci		}
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci		ret = regmap_add_irq_chip(chip->regmap, i2c->irq,
68562306a36Sopenharmony_ci					  trigger_type | IRQF_SHARED | IRQF_ONESHOT,
68662306a36Sopenharmony_ci					  -1, irq_chip, &chip->regmap_irq);
68762306a36Sopenharmony_ci		if (ret) {
68862306a36Sopenharmony_ci			dev_err(chip->dev, "Failed to request IRQ %d: %d\n",
68962306a36Sopenharmony_ci				i2c->irq, ret);
69062306a36Sopenharmony_ci			return ret;
69162306a36Sopenharmony_ci		}
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci		irq_base = regmap_irq_chip_get_base(chip->regmap_irq);
69462306a36Sopenharmony_ci	}
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	ret = mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE, cell,
69762306a36Sopenharmony_ci			      cell_num, NULL, irq_base,
69862306a36Sopenharmony_ci			      NULL);
69962306a36Sopenharmony_ci	if (ret) {
70062306a36Sopenharmony_ci		dev_err(chip->dev, "Cannot register child devices\n");
70162306a36Sopenharmony_ci		if (i2c->irq)
70262306a36Sopenharmony_ci			regmap_del_irq_chip(i2c->irq, chip->regmap_irq);
70362306a36Sopenharmony_ci		return ret;
70462306a36Sopenharmony_ci	}
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	return ret;
70762306a36Sopenharmony_ci}
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_cistatic void da9062_i2c_remove(struct i2c_client *i2c)
71062306a36Sopenharmony_ci{
71162306a36Sopenharmony_ci	struct da9062 *chip = i2c_get_clientdata(i2c);
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci	mfd_remove_devices(chip->dev);
71462306a36Sopenharmony_ci	regmap_del_irq_chip(i2c->irq, chip->regmap_irq);
71562306a36Sopenharmony_ci}
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_cistatic const struct i2c_device_id da9062_i2c_id[] = {
71862306a36Sopenharmony_ci	{ "da9061", COMPAT_TYPE_DA9061 },
71962306a36Sopenharmony_ci	{ "da9062", COMPAT_TYPE_DA9062 },
72062306a36Sopenharmony_ci	{ },
72162306a36Sopenharmony_ci};
72262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, da9062_i2c_id);
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_cistatic struct i2c_driver da9062_i2c_driver = {
72562306a36Sopenharmony_ci	.driver = {
72662306a36Sopenharmony_ci		.name = "da9062",
72762306a36Sopenharmony_ci		.of_match_table = da9062_dt_ids,
72862306a36Sopenharmony_ci	},
72962306a36Sopenharmony_ci	.probe = da9062_i2c_probe,
73062306a36Sopenharmony_ci	.remove   = da9062_i2c_remove,
73162306a36Sopenharmony_ci	.id_table = da9062_i2c_id,
73262306a36Sopenharmony_ci};
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_cimodule_i2c_driver(da9062_i2c_driver);
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ciMODULE_DESCRIPTION("Core device driver for Dialog DA9061 and DA9062");
73762306a36Sopenharmony_ciMODULE_AUTHOR("Steve Twiss <stwiss.opensource@diasemi.com>");
73862306a36Sopenharmony_ciMODULE_LICENSE("GPL");
739