hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/mfd/da9063-i2c.c
....@@ -1,15 +1,10 @@
1
-/* da9063-i2c.c: Interrupt support for Dialog DA9063
1
+// SPDX-License-Identifier: GPL-2.0+
2
+/* I2C support for Dialog DA9063
23 *
34 * Copyright 2012 Dialog Semiconductor Ltd.
45 * Copyright 2013 Philipp Zabel, Pengutronix
56 *
67 * Author: Krystian Garbaciak, Dialog Semiconductor
7
- *
8
- * This program is free software; you can redistribute it and/or modify it
9
- * under the terms of the GNU General Public License as published by the
10
- * Free Software Foundation; either version 2 of the License, or (at your
11
- * option) any later version.
12
- *
138 */
149
1510 #include <linux/kernel.h>
....@@ -22,18 +17,129 @@
2217
2318 #include <linux/mfd/core.h>
2419 #include <linux/mfd/da9063/core.h>
25
-#include <linux/mfd/da9063/pdata.h>
2620 #include <linux/mfd/da9063/registers.h>
2721
2822 #include <linux/of.h>
2923 #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(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
+ */
30136
31137 static const struct regmap_range da9063_ad_readable_ranges[] = {
32138 regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_AD_REG_SECOND_D),
33139 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
34140 regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
35141 regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_AD_REG_GP_ID_19),
36
- regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT),
142
+ regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
37143 };
38144
39145 static const struct regmap_range da9063_ad_writeable_ranges[] = {
....@@ -78,7 +184,7 @@
78184 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
79185 regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
80186 regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19),
81
- regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT),
187
+ regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
82188 };
83189
84190 static const struct regmap_range da9063_bb_writeable_ranges[] = {
....@@ -91,7 +197,7 @@
91197 regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19),
92198 };
93199
94
-static const struct regmap_range da9063_bb_volatile_ranges[] = {
200
+static const struct regmap_range da9063_bb_da_volatile_ranges[] = {
95201 regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),
96202 regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),
97203 regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),
....@@ -113,9 +219,9 @@
113219 .n_yes_ranges = ARRAY_SIZE(da9063_bb_writeable_ranges),
114220 };
115221
116
-static const struct regmap_access_table da9063_bb_volatile_table = {
117
- .yes_ranges = da9063_bb_volatile_ranges,
118
- .n_yes_ranges = ARRAY_SIZE(da9063_bb_volatile_ranges),
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),
119225 };
120226
121227 static const struct regmap_range da9063l_bb_readable_ranges[] = {
....@@ -123,7 +229,7 @@
123229 regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31),
124230 regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW),
125231 regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19),
126
- regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT),
232
+ regmap_reg_range(DA9063_REG_DEVICE_ID, DA9063_REG_VARIANT_ID),
127233 };
128234
129235 static const struct regmap_range da9063l_bb_writeable_ranges[] = {
....@@ -135,7 +241,7 @@
135241 regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19),
136242 };
137243
138
-static const struct regmap_range da9063l_bb_volatile_ranges[] = {
244
+static const struct regmap_range da9063l_bb_da_volatile_ranges[] = {
139245 regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D),
140246 regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B),
141247 regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F),
....@@ -157,15 +263,70 @@
157263 .n_yes_ranges = ARRAY_SIZE(da9063l_bb_writeable_ranges),
158264 };
159265
160
-static const struct regmap_access_table da9063l_bb_volatile_table = {
161
- .yes_ranges = da9063l_bb_volatile_ranges,
162
- .n_yes_ranges = ARRAY_SIZE(da9063l_bb_volatile_ranges),
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),
163324 };
164325
165326 static const struct regmap_range_cfg da9063_range_cfg[] = {
166327 {
167328 .range_min = DA9063_REG_PAGE_CON,
168
- .range_max = DA9063_REG_CHIP_VARIANT,
329
+ .range_max = DA9063_REG_CONFIG_ID,
169330 .selector_reg = DA9063_REG_PAGE_CON,
170331 .selector_mask = 1 << DA9063_I2C_PAGE_SEL_SHIFT,
171332 .selector_shift = DA9063_I2C_PAGE_SEL_SHIFT,
....@@ -179,7 +340,7 @@
179340 .val_bits = 8,
180341 .ranges = da9063_range_cfg,
181342 .num_ranges = ARRAY_SIZE(da9063_range_cfg),
182
- .max_register = DA9063_REG_CHIP_VARIANT,
343
+ .max_register = DA9063_REG_CONFIG_ID,
183344
184345 .cache_type = REGCACHE_RBTREE,
185346 };
....@@ -205,18 +366,72 @@
205366 da9063->chip_irq = i2c->irq;
206367 da9063->type = id->driver_data;
207368
208
- if (da9063->variant_code == PMIC_DA9063_AD) {
209
- da9063_regmap_config.rd_table = &da9063_ad_readable_table;
210
- da9063_regmap_config.wr_table = &da9063_ad_writeable_table;
211
- da9063_regmap_config.volatile_table = &da9063_ad_volatile_table;
212
- } else if (da9063->type == PMIC_TYPE_DA9063L) {
213
- da9063_regmap_config.rd_table = &da9063l_bb_readable_table;
214
- da9063_regmap_config.wr_table = &da9063l_bb_writeable_table;
215
- da9063_regmap_config.volatile_table = &da9063l_bb_volatile_table;
216
- } else {
217
- da9063_regmap_config.rd_table = &da9063_bb_readable_table;
218
- da9063_regmap_config.wr_table = &da9063_bb_writeable_table;
219
- da9063_regmap_config.volatile_table = &da9063_bb_volatile_table;
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
+ da9063_regmap_config.rd_table =
395
+ &da9063_da_readable_table;
396
+ da9063_regmap_config.wr_table =
397
+ &da9063_da_writeable_table;
398
+ da9063_regmap_config.volatile_table =
399
+ &da9063_bb_da_volatile_table;
400
+ break;
401
+ default:
402
+ dev_err(da9063->dev,
403
+ "Chip variant not supported for DA9063\n");
404
+ return -ENODEV;
405
+ }
406
+ break;
407
+ case PMIC_TYPE_DA9063L:
408
+ switch (da9063->variant_code) {
409
+ case PMIC_DA9063_BB:
410
+ case PMIC_DA9063_CA:
411
+ da9063_regmap_config.rd_table =
412
+ &da9063l_bb_readable_table;
413
+ da9063_regmap_config.wr_table =
414
+ &da9063l_bb_writeable_table;
415
+ da9063_regmap_config.volatile_table =
416
+ &da9063l_bb_da_volatile_table;
417
+ break;
418
+ case PMIC_DA9063_DA:
419
+ da9063_regmap_config.rd_table =
420
+ &da9063l_da_readable_table;
421
+ da9063_regmap_config.wr_table =
422
+ &da9063l_da_writeable_table;
423
+ da9063_regmap_config.volatile_table =
424
+ &da9063l_bb_da_volatile_table;
425
+ break;
426
+ default:
427
+ dev_err(da9063->dev,
428
+ "Chip variant not supported for DA9063L\n");
429
+ return -ENODEV;
430
+ }
431
+ break;
432
+ default:
433
+ dev_err(da9063->dev, "Chip type not supported\n");
434
+ return -ENODEV;
220435 }
221436
222437 da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config);
....@@ -227,6 +442,16 @@
227442 return ret;
228443 }
229444
445
+ /* If SMBus is not available and only I2C is possible, enter I2C mode */
446
+ if (i2c_check_functionality(i2c->adapter, I2C_FUNC_I2C)) {
447
+ ret = regmap_clear_bits(da9063->regmap, DA9063_REG_CONFIG_J,
448
+ DA9063_TWOWIRE_TO);
449
+ if (ret < 0) {
450
+ dev_err(da9063->dev, "Failed to set Two-Wire Bus Mode.\n");
451
+ return -EIO;
452
+ }
453
+ }
454
+
230455 return da9063_device_init(da9063, i2c->irq);
231456 }
232457