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 | ||
9cb42e2a | 25 | static const struct regmap_range da9063_ad_readable_ranges[] = { |
2905086d MV |
26 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_AD_REG_SECOND_D), |
27 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), | |
28 | regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), | |
29 | regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_AD_REG_GP_ID_19), | |
30 | regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT), | |
8e685483 KG |
31 | }; |
32 | ||
9cb42e2a | 33 | static const struct regmap_range da9063_ad_writeable_ranges[] = { |
2905086d MV |
34 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON), |
35 | regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON), | |
36 | regmap_reg_range(DA9063_REG_COUNT_S, DA9063_AD_REG_ALARM_Y), | |
37 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), | |
38 | regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), | |
39 | regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_AD_REG_MON_REG_4), | |
40 | regmap_reg_range(DA9063_AD_REG_GP_ID_0, DA9063_AD_REG_GP_ID_19), | |
8e685483 KG |
41 | }; |
42 | ||
9cb42e2a | 43 | static const struct regmap_range da9063_ad_volatile_ranges[] = { |
2905086d MV |
44 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D), |
45 | regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B), | |
46 | regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F), | |
47 | regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT), | |
48 | regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN), | |
49 | regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_AD_REG_SECOND_D), | |
50 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ), | |
51 | regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K), | |
52 | regmap_reg_range(DA9063_AD_REG_MON_REG_5, DA9063_AD_REG_MON_REG_6), | |
8e685483 KG |
53 | }; |
54 | ||
9cb42e2a OST |
55 | static const struct regmap_access_table da9063_ad_readable_table = { |
56 | .yes_ranges = da9063_ad_readable_ranges, | |
57 | .n_yes_ranges = ARRAY_SIZE(da9063_ad_readable_ranges), | |
8e685483 KG |
58 | }; |
59 | ||
9cb42e2a OST |
60 | static const struct regmap_access_table da9063_ad_writeable_table = { |
61 | .yes_ranges = da9063_ad_writeable_ranges, | |
62 | .n_yes_ranges = ARRAY_SIZE(da9063_ad_writeable_ranges), | |
8e685483 KG |
63 | }; |
64 | ||
9cb42e2a OST |
65 | static const struct regmap_access_table da9063_ad_volatile_table = { |
66 | .yes_ranges = da9063_ad_volatile_ranges, | |
67 | .n_yes_ranges = ARRAY_SIZE(da9063_ad_volatile_ranges), | |
68 | }; | |
69 | ||
70 | static const struct regmap_range da9063_bb_readable_ranges[] = { | |
2905086d MV |
71 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_BB_REG_SECOND_D), |
72 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), | |
73 | regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), | |
74 | regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19), | |
75 | regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT), | |
9cb42e2a OST |
76 | }; |
77 | ||
78 | static const struct regmap_range da9063_bb_writeable_ranges[] = { | |
2905086d MV |
79 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON), |
80 | regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON), | |
81 | regmap_reg_range(DA9063_REG_COUNT_S, DA9063_BB_REG_ALARM_Y), | |
82 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), | |
83 | regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), | |
84 | regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4), | |
85 | regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19), | |
9cb42e2a OST |
86 | }; |
87 | ||
88 | static const struct regmap_range da9063_bb_volatile_ranges[] = { | |
2905086d MV |
89 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D), |
90 | regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B), | |
91 | regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F), | |
92 | regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT), | |
93 | regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN), | |
94 | regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_BB_REG_SECOND_D), | |
95 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ), | |
96 | regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K), | |
97 | regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6), | |
9cb42e2a OST |
98 | }; |
99 | ||
100 | static const struct regmap_access_table da9063_bb_readable_table = { | |
101 | .yes_ranges = da9063_bb_readable_ranges, | |
102 | .n_yes_ranges = ARRAY_SIZE(da9063_bb_readable_ranges), | |
103 | }; | |
104 | ||
105 | static const struct regmap_access_table da9063_bb_writeable_table = { | |
106 | .yes_ranges = da9063_bb_writeable_ranges, | |
107 | .n_yes_ranges = ARRAY_SIZE(da9063_bb_writeable_ranges), | |
108 | }; | |
109 | ||
110 | static const struct regmap_access_table da9063_bb_volatile_table = { | |
111 | .yes_ranges = da9063_bb_volatile_ranges, | |
112 | .n_yes_ranges = ARRAY_SIZE(da9063_bb_volatile_ranges), | |
8e685483 KG |
113 | }; |
114 | ||
4bd6ad0a MV |
115 | static const struct regmap_range da9063l_bb_readable_ranges[] = { |
116 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_MON_A10_RES), | |
117 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), | |
118 | regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), | |
119 | regmap_reg_range(DA9063_REG_T_OFFSET, DA9063_BB_REG_GP_ID_19), | |
120 | regmap_reg_range(DA9063_REG_CHIP_ID, DA9063_REG_CHIP_VARIANT), | |
121 | }; | |
122 | ||
123 | static const struct regmap_range da9063l_bb_writeable_ranges[] = { | |
124 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_PAGE_CON), | |
125 | regmap_reg_range(DA9063_REG_FAULT_LOG, DA9063_REG_VSYS_MON), | |
126 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_ID_32_31), | |
127 | regmap_reg_range(DA9063_REG_SEQ_A, DA9063_REG_AUTO3_LOW), | |
128 | regmap_reg_range(DA9063_REG_CONFIG_I, DA9063_BB_REG_MON_REG_4), | |
129 | regmap_reg_range(DA9063_BB_REG_GP_ID_0, DA9063_BB_REG_GP_ID_19), | |
130 | }; | |
131 | ||
132 | static const struct regmap_range da9063l_bb_volatile_ranges[] = { | |
133 | regmap_reg_range(DA9063_REG_PAGE_CON, DA9063_REG_EVENT_D), | |
134 | regmap_reg_range(DA9063_REG_CONTROL_A, DA9063_REG_CONTROL_B), | |
135 | regmap_reg_range(DA9063_REG_CONTROL_E, DA9063_REG_CONTROL_F), | |
136 | regmap_reg_range(DA9063_REG_BCORE2_CONT, DA9063_REG_LDO11_CONT), | |
137 | regmap_reg_range(DA9063_REG_DVC_1, DA9063_REG_ADC_MAN), | |
138 | regmap_reg_range(DA9063_REG_ADC_RES_L, DA9063_REG_MON_A10_RES), | |
139 | regmap_reg_range(DA9063_REG_SEQ, DA9063_REG_SEQ), | |
140 | regmap_reg_range(DA9063_REG_EN_32K, DA9063_REG_EN_32K), | |
141 | regmap_reg_range(DA9063_BB_REG_MON_REG_5, DA9063_BB_REG_MON_REG_6), | |
142 | }; | |
143 | ||
144 | static const struct regmap_access_table da9063l_bb_readable_table = { | |
145 | .yes_ranges = da9063l_bb_readable_ranges, | |
146 | .n_yes_ranges = ARRAY_SIZE(da9063l_bb_readable_ranges), | |
147 | }; | |
148 | ||
149 | static const struct regmap_access_table da9063l_bb_writeable_table = { | |
150 | .yes_ranges = da9063l_bb_writeable_ranges, | |
151 | .n_yes_ranges = ARRAY_SIZE(da9063l_bb_writeable_ranges), | |
152 | }; | |
153 | ||
154 | static const struct regmap_access_table da9063l_bb_volatile_table = { | |
155 | .yes_ranges = da9063l_bb_volatile_ranges, | |
156 | .n_yes_ranges = ARRAY_SIZE(da9063l_bb_volatile_ranges), | |
157 | }; | |
158 | ||
8e685483 KG |
159 | static const struct regmap_range_cfg da9063_range_cfg[] = { |
160 | { | |
161 | .range_min = DA9063_REG_PAGE_CON, | |
162 | .range_max = DA9063_REG_CHIP_VARIANT, | |
163 | .selector_reg = DA9063_REG_PAGE_CON, | |
164 | .selector_mask = 1 << DA9063_I2C_PAGE_SEL_SHIFT, | |
165 | .selector_shift = DA9063_I2C_PAGE_SEL_SHIFT, | |
166 | .window_start = 0, | |
167 | .window_len = 256, | |
168 | } | |
169 | }; | |
170 | ||
171 | static struct regmap_config da9063_regmap_config = { | |
172 | .reg_bits = 8, | |
173 | .val_bits = 8, | |
174 | .ranges = da9063_range_cfg, | |
175 | .num_ranges = ARRAY_SIZE(da9063_range_cfg), | |
176 | .max_register = DA9063_REG_CHIP_VARIANT, | |
177 | ||
178 | .cache_type = REGCACHE_RBTREE, | |
8e685483 KG |
179 | }; |
180 | ||
71e03de4 ST |
181 | static const struct of_device_id da9063_dt_ids[] = { |
182 | { .compatible = "dlg,da9063", }, | |
c287572b | 183 | { .compatible = "dlg,da9063l", }, |
71e03de4 ST |
184 | { } |
185 | }; | |
186 | MODULE_DEVICE_TABLE(of, da9063_dt_ids); | |
8e685483 | 187 | static int da9063_i2c_probe(struct i2c_client *i2c, |
492510dd | 188 | const struct i2c_device_id *id) |
8e685483 KG |
189 | { |
190 | struct da9063 *da9063; | |
191 | int ret; | |
192 | ||
193 | da9063 = devm_kzalloc(&i2c->dev, sizeof(struct da9063), GFP_KERNEL); | |
194 | if (da9063 == NULL) | |
195 | return -ENOMEM; | |
196 | ||
197 | i2c_set_clientdata(i2c, da9063); | |
198 | da9063->dev = &i2c->dev; | |
199 | da9063->chip_irq = i2c->irq; | |
492510dd | 200 | da9063->type = id->driver_data; |
8e685483 | 201 | |
9cb42e2a OST |
202 | if (da9063->variant_code == PMIC_DA9063_AD) { |
203 | da9063_regmap_config.rd_table = &da9063_ad_readable_table; | |
204 | da9063_regmap_config.wr_table = &da9063_ad_writeable_table; | |
205 | da9063_regmap_config.volatile_table = &da9063_ad_volatile_table; | |
4bd6ad0a MV |
206 | } else if (da9063->type == PMIC_TYPE_DA9063L) { |
207 | da9063_regmap_config.rd_table = &da9063l_bb_readable_table; | |
208 | da9063_regmap_config.wr_table = &da9063l_bb_writeable_table; | |
209 | da9063_regmap_config.volatile_table = &da9063l_bb_volatile_table; | |
9cb42e2a OST |
210 | } else { |
211 | da9063_regmap_config.rd_table = &da9063_bb_readable_table; | |
212 | da9063_regmap_config.wr_table = &da9063_bb_writeable_table; | |
213 | da9063_regmap_config.volatile_table = &da9063_bb_volatile_table; | |
214 | } | |
215 | ||
8e685483 KG |
216 | da9063->regmap = devm_regmap_init_i2c(i2c, &da9063_regmap_config); |
217 | if (IS_ERR(da9063->regmap)) { | |
218 | ret = PTR_ERR(da9063->regmap); | |
219 | dev_err(da9063->dev, "Failed to allocate register map: %d\n", | |
220 | ret); | |
221 | return ret; | |
222 | } | |
223 | ||
224 | return da9063_device_init(da9063, i2c->irq); | |
225 | } | |
226 | ||
8e685483 | 227 | static const struct i2c_device_id da9063_i2c_id[] = { |
492510dd | 228 | { "da9063", PMIC_TYPE_DA9063 }, |
c287572b | 229 | { "da9063l", PMIC_TYPE_DA9063L }, |
8e685483 KG |
230 | {}, |
231 | }; | |
232 | MODULE_DEVICE_TABLE(i2c, da9063_i2c_id); | |
233 | ||
234 | static struct i2c_driver da9063_i2c_driver = { | |
235 | .driver = { | |
236 | .name = "da9063", | |
71e03de4 | 237 | .of_match_table = of_match_ptr(da9063_dt_ids), |
8e685483 KG |
238 | }, |
239 | .probe = da9063_i2c_probe, | |
8e685483 KG |
240 | .id_table = da9063_i2c_id, |
241 | }; | |
242 | ||
243 | module_i2c_driver(da9063_i2c_driver); |