162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/* I2C support for Dialog DA9063
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright 2012 Dialog Semiconductor Ltd.
562306a36Sopenharmony_ci * Copyright 2013 Philipp Zabel, Pengutronix
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Author: Krystian Garbaciak, Dialog Semiconductor
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/kernel.h>
1162306a36Sopenharmony_ci#include <linux/module.h>
1262306a36Sopenharmony_ci#include <linux/i2c.h>
1362306a36Sopenharmony_ci#include <linux/regmap.h>
1462306a36Sopenharmony_ci#include <linux/delay.h>
1562306a36Sopenharmony_ci#include <linux/slab.h>
1662306a36Sopenharmony_ci#include <linux/err.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include <linux/mfd/core.h>
1962306a36Sopenharmony_ci#include <linux/mfd/da9063/core.h>
2062306a36Sopenharmony_ci#include <linux/mfd/da9063/registers.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#include <linux/of.h>
2362306a36Sopenharmony_ci#include <linux/regulator/of_regulator.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci/*
2662306a36Sopenharmony_ci * Raw I2C access required for just accessing chip and variant info before we
2762306a36Sopenharmony_ci * know which device is present. The info read from the device using this
2862306a36Sopenharmony_ci * approach is then used to select the correct regmap tables.
2962306a36Sopenharmony_ci */
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define DA9063_REG_PAGE_SIZE		0x100
3262306a36Sopenharmony_ci#define DA9063_REG_PAGED_ADDR_MASK	0xFF
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cienum da9063_page_sel_buf_fmt {
3562306a36Sopenharmony_ci	DA9063_PAGE_SEL_BUF_PAGE_REG = 0,
3662306a36Sopenharmony_ci	DA9063_PAGE_SEL_BUF_PAGE_VAL,
3762306a36Sopenharmony_ci	DA9063_PAGE_SEL_BUF_SIZE,
3862306a36Sopenharmony_ci};
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cienum da9063_paged_read_msgs {
4162306a36Sopenharmony_ci	DA9063_PAGED_READ_MSG_PAGE_SEL = 0,
4262306a36Sopenharmony_ci	DA9063_PAGED_READ_MSG_REG_SEL,
4362306a36Sopenharmony_ci	DA9063_PAGED_READ_MSG_DATA,
4462306a36Sopenharmony_ci	DA9063_PAGED_READ_MSG_CNT,
4562306a36Sopenharmony_ci};
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic int da9063_i2c_blockreg_read(struct i2c_client *client, u16 addr,
4862306a36Sopenharmony_ci				    u8 *buf, int count)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	struct i2c_msg xfer[DA9063_PAGED_READ_MSG_CNT];
5162306a36Sopenharmony_ci	u8 page_sel_buf[DA9063_PAGE_SEL_BUF_SIZE];
5262306a36Sopenharmony_ci	u8 page_num, paged_addr;
5362306a36Sopenharmony_ci	int ret;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	/* Determine page info based on register address */
5662306a36Sopenharmony_ci	page_num = (addr / DA9063_REG_PAGE_SIZE);
5762306a36Sopenharmony_ci	if (page_num > 1) {
5862306a36Sopenharmony_ci		dev_err(&client->dev, "Invalid register address provided\n");
5962306a36Sopenharmony_ci		return -EINVAL;
6062306a36Sopenharmony_ci	}
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	paged_addr = (addr % DA9063_REG_PAGE_SIZE) & DA9063_REG_PAGED_ADDR_MASK;
6362306a36Sopenharmony_ci	page_sel_buf[DA9063_PAGE_SEL_BUF_PAGE_REG] = DA9063_REG_PAGE_CON;
6462306a36Sopenharmony_ci	page_sel_buf[DA9063_PAGE_SEL_BUF_PAGE_VAL] =
6562306a36Sopenharmony_ci		(page_num << DA9063_I2C_PAGE_SEL_SHIFT) & DA9063_REG_PAGE_MASK;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	/* Write reg address, page selection */
6862306a36Sopenharmony_ci	xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].addr = client->addr;
6962306a36Sopenharmony_ci	xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].flags = 0;
7062306a36Sopenharmony_ci	xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].len = DA9063_PAGE_SEL_BUF_SIZE;
7162306a36Sopenharmony_ci	xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].buf = page_sel_buf;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	/* Select register address */
7462306a36Sopenharmony_ci	xfer[DA9063_PAGED_READ_MSG_REG_SEL].addr = client->addr;
7562306a36Sopenharmony_ci	xfer[DA9063_PAGED_READ_MSG_REG_SEL].flags = 0;
7662306a36Sopenharmony_ci	xfer[DA9063_PAGED_READ_MSG_REG_SEL].len = sizeof(paged_addr);
7762306a36Sopenharmony_ci	xfer[DA9063_PAGED_READ_MSG_REG_SEL].buf = &paged_addr;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	/* Read data */
8062306a36Sopenharmony_ci	xfer[DA9063_PAGED_READ_MSG_DATA].addr = client->addr;
8162306a36Sopenharmony_ci	xfer[DA9063_PAGED_READ_MSG_DATA].flags = I2C_M_RD;
8262306a36Sopenharmony_ci	xfer[DA9063_PAGED_READ_MSG_DATA].len = count;
8362306a36Sopenharmony_ci	xfer[DA9063_PAGED_READ_MSG_DATA].buf = buf;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	ret = i2c_transfer(client->adapter, xfer, DA9063_PAGED_READ_MSG_CNT);
8662306a36Sopenharmony_ci	if (ret < 0) {
8762306a36Sopenharmony_ci		dev_err(&client->dev, "Paged block read failed: %d\n", ret);
8862306a36Sopenharmony_ci		return ret;
8962306a36Sopenharmony_ci	}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	if (ret != DA9063_PAGED_READ_MSG_CNT) {
9262306a36Sopenharmony_ci		dev_err(&client->dev, "Paged block read failed to complete\n");
9362306a36Sopenharmony_ci		return -EIO;
9462306a36Sopenharmony_ci	}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	return 0;
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cienum {
10062306a36Sopenharmony_ci	DA9063_DEV_ID_REG = 0,
10162306a36Sopenharmony_ci	DA9063_VAR_ID_REG,
10262306a36Sopenharmony_ci	DA9063_CHIP_ID_REGS,
10362306a36Sopenharmony_ci};
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistatic int da9063_get_device_type(struct i2c_client *i2c, struct da9063 *da9063)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	u8 buf[DA9063_CHIP_ID_REGS];
10862306a36Sopenharmony_ci	int ret;
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	ret = da9063_i2c_blockreg_read(i2c, DA9063_REG_DEVICE_ID, buf,
11162306a36Sopenharmony_ci				       DA9063_CHIP_ID_REGS);
11262306a36Sopenharmony_ci	if (ret)
11362306a36Sopenharmony_ci		return ret;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	if (buf[DA9063_DEV_ID_REG] != PMIC_CHIP_ID_DA9063) {
11662306a36Sopenharmony_ci		dev_err(da9063->dev,
11762306a36Sopenharmony_ci			"Invalid chip device ID: 0x%02x\n",
11862306a36Sopenharmony_ci			buf[DA9063_DEV_ID_REG]);
11962306a36Sopenharmony_ci		return -ENODEV;
12062306a36Sopenharmony_ci	}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	dev_info(da9063->dev,
12362306a36Sopenharmony_ci		 "Device detected (chip-ID: 0x%02X, var-ID: 0x%02X)\n",
12462306a36Sopenharmony_ci		 buf[DA9063_DEV_ID_REG], buf[DA9063_VAR_ID_REG]);
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	da9063->variant_code =
12762306a36Sopenharmony_ci		(buf[DA9063_VAR_ID_REG] & DA9063_VARIANT_ID_MRC_MASK)
12862306a36Sopenharmony_ci		>> DA9063_VARIANT_ID_MRC_SHIFT;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	return 0;
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci/*
13462306a36Sopenharmony_ci * Variant specific regmap configs
13562306a36Sopenharmony_ci */
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_cistatic const struct regmap_range da9063_ad_readable_ranges[] = {
13862306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_AD_REG_SECOND_D),
13962306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
14062306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
14162306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_AD_REG_GP_ID_19),
14262306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
14362306a36Sopenharmony_ci};
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_cistatic const struct regmap_range da9063_ad_writeable_ranges[] = {
14662306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
14762306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
14862306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_COUNT_S, DA9063_AD_REG_ALARM_Y),
14962306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
15062306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
15162306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_AD_REG_MON_REG_4),
15262306a36Sopenharmony_ci	regmap_reg_range(DA9063_AD_REG_GP_ID_0, DA9063_AD_REG_GP_ID_19),
15362306a36Sopenharmony_ci};
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_cistatic const struct regmap_range da9063_ad_volatile_ranges[] = {
15662306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),
15762306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),
15862306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),
15962306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),
16062306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),
16162306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_AD_REG_SECOND_D),
16262306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),
16362306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),
16462306a36Sopenharmony_ci	regmap_reg_range(DA9063_AD_REG_MON_REG_5, DA9063_AD_REG_MON_REG_6),
16562306a36Sopenharmony_ci};
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_cistatic const struct regmap_access_table da9063_ad_readable_table = {
16862306a36Sopenharmony_ci	.yes_ranges = da9063_ad_readable_ranges,
16962306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9063_ad_readable_ranges),
17062306a36Sopenharmony_ci};
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_cistatic const struct regmap_access_table da9063_ad_writeable_table = {
17362306a36Sopenharmony_ci	.yes_ranges = da9063_ad_writeable_ranges,
17462306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9063_ad_writeable_ranges),
17562306a36Sopenharmony_ci};
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_cistatic const struct regmap_access_table da9063_ad_volatile_table = {
17862306a36Sopenharmony_ci	.yes_ranges = da9063_ad_volatile_ranges,
17962306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9063_ad_volatile_ranges),
18062306a36Sopenharmony_ci};
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_cistatic const struct regmap_range da9063_bb_readable_ranges[] = {
18362306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_BB_REG_SECOND_D),
18462306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
18562306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
18662306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19),
18762306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
18862306a36Sopenharmony_ci};
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistatic const struct regmap_range da9063_bb_writeable_ranges[] = {
19162306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
19262306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
19362306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_COUNT_S, DA9063_BB_REG_ALARM_Y),
19462306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
19562306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
19662306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),
19762306a36Sopenharmony_ci	regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19),
19862306a36Sopenharmony_ci};
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_cistatic const struct regmap_range da9063_bb_da_volatile_ranges[] = {
20162306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),
20262306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),
20362306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),
20462306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),
20562306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),
20662306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_BB_REG_SECOND_D),
20762306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),
20862306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),
20962306a36Sopenharmony_ci	regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6),
21062306a36Sopenharmony_ci};
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_cistatic const struct regmap_access_table da9063_bb_readable_table = {
21362306a36Sopenharmony_ci	.yes_ranges = da9063_bb_readable_ranges,
21462306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9063_bb_readable_ranges),
21562306a36Sopenharmony_ci};
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_cistatic const struct regmap_access_table da9063_bb_writeable_table = {
21862306a36Sopenharmony_ci	.yes_ranges = da9063_bb_writeable_ranges,
21962306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9063_bb_writeable_ranges),
22062306a36Sopenharmony_ci};
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_cistatic const struct regmap_access_table da9063_bb_da_volatile_table = {
22362306a36Sopenharmony_ci	.yes_ranges = da9063_bb_da_volatile_ranges,
22462306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9063_bb_da_volatile_ranges),
22562306a36Sopenharmony_ci};
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_cistatic const struct regmap_range da9063l_bb_readable_ranges[] = {
22862306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_MON_A10_RES),
22962306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
23062306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
23162306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19),
23262306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
23362306a36Sopenharmony_ci};
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_cistatic const struct regmap_range da9063l_bb_writeable_ranges[] = {
23662306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
23762306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
23862306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
23962306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
24062306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),
24162306a36Sopenharmony_ci	regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19),
24262306a36Sopenharmony_ci};
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_cistatic const struct regmap_range da9063l_bb_da_volatile_ranges[] = {
24562306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),
24662306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),
24762306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),
24862306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),
24962306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),
25062306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_REG_MON_A10_RES),
25162306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),
25262306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),
25362306a36Sopenharmony_ci	regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6),
25462306a36Sopenharmony_ci};
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_cistatic const struct regmap_access_table da9063l_bb_readable_table = {
25762306a36Sopenharmony_ci	.yes_ranges = da9063l_bb_readable_ranges,
25862306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9063l_bb_readable_ranges),
25962306a36Sopenharmony_ci};
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_cistatic const struct regmap_access_table da9063l_bb_writeable_table = {
26262306a36Sopenharmony_ci	.yes_ranges = da9063l_bb_writeable_ranges,
26362306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9063l_bb_writeable_ranges),
26462306a36Sopenharmony_ci};
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_cistatic const struct regmap_access_table da9063l_bb_da_volatile_table = {
26762306a36Sopenharmony_ci	.yes_ranges = da9063l_bb_da_volatile_ranges,
26862306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9063l_bb_da_volatile_ranges),
26962306a36Sopenharmony_ci};
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_cistatic const struct regmap_range da9063_da_readable_ranges[] = {
27262306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_BB_REG_SECOND_D),
27362306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
27462306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
27562306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_11),
27662306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
27762306a36Sopenharmony_ci};
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_cistatic const struct regmap_range da9063_da_writeable_ranges[] = {
28062306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
28162306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
28262306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_COUNT_S, DA9063_BB_REG_ALARM_Y),
28362306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
28462306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
28562306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),
28662306a36Sopenharmony_ci	regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_11),
28762306a36Sopenharmony_ci};
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_cistatic const struct regmap_access_table da9063_da_readable_table = {
29062306a36Sopenharmony_ci	.yes_ranges = da9063_da_readable_ranges,
29162306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9063_da_readable_ranges),
29262306a36Sopenharmony_ci};
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_cistatic const struct regmap_access_table da9063_da_writeable_table = {
29562306a36Sopenharmony_ci	.yes_ranges = da9063_da_writeable_ranges,
29662306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9063_da_writeable_ranges),
29762306a36Sopenharmony_ci};
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_cistatic const struct regmap_range da9063l_da_readable_ranges[] = {
30062306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_MON_A10_RES),
30162306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
30262306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
30362306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_11),
30462306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
30562306a36Sopenharmony_ci};
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_cistatic const struct regmap_range da9063l_da_writeable_ranges[] = {
30862306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
30962306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
31062306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
31162306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
31262306a36Sopenharmony_ci	regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),
31362306a36Sopenharmony_ci	regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_11),
31462306a36Sopenharmony_ci};
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_cistatic const struct regmap_access_table da9063l_da_readable_table = {
31762306a36Sopenharmony_ci	.yes_ranges = da9063l_da_readable_ranges,
31862306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9063l_da_readable_ranges),
31962306a36Sopenharmony_ci};
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_cistatic const struct regmap_access_table da9063l_da_writeable_table = {
32262306a36Sopenharmony_ci	.yes_ranges = da9063l_da_writeable_ranges,
32362306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(da9063l_da_writeable_ranges),
32462306a36Sopenharmony_ci};
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_cistatic const struct regmap_range_cfg da9063_range_cfg[] = {
32762306a36Sopenharmony_ci	{
32862306a36Sopenharmony_ci		.range_min = DA9063_REG_PAGE_CON,
32962306a36Sopenharmony_ci		.range_max = DA9063_REG_CONFIG_ID,
33062306a36Sopenharmony_ci		.selector_reg = DA9063_REG_PAGE_CON,
33162306a36Sopenharmony_ci		.selector_mask = 1 << DA9063_I2C_PAGE_SEL_SHIFT,
33262306a36Sopenharmony_ci		.selector_shift = DA9063_I2C_PAGE_SEL_SHIFT,
33362306a36Sopenharmony_ci		.window_start = 0,
33462306a36Sopenharmony_ci		.window_len = 256,
33562306a36Sopenharmony_ci	}
33662306a36Sopenharmony_ci};
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_cistatic struct regmap_config da9063_regmap_config = {
33962306a36Sopenharmony_ci	.reg_bits = 8,
34062306a36Sopenharmony_ci	.val_bits = 8,
34162306a36Sopenharmony_ci	.ranges = da9063_range_cfg,
34262306a36Sopenharmony_ci	.num_ranges = ARRAY_SIZE(da9063_range_cfg),
34362306a36Sopenharmony_ci	.max_register = DA9063_REG_CONFIG_ID,
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	.cache_type = REGCACHE_RBTREE,
34662306a36Sopenharmony_ci};
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_cistatic const struct of_device_id da9063_dt_ids[] = {
34962306a36Sopenharmony_ci	{ .compatible = "dlg,da9063", },
35062306a36Sopenharmony_ci	{ .compatible = "dlg,da9063l", },
35162306a36Sopenharmony_ci	{ }
35262306a36Sopenharmony_ci};
35362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, da9063_dt_ids);
35462306a36Sopenharmony_cistatic int da9063_i2c_probe(struct i2c_client *i2c)
35562306a36Sopenharmony_ci{
35662306a36Sopenharmony_ci	const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
35762306a36Sopenharmony_ci	struct da9063 *da9063;
35862306a36Sopenharmony_ci	int ret;
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	da9063 = devm_kzalloc(&i2c->dev, sizeof(struct da9063), GFP_KERNEL);
36162306a36Sopenharmony_ci	if (da9063 == NULL)
36262306a36Sopenharmony_ci		return -ENOMEM;
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	i2c_set_clientdata(i2c, da9063);
36562306a36Sopenharmony_ci	da9063->dev = &i2c->dev;
36662306a36Sopenharmony_ci	da9063->chip_irq = i2c->irq;
36762306a36Sopenharmony_ci	da9063->type = id->driver_data;
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	ret = da9063_get_device_type(i2c, da9063);
37062306a36Sopenharmony_ci	if (ret)
37162306a36Sopenharmony_ci		return ret;
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	switch (da9063->type) {
37462306a36Sopenharmony_ci	case PMIC_TYPE_DA9063:
37562306a36Sopenharmony_ci		switch (da9063->variant_code) {
37662306a36Sopenharmony_ci		case PMIC_DA9063_AD:
37762306a36Sopenharmony_ci			da9063_regmap_config.rd_table =
37862306a36Sopenharmony_ci				&da9063_ad_readable_table;
37962306a36Sopenharmony_ci			da9063_regmap_config.wr_table =
38062306a36Sopenharmony_ci				&da9063_ad_writeable_table;
38162306a36Sopenharmony_ci			da9063_regmap_config.volatile_table =
38262306a36Sopenharmony_ci				&da9063_ad_volatile_table;
38362306a36Sopenharmony_ci			break;
38462306a36Sopenharmony_ci		case PMIC_DA9063_BB:
38562306a36Sopenharmony_ci		case PMIC_DA9063_CA:
38662306a36Sopenharmony_ci			da9063_regmap_config.rd_table =
38762306a36Sopenharmony_ci				&da9063_bb_readable_table;
38862306a36Sopenharmony_ci			da9063_regmap_config.wr_table =
38962306a36Sopenharmony_ci				&da9063_bb_writeable_table;
39062306a36Sopenharmony_ci			da9063_regmap_config.volatile_table =
39162306a36Sopenharmony_ci				&da9063_bb_da_volatile_table;
39262306a36Sopenharmony_ci			break;
39362306a36Sopenharmony_ci		case PMIC_DA9063_DA:
39462306a36Sopenharmony_ci		case PMIC_DA9063_EA:
39562306a36Sopenharmony_ci			da9063_regmap_config.rd_table =
39662306a36Sopenharmony_ci				&da9063_da_readable_table;
39762306a36Sopenharmony_ci			da9063_regmap_config.wr_table =
39862306a36Sopenharmony_ci				&da9063_da_writeable_table;
39962306a36Sopenharmony_ci			da9063_regmap_config.volatile_table =
40062306a36Sopenharmony_ci				&da9063_bb_da_volatile_table;
40162306a36Sopenharmony_ci			break;
40262306a36Sopenharmony_ci		default:
40362306a36Sopenharmony_ci			dev_err(da9063->dev,
40462306a36Sopenharmony_ci				"Chip variant not supported for DA9063\n");
40562306a36Sopenharmony_ci			return -ENODEV;
40662306a36Sopenharmony_ci		}
40762306a36Sopenharmony_ci		break;
40862306a36Sopenharmony_ci	case PMIC_TYPE_DA9063L:
40962306a36Sopenharmony_ci		switch (da9063->variant_code) {
41062306a36Sopenharmony_ci		case PMIC_DA9063_BB:
41162306a36Sopenharmony_ci		case PMIC_DA9063_CA:
41262306a36Sopenharmony_ci			da9063_regmap_config.rd_table =
41362306a36Sopenharmony_ci				&da9063l_bb_readable_table;
41462306a36Sopenharmony_ci			da9063_regmap_config.wr_table =
41562306a36Sopenharmony_ci				&da9063l_bb_writeable_table;
41662306a36Sopenharmony_ci			da9063_regmap_config.volatile_table =
41762306a36Sopenharmony_ci				&da9063l_bb_da_volatile_table;
41862306a36Sopenharmony_ci			break;
41962306a36Sopenharmony_ci		case PMIC_DA9063_DA:
42062306a36Sopenharmony_ci		case PMIC_DA9063_EA:
42162306a36Sopenharmony_ci			da9063_regmap_config.rd_table =
42262306a36Sopenharmony_ci				&da9063l_da_readable_table;
42362306a36Sopenharmony_ci			da9063_regmap_config.wr_table =
42462306a36Sopenharmony_ci				&da9063l_da_writeable_table;
42562306a36Sopenharmony_ci			da9063_regmap_config.volatile_table =
42662306a36Sopenharmony_ci				&da9063l_bb_da_volatile_table;
42762306a36Sopenharmony_ci			break;
42862306a36Sopenharmony_ci		default:
42962306a36Sopenharmony_ci			dev_err(da9063->dev,
43062306a36Sopenharmony_ci				"Chip variant not supported for DA9063L\n");
43162306a36Sopenharmony_ci			return -ENODEV;
43262306a36Sopenharmony_ci		}
43362306a36Sopenharmony_ci		break;
43462306a36Sopenharmony_ci	default:
43562306a36Sopenharmony_ci		dev_err(da9063->dev, "Chip type not supported\n");
43662306a36Sopenharmony_ci		return -ENODEV;
43762306a36Sopenharmony_ci	}
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config);
44062306a36Sopenharmony_ci	if (IS_ERR(da9063->regmap)) {
44162306a36Sopenharmony_ci		ret = PTR_ERR(da9063->regmap);
44262306a36Sopenharmony_ci		dev_err(da9063->dev, "Failed to allocate register map: %d\n",
44362306a36Sopenharmony_ci			ret);
44462306a36Sopenharmony_ci		return ret;
44562306a36Sopenharmony_ci	}
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	/* If SMBus is not available and only I2C is possible, enter I2C mode */
44862306a36Sopenharmony_ci	if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) {
44962306a36Sopenharmony_ci		ret = regmap_clear_bits(da9063->regmap, DA9063_REG_CONFIG_J,
45062306a36Sopenharmony_ci					DA9063_TWOWIRE_TO);
45162306a36Sopenharmony_ci		if (ret < 0) {
45262306a36Sopenharmony_ci			dev_err(da9063->dev, "Failed to set Two-Wire Bus Mode.\n");
45362306a36Sopenharmony_ci			return ret;
45462306a36Sopenharmony_ci		}
45562306a36Sopenharmony_ci	}
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	return da9063_device_init(da9063, i2c->irq);
45862306a36Sopenharmony_ci}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_cistatic const struct i2c_device_id da9063_i2c_id[] = {
46162306a36Sopenharmony_ci	{ "da9063", PMIC_TYPE_DA9063 },
46262306a36Sopenharmony_ci	{ "da9063l", PMIC_TYPE_DA9063L },
46362306a36Sopenharmony_ci	{},
46462306a36Sopenharmony_ci};
46562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, da9063_i2c_id);
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_cistatic struct i2c_driver da9063_i2c_driver = {
46862306a36Sopenharmony_ci	.driver = {
46962306a36Sopenharmony_ci		.name = "da9063",
47062306a36Sopenharmony_ci		.of_match_table = da9063_dt_ids,
47162306a36Sopenharmony_ci	},
47262306a36Sopenharmony_ci	.probe = da9063_i2c_probe,
47362306a36Sopenharmony_ci	.id_table = da9063_i2c_id,
47462306a36Sopenharmony_ci};
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_cimodule_i2c_driver(da9063_i2c_driver);
477