Commit | Line | Data |
---|---|---|
9efbc6f1 WS |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* I2C support for Dialog DA9063 | |
8e685483 KG |
3 | * |
4 | * Copyright 2012 Dialog Semiconductor Ltd. | |
5 | * Copyright 2013 Philipp Zabel, Pengutronix | |
6 | * | |
37778d83 | 7 | * Author: Krystian Garbaciak, Dialog Semiconductor |
8e685483 KG |
8 | */ |
9 | ||
10 | #include <linux/kernel.h> | |
11 | #include <linux/module.h> | |
12 | #include <linux/i2c.h> | |
13 | #include <linux/regmap.h> | |
14 | #include <linux/delay.h> | |
15 | #include <linux/slab.h> | |
16 | #include <linux/err.h> | |
17 | ||
18 | #include <linux/mfd/core.h> | |
19 | #include <linux/mfd/da9063/core.h> | |
8e685483 KG |
20 | #include <linux/mfd/da9063/registers.h> |
21 | ||
71e03de4 ST |
22 | #include <linux/of.h> |
23 | #include <linux/regulator/of_regulator.h> | |
24 | ||
091c6110 AT |
25 | /* |
26 | * Raw I2C access required for just accessing chip and variant info before we | |
27 | * know which device is present. The info read from the device using this | |
28 | * approach is then used to select the correct regmap tables. | |
29 | */ | |
30 | ||
31 | #define DA9063_REG_PAGE_SIZE 0x100 | |
32 | #define DA9063_REG_PAGED_ADDR_MASK 0xFF | |
33 | ||
34 | enum da9063_page_sel_buf_fmt { | |
35 | DA9063_PAGE_SEL_BUF_PAGE_REG = 0, | |
36 | DA9063_PAGE_SEL_BUF_PAGE_VAL, | |
37 | DA9063_PAGE_SEL_BUF_SIZE, | |
38 | }; | |
39 | ||
40 | enum da9063_paged_read_msgs { | |
41 | DA9063_PAGED_READ_MSG_PAGE_SEL = 0, | |
42 | DA9063_PAGED_READ_MSG_REG_SEL, | |
43 | DA9063_PAGED_READ_MSG_DATA, | |
44 | DA9063_PAGED_READ_MSG_CNT, | |
45 | }; | |
46 | ||
47 | static int da9063_i2c_blockreg_read(struct i2c_client *client, u16 addr, | |
48 | u8 *buf, int count) | |
49 | { | |
50 | struct i2c_msg xfer[DA9063_PAGED_READ_MSG_CNT]; | |
51 | u8 page_sel_buf[DA9063_PAGE_SEL_BUF_SIZE]; | |
52 | u8 page_num, paged_addr; | |
53 | int ret; | |
54 | ||
55 | /* Determine page info based on register address */ | |
56 | page_num = (addr / DA9063_REG_PAGE_SIZE); | |
57 | if (page_num > 1) { | |
58 | dev_err(&client->dev, "Invalid register address provided\n"); | |
59 | return -EINVAL; | |
60 | } | |
61 | ||
62 | paged_addr = (addr % DA9063_REG_PAGE_SIZE) & DA9063_REG_PAGED_ADDR_MASK; | |
63 | page_sel_buf[DA9063_PAGE_SEL_BUF_PAGE_REG] = DA9063_REG_PAGE_CON; | |
64 | page_sel_buf[DA9063_PAGE_SEL_BUF_PAGE_VAL] = | |
65 | (page_num << DA9063_I2C_PAGE_SEL_SHIFT) & DA9063_REG_PAGE_MASK; | |
66 | ||
67 | /* Write reg address, page selection */ | |
68 | xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].addr = client->addr; | |
69 | xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].flags = 0; | |
70 | xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].len = DA9063_PAGE_SEL_BUF_SIZE; | |
71 | xfer[DA9063_PAGED_READ_MSG_PAGE_SEL].buf = page_sel_buf; | |
72 | ||
73 | /* Select register address */ | |
74 | xfer[DA9063_PAGED_READ_MSG_REG_SEL].addr = client->addr; | |
75 | xfer[DA9063_PAGED_READ_MSG_REG_SEL].flags = 0; | |
76 | xfer[DA9063_PAGED_READ_MSG_REG_SEL].len = sizeof(paged_addr); | |
77 | xfer[DA9063_PAGED_READ_MSG_REG_SEL].buf = &paged_addr; | |
78 | ||
79 | /* Read data */ | |
80 | xfer[DA9063_PAGED_READ_MSG_DATA].addr = client->addr; | |
81 | xfer[DA9063_PAGED_READ_MSG_DATA].flags = I2C_M_RD; | |
82 | xfer[DA9063_PAGED_READ_MSG_DATA].len = count; | |
83 | xfer[DA9063_PAGED_READ_MSG_DATA].buf = buf; | |
84 | ||
85 | ret = i2c_transfer(client->adapter, xfer, DA9063_PAGED_READ_MSG_CNT); | |
86 | if (ret < 0) { | |
87 | dev_err(&client->dev, "Paged block read failed: %d\n", ret); | |
88 | return ret; | |
89 | } | |
90 | ||
91 | if (ret != DA9063_PAGED_READ_MSG_CNT) { | |
92 | dev_err(&client->dev, "Paged block read failed to complete\n"); | |
93 | return -EIO; | |
94 | } | |
95 | ||
96 | return 0; | |
97 | } | |
98 | ||
99 | enum { | |
100 | DA9063_DEV_ID_REG = 0, | |
101 | DA9063_VAR_ID_REG, | |
102 | DA9063_CHIP_ID_REGS, | |
103 | }; | |
104 | ||
105 | static int da9063_get_device_type(struct i2c_client *i2c, struct da9063 *da9063) | |
106 | { | |
107 | u8 buf[DA9063_CHIP_ID_REGS]; | |
108 | int ret; | |
109 | ||
110 | ret = da9063_i2c_blockreg_read(i2c, DA9063_REG_DEVICE_ID, buf, | |
111 | DA9063_CHIP_ID_REGS); | |
112 | if (ret) | |
113 | return ret; | |
114 | ||
115 | if (buf[DA9063_DEV_ID_REG] != PMIC_CHIP_ID_DA9063) { | |
116 | dev_err(da9063->dev, | |
117 | "Invalid chip device ID: 0x%02x\n", | |
118 | buf[DA9063_DEV_ID_REG]); | |
119 | return -ENODEV; | |
120 | } | |
121 | ||
122 | dev_info(da9063->dev, | |
123 | "Device detected (chip-ID: 0x%02X, var-ID: 0x%02X)\n", | |
124 | buf[DA9063_DEV_ID_REG], buf[DA9063_VAR_ID_REG]); | |
125 | ||
126 | da9063->variant_code = | |
127 | (buf[DA9063_VAR_ID_REG] & DA9063_VARIANT_ID_MRC_MASK) | |
128 | >> DA9063_VARIANT_ID_MRC_SHIFT; | |
129 | ||
130 | return 0; | |
131 | } | |
132 | ||
133 | /* | |
134 | * Variant specific regmap configs | |
135 | */ | |
136 | ||
9cb42e2a | 137 | static const struct regmap_range da9063_ad_readable_ranges[] = { |
2905086d MV |
138 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_AD_REG_SECOND_D), |
139 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), | |
140 | regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), | |
141 | regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_AD_REG_GP_ID_19), | |
091c6110 | 142 | regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID), |
8e685483 KG |
143 | }; |
144 | ||
9cb42e2a | 145 | static const struct regmap_range da9063_ad_writeable_ranges[] = { |
2905086d MV |
146 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON), |
147 | regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON), | |
148 | regmap_reg_range(DA9063_REG_COUNT_S, DA9063_AD_REG_ALARM_Y), | |
149 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), | |
150 | regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), | |
151 | regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_AD_REG_MON_REG_4), | |
152 | regmap_reg_range(DA9063_AD_REG_GP_ID_0, DA9063_AD_REG_GP_ID_19), | |
8e685483 KG |
153 | }; |
154 | ||
9cb42e2a | 155 | static const struct regmap_range da9063_ad_volatile_ranges[] = { |
2905086d MV |
156 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D), |
157 | regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B), | |
158 | regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F), | |
159 | regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT), | |
160 | regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN), | |
161 | regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_AD_REG_SECOND_D), | |
162 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ), | |
163 | regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K), | |
164 | regmap_reg_range(DA9063_AD_REG_MON_REG_5, DA9063_AD_REG_MON_REG_6), | |
8e685483 KG |
165 | }; |
166 | ||
9cb42e2a OST |
167 | static const struct regmap_access_table da9063_ad_readable_table = { |
168 | .yes_ranges = da9063_ad_readable_ranges, | |
169 | .n_yes_ranges = ARRAY_SIZE(da9063_ad_readable_ranges), | |
8e685483 KG |
170 | }; |
171 | ||
9cb42e2a OST |
172 | static const struct regmap_access_table da9063_ad_writeable_table = { |
173 | .yes_ranges = da9063_ad_writeable_ranges, | |
174 | .n_yes_ranges = ARRAY_SIZE(da9063_ad_writeable_ranges), | |
8e685483 KG |
175 | }; |
176 | ||
9cb42e2a OST |
177 | static const struct regmap_access_table da9063_ad_volatile_table = { |
178 | .yes_ranges = da9063_ad_volatile_ranges, | |
179 | .n_yes_ranges = ARRAY_SIZE(da9063_ad_volatile_ranges), | |
180 | }; | |
181 | ||
182 | static const struct regmap_range da9063_bb_readable_ranges[] = { | |
2905086d MV |
183 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_BB_REG_SECOND_D), |
184 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), | |
185 | regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), | |
186 | regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19), | |
091c6110 | 187 | regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID), |
9cb42e2a OST |
188 | }; |
189 | ||
190 | static const struct regmap_range da9063_bb_writeable_ranges[] = { | |
2905086d MV |
191 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON), |
192 | regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON), | |
193 | regmap_reg_range(DA9063_REG_COUNT_S, DA9063_BB_REG_ALARM_Y), | |
194 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), | |
195 | regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), | |
196 | regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4), | |
197 | regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19), | |
9cb42e2a OST |
198 | }; |
199 | ||
9ece3601 | 200 | static const struct regmap_range da9063_bb_da_volatile_ranges[] = { |
2905086d MV |
201 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D), |
202 | regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B), | |
203 | regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F), | |
204 | regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT), | |
205 | regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN), | |
206 | regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_BB_REG_SECOND_D), | |
207 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ), | |
208 | regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K), | |
209 | regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6), | |
9cb42e2a OST |
210 | }; |
211 | ||
212 | static const struct regmap_access_table da9063_bb_readable_table = { | |
213 | .yes_ranges = da9063_bb_readable_ranges, | |
214 | .n_yes_ranges = ARRAY_SIZE(da9063_bb_readable_ranges), | |
215 | }; | |
216 | ||
217 | static const struct regmap_access_table da9063_bb_writeable_table = { | |
218 | .yes_ranges = da9063_bb_writeable_ranges, | |
219 | .n_yes_ranges = ARRAY_SIZE(da9063_bb_writeable_ranges), | |
220 | }; | |
221 | ||
9ece3601 AT |
222 | static const struct regmap_access_table da9063_bb_da_volatile_table = { |
223 | .yes_ranges = da9063_bb_da_volatile_ranges, | |
224 | .n_yes_ranges = ARRAY_SIZE(da9063_bb_da_volatile_ranges), | |
8e685483 KG |
225 | }; |
226 | ||
4bd6ad0a MV |
227 | static const struct regmap_range da9063l_bb_readable_ranges[] = { |
228 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_MON_A10_RES), | |
229 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), | |
230 | regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), | |
231 | regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19), | |
091c6110 | 232 | regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID), |
4bd6ad0a MV |
233 | }; |
234 | ||
235 | static const struct regmap_range da9063l_bb_writeable_ranges[] = { | |
236 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON), | |
237 | regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON), | |
238 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), | |
239 | regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), | |
240 | regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4), | |
241 | regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19), | |
242 | }; | |
243 | ||
9ece3601 | 244 | static const struct regmap_range da9063l_bb_da_volatile_ranges[] = { |
4bd6ad0a MV |
245 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D), |
246 | regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B), | |
247 | regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F), | |
248 | regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT), | |
249 | regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN), | |
250 | regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_REG_MON_A10_RES), | |
251 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ), | |
252 | regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K), | |
253 | regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6), | |
254 | }; | |
255 | ||
256 | static const struct regmap_access_table da9063l_bb_readable_table = { | |
257 | .yes_ranges = da9063l_bb_readable_ranges, | |
258 | .n_yes_ranges = ARRAY_SIZE(da9063l_bb_readable_ranges), | |
259 | }; | |
260 | ||
261 | static const struct regmap_access_table da9063l_bb_writeable_table = { | |
262 | .yes_ranges = da9063l_bb_writeable_ranges, | |
263 | .n_yes_ranges = ARRAY_SIZE(da9063l_bb_writeable_ranges), | |
264 | }; | |
265 | ||
9ece3601 AT |
266 | static const struct regmap_access_table da9063l_bb_da_volatile_table = { |
267 | .yes_ranges = da9063l_bb_da_volatile_ranges, | |
268 | .n_yes_ranges = ARRAY_SIZE(da9063l_bb_da_volatile_ranges), | |
269 | }; | |
270 | ||
271 | static const struct regmap_range da9063_da_readable_ranges[] = { | |
272 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_BB_REG_SECOND_D), | |
273 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), | |
274 | regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), | |
275 | regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_11), | |
276 | regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID), | |
277 | }; | |
278 | ||
279 | static const struct regmap_range da9063_da_writeable_ranges[] = { | |
280 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON), | |
281 | regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON), | |
282 | regmap_reg_range(DA9063_REG_COUNT_S, DA9063_BB_REG_ALARM_Y), | |
283 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), | |
284 | regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), | |
285 | regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4), | |
286 | regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_11), | |
287 | }; | |
288 | ||
289 | static const struct regmap_access_table da9063_da_readable_table = { | |
290 | .yes_ranges = da9063_da_readable_ranges, | |
291 | .n_yes_ranges = ARRAY_SIZE(da9063_da_readable_ranges), | |
292 | }; | |
293 | ||
294 | static const struct regmap_access_table da9063_da_writeable_table = { | |
295 | .yes_ranges = da9063_da_writeable_ranges, | |
296 | .n_yes_ranges = ARRAY_SIZE(da9063_da_writeable_ranges), | |
297 | }; | |
298 | ||
299 | static const struct regmap_range da9063l_da_readable_ranges[] = { | |
300 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_MON_A10_RES), | |
301 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), | |
302 | regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), | |
303 | regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_11), | |
304 | regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID), | |
305 | }; | |
306 | ||
307 | static const struct regmap_range da9063l_da_writeable_ranges[] = { | |
308 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON), | |
309 | regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON), | |
310 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), | |
311 | regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), | |
312 | regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4), | |
313 | regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_11), | |
314 | }; | |
315 | ||
316 | static const struct regmap_access_table da9063l_da_readable_table = { | |
317 | .yes_ranges = da9063l_da_readable_ranges, | |
318 | .n_yes_ranges = ARRAY_SIZE(da9063l_da_readable_ranges), | |
319 | }; | |
320 | ||
321 | static const struct regmap_access_table da9063l_da_writeable_table = { | |
322 | .yes_ranges = da9063l_da_writeable_ranges, | |
323 | .n_yes_ranges = ARRAY_SIZE(da9063l_da_writeable_ranges), | |
4bd6ad0a MV |
324 | }; |
325 | ||
8e685483 KG |
326 | static const struct regmap_range_cfg da9063_range_cfg[] = { |
327 | { | |
328 | .range_min = DA9063_REG_PAGE_CON, | |
091c6110 | 329 | .range_max = DA9063_REG_CONFIG_ID, |
8e685483 KG |
330 | .selector_reg = DA9063_REG_PAGE_CON, |
331 | .selector_mask = 1 << DA9063_I2C_PAGE_SEL_SHIFT, | |
332 | .selector_shift = DA9063_I2C_PAGE_SEL_SHIFT, | |
333 | .window_start = 0, | |
334 | .window_len = 256, | |
335 | } | |
336 | }; | |
337 | ||
338 | static struct regmap_config da9063_regmap_config = { | |
339 | .reg_bits = 8, | |
340 | .val_bits = 8, | |
341 | .ranges = da9063_range_cfg, | |
342 | .num_ranges = ARRAY_SIZE(da9063_range_cfg), | |
091c6110 | 343 | .max_register = DA9063_REG_CONFIG_ID, |
8e685483 KG |
344 | |
345 | .cache_type = REGCACHE_RBTREE, | |
8e685483 KG |
346 | }; |
347 | ||
71e03de4 ST |
348 | static const struct of_device_id da9063_dt_ids[] = { |
349 | { .compatible = "dlg,da9063", }, | |
c287572b | 350 | { .compatible = "dlg,da9063l", }, |
71e03de4 ST |
351 | { } |
352 | }; | |
353 | MODULE_DEVICE_TABLE(of, da9063_dt_ids); | |
b309636b | 354 | static int da9063_i2c_probe(struct i2c_client *i2c) |
8e685483 | 355 | { |
b309636b | 356 | const struct i2c_device_id *id = i2c_client_get_device_id(i2c); |
8e685483 KG |
357 | struct da9063 *da9063; |
358 | int ret; | |
359 | ||
360 | da9063 = devm_kzalloc(&i2c->dev, sizeof(struct da9063), GFP_KERNEL); | |
361 | if (da9063 == NULL) | |
362 | return -ENOMEM; | |
363 | ||
364 | i2c_set_clientdata(i2c, da9063); | |
365 | da9063->dev = &i2c->dev; | |
366 | da9063->chip_irq = i2c->irq; | |
492510dd | 367 | da9063->type = id->driver_data; |
8e685483 | 368 | |
091c6110 AT |
369 | ret = da9063_get_device_type(i2c, da9063); |
370 | if (ret) | |
371 | return ret; | |
372 | ||
373 | switch (da9063->type) { | |
374 | case PMIC_TYPE_DA9063: | |
375 | switch (da9063->variant_code) { | |
376 | case PMIC_DA9063_AD: | |
377 | da9063_regmap_config.rd_table = | |
378 | &da9063_ad_readable_table; | |
379 | da9063_regmap_config.wr_table = | |
380 | &da9063_ad_writeable_table; | |
381 | da9063_regmap_config.volatile_table = | |
382 | &da9063_ad_volatile_table; | |
383 | break; | |
384 | case PMIC_DA9063_BB: | |
385 | case PMIC_DA9063_CA: | |
386 | da9063_regmap_config.rd_table = | |
387 | &da9063_bb_readable_table; | |
388 | da9063_regmap_config.wr_table = | |
389 | &da9063_bb_writeable_table; | |
390 | da9063_regmap_config.volatile_table = | |
9ece3601 AT |
391 | &da9063_bb_da_volatile_table; |
392 | break; | |
393 | case PMIC_DA9063_DA: | |
c9a20383 | 394 | case PMIC_DA9063_EA: |
9ece3601 AT |
395 | da9063_regmap_config.rd_table = |
396 | &da9063_da_readable_table; | |
397 | da9063_regmap_config.wr_table = | |
398 | &da9063_da_writeable_table; | |
399 | da9063_regmap_config.volatile_table = | |
400 | &da9063_bb_da_volatile_table; | |
091c6110 AT |
401 | break; |
402 | default: | |
403 | dev_err(da9063->dev, | |
404 | "Chip variant not supported for DA9063\n"); | |
405 | return -ENODEV; | |
406 | } | |
407 | break; | |
408 | case PMIC_TYPE_DA9063L: | |
409 | switch (da9063->variant_code) { | |
410 | case PMIC_DA9063_BB: | |
411 | case PMIC_DA9063_CA: | |
412 | da9063_regmap_config.rd_table = | |
413 | &da9063l_bb_readable_table; | |
414 | da9063_regmap_config.wr_table = | |
415 | &da9063l_bb_writeable_table; | |
416 | da9063_regmap_config.volatile_table = | |
9ece3601 AT |
417 | &da9063l_bb_da_volatile_table; |
418 | break; | |
419 | case PMIC_DA9063_DA: | |
c9a20383 | 420 | case PMIC_DA9063_EA: |
9ece3601 AT |
421 | da9063_regmap_config.rd_table = |
422 | &da9063l_da_readable_table; | |
423 | da9063_regmap_config.wr_table = | |
424 | &da9063l_da_writeable_table; | |
425 | da9063_regmap_config.volatile_table = | |
426 | &da9063l_bb_da_volatile_table; | |
091c6110 AT |
427 | break; |
428 | default: | |
429 | dev_err(da9063->dev, | |
430 | "Chip variant not supported for DA9063L\n"); | |
431 | return -ENODEV; | |
432 | } | |
433 | break; | |
434 | default: | |
435 | dev_err(da9063->dev, "Chip type not supported\n"); | |
436 | return -ENODEV; | |
9cb42e2a OST |
437 | } |
438 | ||
8e685483 KG |
439 | da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config); |
440 | if (IS_ERR(da9063->regmap)) { | |
441 | ret = PTR_ERR(da9063->regmap); | |
442 | dev_err(da9063->dev, "Failed to allocate register map: %d\n", | |
443 | ret); | |
444 | return ret; | |
445 | } | |
446 | ||
586478bf HS |
447 | /* If SMBus is not available and only I2C is possible, enter I2C mode */ |
448 | if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) { | |
449 | ret = regmap_clear_bits(da9063->regmap, DA9063_REG_CONFIG_J, | |
450 | DA9063_TWOWIRE_TO); | |
451 | if (ret < 0) { | |
452 | dev_err(da9063->dev, "Failed to set Two-Wire Bus Mode.\n"); | |
921071a8 | 453 | return ret; |
586478bf HS |
454 | } |
455 | } | |
456 | ||
8e685483 KG |
457 | return da9063_device_init(da9063, i2c->irq); |
458 | } | |
459 | ||
8e685483 | 460 | static const struct i2c_device_id da9063_i2c_id[] = { |
492510dd | 461 | { "da9063", PMIC_TYPE_DA9063 }, |
c287572b | 462 | { "da9063l", PMIC_TYPE_DA9063L }, |
8e685483 KG |
463 | {}, |
464 | }; | |
465 | MODULE_DEVICE_TABLE(i2c, da9063_i2c_id); | |
466 | ||
467 | static struct i2c_driver da9063_i2c_driver = { | |
468 | .driver = { | |
469 | .name = "da9063", | |
5f2bf438 | 470 | .of_match_table = da9063_dt_ids, |
8e685483 | 471 | }, |
9816d859 | 472 | .probe = da9063_i2c_probe, |
8e685483 KG |
473 | .id_table = da9063_i2c_id, |
474 | }; | |
475 | ||
476 | module_i2c_driver(da9063_i2c_driver); |