diff options
Diffstat (limited to 'drivers/power/smb347-charger.c')
-rw-r--r-- | drivers/power/smb347-charger.c | 558 |
1 files changed, 231 insertions, 327 deletions
diff --git a/drivers/power/smb347-charger.c b/drivers/power/smb347-charger.c index de6898f5d166..cf31b31cc653 100644 --- a/drivers/power/smb347-charger.c +++ b/drivers/power/smb347-charger.c | |||
@@ -11,7 +11,6 @@ | |||
11 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/debugfs.h> | ||
15 | #include <linux/gpio.h> | 14 | #include <linux/gpio.h> |
16 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
17 | #include <linux/module.h> | 16 | #include <linux/module.h> |
@@ -21,7 +20,7 @@ | |||
21 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
22 | #include <linux/power_supply.h> | 21 | #include <linux/power_supply.h> |
23 | #include <linux/power/smb347-charger.h> | 22 | #include <linux/power/smb347-charger.h> |
24 | #include <linux/seq_file.h> | 23 | #include <linux/regmap.h> |
25 | 24 | ||
26 | /* | 25 | /* |
27 | * Configuration registers. These are mirrored to volatile RAM and can be | 26 | * Configuration registers. These are mirrored to volatile RAM and can be |
@@ -39,6 +38,7 @@ | |||
39 | #define CFG_CURRENT_LIMIT_DC_SHIFT 4 | 38 | #define CFG_CURRENT_LIMIT_DC_SHIFT 4 |
40 | #define CFG_CURRENT_LIMIT_USB_MASK 0x0f | 39 | #define CFG_CURRENT_LIMIT_USB_MASK 0x0f |
41 | #define CFG_FLOAT_VOLTAGE 0x03 | 40 | #define CFG_FLOAT_VOLTAGE 0x03 |
41 | #define CFG_FLOAT_VOLTAGE_FLOAT_MASK 0x3f | ||
42 | #define CFG_FLOAT_VOLTAGE_THRESHOLD_MASK 0xc0 | 42 | #define CFG_FLOAT_VOLTAGE_THRESHOLD_MASK 0xc0 |
43 | #define CFG_FLOAT_VOLTAGE_THRESHOLD_SHIFT 6 | 43 | #define CFG_FLOAT_VOLTAGE_THRESHOLD_SHIFT 6 |
44 | #define CFG_STAT 0x05 | 44 | #define CFG_STAT 0x05 |
@@ -113,29 +113,31 @@ | |||
113 | #define STAT_C_CHARGER_ERROR BIT(6) | 113 | #define STAT_C_CHARGER_ERROR BIT(6) |
114 | #define STAT_E 0x3f | 114 | #define STAT_E 0x3f |
115 | 115 | ||
116 | #define SMB347_MAX_REGISTER 0x3f | ||
117 | |||
116 | /** | 118 | /** |
117 | * struct smb347_charger - smb347 charger instance | 119 | * struct smb347_charger - smb347 charger instance |
118 | * @lock: protects concurrent access to online variables | 120 | * @lock: protects concurrent access to online variables |
119 | * @client: pointer to i2c client | 121 | * @dev: pointer to device |
122 | * @regmap: pointer to driver regmap | ||
120 | * @mains: power_supply instance for AC/DC power | 123 | * @mains: power_supply instance for AC/DC power |
121 | * @usb: power_supply instance for USB power | 124 | * @usb: power_supply instance for USB power |
122 | * @battery: power_supply instance for battery | 125 | * @battery: power_supply instance for battery |
123 | * @mains_online: is AC/DC input connected | 126 | * @mains_online: is AC/DC input connected |
124 | * @usb_online: is USB input connected | 127 | * @usb_online: is USB input connected |
125 | * @charging_enabled: is charging enabled | 128 | * @charging_enabled: is charging enabled |
126 | * @dentry: for debugfs | ||
127 | * @pdata: pointer to platform data | 129 | * @pdata: pointer to platform data |
128 | */ | 130 | */ |
129 | struct smb347_charger { | 131 | struct smb347_charger { |
130 | struct mutex lock; | 132 | struct mutex lock; |
131 | struct i2c_client *client; | 133 | struct device *dev; |
134 | struct regmap *regmap; | ||
132 | struct power_supply mains; | 135 | struct power_supply mains; |
133 | struct power_supply usb; | 136 | struct power_supply usb; |
134 | struct power_supply battery; | 137 | struct power_supply battery; |
135 | bool mains_online; | 138 | bool mains_online; |
136 | bool usb_online; | 139 | bool usb_online; |
137 | bool charging_enabled; | 140 | bool charging_enabled; |
138 | struct dentry *dentry; | ||
139 | const struct smb347_charger_platform_data *pdata; | 141 | const struct smb347_charger_platform_data *pdata; |
140 | }; | 142 | }; |
141 | 143 | ||
@@ -212,28 +214,6 @@ static int current_to_hw(const unsigned int *tbl, size_t size, unsigned int val) | |||
212 | return i > 0 ? i - 1 : -EINVAL; | 214 | return i > 0 ? i - 1 : -EINVAL; |
213 | } | 215 | } |
214 | 216 | ||
215 | static int smb347_read(struct smb347_charger *smb, u8 reg) | ||
216 | { | ||
217 | int ret; | ||
218 | |||
219 | ret = i2c_smbus_read_byte_data(smb->client, reg); | ||
220 | if (ret < 0) | ||
221 | dev_warn(&smb->client->dev, "failed to read reg 0x%x: %d\n", | ||
222 | reg, ret); | ||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | static int smb347_write(struct smb347_charger *smb, u8 reg, u8 val) | ||
227 | { | ||
228 | int ret; | ||
229 | |||
230 | ret = i2c_smbus_write_byte_data(smb->client, reg, val); | ||
231 | if (ret < 0) | ||
232 | dev_warn(&smb->client->dev, "failed to write reg 0x%x: %d\n", | ||
233 | reg, ret); | ||
234 | return ret; | ||
235 | } | ||
236 | |||
237 | /** | 217 | /** |
238 | * smb347_update_ps_status - refreshes the power source status | 218 | * smb347_update_ps_status - refreshes the power source status |
239 | * @smb: pointer to smb347 charger instance | 219 | * @smb: pointer to smb347 charger instance |
@@ -246,9 +226,10 @@ static int smb347_update_ps_status(struct smb347_charger *smb) | |||
246 | { | 226 | { |
247 | bool usb = false; | 227 | bool usb = false; |
248 | bool dc = false; | 228 | bool dc = false; |
229 | unsigned int val; | ||
249 | int ret; | 230 | int ret; |
250 | 231 | ||
251 | ret = smb347_read(smb, IRQSTAT_E); | 232 | ret = regmap_read(smb->regmap, IRQSTAT_E, &val); |
252 | if (ret < 0) | 233 | if (ret < 0) |
253 | return ret; | 234 | return ret; |
254 | 235 | ||
@@ -257,9 +238,9 @@ static int smb347_update_ps_status(struct smb347_charger *smb) | |||
257 | * platform data _and_ whether corresponding undervoltage is set. | 238 | * platform data _and_ whether corresponding undervoltage is set. |
258 | */ | 239 | */ |
259 | if (smb->pdata->use_mains) | 240 | if (smb->pdata->use_mains) |
260 | dc = !(ret & IRQSTAT_E_DCIN_UV_STAT); | 241 | dc = !(val & IRQSTAT_E_DCIN_UV_STAT); |
261 | if (smb->pdata->use_usb) | 242 | if (smb->pdata->use_usb) |
262 | usb = !(ret & IRQSTAT_E_USBIN_UV_STAT); | 243 | usb = !(val & IRQSTAT_E_USBIN_UV_STAT); |
263 | 244 | ||
264 | mutex_lock(&smb->lock); | 245 | mutex_lock(&smb->lock); |
265 | ret = smb->mains_online != dc || smb->usb_online != usb; | 246 | ret = smb->mains_online != dc || smb->usb_online != usb; |
@@ -299,16 +280,17 @@ static bool smb347_is_ps_online(struct smb347_charger *smb) | |||
299 | */ | 280 | */ |
300 | static int smb347_charging_status(struct smb347_charger *smb) | 281 | static int smb347_charging_status(struct smb347_charger *smb) |
301 | { | 282 | { |
283 | unsigned int val; | ||
302 | int ret; | 284 | int ret; |
303 | 285 | ||
304 | if (!smb347_is_ps_online(smb)) | 286 | if (!smb347_is_ps_online(smb)) |
305 | return 0; | 287 | return 0; |
306 | 288 | ||
307 | ret = smb347_read(smb, STAT_C); | 289 | ret = regmap_read(smb->regmap, STAT_C, &val); |
308 | if (ret < 0) | 290 | if (ret < 0) |
309 | return 0; | 291 | return 0; |
310 | 292 | ||
311 | return (ret & STAT_C_CHG_MASK) >> STAT_C_CHG_SHIFT; | 293 | return (val & STAT_C_CHG_MASK) >> STAT_C_CHG_SHIFT; |
312 | } | 294 | } |
313 | 295 | ||
314 | static int smb347_charging_set(struct smb347_charger *smb, bool enable) | 296 | static int smb347_charging_set(struct smb347_charger *smb, bool enable) |
@@ -316,27 +298,17 @@ static int smb347_charging_set(struct smb347_charger *smb, bool enable) | |||
316 | int ret = 0; | 298 | int ret = 0; |
317 | 299 | ||
318 | if (smb->pdata->enable_control != SMB347_CHG_ENABLE_SW) { | 300 | if (smb->pdata->enable_control != SMB347_CHG_ENABLE_SW) { |
319 | dev_dbg(&smb->client->dev, | 301 | dev_dbg(smb->dev, "charging enable/disable in SW disabled\n"); |
320 | "charging enable/disable in SW disabled\n"); | ||
321 | return 0; | 302 | return 0; |
322 | } | 303 | } |
323 | 304 | ||
324 | mutex_lock(&smb->lock); | 305 | mutex_lock(&smb->lock); |
325 | if (smb->charging_enabled != enable) { | 306 | if (smb->charging_enabled != enable) { |
326 | ret = smb347_read(smb, CMD_A); | 307 | ret = regmap_update_bits(smb->regmap, CMD_A, CMD_A_CHG_ENABLED, |
327 | if (ret < 0) | 308 | enable ? CMD_A_CHG_ENABLED : 0); |
328 | goto out; | 309 | if (!ret) |
329 | 310 | smb->charging_enabled = enable; | |
330 | smb->charging_enabled = enable; | ||
331 | |||
332 | if (enable) | ||
333 | ret |= CMD_A_CHG_ENABLED; | ||
334 | else | ||
335 | ret &= ~CMD_A_CHG_ENABLED; | ||
336 | |||
337 | ret = smb347_write(smb, CMD_A, ret); | ||
338 | } | 311 | } |
339 | out: | ||
340 | mutex_unlock(&smb->lock); | 312 | mutex_unlock(&smb->lock); |
341 | return ret; | 313 | return ret; |
342 | } | 314 | } |
@@ -363,13 +335,11 @@ static int smb347_start_stop_charging(struct smb347_charger *smb) | |||
363 | if (smb347_is_ps_online(smb)) { | 335 | if (smb347_is_ps_online(smb)) { |
364 | ret = smb347_charging_enable(smb); | 336 | ret = smb347_charging_enable(smb); |
365 | if (ret < 0) | 337 | if (ret < 0) |
366 | dev_err(&smb->client->dev, | 338 | dev_err(smb->dev, "failed to enable charging\n"); |
367 | "failed to enable charging\n"); | ||
368 | } else { | 339 | } else { |
369 | ret = smb347_charging_disable(smb); | 340 | ret = smb347_charging_disable(smb); |
370 | if (ret < 0) | 341 | if (ret < 0) |
371 | dev_err(&smb->client->dev, | 342 | dev_err(smb->dev, "failed to disable charging\n"); |
372 | "failed to disable charging\n"); | ||
373 | } | 343 | } |
374 | 344 | ||
375 | return ret; | 345 | return ret; |
@@ -377,112 +347,120 @@ static int smb347_start_stop_charging(struct smb347_charger *smb) | |||
377 | 347 | ||
378 | static int smb347_set_charge_current(struct smb347_charger *smb) | 348 | static int smb347_set_charge_current(struct smb347_charger *smb) |
379 | { | 349 | { |
380 | int ret, val; | 350 | int ret; |
381 | |||
382 | ret = smb347_read(smb, CFG_CHARGE_CURRENT); | ||
383 | if (ret < 0) | ||
384 | return ret; | ||
385 | 351 | ||
386 | if (smb->pdata->max_charge_current) { | 352 | if (smb->pdata->max_charge_current) { |
387 | val = current_to_hw(fcc_tbl, ARRAY_SIZE(fcc_tbl), | 353 | ret = current_to_hw(fcc_tbl, ARRAY_SIZE(fcc_tbl), |
388 | smb->pdata->max_charge_current); | 354 | smb->pdata->max_charge_current); |
389 | if (val < 0) | 355 | if (ret < 0) |
390 | return val; | 356 | return ret; |
391 | 357 | ||
392 | ret &= ~CFG_CHARGE_CURRENT_FCC_MASK; | 358 | ret = regmap_update_bits(smb->regmap, CFG_CHARGE_CURRENT, |
393 | ret |= val << CFG_CHARGE_CURRENT_FCC_SHIFT; | 359 | CFG_CHARGE_CURRENT_FCC_MASK, |
360 | ret << CFG_CHARGE_CURRENT_FCC_SHIFT); | ||
361 | if (ret < 0) | ||
362 | return ret; | ||
394 | } | 363 | } |
395 | 364 | ||
396 | if (smb->pdata->pre_charge_current) { | 365 | if (smb->pdata->pre_charge_current) { |
397 | val = current_to_hw(pcc_tbl, ARRAY_SIZE(pcc_tbl), | 366 | ret = current_to_hw(pcc_tbl, ARRAY_SIZE(pcc_tbl), |
398 | smb->pdata->pre_charge_current); | 367 | smb->pdata->pre_charge_current); |
399 | if (val < 0) | 368 | if (ret < 0) |
400 | return val; | 369 | return ret; |
401 | 370 | ||
402 | ret &= ~CFG_CHARGE_CURRENT_PCC_MASK; | 371 | ret = regmap_update_bits(smb->regmap, CFG_CHARGE_CURRENT, |
403 | ret |= val << CFG_CHARGE_CURRENT_PCC_SHIFT; | 372 | CFG_CHARGE_CURRENT_PCC_MASK, |
373 | ret << CFG_CHARGE_CURRENT_PCC_SHIFT); | ||
374 | if (ret < 0) | ||
375 | return ret; | ||
404 | } | 376 | } |
405 | 377 | ||
406 | if (smb->pdata->termination_current) { | 378 | if (smb->pdata->termination_current) { |
407 | val = current_to_hw(tc_tbl, ARRAY_SIZE(tc_tbl), | 379 | ret = current_to_hw(tc_tbl, ARRAY_SIZE(tc_tbl), |
408 | smb->pdata->termination_current); | 380 | smb->pdata->termination_current); |
409 | if (val < 0) | 381 | if (ret < 0) |
410 | return val; | 382 | return ret; |
411 | 383 | ||
412 | ret &= ~CFG_CHARGE_CURRENT_TC_MASK; | 384 | ret = regmap_update_bits(smb->regmap, CFG_CHARGE_CURRENT, |
413 | ret |= val; | 385 | CFG_CHARGE_CURRENT_TC_MASK, ret); |
386 | if (ret < 0) | ||
387 | return ret; | ||
414 | } | 388 | } |
415 | 389 | ||
416 | return smb347_write(smb, CFG_CHARGE_CURRENT, ret); | 390 | return 0; |
417 | } | 391 | } |
418 | 392 | ||
419 | static int smb347_set_current_limits(struct smb347_charger *smb) | 393 | static int smb347_set_current_limits(struct smb347_charger *smb) |
420 | { | 394 | { |
421 | int ret, val; | 395 | int ret; |
422 | |||
423 | ret = smb347_read(smb, CFG_CURRENT_LIMIT); | ||
424 | if (ret < 0) | ||
425 | return ret; | ||
426 | 396 | ||
427 | if (smb->pdata->mains_current_limit) { | 397 | if (smb->pdata->mains_current_limit) { |
428 | val = current_to_hw(icl_tbl, ARRAY_SIZE(icl_tbl), | 398 | ret = current_to_hw(icl_tbl, ARRAY_SIZE(icl_tbl), |
429 | smb->pdata->mains_current_limit); | 399 | smb->pdata->mains_current_limit); |
430 | if (val < 0) | 400 | if (ret < 0) |
431 | return val; | 401 | return ret; |
432 | 402 | ||
433 | ret &= ~CFG_CURRENT_LIMIT_DC_MASK; | 403 | ret = regmap_update_bits(smb->regmap, CFG_CURRENT_LIMIT, |
434 | ret |= val << CFG_CURRENT_LIMIT_DC_SHIFT; | 404 | CFG_CURRENT_LIMIT_DC_MASK, |
405 | ret << CFG_CURRENT_LIMIT_DC_SHIFT); | ||
406 | if (ret < 0) | ||
407 | return ret; | ||
435 | } | 408 | } |
436 | 409 | ||
437 | if (smb->pdata->usb_hc_current_limit) { | 410 | if (smb->pdata->usb_hc_current_limit) { |
438 | val = current_to_hw(icl_tbl, ARRAY_SIZE(icl_tbl), | 411 | ret = current_to_hw(icl_tbl, ARRAY_SIZE(icl_tbl), |
439 | smb->pdata->usb_hc_current_limit); | 412 | smb->pdata->usb_hc_current_limit); |
440 | if (val < 0) | 413 | if (ret < 0) |
441 | return val; | 414 | return ret; |
442 | 415 | ||
443 | ret &= ~CFG_CURRENT_LIMIT_USB_MASK; | 416 | ret = regmap_update_bits(smb->regmap, CFG_CURRENT_LIMIT, |
444 | ret |= val; | 417 | CFG_CURRENT_LIMIT_USB_MASK, ret); |
418 | if (ret < 0) | ||
419 | return ret; | ||
445 | } | 420 | } |
446 | 421 | ||
447 | return smb347_write(smb, CFG_CURRENT_LIMIT, ret); | 422 | return 0; |
448 | } | 423 | } |
449 | 424 | ||
450 | static int smb347_set_voltage_limits(struct smb347_charger *smb) | 425 | static int smb347_set_voltage_limits(struct smb347_charger *smb) |
451 | { | 426 | { |
452 | int ret, val; | 427 | int ret; |
453 | |||
454 | ret = smb347_read(smb, CFG_FLOAT_VOLTAGE); | ||
455 | if (ret < 0) | ||
456 | return ret; | ||
457 | 428 | ||
458 | if (smb->pdata->pre_to_fast_voltage) { | 429 | if (smb->pdata->pre_to_fast_voltage) { |
459 | val = smb->pdata->pre_to_fast_voltage; | 430 | ret = smb->pdata->pre_to_fast_voltage; |
460 | 431 | ||
461 | /* uV */ | 432 | /* uV */ |
462 | val = clamp_val(val, 2400000, 3000000) - 2400000; | 433 | ret = clamp_val(ret, 2400000, 3000000) - 2400000; |
463 | val /= 200000; | 434 | ret /= 200000; |
464 | 435 | ||
465 | ret &= ~CFG_FLOAT_VOLTAGE_THRESHOLD_MASK; | 436 | ret = regmap_update_bits(smb->regmap, CFG_FLOAT_VOLTAGE, |
466 | ret |= val << CFG_FLOAT_VOLTAGE_THRESHOLD_SHIFT; | 437 | CFG_FLOAT_VOLTAGE_THRESHOLD_MASK, |
438 | ret << CFG_FLOAT_VOLTAGE_THRESHOLD_SHIFT); | ||
439 | if (ret < 0) | ||
440 | return ret; | ||
467 | } | 441 | } |
468 | 442 | ||
469 | if (smb->pdata->max_charge_voltage) { | 443 | if (smb->pdata->max_charge_voltage) { |
470 | val = smb->pdata->max_charge_voltage; | 444 | ret = smb->pdata->max_charge_voltage; |
471 | 445 | ||
472 | /* uV */ | 446 | /* uV */ |
473 | val = clamp_val(val, 3500000, 4500000) - 3500000; | 447 | ret = clamp_val(ret, 3500000, 4500000) - 3500000; |
474 | val /= 20000; | 448 | ret /= 20000; |
475 | 449 | ||
476 | ret |= val; | 450 | ret = regmap_update_bits(smb->regmap, CFG_FLOAT_VOLTAGE, |
451 | CFG_FLOAT_VOLTAGE_FLOAT_MASK, ret); | ||
452 | if (ret < 0) | ||
453 | return ret; | ||
477 | } | 454 | } |
478 | 455 | ||
479 | return smb347_write(smb, CFG_FLOAT_VOLTAGE, ret); | 456 | return 0; |
480 | } | 457 | } |
481 | 458 | ||
482 | static int smb347_set_temp_limits(struct smb347_charger *smb) | 459 | static int smb347_set_temp_limits(struct smb347_charger *smb) |
483 | { | 460 | { |
484 | bool enable_therm_monitor = false; | 461 | bool enable_therm_monitor = false; |
485 | int ret, val; | 462 | int ret = 0; |
463 | int val; | ||
486 | 464 | ||
487 | if (smb->pdata->chip_temp_threshold) { | 465 | if (smb->pdata->chip_temp_threshold) { |
488 | val = smb->pdata->chip_temp_threshold; | 466 | val = smb->pdata->chip_temp_threshold; |
@@ -491,22 +469,13 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) | |||
491 | val = clamp_val(val, 100, 130) - 100; | 469 | val = clamp_val(val, 100, 130) - 100; |
492 | val /= 10; | 470 | val /= 10; |
493 | 471 | ||
494 | ret = smb347_read(smb, CFG_OTG); | 472 | ret = regmap_update_bits(smb->regmap, CFG_OTG, |
495 | if (ret < 0) | 473 | CFG_OTG_TEMP_THRESHOLD_MASK, |
496 | return ret; | 474 | val << CFG_OTG_TEMP_THRESHOLD_SHIFT); |
497 | |||
498 | ret &= ~CFG_OTG_TEMP_THRESHOLD_MASK; | ||
499 | ret |= val << CFG_OTG_TEMP_THRESHOLD_SHIFT; | ||
500 | |||
501 | ret = smb347_write(smb, CFG_OTG, ret); | ||
502 | if (ret < 0) | 475 | if (ret < 0) |
503 | return ret; | 476 | return ret; |
504 | } | 477 | } |
505 | 478 | ||
506 | ret = smb347_read(smb, CFG_TEMP_LIMIT); | ||
507 | if (ret < 0) | ||
508 | return ret; | ||
509 | |||
510 | if (smb->pdata->soft_cold_temp_limit != SMB347_TEMP_USE_DEFAULT) { | 479 | if (smb->pdata->soft_cold_temp_limit != SMB347_TEMP_USE_DEFAULT) { |
511 | val = smb->pdata->soft_cold_temp_limit; | 480 | val = smb->pdata->soft_cold_temp_limit; |
512 | 481 | ||
@@ -515,8 +484,11 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) | |||
515 | /* this goes from higher to lower so invert the value */ | 484 | /* this goes from higher to lower so invert the value */ |
516 | val = ~val & 0x3; | 485 | val = ~val & 0x3; |
517 | 486 | ||
518 | ret &= ~CFG_TEMP_LIMIT_SOFT_COLD_MASK; | 487 | ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT, |
519 | ret |= val << CFG_TEMP_LIMIT_SOFT_COLD_SHIFT; | 488 | CFG_TEMP_LIMIT_SOFT_COLD_MASK, |
489 | val << CFG_TEMP_LIMIT_SOFT_COLD_SHIFT); | ||
490 | if (ret < 0) | ||
491 | return ret; | ||
520 | 492 | ||
521 | enable_therm_monitor = true; | 493 | enable_therm_monitor = true; |
522 | } | 494 | } |
@@ -527,8 +499,11 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) | |||
527 | val = clamp_val(val, 40, 55) - 40; | 499 | val = clamp_val(val, 40, 55) - 40; |
528 | val /= 5; | 500 | val /= 5; |
529 | 501 | ||
530 | ret &= ~CFG_TEMP_LIMIT_SOFT_HOT_MASK; | 502 | ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT, |
531 | ret |= val << CFG_TEMP_LIMIT_SOFT_HOT_SHIFT; | 503 | CFG_TEMP_LIMIT_SOFT_HOT_MASK, |
504 | val << CFG_TEMP_LIMIT_SOFT_HOT_SHIFT); | ||
505 | if (ret < 0) | ||
506 | return ret; | ||
532 | 507 | ||
533 | enable_therm_monitor = true; | 508 | enable_therm_monitor = true; |
534 | } | 509 | } |
@@ -541,8 +516,11 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) | |||
541 | /* this goes from higher to lower so invert the value */ | 516 | /* this goes from higher to lower so invert the value */ |
542 | val = ~val & 0x3; | 517 | val = ~val & 0x3; |
543 | 518 | ||
544 | ret &= ~CFG_TEMP_LIMIT_HARD_COLD_MASK; | 519 | ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT, |
545 | ret |= val << CFG_TEMP_LIMIT_HARD_COLD_SHIFT; | 520 | CFG_TEMP_LIMIT_HARD_COLD_MASK, |
521 | val << CFG_TEMP_LIMIT_HARD_COLD_SHIFT); | ||
522 | if (ret < 0) | ||
523 | return ret; | ||
546 | 524 | ||
547 | enable_therm_monitor = true; | 525 | enable_therm_monitor = true; |
548 | } | 526 | } |
@@ -553,16 +531,15 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) | |||
553 | val = clamp_val(val, 50, 65) - 50; | 531 | val = clamp_val(val, 50, 65) - 50; |
554 | val /= 5; | 532 | val /= 5; |
555 | 533 | ||
556 | ret &= ~CFG_TEMP_LIMIT_HARD_HOT_MASK; | 534 | ret = regmap_update_bits(smb->regmap, CFG_TEMP_LIMIT, |
557 | ret |= val << CFG_TEMP_LIMIT_HARD_HOT_SHIFT; | 535 | CFG_TEMP_LIMIT_HARD_HOT_MASK, |
536 | val << CFG_TEMP_LIMIT_HARD_HOT_SHIFT); | ||
537 | if (ret < 0) | ||
538 | return ret; | ||
558 | 539 | ||
559 | enable_therm_monitor = true; | 540 | enable_therm_monitor = true; |
560 | } | 541 | } |
561 | 542 | ||
562 | ret = smb347_write(smb, CFG_TEMP_LIMIT, ret); | ||
563 | if (ret < 0) | ||
564 | return ret; | ||
565 | |||
566 | /* | 543 | /* |
567 | * If any of the temperature limits are set, we also enable the | 544 | * If any of the temperature limits are set, we also enable the |
568 | * thermistor monitoring. | 545 | * thermistor monitoring. |
@@ -574,25 +551,15 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) | |||
574 | * depending on the configuration. | 551 | * depending on the configuration. |
575 | */ | 552 | */ |
576 | if (enable_therm_monitor) { | 553 | if (enable_therm_monitor) { |
577 | ret = smb347_read(smb, CFG_THERM); | 554 | ret = regmap_update_bits(smb->regmap, CFG_THERM, |
578 | if (ret < 0) | 555 | CFG_THERM_MONITOR_DISABLED, 0); |
579 | return ret; | ||
580 | |||
581 | ret &= ~CFG_THERM_MONITOR_DISABLED; | ||
582 | |||
583 | ret = smb347_write(smb, CFG_THERM, ret); | ||
584 | if (ret < 0) | 556 | if (ret < 0) |
585 | return ret; | 557 | return ret; |
586 | } | 558 | } |
587 | 559 | ||
588 | if (smb->pdata->suspend_on_hard_temp_limit) { | 560 | if (smb->pdata->suspend_on_hard_temp_limit) { |
589 | ret = smb347_read(smb, CFG_SYSOK); | 561 | ret = regmap_update_bits(smb->regmap, CFG_SYSOK, |
590 | if (ret < 0) | 562 | CFG_SYSOK_SUSPEND_HARD_LIMIT_DISABLED, 0); |
591 | return ret; | ||
592 | |||
593 | ret &= ~CFG_SYSOK_SUSPEND_HARD_LIMIT_DISABLED; | ||
594 | |||
595 | ret = smb347_write(smb, CFG_SYSOK, ret); | ||
596 | if (ret < 0) | 563 | if (ret < 0) |
597 | return ret; | 564 | return ret; |
598 | } | 565 | } |
@@ -601,17 +568,15 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) | |||
601 | SMB347_SOFT_TEMP_COMPENSATE_DEFAULT) { | 568 | SMB347_SOFT_TEMP_COMPENSATE_DEFAULT) { |
602 | val = smb->pdata->soft_temp_limit_compensation & 0x3; | 569 | val = smb->pdata->soft_temp_limit_compensation & 0x3; |
603 | 570 | ||
604 | ret = smb347_read(smb, CFG_THERM); | 571 | ret = regmap_update_bits(smb->regmap, CFG_THERM, |
572 | CFG_THERM_SOFT_HOT_COMPENSATION_MASK, | ||
573 | val << CFG_THERM_SOFT_HOT_COMPENSATION_SHIFT); | ||
605 | if (ret < 0) | 574 | if (ret < 0) |
606 | return ret; | 575 | return ret; |
607 | 576 | ||
608 | ret &= ~CFG_THERM_SOFT_HOT_COMPENSATION_MASK; | 577 | ret = regmap_update_bits(smb->regmap, CFG_THERM, |
609 | ret |= val << CFG_THERM_SOFT_HOT_COMPENSATION_SHIFT; | 578 | CFG_THERM_SOFT_COLD_COMPENSATION_MASK, |
610 | 579 | val << CFG_THERM_SOFT_COLD_COMPENSATION_SHIFT); | |
611 | ret &= ~CFG_THERM_SOFT_COLD_COMPENSATION_MASK; | ||
612 | ret |= val << CFG_THERM_SOFT_COLD_COMPENSATION_SHIFT; | ||
613 | |||
614 | ret = smb347_write(smb, CFG_THERM, ret); | ||
615 | if (ret < 0) | 580 | if (ret < 0) |
616 | return ret; | 581 | return ret; |
617 | } | 582 | } |
@@ -622,14 +587,9 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) | |||
622 | if (val < 0) | 587 | if (val < 0) |
623 | return val; | 588 | return val; |
624 | 589 | ||
625 | ret = smb347_read(smb, CFG_OTG); | 590 | ret = regmap_update_bits(smb->regmap, CFG_OTG, |
626 | if (ret < 0) | 591 | CFG_OTG_CC_COMPENSATION_MASK, |
627 | return ret; | 592 | (val & 0x3) << CFG_OTG_CC_COMPENSATION_SHIFT); |
628 | |||
629 | ret &= ~CFG_OTG_CC_COMPENSATION_MASK; | ||
630 | ret |= (val & 0x3) << CFG_OTG_CC_COMPENSATION_SHIFT; | ||
631 | |||
632 | ret = smb347_write(smb, CFG_OTG, ret); | ||
633 | if (ret < 0) | 593 | if (ret < 0) |
634 | return ret; | 594 | return ret; |
635 | } | 595 | } |
@@ -648,22 +608,13 @@ static int smb347_set_temp_limits(struct smb347_charger *smb) | |||
648 | */ | 608 | */ |
649 | static int smb347_set_writable(struct smb347_charger *smb, bool writable) | 609 | static int smb347_set_writable(struct smb347_charger *smb, bool writable) |
650 | { | 610 | { |
651 | int ret; | 611 | return regmap_update_bits(smb->regmap, CMD_A, CMD_A_ALLOW_WRITE, |
652 | 612 | writable ? CMD_A_ALLOW_WRITE : 0); | |
653 | ret = smb347_read(smb, CMD_A); | ||
654 | if (ret < 0) | ||
655 | return ret; | ||
656 | |||
657 | if (writable) | ||
658 | ret |= CMD_A_ALLOW_WRITE; | ||
659 | else | ||
660 | ret &= ~CMD_A_ALLOW_WRITE; | ||
661 | |||
662 | return smb347_write(smb, CMD_A, ret); | ||
663 | } | 613 | } |
664 | 614 | ||
665 | static int smb347_hw_init(struct smb347_charger *smb) | 615 | static int smb347_hw_init(struct smb347_charger *smb) |
666 | { | 616 | { |
617 | unsigned int val; | ||
667 | int ret; | 618 | int ret; |
668 | 619 | ||
669 | ret = smb347_set_writable(smb, true); | 620 | ret = smb347_set_writable(smb, true); |
@@ -692,34 +643,19 @@ static int smb347_hw_init(struct smb347_charger *smb) | |||
692 | 643 | ||
693 | /* If USB charging is disabled we put the USB in suspend mode */ | 644 | /* If USB charging is disabled we put the USB in suspend mode */ |
694 | if (!smb->pdata->use_usb) { | 645 | if (!smb->pdata->use_usb) { |
695 | ret = smb347_read(smb, CMD_A); | 646 | ret = regmap_update_bits(smb->regmap, CMD_A, |
696 | if (ret < 0) | 647 | CMD_A_SUSPEND_ENABLED, |
697 | goto fail; | 648 | CMD_A_SUSPEND_ENABLED); |
698 | |||
699 | ret |= CMD_A_SUSPEND_ENABLED; | ||
700 | |||
701 | ret = smb347_write(smb, CMD_A, ret); | ||
702 | if (ret < 0) | 649 | if (ret < 0) |
703 | goto fail; | 650 | goto fail; |
704 | } | 651 | } |
705 | 652 | ||
706 | ret = smb347_read(smb, CFG_OTHER); | ||
707 | if (ret < 0) | ||
708 | goto fail; | ||
709 | |||
710 | /* | 653 | /* |
711 | * If configured by platform data, we enable hardware Auto-OTG | 654 | * If configured by platform data, we enable hardware Auto-OTG |
712 | * support for driving VBUS. Otherwise we disable it. | 655 | * support for driving VBUS. Otherwise we disable it. |
713 | */ | 656 | */ |
714 | ret &= ~CFG_OTHER_RID_MASK; | 657 | ret = regmap_update_bits(smb->regmap, CFG_OTHER, CFG_OTHER_RID_MASK, |
715 | if (smb->pdata->use_usb_otg) | 658 | smb->pdata->use_usb_otg ? CFG_OTHER_RID_ENABLED_AUTO_OTG : 0); |
716 | ret |= CFG_OTHER_RID_ENABLED_AUTO_OTG; | ||
717 | |||
718 | ret = smb347_write(smb, CFG_OTHER, ret); | ||
719 | if (ret < 0) | ||
720 | goto fail; | ||
721 | |||
722 | ret = smb347_read(smb, CFG_PIN); | ||
723 | if (ret < 0) | 659 | if (ret < 0) |
724 | goto fail; | 660 | goto fail; |
725 | 661 | ||
@@ -728,24 +664,25 @@ static int smb347_hw_init(struct smb347_charger *smb) | |||
728 | * command register unless pin control is specified in the platform | 664 | * command register unless pin control is specified in the platform |
729 | * data. | 665 | * data. |
730 | */ | 666 | */ |
731 | ret &= ~CFG_PIN_EN_CTRL_MASK; | ||
732 | |||
733 | switch (smb->pdata->enable_control) { | 667 | switch (smb->pdata->enable_control) { |
734 | case SMB347_CHG_ENABLE_SW: | ||
735 | /* Do nothing, 0 means i2c control */ | ||
736 | break; | ||
737 | case SMB347_CHG_ENABLE_PIN_ACTIVE_LOW: | 668 | case SMB347_CHG_ENABLE_PIN_ACTIVE_LOW: |
738 | ret |= CFG_PIN_EN_CTRL_ACTIVE_LOW; | 669 | val = CFG_PIN_EN_CTRL_ACTIVE_LOW; |
739 | break; | 670 | break; |
740 | case SMB347_CHG_ENABLE_PIN_ACTIVE_HIGH: | 671 | case SMB347_CHG_ENABLE_PIN_ACTIVE_HIGH: |
741 | ret |= CFG_PIN_EN_CTRL_ACTIVE_HIGH; | 672 | val = CFG_PIN_EN_CTRL_ACTIVE_HIGH; |
673 | break; | ||
674 | default: | ||
675 | val = 0; | ||
742 | break; | 676 | break; |
743 | } | 677 | } |
744 | 678 | ||
745 | /* Disable Automatic Power Source Detection (APSD) interrupt. */ | 679 | ret = regmap_update_bits(smb->regmap, CFG_PIN, CFG_PIN_EN_CTRL_MASK, |
746 | ret &= ~CFG_PIN_EN_APSD_IRQ; | 680 | val); |
681 | if (ret < 0) | ||
682 | goto fail; | ||
747 | 683 | ||
748 | ret = smb347_write(smb, CFG_PIN, ret); | 684 | /* Disable Automatic Power Source Detection (APSD) interrupt. */ |
685 | ret = regmap_update_bits(smb->regmap, CFG_PIN, CFG_PIN_EN_APSD_IRQ, 0); | ||
749 | if (ret < 0) | 686 | if (ret < 0) |
750 | goto fail; | 687 | goto fail; |
751 | 688 | ||
@@ -763,24 +700,25 @@ fail: | |||
763 | static irqreturn_t smb347_interrupt(int irq, void *data) | 700 | static irqreturn_t smb347_interrupt(int irq, void *data) |
764 | { | 701 | { |
765 | struct smb347_charger *smb = data; | 702 | struct smb347_charger *smb = data; |
766 | int stat_c, irqstat_e, irqstat_c; | 703 | unsigned int stat_c, irqstat_e, irqstat_c; |
767 | irqreturn_t ret = IRQ_NONE; | 704 | bool handled = false; |
705 | int ret; | ||
768 | 706 | ||
769 | stat_c = smb347_read(smb, STAT_C); | 707 | ret = regmap_read(smb->regmap, STAT_C, &stat_c); |
770 | if (stat_c < 0) { | 708 | if (ret < 0) { |
771 | dev_warn(&smb->client->dev, "reading STAT_C failed\n"); | 709 | dev_warn(smb->dev, "reading STAT_C failed\n"); |
772 | return IRQ_NONE; | 710 | return IRQ_NONE; |
773 | } | 711 | } |
774 | 712 | ||
775 | irqstat_c = smb347_read(smb, IRQSTAT_C); | 713 | ret = regmap_read(smb->regmap, IRQSTAT_C, &irqstat_c); |
776 | if (irqstat_c < 0) { | 714 | if (ret < 0) { |
777 | dev_warn(&smb->client->dev, "reading IRQSTAT_C failed\n"); | 715 | dev_warn(smb->dev, "reading IRQSTAT_C failed\n"); |
778 | return IRQ_NONE; | 716 | return IRQ_NONE; |
779 | } | 717 | } |
780 | 718 | ||
781 | irqstat_e = smb347_read(smb, IRQSTAT_E); | 719 | ret = regmap_read(smb->regmap, IRQSTAT_E, &irqstat_e); |
782 | if (irqstat_e < 0) { | 720 | if (ret < 0) { |
783 | dev_warn(&smb->client->dev, "reading IRQSTAT_E failed\n"); | 721 | dev_warn(smb->dev, "reading IRQSTAT_E failed\n"); |
784 | return IRQ_NONE; | 722 | return IRQ_NONE; |
785 | } | 723 | } |
786 | 724 | ||
@@ -789,13 +727,11 @@ static irqreturn_t smb347_interrupt(int irq, void *data) | |||
789 | * disable charging. | 727 | * disable charging. |
790 | */ | 728 | */ |
791 | if (stat_c & STAT_C_CHARGER_ERROR) { | 729 | if (stat_c & STAT_C_CHARGER_ERROR) { |
792 | dev_err(&smb->client->dev, | 730 | dev_err(smb->dev, "error in charger, disabling charging\n"); |
793 | "error in charger, disabling charging\n"); | ||
794 | 731 | ||
795 | smb347_charging_disable(smb); | 732 | smb347_charging_disable(smb); |
796 | power_supply_changed(&smb->battery); | 733 | power_supply_changed(&smb->battery); |
797 | 734 | handled = true; | |
798 | ret = IRQ_HANDLED; | ||
799 | } | 735 | } |
800 | 736 | ||
801 | /* | 737 | /* |
@@ -806,7 +742,7 @@ static irqreturn_t smb347_interrupt(int irq, void *data) | |||
806 | if (irqstat_c & (IRQSTAT_C_TERMINATION_IRQ | IRQSTAT_C_TAPER_IRQ)) { | 742 | if (irqstat_c & (IRQSTAT_C_TERMINATION_IRQ | IRQSTAT_C_TAPER_IRQ)) { |
807 | if (irqstat_c & IRQSTAT_C_TERMINATION_STAT) | 743 | if (irqstat_c & IRQSTAT_C_TERMINATION_STAT) |
808 | power_supply_changed(&smb->battery); | 744 | power_supply_changed(&smb->battery); |
809 | ret = IRQ_HANDLED; | 745 | handled = true; |
810 | } | 746 | } |
811 | 747 | ||
812 | /* | 748 | /* |
@@ -821,10 +757,10 @@ static irqreturn_t smb347_interrupt(int irq, void *data) | |||
821 | if (smb->pdata->use_usb) | 757 | if (smb->pdata->use_usb) |
822 | power_supply_changed(&smb->usb); | 758 | power_supply_changed(&smb->usb); |
823 | } | 759 | } |
824 | ret = IRQ_HANDLED; | 760 | handled = true; |
825 | } | 761 | } |
826 | 762 | ||
827 | return ret; | 763 | return handled ? IRQ_HANDLED : IRQ_NONE; |
828 | } | 764 | } |
829 | 765 | ||
830 | static int smb347_irq_set(struct smb347_charger *smb, bool enable) | 766 | static int smb347_irq_set(struct smb347_charger *smb, bool enable) |
@@ -841,41 +777,18 @@ static int smb347_irq_set(struct smb347_charger *smb, bool enable) | |||
841 | * - termination current reached | 777 | * - termination current reached |
842 | * - charger error | 778 | * - charger error |
843 | */ | 779 | */ |
844 | if (enable) { | 780 | ret = regmap_update_bits(smb->regmap, CFG_FAULT_IRQ, 0xff, |
845 | ret = smb347_write(smb, CFG_FAULT_IRQ, CFG_FAULT_IRQ_DCIN_UV); | 781 | enable ? CFG_FAULT_IRQ_DCIN_UV : 0); |
846 | if (ret < 0) | 782 | if (ret < 0) |
847 | goto fail; | 783 | goto fail; |
848 | |||
849 | ret = smb347_write(smb, CFG_STATUS_IRQ, | ||
850 | CFG_STATUS_IRQ_TERMINATION_OR_TAPER); | ||
851 | if (ret < 0) | ||
852 | goto fail; | ||
853 | |||
854 | ret = smb347_read(smb, CFG_PIN); | ||
855 | if (ret < 0) | ||
856 | goto fail; | ||
857 | |||
858 | ret |= CFG_PIN_EN_CHARGER_ERROR; | ||
859 | |||
860 | ret = smb347_write(smb, CFG_PIN, ret); | ||
861 | } else { | ||
862 | ret = smb347_write(smb, CFG_FAULT_IRQ, 0); | ||
863 | if (ret < 0) | ||
864 | goto fail; | ||
865 | |||
866 | ret = smb347_write(smb, CFG_STATUS_IRQ, 0); | ||
867 | if (ret < 0) | ||
868 | goto fail; | ||
869 | |||
870 | ret = smb347_read(smb, CFG_PIN); | ||
871 | if (ret < 0) | ||
872 | goto fail; | ||
873 | |||
874 | ret &= ~CFG_PIN_EN_CHARGER_ERROR; | ||
875 | 784 | ||
876 | ret = smb347_write(smb, CFG_PIN, ret); | 785 | ret = regmap_update_bits(smb->regmap, CFG_STATUS_IRQ, 0xff, |
877 | } | 786 | enable ? CFG_STATUS_IRQ_TERMINATION_OR_TAPER : 0); |
787 | if (ret < 0) | ||
788 | goto fail; | ||
878 | 789 | ||
790 | ret = regmap_update_bits(smb->regmap, CFG_PIN, CFG_PIN_EN_CHARGER_ERROR, | ||
791 | enable ? CFG_PIN_EN_CHARGER_ERROR : 0); | ||
879 | fail: | 792 | fail: |
880 | smb347_set_writable(smb, false); | 793 | smb347_set_writable(smb, false); |
881 | return ret; | 794 | return ret; |
@@ -891,18 +804,18 @@ static inline int smb347_irq_disable(struct smb347_charger *smb) | |||
891 | return smb347_irq_set(smb, false); | 804 | return smb347_irq_set(smb, false); |
892 | } | 805 | } |
893 | 806 | ||
894 | static int smb347_irq_init(struct smb347_charger *smb) | 807 | static int smb347_irq_init(struct smb347_charger *smb, |
808 | struct i2c_client *client) | ||
895 | { | 809 | { |
896 | const struct smb347_charger_platform_data *pdata = smb->pdata; | 810 | const struct smb347_charger_platform_data *pdata = smb->pdata; |
897 | int ret, irq = gpio_to_irq(pdata->irq_gpio); | 811 | int ret, irq = gpio_to_irq(pdata->irq_gpio); |
898 | 812 | ||
899 | ret = gpio_request_one(pdata->irq_gpio, GPIOF_IN, smb->client->name); | 813 | ret = gpio_request_one(pdata->irq_gpio, GPIOF_IN, client->name); |
900 | if (ret < 0) | 814 | if (ret < 0) |
901 | goto fail; | 815 | goto fail; |
902 | 816 | ||
903 | ret = request_threaded_irq(irq, NULL, smb347_interrupt, | 817 | ret = request_threaded_irq(irq, NULL, smb347_interrupt, |
904 | IRQF_TRIGGER_FALLING, smb->client->name, | 818 | IRQF_TRIGGER_FALLING, client->name, smb); |
905 | smb); | ||
906 | if (ret < 0) | 819 | if (ret < 0) |
907 | goto fail_gpio; | 820 | goto fail_gpio; |
908 | 821 | ||
@@ -914,19 +827,14 @@ static int smb347_irq_init(struct smb347_charger *smb) | |||
914 | * Configure the STAT output to be suitable for interrupts: disable | 827 | * Configure the STAT output to be suitable for interrupts: disable |
915 | * all other output (except interrupts) and make it active low. | 828 | * all other output (except interrupts) and make it active low. |
916 | */ | 829 | */ |
917 | ret = smb347_read(smb, CFG_STAT); | 830 | ret = regmap_update_bits(smb->regmap, CFG_STAT, |
918 | if (ret < 0) | 831 | CFG_STAT_ACTIVE_HIGH | CFG_STAT_DISABLED, |
919 | goto fail_readonly; | 832 | CFG_STAT_DISABLED); |
920 | |||
921 | ret &= ~CFG_STAT_ACTIVE_HIGH; | ||
922 | ret |= CFG_STAT_DISABLED; | ||
923 | |||
924 | ret = smb347_write(smb, CFG_STAT, ret); | ||
925 | if (ret < 0) | 833 | if (ret < 0) |
926 | goto fail_readonly; | 834 | goto fail_readonly; |
927 | 835 | ||
928 | smb347_set_writable(smb, false); | 836 | smb347_set_writable(smb, false); |
929 | smb->client->irq = irq; | 837 | client->irq = irq; |
930 | return 0; | 838 | return 0; |
931 | 839 | ||
932 | fail_readonly: | 840 | fail_readonly: |
@@ -936,7 +844,7 @@ fail_irq: | |||
936 | fail_gpio: | 844 | fail_gpio: |
937 | gpio_free(pdata->irq_gpio); | 845 | gpio_free(pdata->irq_gpio); |
938 | fail: | 846 | fail: |
939 | smb->client->irq = 0; | 847 | client->irq = 0; |
940 | return ret; | 848 | return ret; |
941 | } | 849 | } |
942 | 850 | ||
@@ -983,6 +891,7 @@ static int smb347_battery_get_property(struct power_supply *psy, | |||
983 | struct smb347_charger *smb = | 891 | struct smb347_charger *smb = |
984 | container_of(psy, struct smb347_charger, battery); | 892 | container_of(psy, struct smb347_charger, battery); |
985 | const struct smb347_charger_platform_data *pdata = smb->pdata; | 893 | const struct smb347_charger_platform_data *pdata = smb->pdata; |
894 | unsigned int v; | ||
986 | int ret; | 895 | int ret; |
987 | 896 | ||
988 | ret = smb347_update_ps_status(smb); | 897 | ret = smb347_update_ps_status(smb); |
@@ -1037,22 +946,22 @@ static int smb347_battery_get_property(struct power_supply *psy, | |||
1037 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: | 946 | case POWER_SUPPLY_PROP_VOLTAGE_NOW: |
1038 | if (!smb347_is_ps_online(smb)) | 947 | if (!smb347_is_ps_online(smb)) |
1039 | return -ENODATA; | 948 | return -ENODATA; |
1040 | ret = smb347_read(smb, STAT_A); | 949 | ret = regmap_read(smb->regmap, STAT_A, &v); |
1041 | if (ret < 0) | 950 | if (ret < 0) |
1042 | return ret; | 951 | return ret; |
1043 | 952 | ||
1044 | ret &= STAT_A_FLOAT_VOLTAGE_MASK; | 953 | v &= STAT_A_FLOAT_VOLTAGE_MASK; |
1045 | if (ret > 0x3d) | 954 | if (v > 0x3d) |
1046 | ret = 0x3d; | 955 | v = 0x3d; |
1047 | 956 | ||
1048 | val->intval = 3500000 + ret * 20000; | 957 | val->intval = 3500000 + v * 20000; |
1049 | break; | 958 | break; |
1050 | 959 | ||
1051 | case POWER_SUPPLY_PROP_CURRENT_NOW: | 960 | case POWER_SUPPLY_PROP_CURRENT_NOW: |
1052 | if (!smb347_is_ps_online(smb)) | 961 | if (!smb347_is_ps_online(smb)) |
1053 | return -ENODATA; | 962 | return -ENODATA; |
1054 | 963 | ||
1055 | ret = smb347_read(smb, STAT_B); | 964 | ret = regmap_read(smb->regmap, STAT_B, &v); |
1056 | if (ret < 0) | 965 | if (ret < 0) |
1057 | return ret; | 966 | return ret; |
1058 | 967 | ||
@@ -1060,15 +969,15 @@ static int smb347_battery_get_property(struct power_supply *psy, | |||
1060 | * The current value is composition of FCC and PCC values | 969 | * The current value is composition of FCC and PCC values |
1061 | * and we can detect which table to use from bit 5. | 970 | * and we can detect which table to use from bit 5. |
1062 | */ | 971 | */ |
1063 | if (ret & 0x20) { | 972 | if (v & 0x20) { |
1064 | val->intval = hw_to_current(fcc_tbl, | 973 | val->intval = hw_to_current(fcc_tbl, |
1065 | ARRAY_SIZE(fcc_tbl), | 974 | ARRAY_SIZE(fcc_tbl), |
1066 | ret & 7); | 975 | v & 7); |
1067 | } else { | 976 | } else { |
1068 | ret >>= 3; | 977 | v >>= 3; |
1069 | val->intval = hw_to_current(pcc_tbl, | 978 | val->intval = hw_to_current(pcc_tbl, |
1070 | ARRAY_SIZE(pcc_tbl), | 979 | ARRAY_SIZE(pcc_tbl), |
1071 | ret & 7); | 980 | v & 7); |
1072 | } | 981 | } |
1073 | break; | 982 | break; |
1074 | 983 | ||
@@ -1099,58 +1008,54 @@ static enum power_supply_property smb347_battery_properties[] = { | |||
1099 | POWER_SUPPLY_PROP_MODEL_NAME, | 1008 | POWER_SUPPLY_PROP_MODEL_NAME, |
1100 | }; | 1009 | }; |
1101 | 1010 | ||
1102 | static int smb347_debugfs_show(struct seq_file *s, void *data) | 1011 | static bool smb347_volatile_reg(struct device *dev, unsigned int reg) |
1103 | { | 1012 | { |
1104 | struct smb347_charger *smb = s->private; | 1013 | switch (reg) { |
1105 | int ret; | 1014 | case IRQSTAT_A: |
1106 | u8 reg; | 1015 | case IRQSTAT_C: |
1107 | 1016 | case IRQSTAT_E: | |
1108 | seq_printf(s, "Control registers:\n"); | 1017 | case IRQSTAT_F: |
1109 | seq_printf(s, "==================\n"); | 1018 | case STAT_A: |
1110 | for (reg = CFG_CHARGE_CURRENT; reg <= CFG_ADDRESS; reg++) { | 1019 | case STAT_B: |
1111 | ret = smb347_read(smb, reg); | 1020 | case STAT_C: |
1112 | seq_printf(s, "0x%02x:\t0x%02x\n", reg, ret); | 1021 | case STAT_E: |
1113 | } | 1022 | return true; |
1114 | seq_printf(s, "\n"); | ||
1115 | |||
1116 | seq_printf(s, "Command registers:\n"); | ||
1117 | seq_printf(s, "==================\n"); | ||
1118 | ret = smb347_read(smb, CMD_A); | ||
1119 | seq_printf(s, "0x%02x:\t0x%02x\n", CMD_A, ret); | ||
1120 | ret = smb347_read(smb, CMD_B); | ||
1121 | seq_printf(s, "0x%02x:\t0x%02x\n", CMD_B, ret); | ||
1122 | ret = smb347_read(smb, CMD_C); | ||
1123 | seq_printf(s, "0x%02x:\t0x%02x\n", CMD_C, ret); | ||
1124 | seq_printf(s, "\n"); | ||
1125 | |||
1126 | seq_printf(s, "Interrupt status registers:\n"); | ||
1127 | seq_printf(s, "===========================\n"); | ||
1128 | for (reg = IRQSTAT_A; reg <= IRQSTAT_F; reg++) { | ||
1129 | ret = smb347_read(smb, reg); | ||
1130 | seq_printf(s, "0x%02x:\t0x%02x\n", reg, ret); | ||
1131 | } | ||
1132 | seq_printf(s, "\n"); | ||
1133 | |||
1134 | seq_printf(s, "Status registers:\n"); | ||
1135 | seq_printf(s, "=================\n"); | ||
1136 | for (reg = STAT_A; reg <= STAT_E; reg++) { | ||
1137 | ret = smb347_read(smb, reg); | ||
1138 | seq_printf(s, "0x%02x:\t0x%02x\n", reg, ret); | ||
1139 | } | 1023 | } |
1140 | 1024 | ||
1141 | return 0; | 1025 | return false; |
1142 | } | 1026 | } |
1143 | 1027 | ||
1144 | static int smb347_debugfs_open(struct inode *inode, struct file *file) | 1028 | static bool smb347_readable_reg(struct device *dev, unsigned int reg) |
1145 | { | 1029 | { |
1146 | return single_open(file, smb347_debugfs_show, inode->i_private); | 1030 | switch (reg) { |
1031 | case CFG_CHARGE_CURRENT: | ||
1032 | case CFG_CURRENT_LIMIT: | ||
1033 | case CFG_FLOAT_VOLTAGE: | ||
1034 | case CFG_STAT: | ||
1035 | case CFG_PIN: | ||
1036 | case CFG_THERM: | ||
1037 | case CFG_SYSOK: | ||
1038 | case CFG_OTHER: | ||
1039 | case CFG_OTG: | ||
1040 | case CFG_TEMP_LIMIT: | ||
1041 | case CFG_FAULT_IRQ: | ||
1042 | case CFG_STATUS_IRQ: | ||
1043 | case CFG_ADDRESS: | ||
1044 | case CMD_A: | ||
1045 | case CMD_B: | ||
1046 | case CMD_C: | ||
1047 | return true; | ||
1048 | } | ||
1049 | |||
1050 | return smb347_volatile_reg(dev, reg); | ||
1147 | } | 1051 | } |
1148 | 1052 | ||
1149 | static const struct file_operations smb347_debugfs_fops = { | 1053 | static const struct regmap_config smb347_regmap = { |
1150 | .open = smb347_debugfs_open, | 1054 | .reg_bits = 8, |
1151 | .read = seq_read, | 1055 | .val_bits = 8, |
1152 | .llseek = seq_lseek, | 1056 | .max_register = SMB347_MAX_REGISTER, |
1153 | .release = single_release, | 1057 | .volatile_reg = smb347_volatile_reg, |
1058 | .readable_reg = smb347_readable_reg, | ||
1154 | }; | 1059 | }; |
1155 | 1060 | ||
1156 | static int smb347_probe(struct i2c_client *client, | 1061 | static int smb347_probe(struct i2c_client *client, |
@@ -1176,9 +1081,13 @@ static int smb347_probe(struct i2c_client *client, | |||
1176 | i2c_set_clientdata(client, smb); | 1081 | i2c_set_clientdata(client, smb); |
1177 | 1082 | ||
1178 | mutex_init(&smb->lock); | 1083 | mutex_init(&smb->lock); |
1179 | smb->client = client; | 1084 | smb->dev = &client->dev; |
1180 | smb->pdata = pdata; | 1085 | smb->pdata = pdata; |
1181 | 1086 | ||
1087 | smb->regmap = devm_regmap_init_i2c(client, &smb347_regmap); | ||
1088 | if (IS_ERR(smb->regmap)) | ||
1089 | return PTR_ERR(smb->regmap); | ||
1090 | |||
1182 | ret = smb347_hw_init(smb); | 1091 | ret = smb347_hw_init(smb); |
1183 | if (ret < 0) | 1092 | if (ret < 0) |
1184 | return ret; | 1093 | return ret; |
@@ -1233,7 +1142,7 @@ static int smb347_probe(struct i2c_client *client, | |||
1233 | * interrupt support here. | 1142 | * interrupt support here. |
1234 | */ | 1143 | */ |
1235 | if (pdata->irq_gpio >= 0) { | 1144 | if (pdata->irq_gpio >= 0) { |
1236 | ret = smb347_irq_init(smb); | 1145 | ret = smb347_irq_init(smb, client); |
1237 | if (ret < 0) { | 1146 | if (ret < 0) { |
1238 | dev_warn(dev, "failed to initialize IRQ: %d\n", ret); | 1147 | dev_warn(dev, "failed to initialize IRQ: %d\n", ret); |
1239 | dev_warn(dev, "disabling IRQ support\n"); | 1148 | dev_warn(dev, "disabling IRQ support\n"); |
@@ -1242,8 +1151,6 @@ static int smb347_probe(struct i2c_client *client, | |||
1242 | } | 1151 | } |
1243 | } | 1152 | } |
1244 | 1153 | ||
1245 | smb->dentry = debugfs_create_file("smb347-regs", S_IRUSR, NULL, smb, | ||
1246 | &smb347_debugfs_fops); | ||
1247 | return 0; | 1154 | return 0; |
1248 | } | 1155 | } |
1249 | 1156 | ||
@@ -1251,9 +1158,6 @@ static int smb347_remove(struct i2c_client *client) | |||
1251 | { | 1158 | { |
1252 | struct smb347_charger *smb = i2c_get_clientdata(client); | 1159 | struct smb347_charger *smb = i2c_get_clientdata(client); |
1253 | 1160 | ||
1254 | if (!IS_ERR_OR_NULL(smb->dentry)) | ||
1255 | debugfs_remove(smb->dentry); | ||
1256 | |||
1257 | if (client->irq) { | 1161 | if (client->irq) { |
1258 | smb347_irq_disable(smb); | 1162 | smb347_irq_disable(smb); |
1259 | free_irq(client->irq, smb); | 1163 | free_irq(client->irq, smb); |