1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* I2C support for Dialog DA9063 |
3 | * |
4 | * Copyright 2012 Dialog Semiconductor Ltd. |
5 | * Copyright 2013 Philipp Zabel, Pengutronix |
6 | * |
7 | * Author: Krystian Garbaciak, Dialog Semiconductor |
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> |
20 | #include <linux/mfd/da9063/registers.h> |
21 | |
22 | #include <linux/of.h> |
23 | #include <linux/regulator/of_regulator.h> |
24 | |
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(adap: client->adapter, msgs: xfer, num: 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(client: i2c, DA9063_REG_DEVICE_ID, buf, |
111 | count: 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 | |
137 | static const struct regmap_range da9063_ad_readable_ranges[] = { |
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), |
142 | regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID), |
143 | }; |
144 | |
145 | static const struct regmap_range da9063_ad_writeable_ranges[] = { |
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), |
153 | }; |
154 | |
155 | static const struct regmap_range da9063_ad_volatile_ranges[] = { |
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), |
165 | }; |
166 | |
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), |
170 | }; |
171 | |
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), |
175 | }; |
176 | |
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[] = { |
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), |
187 | regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID), |
188 | }; |
189 | |
190 | static const struct regmap_range da9063_bb_writeable_ranges[] = { |
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), |
198 | }; |
199 | |
200 | static const struct regmap_range da9063_bb_da_volatile_ranges[] = { |
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), |
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 | |
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), |
225 | }; |
226 | |
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), |
232 | regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID), |
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 | |
244 | static const struct regmap_range da9063l_bb_da_volatile_ranges[] = { |
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 | |
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), |
324 | }; |
325 | |
326 | static const struct regmap_range_cfg da9063_range_cfg[] = { |
327 | { |
328 | .range_min = DA9063_REG_PAGE_CON, |
329 | .range_max = DA9063_REG_CONFIG_ID, |
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), |
343 | .max_register = DA9063_REG_CONFIG_ID, |
344 | |
345 | .cache_type = REGCACHE_RBTREE, |
346 | }; |
347 | |
348 | static const struct of_device_id da9063_dt_ids[] = { |
349 | { .compatible = "dlg,da9063" , }, |
350 | { .compatible = "dlg,da9063l" , }, |
351 | { } |
352 | }; |
353 | MODULE_DEVICE_TABLE(of, da9063_dt_ids); |
354 | static int da9063_i2c_probe(struct i2c_client *i2c) |
355 | { |
356 | const struct i2c_device_id *id = i2c_client_get_device_id(client: i2c); |
357 | struct da9063 *da9063; |
358 | int ret; |
359 | |
360 | da9063 = devm_kzalloc(dev: &i2c->dev, size: sizeof(struct da9063), GFP_KERNEL); |
361 | if (da9063 == NULL) |
362 | return -ENOMEM; |
363 | |
364 | i2c_set_clientdata(client: i2c, data: da9063); |
365 | da9063->dev = &i2c->dev; |
366 | da9063->chip_irq = i2c->irq; |
367 | da9063->type = id->driver_data; |
368 | |
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 = |
391 | &da9063_bb_da_volatile_table; |
392 | break; |
393 | case PMIC_DA9063_DA: |
394 | case PMIC_DA9063_EA: |
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; |
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 = |
417 | &da9063l_bb_da_volatile_table; |
418 | break; |
419 | case PMIC_DA9063_DA: |
420 | case PMIC_DA9063_EA: |
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; |
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; |
437 | } |
438 | |
439 | da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config); |
440 | if (IS_ERR(ptr: da9063->regmap)) { |
441 | ret = PTR_ERR(ptr: da9063->regmap); |
442 | dev_err(da9063->dev, "Failed to allocate register map: %d\n" , |
443 | ret); |
444 | return ret; |
445 | } |
446 | |
447 | /* If SMBus is not available and only I2C is possible, enter I2C mode */ |
448 | if (i2c_check_functionality(adap: i2c->adapter, I2C_FUNC_I2C)) { |
449 | ret = regmap_clear_bits(map: 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" ); |
453 | return ret; |
454 | } |
455 | } |
456 | |
457 | return da9063_device_init(da9063, irq: i2c->irq); |
458 | } |
459 | |
460 | static const struct i2c_device_id da9063_i2c_id[] = { |
461 | { "da9063" , PMIC_TYPE_DA9063 }, |
462 | { "da9063l" , PMIC_TYPE_DA9063L }, |
463 | {}, |
464 | }; |
465 | MODULE_DEVICE_TABLE(i2c, da9063_i2c_id); |
466 | |
467 | static struct i2c_driver da9063_i2c_driver = { |
468 | .driver = { |
469 | .name = "da9063" , |
470 | .of_match_table = da9063_dt_ids, |
471 | }, |
472 | .probe = da9063_i2c_probe, |
473 | .id_table = da9063_i2c_id, |
474 | }; |
475 | |
476 | module_i2c_driver(da9063_i2c_driver); |
477 | |