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