]>
Commit | Line | Data |
---|---|---|
d7d8d7a2 KK |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | // | |
3 | // max14577.c - mfd core driver for the Maxim 14577/77836 | |
4 | // | |
5 | // Copyright (C) 2014 Samsung Electronics | |
6 | // Chanwoo Choi <[email protected]> | |
7 | // Krzysztof Kozlowski <[email protected]> | |
8 | // | |
9 | // This driver is based on max8997.c | |
3008ddbe | 10 | |
c8016d45 | 11 | #include <linux/err.h> |
3008ddbe CC |
12 | #include <linux/module.h> |
13 | #include <linux/interrupt.h> | |
eccb80cc | 14 | #include <linux/of_device.h> |
3008ddbe CC |
15 | #include <linux/mfd/core.h> |
16 | #include <linux/mfd/max14577.h> | |
17 | #include <linux/mfd/max14577-private.h> | |
18 | ||
b8f139f6 KK |
19 | /* |
20 | * Table of valid charger currents for different Maxim chipsets. | |
21 | * It is placed here because it is used by both charger and regulator driver. | |
22 | */ | |
23 | const struct maxim_charger_current maxim_charger_currents[] = { | |
24 | [MAXIM_DEVICE_TYPE_UNKNOWN] = { 0, 0, 0, 0 }, | |
25 | [MAXIM_DEVICE_TYPE_MAX14577] = { | |
26 | .min = MAX14577_CHARGER_CURRENT_LIMIT_MIN, | |
27 | .high_start = MAX14577_CHARGER_CURRENT_LIMIT_HIGH_START, | |
28 | .high_step = MAX14577_CHARGER_CURRENT_LIMIT_HIGH_STEP, | |
29 | .max = MAX14577_CHARGER_CURRENT_LIMIT_MAX, | |
30 | }, | |
31 | [MAXIM_DEVICE_TYPE_MAX77836] = { | |
32 | .min = MAX77836_CHARGER_CURRENT_LIMIT_MIN, | |
33 | .high_start = MAX77836_CHARGER_CURRENT_LIMIT_HIGH_START, | |
34 | .high_step = MAX77836_CHARGER_CURRENT_LIMIT_HIGH_STEP, | |
35 | .max = MAX77836_CHARGER_CURRENT_LIMIT_MAX, | |
36 | }, | |
37 | }; | |
38 | EXPORT_SYMBOL_GPL(maxim_charger_currents); | |
39 | ||
40 | /* | |
41 | * maxim_charger_calc_reg_current - Calculate register value for current | |
42 | * @limits: constraints for charger, matching the MBCICHWRC register | |
43 | * @min_ua: minimal requested current, micro Amps | |
44 | * @max_ua: maximum requested current, micro Amps | |
45 | * @dst: destination to store calculated register value | |
46 | * | |
47 | * Calculates the value of MBCICHWRC (Fast Battery Charge Current) register | |
48 | * for given current and stores it under pointed 'dst'. The stored value | |
49 | * combines low bit (MBCICHWRCL) and high bits (MBCICHWRCH). It is also | |
50 | * properly shifted. | |
51 | * | |
52 | * The calculated register value matches the current which: | |
53 | * - is always between <limits.min, limits.max>; | |
54 | * - is always less or equal to max_ua; | |
55 | * - is the highest possible value; | |
56 | * - may be lower than min_ua. | |
57 | * | |
58 | * On success returns 0. On error returns -EINVAL (requested min/max current | |
59 | * is outside of given charger limits) and 'dst' is not set. | |
60 | */ | |
61 | int maxim_charger_calc_reg_current(const struct maxim_charger_current *limits, | |
62 | unsigned int min_ua, unsigned int max_ua, u8 *dst) | |
63 | { | |
64 | unsigned int current_bits = 0xf; | |
65 | ||
66 | if (min_ua > max_ua) | |
67 | return -EINVAL; | |
68 | ||
69 | if (min_ua > limits->max || max_ua < limits->min) | |
70 | return -EINVAL; | |
71 | ||
72 | if (max_ua < limits->high_start) { | |
73 | /* | |
74 | * Less than high_start, so set the minimal current | |
75 | * (turn Low Bit off, 0 as high bits). | |
76 | */ | |
77 | *dst = 0x0; | |
78 | return 0; | |
79 | } | |
80 | ||
81 | /* max_ua is in range: <high_start, infinite>, cut it to limits.max */ | |
82 | max_ua = min(limits->max, max_ua); | |
83 | max_ua -= limits->high_start; | |
84 | /* | |
85 | * There is no risk of overflow 'max_ua' here because: | |
86 | * - max_ua >= limits.high_start | |
87 | * - BUILD_BUG checks that 'limits' are: max >= high_start + high_step | |
88 | */ | |
89 | current_bits = max_ua / limits->high_step; | |
90 | ||
91 | /* Turn Low Bit on (use range <limits.high_start, limits.max>) ... */ | |
92 | *dst = 0x1 << CHGCTRL4_MBCICHWRCL_SHIFT; | |
93 | /* and set proper High Bits */ | |
94 | *dst |= current_bits << CHGCTRL4_MBCICHWRCH_SHIFT; | |
95 | ||
96 | return 0; | |
97 | } | |
98 | EXPORT_SYMBOL_GPL(maxim_charger_calc_reg_current); | |
99 | ||
92725493 | 100 | static const struct mfd_cell max14577_devs[] = { |
a0b0ea49 KK |
101 | { |
102 | .name = "max14577-muic", | |
103 | .of_compatible = "maxim,max14577-muic", | |
104 | }, | |
41096801 KK |
105 | { |
106 | .name = "max14577-regulator", | |
107 | .of_compatible = "maxim,max14577-regulator", | |
108 | }, | |
4476767c KK |
109 | { |
110 | .name = "max14577-charger", | |
111 | .of_compatible = "maxim,max14577-charger", | |
112 | }, | |
3008ddbe CC |
113 | }; |
114 | ||
92725493 | 115 | static const struct mfd_cell max77836_devs[] = { |
aee2a57c KK |
116 | { |
117 | .name = "max77836-muic", | |
118 | .of_compatible = "maxim,max77836-muic", | |
119 | }, | |
120 | { | |
121 | .name = "max77836-regulator", | |
122 | .of_compatible = "maxim,max77836-regulator", | |
123 | }, | |
124 | { | |
125 | .name = "max77836-charger", | |
126 | .of_compatible = "maxim,max77836-charger", | |
127 | }, | |
128 | { | |
129 | .name = "max77836-battery", | |
130 | .of_compatible = "maxim,max77836-battery", | |
131 | }, | |
132 | }; | |
133 | ||
8f7f6270 | 134 | static const struct of_device_id max14577_dt_match[] = { |
eccb80cc KK |
135 | { |
136 | .compatible = "maxim,max14577", | |
137 | .data = (void *)MAXIM_DEVICE_TYPE_MAX14577, | |
138 | }, | |
aee2a57c KK |
139 | { |
140 | .compatible = "maxim,max77836", | |
141 | .data = (void *)MAXIM_DEVICE_TYPE_MAX77836, | |
142 | }, | |
eccb80cc KK |
143 | {}, |
144 | }; | |
145 | ||
575343d1 | 146 | static bool max14577_muic_volatile_reg(struct device *dev, unsigned int reg) |
3008ddbe CC |
147 | { |
148 | switch (reg) { | |
149 | case MAX14577_REG_INT1 ... MAX14577_REG_STATUS3: | |
150 | return true; | |
151 | default: | |
152 | break; | |
153 | } | |
154 | return false; | |
155 | } | |
156 | ||
aee2a57c KK |
157 | static bool max77836_muic_volatile_reg(struct device *dev, unsigned int reg) |
158 | { | |
159 | /* Any max14577 volatile registers are also max77836 volatile. */ | |
160 | if (max14577_muic_volatile_reg(dev, reg)) | |
161 | return true; | |
162 | ||
163 | switch (reg) { | |
164 | case MAX77836_FG_REG_VCELL_MSB ... MAX77836_FG_REG_SOC_LSB: | |
165 | case MAX77836_FG_REG_CRATE_MSB ... MAX77836_FG_REG_CRATE_LSB: | |
166 | case MAX77836_FG_REG_STATUS_H ... MAX77836_FG_REG_STATUS_L: | |
167 | case MAX77836_PMIC_REG_INTSRC: | |
168 | case MAX77836_PMIC_REG_TOPSYS_INT: | |
169 | case MAX77836_PMIC_REG_TOPSYS_STAT: | |
170 | return true; | |
171 | default: | |
172 | break; | |
173 | } | |
174 | return false; | |
175 | } | |
176 | ||
575343d1 | 177 | static const struct regmap_config max14577_muic_regmap_config = { |
3008ddbe CC |
178 | .reg_bits = 8, |
179 | .val_bits = 8, | |
575343d1 | 180 | .volatile_reg = max14577_muic_volatile_reg, |
3008ddbe CC |
181 | .max_register = MAX14577_REG_END, |
182 | }; | |
183 | ||
aee2a57c KK |
184 | static const struct regmap_config max77836_pmic_regmap_config = { |
185 | .reg_bits = 8, | |
186 | .val_bits = 8, | |
187 | .volatile_reg = max77836_muic_volatile_reg, | |
188 | .max_register = MAX77836_PMIC_REG_END, | |
189 | }; | |
190 | ||
3008ddbe CC |
191 | static const struct regmap_irq max14577_irqs[] = { |
192 | /* INT1 interrupts */ | |
c7846852 KK |
193 | { .reg_offset = 0, .mask = MAX14577_INT1_ADC_MASK, }, |
194 | { .reg_offset = 0, .mask = MAX14577_INT1_ADCLOW_MASK, }, | |
195 | { .reg_offset = 0, .mask = MAX14577_INT1_ADCERR_MASK, }, | |
3008ddbe | 196 | /* INT2 interrupts */ |
c7846852 KK |
197 | { .reg_offset = 1, .mask = MAX14577_INT2_CHGTYP_MASK, }, |
198 | { .reg_offset = 1, .mask = MAX14577_INT2_CHGDETRUN_MASK, }, | |
199 | { .reg_offset = 1, .mask = MAX14577_INT2_DCDTMR_MASK, }, | |
200 | { .reg_offset = 1, .mask = MAX14577_INT2_DBCHG_MASK, }, | |
201 | { .reg_offset = 1, .mask = MAX14577_INT2_VBVOLT_MASK, }, | |
3008ddbe | 202 | /* INT3 interrupts */ |
c7846852 KK |
203 | { .reg_offset = 2, .mask = MAX14577_INT3_EOC_MASK, }, |
204 | { .reg_offset = 2, .mask = MAX14577_INT3_CGMBC_MASK, }, | |
205 | { .reg_offset = 2, .mask = MAX14577_INT3_OVP_MASK, }, | |
206 | { .reg_offset = 2, .mask = MAX14577_INT3_MBCCHGERR_MASK, }, | |
3008ddbe CC |
207 | }; |
208 | ||
209 | static const struct regmap_irq_chip max14577_irq_chip = { | |
210 | .name = "max14577", | |
211 | .status_base = MAX14577_REG_INT1, | |
212 | .mask_base = MAX14577_REG_INTMASK1, | |
aee2a57c | 213 | .mask_invert = true, |
3008ddbe CC |
214 | .num_regs = 3, |
215 | .irqs = max14577_irqs, | |
216 | .num_irqs = ARRAY_SIZE(max14577_irqs), | |
217 | }; | |
218 | ||
aee2a57c KK |
219 | static const struct regmap_irq max77836_muic_irqs[] = { |
220 | /* INT1 interrupts */ | |
221 | { .reg_offset = 0, .mask = MAX14577_INT1_ADC_MASK, }, | |
222 | { .reg_offset = 0, .mask = MAX14577_INT1_ADCLOW_MASK, }, | |
223 | { .reg_offset = 0, .mask = MAX14577_INT1_ADCERR_MASK, }, | |
4706a525 | 224 | { .reg_offset = 0, .mask = MAX77836_INT1_ADC1K_MASK, }, |
aee2a57c KK |
225 | /* INT2 interrupts */ |
226 | { .reg_offset = 1, .mask = MAX14577_INT2_CHGTYP_MASK, }, | |
227 | { .reg_offset = 1, .mask = MAX14577_INT2_CHGDETRUN_MASK, }, | |
228 | { .reg_offset = 1, .mask = MAX14577_INT2_DCDTMR_MASK, }, | |
229 | { .reg_offset = 1, .mask = MAX14577_INT2_DBCHG_MASK, }, | |
230 | { .reg_offset = 1, .mask = MAX14577_INT2_VBVOLT_MASK, }, | |
231 | { .reg_offset = 1, .mask = MAX77836_INT2_VIDRM_MASK, }, | |
232 | /* INT3 interrupts */ | |
233 | { .reg_offset = 2, .mask = MAX14577_INT3_EOC_MASK, }, | |
234 | { .reg_offset = 2, .mask = MAX14577_INT3_CGMBC_MASK, }, | |
235 | { .reg_offset = 2, .mask = MAX14577_INT3_OVP_MASK, }, | |
236 | { .reg_offset = 2, .mask = MAX14577_INT3_MBCCHGERR_MASK, }, | |
237 | }; | |
238 | ||
239 | static const struct regmap_irq_chip max77836_muic_irq_chip = { | |
240 | .name = "max77836-muic", | |
241 | .status_base = MAX14577_REG_INT1, | |
242 | .mask_base = MAX14577_REG_INTMASK1, | |
243 | .mask_invert = true, | |
244 | .num_regs = 3, | |
245 | .irqs = max77836_muic_irqs, | |
246 | .num_irqs = ARRAY_SIZE(max77836_muic_irqs), | |
247 | }; | |
248 | ||
249 | static const struct regmap_irq max77836_pmic_irqs[] = { | |
250 | { .reg_offset = 0, .mask = MAX77836_TOPSYS_INT_T120C_MASK, }, | |
251 | { .reg_offset = 0, .mask = MAX77836_TOPSYS_INT_T140C_MASK, }, | |
252 | }; | |
253 | ||
254 | static const struct regmap_irq_chip max77836_pmic_irq_chip = { | |
255 | .name = "max77836-pmic", | |
256 | .status_base = MAX77836_PMIC_REG_TOPSYS_INT, | |
257 | .mask_base = MAX77836_PMIC_REG_TOPSYS_INT_MASK, | |
258 | .mask_invert = false, | |
259 | .num_regs = 1, | |
260 | .irqs = max77836_pmic_irqs, | |
261 | .num_irqs = ARRAY_SIZE(max77836_pmic_irqs), | |
262 | }; | |
263 | ||
eccb80cc KK |
264 | static void max14577_print_dev_type(struct max14577 *max14577) |
265 | { | |
266 | u8 reg_data, vendor_id, device_id; | |
267 | int ret; | |
268 | ||
269 | ret = max14577_read_reg(max14577->regmap, MAX14577_REG_DEVICEID, | |
270 | ®_data); | |
271 | if (ret) { | |
272 | dev_err(max14577->dev, | |
273 | "Failed to read DEVICEID register: %d\n", ret); | |
274 | return; | |
275 | } | |
276 | ||
277 | vendor_id = ((reg_data & DEVID_VENDORID_MASK) >> | |
278 | DEVID_VENDORID_SHIFT); | |
279 | device_id = ((reg_data & DEVID_DEVICEID_MASK) >> | |
280 | DEVID_DEVICEID_SHIFT); | |
281 | ||
282 | dev_info(max14577->dev, "Device type: %u (ID: 0x%x, vendor: 0x%x)\n", | |
283 | max14577->dev_type, device_id, vendor_id); | |
284 | } | |
285 | ||
aee2a57c KK |
286 | /* |
287 | * Max77836 specific initialization code for driver probe. | |
288 | * Adds new I2C dummy device, regmap and regmap IRQ chip. | |
289 | * Unmasks Interrupt Source register. | |
290 | * | |
291 | * On success returns 0. | |
292 | * On failure returns errno and reverts any changes done so far (e.g. remove | |
293 | * I2C dummy device), except masking the INT SRC register. | |
294 | */ | |
295 | static int max77836_init(struct max14577 *max14577) | |
296 | { | |
297 | int ret; | |
298 | u8 intsrc_mask; | |
299 | ||
300 | max14577->i2c_pmic = i2c_new_dummy(max14577->i2c->adapter, | |
301 | I2C_ADDR_PMIC); | |
302 | if (!max14577->i2c_pmic) { | |
303 | dev_err(max14577->dev, "Failed to register PMIC I2C device\n"); | |
304 | return -ENODEV; | |
305 | } | |
306 | i2c_set_clientdata(max14577->i2c_pmic, max14577); | |
307 | ||
308 | max14577->regmap_pmic = devm_regmap_init_i2c(max14577->i2c_pmic, | |
309 | &max77836_pmic_regmap_config); | |
310 | if (IS_ERR(max14577->regmap_pmic)) { | |
311 | ret = PTR_ERR(max14577->regmap_pmic); | |
312 | dev_err(max14577->dev, "Failed to allocate PMIC register map: %d\n", | |
313 | ret); | |
314 | goto err; | |
315 | } | |
316 | ||
317 | /* Un-mask MAX77836 Interrupt Source register */ | |
318 | ret = max14577_read_reg(max14577->regmap_pmic, | |
319 | MAX77836_PMIC_REG_INTSRC_MASK, &intsrc_mask); | |
320 | if (ret < 0) { | |
321 | dev_err(max14577->dev, "Failed to read PMIC register\n"); | |
322 | goto err; | |
323 | } | |
324 | ||
325 | intsrc_mask &= ~(MAX77836_INTSRC_MASK_TOP_INT_MASK); | |
326 | intsrc_mask &= ~(MAX77836_INTSRC_MASK_MUIC_CHG_INT_MASK); | |
327 | ret = max14577_write_reg(max14577->regmap_pmic, | |
328 | MAX77836_PMIC_REG_INTSRC_MASK, intsrc_mask); | |
329 | if (ret < 0) { | |
330 | dev_err(max14577->dev, "Failed to write PMIC register\n"); | |
331 | goto err; | |
332 | } | |
333 | ||
334 | ret = regmap_add_irq_chip(max14577->regmap_pmic, max14577->irq, | |
335 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED, | |
336 | 0, &max77836_pmic_irq_chip, | |
337 | &max14577->irq_data_pmic); | |
338 | if (ret != 0) { | |
339 | dev_err(max14577->dev, "Failed to request PMIC IRQ %d: %d\n", | |
340 | max14577->irq, ret); | |
341 | goto err; | |
342 | } | |
343 | ||
344 | return 0; | |
345 | ||
346 | err: | |
347 | i2c_unregister_device(max14577->i2c_pmic); | |
348 | ||
349 | return ret; | |
350 | } | |
351 | ||
352 | /* | |
353 | * Max77836 specific de-initialization code for driver remove. | |
354 | */ | |
355 | static void max77836_remove(struct max14577 *max14577) | |
356 | { | |
357 | regmap_del_irq_chip(max14577->irq, max14577->irq_data_pmic); | |
358 | i2c_unregister_device(max14577->i2c_pmic); | |
359 | } | |
360 | ||
3008ddbe CC |
361 | static int max14577_i2c_probe(struct i2c_client *i2c, |
362 | const struct i2c_device_id *id) | |
363 | { | |
364 | struct max14577 *max14577; | |
365 | struct max14577_platform_data *pdata = dev_get_platdata(&i2c->dev); | |
366 | struct device_node *np = i2c->dev.of_node; | |
3008ddbe | 367 | int ret = 0; |
aee2a57c | 368 | const struct regmap_irq_chip *irq_chip; |
92725493 | 369 | const struct mfd_cell *mfd_devs; |
aee2a57c KK |
370 | unsigned int mfd_devs_size; |
371 | int irq_flags; | |
3008ddbe CC |
372 | |
373 | if (np) { | |
374 | pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL); | |
375 | if (!pdata) | |
376 | return -ENOMEM; | |
377 | i2c->dev.platform_data = pdata; | |
378 | } | |
379 | ||
380 | if (!pdata) { | |
aab5dc68 | 381 | dev_err(&i2c->dev, "No platform data found.\n"); |
3008ddbe CC |
382 | return -EINVAL; |
383 | } | |
384 | ||
385 | max14577 = devm_kzalloc(&i2c->dev, sizeof(*max14577), GFP_KERNEL); | |
386 | if (!max14577) | |
387 | return -ENOMEM; | |
388 | ||
389 | i2c_set_clientdata(i2c, max14577); | |
390 | max14577->dev = &i2c->dev; | |
391 | max14577->i2c = i2c; | |
392 | max14577->irq = i2c->irq; | |
393 | ||
575343d1 KK |
394 | max14577->regmap = devm_regmap_init_i2c(i2c, |
395 | &max14577_muic_regmap_config); | |
3008ddbe CC |
396 | if (IS_ERR(max14577->regmap)) { |
397 | ret = PTR_ERR(max14577->regmap); | |
398 | dev_err(max14577->dev, "Failed to allocate register map: %d\n", | |
399 | ret); | |
400 | return ret; | |
401 | } | |
402 | ||
eccb80cc KK |
403 | if (np) { |
404 | const struct of_device_id *of_id; | |
405 | ||
406 | of_id = of_match_device(max14577_dt_match, &i2c->dev); | |
407 | if (of_id) | |
fab8445c LJ |
408 | max14577->dev_type = |
409 | (enum maxim_device_type)of_id->data; | |
eccb80cc KK |
410 | } else { |
411 | max14577->dev_type = id->driver_data; | |
3008ddbe | 412 | } |
eccb80cc KK |
413 | |
414 | max14577_print_dev_type(max14577); | |
3008ddbe | 415 | |
aee2a57c KK |
416 | switch (max14577->dev_type) { |
417 | case MAXIM_DEVICE_TYPE_MAX77836: | |
418 | irq_chip = &max77836_muic_irq_chip; | |
419 | mfd_devs = max77836_devs; | |
420 | mfd_devs_size = ARRAY_SIZE(max77836_devs); | |
421 | irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_SHARED; | |
422 | break; | |
423 | case MAXIM_DEVICE_TYPE_MAX14577: | |
424 | default: | |
425 | irq_chip = &max14577_irq_chip; | |
426 | mfd_devs = max14577_devs; | |
427 | mfd_devs_size = ARRAY_SIZE(max14577_devs); | |
428 | irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; | |
429 | break; | |
430 | } | |
431 | ||
3008ddbe | 432 | ret = regmap_add_irq_chip(max14577->regmap, max14577->irq, |
aee2a57c | 433 | irq_flags, 0, irq_chip, |
3008ddbe CC |
434 | &max14577->irq_data); |
435 | if (ret != 0) { | |
436 | dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n", | |
437 | max14577->irq, ret); | |
438 | return ret; | |
439 | } | |
440 | ||
aee2a57c KK |
441 | /* Max77836 specific initialization code (additional regmap) */ |
442 | if (max14577->dev_type == MAXIM_DEVICE_TYPE_MAX77836) { | |
443 | ret = max77836_init(max14577); | |
444 | if (ret < 0) | |
445 | goto err_max77836; | |
446 | } | |
447 | ||
448 | ret = mfd_add_devices(max14577->dev, -1, mfd_devs, | |
be69e9e0 | 449 | mfd_devs_size, NULL, 0, NULL); |
3008ddbe CC |
450 | if (ret < 0) |
451 | goto err_mfd; | |
452 | ||
453 | device_init_wakeup(max14577->dev, 1); | |
454 | ||
455 | return 0; | |
456 | ||
457 | err_mfd: | |
aee2a57c KK |
458 | if (max14577->dev_type == MAXIM_DEVICE_TYPE_MAX77836) |
459 | max77836_remove(max14577); | |
460 | err_max77836: | |
3008ddbe CC |
461 | regmap_del_irq_chip(max14577->irq, max14577->irq_data); |
462 | ||
463 | return ret; | |
464 | } | |
465 | ||
466 | static int max14577_i2c_remove(struct i2c_client *i2c) | |
467 | { | |
468 | struct max14577 *max14577 = i2c_get_clientdata(i2c); | |
469 | ||
470 | mfd_remove_devices(max14577->dev); | |
471 | regmap_del_irq_chip(max14577->irq, max14577->irq_data); | |
aee2a57c KK |
472 | if (max14577->dev_type == MAXIM_DEVICE_TYPE_MAX77836) |
473 | max77836_remove(max14577); | |
3008ddbe CC |
474 | |
475 | return 0; | |
476 | } | |
477 | ||
478 | static const struct i2c_device_id max14577_i2c_id[] = { | |
eccb80cc | 479 | { "max14577", MAXIM_DEVICE_TYPE_MAX14577, }, |
aee2a57c | 480 | { "max77836", MAXIM_DEVICE_TYPE_MAX77836, }, |
3008ddbe CC |
481 | { } |
482 | }; | |
483 | MODULE_DEVICE_TABLE(i2c, max14577_i2c_id); | |
484 | ||
3edeb1e4 | 485 | #ifdef CONFIG_PM_SLEEP |
3008ddbe CC |
486 | static int max14577_suspend(struct device *dev) |
487 | { | |
1b5420e1 | 488 | struct i2c_client *i2c = to_i2c_client(dev); |
3008ddbe CC |
489 | struct max14577 *max14577 = i2c_get_clientdata(i2c); |
490 | ||
c4f725b5 | 491 | if (device_may_wakeup(dev)) |
3008ddbe | 492 | enable_irq_wake(max14577->irq); |
c4f725b5 KK |
493 | /* |
494 | * MUIC IRQ must be disabled during suspend because if it happens | |
495 | * while suspended it will be handled before resuming I2C. | |
496 | * | |
497 | * When device is woken up from suspend (e.g. by ADC change), | |
498 | * an interrupt occurs before resuming I2C bus controller. | |
499 | * Interrupt handler tries to read registers but this read | |
500 | * will fail because I2C is still suspended. | |
501 | */ | |
502 | disable_irq(max14577->irq); | |
3008ddbe CC |
503 | |
504 | return 0; | |
505 | } | |
506 | ||
507 | static int max14577_resume(struct device *dev) | |
508 | { | |
1b5420e1 | 509 | struct i2c_client *i2c = to_i2c_client(dev); |
3008ddbe CC |
510 | struct max14577 *max14577 = i2c_get_clientdata(i2c); |
511 | ||
c4f725b5 | 512 | if (device_may_wakeup(dev)) |
3008ddbe | 513 | disable_irq_wake(max14577->irq); |
c4f725b5 | 514 | enable_irq(max14577->irq); |
3008ddbe CC |
515 | |
516 | return 0; | |
517 | } | |
3edeb1e4 | 518 | #endif /* CONFIG_PM_SLEEP */ |
3008ddbe | 519 | |
3008ddbe CC |
520 | static SIMPLE_DEV_PM_OPS(max14577_pm, max14577_suspend, max14577_resume); |
521 | ||
522 | static struct i2c_driver max14577_i2c_driver = { | |
523 | .driver = { | |
524 | .name = "max14577", | |
3008ddbe | 525 | .pm = &max14577_pm, |
ae679c12 | 526 | .of_match_table = max14577_dt_match, |
3008ddbe CC |
527 | }, |
528 | .probe = max14577_i2c_probe, | |
529 | .remove = max14577_i2c_remove, | |
530 | .id_table = max14577_i2c_id, | |
531 | }; | |
532 | ||
533 | static int __init max14577_i2c_init(void) | |
534 | { | |
eccb80cc KK |
535 | BUILD_BUG_ON(ARRAY_SIZE(max14577_i2c_id) != MAXIM_DEVICE_TYPE_NUM); |
536 | BUILD_BUG_ON(ARRAY_SIZE(max14577_dt_match) != MAXIM_DEVICE_TYPE_NUM); | |
537 | ||
b8f139f6 KK |
538 | /* Valid charger current values must be provided for each chipset */ |
539 | BUILD_BUG_ON(ARRAY_SIZE(maxim_charger_currents) != MAXIM_DEVICE_TYPE_NUM); | |
540 | ||
541 | /* Check for valid values for charger */ | |
542 | BUILD_BUG_ON(MAX14577_CHARGER_CURRENT_LIMIT_HIGH_START + | |
543 | MAX14577_CHARGER_CURRENT_LIMIT_HIGH_STEP * 0xf != | |
544 | MAX14577_CHARGER_CURRENT_LIMIT_MAX); | |
545 | BUILD_BUG_ON(MAX14577_CHARGER_CURRENT_LIMIT_HIGH_STEP == 0); | |
546 | ||
547 | BUILD_BUG_ON(MAX77836_CHARGER_CURRENT_LIMIT_HIGH_START + | |
548 | MAX77836_CHARGER_CURRENT_LIMIT_HIGH_STEP * 0xf != | |
549 | MAX77836_CHARGER_CURRENT_LIMIT_MAX); | |
550 | BUILD_BUG_ON(MAX77836_CHARGER_CURRENT_LIMIT_HIGH_STEP == 0); | |
551 | ||
3008ddbe CC |
552 | return i2c_add_driver(&max14577_i2c_driver); |
553 | } | |
9961bf18 | 554 | module_init(max14577_i2c_init); |
3008ddbe CC |
555 | |
556 | static void __exit max14577_i2c_exit(void) | |
557 | { | |
558 | i2c_del_driver(&max14577_i2c_driver); | |
559 | } | |
560 | module_exit(max14577_i2c_exit); | |
561 | ||
8c5d0571 | 562 | MODULE_AUTHOR("Chanwoo Choi <[email protected]>, Krzysztof Kozlowski <[email protected]>"); |
aee2a57c | 563 | MODULE_DESCRIPTION("Maxim 14577/77836 multi-function core driver"); |
3008ddbe | 564 | MODULE_LICENSE("GPL"); |