xref: /openbmc/linux/drivers/mfd/da9063-i2c.c (revision 9816d859)
19efbc6f1SWolfram Sang // SPDX-License-Identifier: GPL-2.0+
29efbc6f1SWolfram Sang /* I2C support for Dialog DA9063
38e685483SKrystian Garbaciak  *
48e685483SKrystian Garbaciak  * Copyright 2012 Dialog Semiconductor Ltd.
58e685483SKrystian Garbaciak  * Copyright 2013 Philipp Zabel, Pengutronix
68e685483SKrystian Garbaciak  *
737778d83SSteve Twiss  * Author: Krystian Garbaciak, Dialog Semiconductor
88e685483SKrystian Garbaciak  */
98e685483SKrystian Garbaciak 
108e685483SKrystian Garbaciak #include <linux/kernel.h>
118e685483SKrystian Garbaciak #include <linux/module.h>
128e685483SKrystian Garbaciak #include <linux/i2c.h>
138e685483SKrystian Garbaciak #include <linux/regmap.h>
148e685483SKrystian Garbaciak #include <linux/delay.h>
158e685483SKrystian Garbaciak #include <linux/slab.h>
168e685483SKrystian Garbaciak #include <linux/err.h>
178e685483SKrystian Garbaciak 
188e685483SKrystian Garbaciak #include <linux/mfd/core.h>
198e685483SKrystian Garbaciak #include <linux/mfd/da9063/core.h>
208e685483SKrystian Garbaciak #include <linux/mfd/da9063/registers.h>
218e685483SKrystian Garbaciak 
2271e03de4SSteve Twiss #include <linux/of.h>
2371e03de4SSteve Twiss #include <linux/regulator/of_regulator.h>
2471e03de4SSteve Twiss 
25091c6110SAdam Thomson /*
26091c6110SAdam Thomson  * Raw I2C access required for just accessing chip and variant info before we
27091c6110SAdam Thomson  * know which device is present. The info read from the device using this
28091c6110SAdam Thomson  * approach is then used to select the correct regmap tables.
29091c6110SAdam Thomson  */
30091c6110SAdam Thomson 
31091c6110SAdam Thomson #define DA9063_REG_PAGE_SIZE		0x100
32091c6110SAdam Thomson #define DA9063_REG_PAGED_ADDR_MASK	0xFF
33091c6110SAdam Thomson 
34091c6110SAdam Thomson enum da9063_page_sel_buf_fmt {
35091c6110SAdam Thomson 	DA9063_PAGE_SEL_BUF_PAGE_REG = 0,
36091c6110SAdam Thomson 	DA9063_PAGE_SEL_BUF_PAGE_VAL,
37091c6110SAdam Thomson 	DA9063_PAGE_SEL_BUF_SIZE,
38091c6110SAdam Thomson };
39091c6110SAdam Thomson 
40091c6110SAdam Thomson enum da9063_paged_read_msgs {
41091c6110SAdam Thomson 	DA9063_PAGED_READ_MSG_PAGE_SEL = 0,
42091c6110SAdam Thomson 	DA9063_PAGED_READ_MSG_REG_SEL,
43091c6110SAdam Thomson 	DA9063_PAGED_READ_MSG_DATA,
44091c6110SAdam Thomson 	DA9063_PAGED_READ_MSG_CNT,
45091c6110SAdam Thomson };
46091c6110SAdam Thomson 
da9063_i2c_blockreg_read(struct i2c_client * client,u16 addr,u8 * buf,int count)47091c6110SAdam Thomson static int da9063_i2c_blockreg_read(struct i2c_client *client, u16 addr,
48091c6110SAdam Thomson 				    u8 *buf, int count)
49091c6110SAdam Thomson {
50091c6110SAdam Thomson 	struct i2c_msg xfer[DA9063_PAGED_READ_MSG_CNT];
51091c6110SAdam Thomson 	u8 page_sel_buf[DA9063_PAGE_SEL_BUF_SIZE];
52091c6110SAdam Thomson 	u8 page_num, paged_addr;
53091c6110SAdam Thomson 	int ret;
54091c6110SAdam Thomson 
55091c6110SAdam Thomson 	/* Determine page info based on register address */
56091c6110SAdam Thomson 	page_num = (addr / DA9063_REG_PAGE_SIZE);
57091c6110SAdam Thomson 	if (page_num > 1) {
58091c6110SAdam Thomson 		dev_err(&client->dev, "Invalid register address provided\n");
59091c6110SAdam Thomson 		return -EINVAL;
60091c6110SAdam Thomson 	}
61091c6110SAdam Thomson 
62091c6110SAdam Thomson 	paged_addr = (addr % DA9063_REG_PAGE_SIZE) & DA9063_REG_PAGED_ADDR_MASK;
63091c6110SAdam Thomson 	page_sel_buf[DA9063_PAGE_SEL_BUF_PAGE_REG] = DA9063_REG_PAGE_CON;
64091c6110SAdam Thomson 	page_sel_buf[DA9063_PAGE_SEL_BUF_PAGE_VAL] =
65091c6110SAdam Thomson 		(page_num << DA9063_I2C_PAGE_SEL_SHIFT) & DA9063_REG_PAGE_MASK;
66091c6110SAdam Thomson 
67091c6110SAdam Thomson 	/* Write reg address, page selection */
68091c6110SAdam Thomson 	xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].addr = client->addr;
69091c6110SAdam Thomson 	xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].flags = 0;
70091c6110SAdam Thomson 	xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].len = DA9063_PAGE_SEL_BUF_SIZE;
71091c6110SAdam Thomson 	xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].buf = page_sel_buf;
72091c6110SAdam Thomson 
73091c6110SAdam Thomson 	/* Select register address */
74091c6110SAdam Thomson 	xfer[DA9063_PAGED_READ_MSG_REG_SEL].addr = client->addr;
75091c6110SAdam Thomson 	xfer[DA9063_PAGED_READ_MSG_REG_SEL].flags = 0;
76091c6110SAdam Thomson 	xfer[DA9063_PAGED_READ_MSG_REG_SEL].len = sizeof(paged_addr);
77091c6110SAdam Thomson 	xfer[DA9063_PAGED_READ_MSG_REG_SEL].buf = &paged_addr;
78091c6110SAdam Thomson 
79091c6110SAdam Thomson 	/* Read data */
80091c6110SAdam Thomson 	xfer[DA9063_PAGED_READ_MSG_DATA].addr = client->addr;
81091c6110SAdam Thomson 	xfer[DA9063_PAGED_READ_MSG_DATA].flags = I2C_M_RD;
82091c6110SAdam Thomson 	xfer[DA9063_PAGED_READ_MSG_DATA].len = count;
83091c6110SAdam Thomson 	xfer[DA9063_PAGED_READ_MSG_DATA].buf = buf;
84091c6110SAdam Thomson 
85091c6110SAdam Thomson 	ret = i2c_transfer(client->adapter, xfer, DA9063_PAGED_READ_MSG_CNT);
86091c6110SAdam Thomson 	if (ret < 0) {
87091c6110SAdam Thomson 		dev_err(&client->dev, "Paged block read failed: %d\n", ret);
88091c6110SAdam Thomson 		return ret;
89091c6110SAdam Thomson 	}
90091c6110SAdam Thomson 
91091c6110SAdam Thomson 	if (ret != DA9063_PAGED_READ_MSG_CNT) {
92091c6110SAdam Thomson 		dev_err(&client->dev, "Paged block read failed to complete\n");
93091c6110SAdam Thomson 		return -EIO;
94091c6110SAdam Thomson 	}
95091c6110SAdam Thomson 
96091c6110SAdam Thomson 	return 0;
97091c6110SAdam Thomson }
98091c6110SAdam Thomson 
99091c6110SAdam Thomson enum {
100091c6110SAdam Thomson 	DA9063_DEV_ID_REG = 0,
101091c6110SAdam Thomson 	DA9063_VAR_ID_REG,
102091c6110SAdam Thomson 	DA9063_CHIP_ID_REGS,
103091c6110SAdam Thomson };
104091c6110SAdam Thomson 
da9063_get_device_type(struct i2c_client * i2c,struct da9063 * da9063)105091c6110SAdam Thomson static int da9063_get_device_type(struct i2c_client *i2c, struct da9063 *da9063)
106091c6110SAdam Thomson {
107091c6110SAdam Thomson 	u8 buf[DA9063_CHIP_ID_REGS];
108091c6110SAdam Thomson 	int ret;
109091c6110SAdam Thomson 
110091c6110SAdam Thomson 	ret = da9063_i2c_blockreg_read(i2c, DA9063_REG_DEVICE_ID, buf,
111091c6110SAdam Thomson 				       DA9063_CHIP_ID_REGS);
112091c6110SAdam Thomson 	if (ret)
113091c6110SAdam Thomson 		return ret;
114091c6110SAdam Thomson 
115091c6110SAdam Thomson 	if (buf[DA9063_DEV_ID_REG] != PMIC_CHIP_ID_DA9063) {
116091c6110SAdam Thomson 		dev_err(da9063->dev,
117091c6110SAdam Thomson 			"Invalid chip device ID: 0x%02x\n",
118091c6110SAdam Thomson 			buf[DA9063_DEV_ID_REG]);
119091c6110SAdam Thomson 		return -ENODEV;
120091c6110SAdam Thomson 	}
121091c6110SAdam Thomson 
122091c6110SAdam Thomson 	dev_info(da9063->dev,
123091c6110SAdam Thomson 		 "Device detected (chip-ID: 0x%02X, var-ID: 0x%02X)\n",
124091c6110SAdam Thomson 		 buf[DA9063_DEV_ID_REG], buf[DA9063_VAR_ID_REG]);
125091c6110SAdam Thomson 
126091c6110SAdam Thomson 	da9063->variant_code =
127091c6110SAdam Thomson 		(buf[DA9063_VAR_ID_REG] & DA9063_VARIANT_ID_MRC_MASK)
128091c6110SAdam Thomson 		>> DA9063_VARIANT_ID_MRC_SHIFT;
129091c6110SAdam Thomson 
130091c6110SAdam Thomson 	return 0;
131091c6110SAdam Thomson }
132091c6110SAdam Thomson 
133091c6110SAdam Thomson /*
134091c6110SAdam Thomson  * Variant specific regmap configs
135091c6110SAdam Thomson  */
136091c6110SAdam Thomson 
1379cb42e2aSOpensource [Steve Twiss] static const struct regmap_range da9063_ad_readable_ranges[] = {
1382905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_AD_REG_SECOND_D),
1392905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
1402905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
1412905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_AD_REG_GP_ID_19),
142091c6110SAdam Thomson 	regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
1438e685483SKrystian Garbaciak };
1448e685483SKrystian Garbaciak 
1459cb42e2aSOpensource [Steve Twiss] static const struct regmap_range da9063_ad_writeable_ranges[] = {
1462905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
1472905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
1482905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_COUNT_S, DA9063_AD_REG_ALARM_Y),
1492905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
1502905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
1512905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_AD_REG_MON_REG_4),
1522905086dSMarek Vasut 	regmap_reg_range(DA9063_AD_REG_GP_ID_0, DA9063_AD_REG_GP_ID_19),
1538e685483SKrystian Garbaciak };
1548e685483SKrystian Garbaciak 
1559cb42e2aSOpensource [Steve Twiss] static const struct regmap_range da9063_ad_volatile_ranges[] = {
1562905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),
1572905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),
1582905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),
1592905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),
1602905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),
1612905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_AD_REG_SECOND_D),
1622905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),
1632905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),
1642905086dSMarek Vasut 	regmap_reg_range(DA9063_AD_REG_MON_REG_5, DA9063_AD_REG_MON_REG_6),
1658e685483SKrystian Garbaciak };
1668e685483SKrystian Garbaciak 
1679cb42e2aSOpensource [Steve Twiss] static const struct regmap_access_table da9063_ad_readable_table = {
1689cb42e2aSOpensource [Steve Twiss] 	.yes_ranges = da9063_ad_readable_ranges,
1699cb42e2aSOpensource [Steve Twiss] 	.n_yes_ranges = ARRAY_SIZE(da9063_ad_readable_ranges),
1708e685483SKrystian Garbaciak };
1718e685483SKrystian Garbaciak 
1729cb42e2aSOpensource [Steve Twiss] static const struct regmap_access_table da9063_ad_writeable_table = {
1739cb42e2aSOpensource [Steve Twiss] 	.yes_ranges = da9063_ad_writeable_ranges,
1749cb42e2aSOpensource [Steve Twiss] 	.n_yes_ranges = ARRAY_SIZE(da9063_ad_writeable_ranges),
1758e685483SKrystian Garbaciak };
1768e685483SKrystian Garbaciak 
1779cb42e2aSOpensource [Steve Twiss] static const struct regmap_access_table da9063_ad_volatile_table = {
1789cb42e2aSOpensource [Steve Twiss] 	.yes_ranges = da9063_ad_volatile_ranges,
1799cb42e2aSOpensource [Steve Twiss] 	.n_yes_ranges = ARRAY_SIZE(da9063_ad_volatile_ranges),
1809cb42e2aSOpensource [Steve Twiss] };
1819cb42e2aSOpensource [Steve Twiss] 
1829cb42e2aSOpensource [Steve Twiss] static const struct regmap_range da9063_bb_readable_ranges[] = {
1832905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_BB_REG_SECOND_D),
1842905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
1852905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
1862905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19),
187091c6110SAdam Thomson 	regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
1889cb42e2aSOpensource [Steve Twiss] };
1899cb42e2aSOpensource [Steve Twiss] 
1909cb42e2aSOpensource [Steve Twiss] static const struct regmap_range da9063_bb_writeable_ranges[] = {
1912905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
1922905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
1932905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_COUNT_S, DA9063_BB_REG_ALARM_Y),
1942905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
1952905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
1962905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),
1972905086dSMarek Vasut 	regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19),
1989cb42e2aSOpensource [Steve Twiss] };
1999cb42e2aSOpensource [Steve Twiss] 
2009ece3601SAdam Thomson static const struct regmap_range da9063_bb_da_volatile_ranges[] = {
2012905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),
2022905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),
2032905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),
2042905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),
2052905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),
2062905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_BB_REG_SECOND_D),
2072905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),
2082905086dSMarek Vasut 	regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),
2092905086dSMarek Vasut 	regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6),
2109cb42e2aSOpensource [Steve Twiss] };
2119cb42e2aSOpensource [Steve Twiss] 
2129cb42e2aSOpensource [Steve Twiss] static const struct regmap_access_table da9063_bb_readable_table = {
2139cb42e2aSOpensource [Steve Twiss] 	.yes_ranges = da9063_bb_readable_ranges,
2149cb42e2aSOpensource [Steve Twiss] 	.n_yes_ranges = ARRAY_SIZE(da9063_bb_readable_ranges),
2159cb42e2aSOpensource [Steve Twiss] };
2169cb42e2aSOpensource [Steve Twiss] 
2179cb42e2aSOpensource [Steve Twiss] static const struct regmap_access_table da9063_bb_writeable_table = {
2189cb42e2aSOpensource [Steve Twiss] 	.yes_ranges = da9063_bb_writeable_ranges,
2199cb42e2aSOpensource [Steve Twiss] 	.n_yes_ranges = ARRAY_SIZE(da9063_bb_writeable_ranges),
2209cb42e2aSOpensource [Steve Twiss] };
2219cb42e2aSOpensource [Steve Twiss] 
2229ece3601SAdam Thomson static const struct regmap_access_table da9063_bb_da_volatile_table = {
2239ece3601SAdam Thomson 	.yes_ranges = da9063_bb_da_volatile_ranges,
2249ece3601SAdam Thomson 	.n_yes_ranges = ARRAY_SIZE(da9063_bb_da_volatile_ranges),
2258e685483SKrystian Garbaciak };
2268e685483SKrystian Garbaciak 
2274bd6ad0aSMarek Vasut static const struct regmap_range da9063l_bb_readable_ranges[] = {
2284bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_MON_A10_RES),
2294bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
2304bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
2314bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19),
232091c6110SAdam Thomson 	regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
2334bd6ad0aSMarek Vasut };
2344bd6ad0aSMarek Vasut 
2354bd6ad0aSMarek Vasut static const struct regmap_range da9063l_bb_writeable_ranges[] = {
2364bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
2374bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
2384bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
2394bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
2404bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),
2414bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19),
2424bd6ad0aSMarek Vasut };
2434bd6ad0aSMarek Vasut 
2449ece3601SAdam Thomson static const struct regmap_range da9063l_bb_da_volatile_ranges[] = {
2454bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),
2464bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),
2474bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),
2484bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT),
2494bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN),
2504bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_REG_MON_A10_RES),
2514bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ),
2524bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K),
2534bd6ad0aSMarek Vasut 	regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6),
2544bd6ad0aSMarek Vasut };
2554bd6ad0aSMarek Vasut 
2564bd6ad0aSMarek Vasut static const struct regmap_access_table da9063l_bb_readable_table = {
2574bd6ad0aSMarek Vasut 	.yes_ranges = da9063l_bb_readable_ranges,
2584bd6ad0aSMarek Vasut 	.n_yes_ranges = ARRAY_SIZE(da9063l_bb_readable_ranges),
2594bd6ad0aSMarek Vasut };
2604bd6ad0aSMarek Vasut 
2614bd6ad0aSMarek Vasut static const struct regmap_access_table da9063l_bb_writeable_table = {
2624bd6ad0aSMarek Vasut 	.yes_ranges = da9063l_bb_writeable_ranges,
2634bd6ad0aSMarek Vasut 	.n_yes_ranges = ARRAY_SIZE(da9063l_bb_writeable_ranges),
2644bd6ad0aSMarek Vasut };
2654bd6ad0aSMarek Vasut 
2669ece3601SAdam Thomson static const struct regmap_access_table da9063l_bb_da_volatile_table = {
2679ece3601SAdam Thomson 	.yes_ranges = da9063l_bb_da_volatile_ranges,
2689ece3601SAdam Thomson 	.n_yes_ranges = ARRAY_SIZE(da9063l_bb_da_volatile_ranges),
2699ece3601SAdam Thomson };
2709ece3601SAdam Thomson 
2719ece3601SAdam Thomson static const struct regmap_range da9063_da_readable_ranges[] = {
2729ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_BB_REG_SECOND_D),
2739ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
2749ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
2759ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_11),
2769ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
2779ece3601SAdam Thomson };
2789ece3601SAdam Thomson 
2799ece3601SAdam Thomson static const struct regmap_range da9063_da_writeable_ranges[] = {
2809ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
2819ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
2829ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_COUNT_S, DA9063_BB_REG_ALARM_Y),
2839ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
2849ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
2859ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),
2869ece3601SAdam Thomson 	regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_11),
2879ece3601SAdam Thomson };
2889ece3601SAdam Thomson 
2899ece3601SAdam Thomson static const struct regmap_access_table da9063_da_readable_table = {
2909ece3601SAdam Thomson 	.yes_ranges = da9063_da_readable_ranges,
2919ece3601SAdam Thomson 	.n_yes_ranges = ARRAY_SIZE(da9063_da_readable_ranges),
2929ece3601SAdam Thomson };
2939ece3601SAdam Thomson 
2949ece3601SAdam Thomson static const struct regmap_access_table da9063_da_writeable_table = {
2959ece3601SAdam Thomson 	.yes_ranges = da9063_da_writeable_ranges,
2969ece3601SAdam Thomson 	.n_yes_ranges = ARRAY_SIZE(da9063_da_writeable_ranges),
2979ece3601SAdam Thomson };
2989ece3601SAdam Thomson 
2999ece3601SAdam Thomson static const struct regmap_range da9063l_da_readable_ranges[] = {
3009ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_MON_A10_RES),
3019ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
3029ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
3039ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_11),
3049ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
3059ece3601SAdam Thomson };
3069ece3601SAdam Thomson 
3079ece3601SAdam Thomson static const struct regmap_range da9063l_da_writeable_ranges[] = {
3089ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON),
3099ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON),
3109ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
3119ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
3129ece3601SAdam Thomson 	regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4),
3139ece3601SAdam Thomson 	regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_11),
3149ece3601SAdam Thomson };
3159ece3601SAdam Thomson 
3169ece3601SAdam Thomson static const struct regmap_access_table da9063l_da_readable_table = {
3179ece3601SAdam Thomson 	.yes_ranges = da9063l_da_readable_ranges,
3189ece3601SAdam Thomson 	.n_yes_ranges = ARRAY_SIZE(da9063l_da_readable_ranges),
3199ece3601SAdam Thomson };
3209ece3601SAdam Thomson 
3219ece3601SAdam Thomson static const struct regmap_access_table da9063l_da_writeable_table = {
3229ece3601SAdam Thomson 	.yes_ranges = da9063l_da_writeable_ranges,
3239ece3601SAdam Thomson 	.n_yes_ranges = ARRAY_SIZE(da9063l_da_writeable_ranges),
3244bd6ad0aSMarek Vasut };
3254bd6ad0aSMarek Vasut 
3268e685483SKrystian Garbaciak static const struct regmap_range_cfg da9063_range_cfg[] = {
3278e685483SKrystian Garbaciak 	{
3288e685483SKrystian Garbaciak 		.range_min = DA9063_REG_PAGE_CON,
329091c6110SAdam Thomson 		.range_max = DA9063_REG_CONFIG_ID,
3308e685483SKrystian Garbaciak 		.selector_reg = DA9063_REG_PAGE_CON,
3318e685483SKrystian Garbaciak 		.selector_mask = 1 << DA9063_I2C_PAGE_SEL_SHIFT,
3328e685483SKrystian Garbaciak 		.selector_shift = DA9063_I2C_PAGE_SEL_SHIFT,
3338e685483SKrystian Garbaciak 		.window_start = 0,
3348e685483SKrystian Garbaciak 		.window_len = 256,
3358e685483SKrystian Garbaciak 	}
3368e685483SKrystian Garbaciak };
3378e685483SKrystian Garbaciak 
3388e685483SKrystian Garbaciak static struct regmap_config da9063_regmap_config = {
3398e685483SKrystian Garbaciak 	.reg_bits = 8,
3408e685483SKrystian Garbaciak 	.val_bits = 8,
3418e685483SKrystian Garbaciak 	.ranges = da9063_range_cfg,
3428e685483SKrystian Garbaciak 	.num_ranges = ARRAY_SIZE(da9063_range_cfg),
343091c6110SAdam Thomson 	.max_register = DA9063_REG_CONFIG_ID,
3448e685483SKrystian Garbaciak 
3458e685483SKrystian Garbaciak 	.cache_type = REGCACHE_RBTREE,
3468e685483SKrystian Garbaciak };
3478e685483SKrystian Garbaciak 
34871e03de4SSteve Twiss static const struct of_device_id da9063_dt_ids[] = {
34971e03de4SSteve Twiss 	{ .compatible = "dlg,da9063", },
350c287572bSMarek Vasut 	{ .compatible = "dlg,da9063l", },
35171e03de4SSteve Twiss 	{ }
35271e03de4SSteve Twiss };
35371e03de4SSteve Twiss MODULE_DEVICE_TABLE(of, da9063_dt_ids);
da9063_i2c_probe(struct i2c_client * i2c)354b309636bSUwe Kleine-König static int da9063_i2c_probe(struct i2c_client *i2c)
3558e685483SKrystian Garbaciak {
356b309636bSUwe Kleine-König 	const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
3578e685483SKrystian Garbaciak 	struct da9063 *da9063;
3588e685483SKrystian Garbaciak 	int ret;
3598e685483SKrystian Garbaciak 
3608e685483SKrystian Garbaciak 	da9063 = devm_kzalloc(&i2c->dev, sizeof(struct da9063), GFP_KERNEL);
3618e685483SKrystian Garbaciak 	if (da9063 == NULL)
3628e685483SKrystian Garbaciak 		return -ENOMEM;
3638e685483SKrystian Garbaciak 
3648e685483SKrystian Garbaciak 	i2c_set_clientdata(i2c, da9063);
3658e685483SKrystian Garbaciak 	da9063->dev = &i2c->dev;
3668e685483SKrystian Garbaciak 	da9063->chip_irq = i2c->irq;
367492510ddSMarek Vasut 	da9063->type = id->driver_data;
3688e685483SKrystian Garbaciak 
369091c6110SAdam Thomson 	ret = da9063_get_device_type(i2c, da9063);
370091c6110SAdam Thomson 	if (ret)
371091c6110SAdam Thomson 		return ret;
372091c6110SAdam Thomson 
373091c6110SAdam Thomson 	switch (da9063->type) {
374091c6110SAdam Thomson 	case PMIC_TYPE_DA9063:
375091c6110SAdam Thomson 		switch (da9063->variant_code) {
376091c6110SAdam Thomson 		case PMIC_DA9063_AD:
377091c6110SAdam Thomson 			da9063_regmap_config.rd_table =
378091c6110SAdam Thomson 				&da9063_ad_readable_table;
379091c6110SAdam Thomson 			da9063_regmap_config.wr_table =
380091c6110SAdam Thomson 				&da9063_ad_writeable_table;
381091c6110SAdam Thomson 			da9063_regmap_config.volatile_table =
382091c6110SAdam Thomson 				&da9063_ad_volatile_table;
383091c6110SAdam Thomson 			break;
384091c6110SAdam Thomson 		case PMIC_DA9063_BB:
385091c6110SAdam Thomson 		case PMIC_DA9063_CA:
386091c6110SAdam Thomson 			da9063_regmap_config.rd_table =
387091c6110SAdam Thomson 				&da9063_bb_readable_table;
388091c6110SAdam Thomson 			da9063_regmap_config.wr_table =
389091c6110SAdam Thomson 				&da9063_bb_writeable_table;
390091c6110SAdam Thomson 			da9063_regmap_config.volatile_table =
3919ece3601SAdam Thomson 				&da9063_bb_da_volatile_table;
3929ece3601SAdam Thomson 			break;
3939ece3601SAdam Thomson 		case PMIC_DA9063_DA:
394c9a20383SCarlos de Paula 		case PMIC_DA9063_EA:
3959ece3601SAdam Thomson 			da9063_regmap_config.rd_table =
3969ece3601SAdam Thomson 				&da9063_da_readable_table;
3979ece3601SAdam Thomson 			da9063_regmap_config.wr_table =
3989ece3601SAdam Thomson 				&da9063_da_writeable_table;
3999ece3601SAdam Thomson 			da9063_regmap_config.volatile_table =
4009ece3601SAdam Thomson 				&da9063_bb_da_volatile_table;
401091c6110SAdam Thomson 			break;
402091c6110SAdam Thomson 		default:
403091c6110SAdam Thomson 			dev_err(da9063->dev,
404091c6110SAdam Thomson 				"Chip variant not supported for DA9063\n");
405091c6110SAdam Thomson 			return -ENODEV;
406091c6110SAdam Thomson 		}
407091c6110SAdam Thomson 		break;
408091c6110SAdam Thomson 	case PMIC_TYPE_DA9063L:
409091c6110SAdam Thomson 		switch (da9063->variant_code) {
410091c6110SAdam Thomson 		case PMIC_DA9063_BB:
411091c6110SAdam Thomson 		case PMIC_DA9063_CA:
412091c6110SAdam Thomson 			da9063_regmap_config.rd_table =
413091c6110SAdam Thomson 				&da9063l_bb_readable_table;
414091c6110SAdam Thomson 			da9063_regmap_config.wr_table =
415091c6110SAdam Thomson 				&da9063l_bb_writeable_table;
416091c6110SAdam Thomson 			da9063_regmap_config.volatile_table =
4179ece3601SAdam Thomson 				&da9063l_bb_da_volatile_table;
4189ece3601SAdam Thomson 			break;
4199ece3601SAdam Thomson 		case PMIC_DA9063_DA:
420c9a20383SCarlos de Paula 		case PMIC_DA9063_EA:
4219ece3601SAdam Thomson 			da9063_regmap_config.rd_table =
4229ece3601SAdam Thomson 				&da9063l_da_readable_table;
4239ece3601SAdam Thomson 			da9063_regmap_config.wr_table =
4249ece3601SAdam Thomson 				&da9063l_da_writeable_table;
4259ece3601SAdam Thomson 			da9063_regmap_config.volatile_table =
4269ece3601SAdam Thomson 				&da9063l_bb_da_volatile_table;
427091c6110SAdam Thomson 			break;
428091c6110SAdam Thomson 		default:
429091c6110SAdam Thomson 			dev_err(da9063->dev,
430091c6110SAdam Thomson 				"Chip variant not supported for DA9063L\n");
431091c6110SAdam Thomson 			return -ENODEV;
432091c6110SAdam Thomson 		}
433091c6110SAdam Thomson 		break;
434091c6110SAdam Thomson 	default:
435091c6110SAdam Thomson 		dev_err(da9063->dev, "Chip type not supported\n");
436091c6110SAdam Thomson 		return -ENODEV;
4379cb42e2aSOpensource [Steve Twiss] 	}
4389cb42e2aSOpensource [Steve Twiss] 
4398e685483SKrystian Garbaciak 	da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config);
4408e685483SKrystian Garbaciak 	if (IS_ERR(da9063->regmap)) {
4418e685483SKrystian Garbaciak 		ret = PTR_ERR(da9063->regmap);
4428e685483SKrystian Garbaciak 		dev_err(da9063->dev, "Failed to allocate register map: %d\n",
4438e685483SKrystian Garbaciak 			ret);
4448e685483SKrystian Garbaciak 		return ret;
4458e685483SKrystian Garbaciak 	}
4468e685483SKrystian Garbaciak 
447586478bfSHubert Streidl 	/* If SMBus is not available and only I2C is possible, enter I2C mode */
448586478bfSHubert Streidl 	if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) {
449586478bfSHubert Streidl 		ret = regmap_clear_bits(da9063->regmap, DA9063_REG_CONFIG_J,
450586478bfSHubert Streidl 					DA9063_TWOWIRE_TO);
451586478bfSHubert Streidl 		if (ret < 0) {
452586478bfSHubert Streidl 			dev_err(da9063->dev, "Failed to set Two-Wire Bus Mode.\n");
453921071a8SWolfram Sang 			return ret;
454586478bfSHubert Streidl 		}
455586478bfSHubert Streidl 	}
456586478bfSHubert Streidl 
4578e685483SKrystian Garbaciak 	return da9063_device_init(da9063, i2c->irq);
4588e685483SKrystian Garbaciak }
4598e685483SKrystian Garbaciak 
4608e685483SKrystian Garbaciak static const struct i2c_device_id da9063_i2c_id[] = {
461492510ddSMarek Vasut 	{ "da9063", PMIC_TYPE_DA9063 },
462c287572bSMarek Vasut 	{ "da9063l", PMIC_TYPE_DA9063L },
4638e685483SKrystian Garbaciak 	{},
4648e685483SKrystian Garbaciak };
4658e685483SKrystian Garbaciak MODULE_DEVICE_TABLE(i2c, da9063_i2c_id);
4668e685483SKrystian Garbaciak 
4678e685483SKrystian Garbaciak static struct i2c_driver da9063_i2c_driver = {
4688e685483SKrystian Garbaciak 	.driver = {
4698e685483SKrystian Garbaciak 		.name = "da9063",
4705f2bf438SKrzysztof Kozlowski 		.of_match_table = da9063_dt_ids,
4718e685483SKrystian Garbaciak 	},
472*9816d859SUwe Kleine-König 	.probe = da9063_i2c_probe,
4738e685483SKrystian Garbaciak 	.id_table = da9063_i2c_id,
4748e685483SKrystian Garbaciak };
4758e685483SKrystian Garbaciak 
4768e685483SKrystian Garbaciak module_i2c_driver(da9063_i2c_driver);
477