Commit ac195d94280a783f030a01ee84998a198b779d99

Authored by Stefan Mavrodiev
Committed by Lee Jones
1 parent 7630499464

mfd: rk808: Prepare rk805 for poweroff

RK805 has SLEEP signal, which can put the device into SLEEP or OFF
mode. The default is SLEEP mode.

However, when the kernel performs power-off (actually the ATF) the
device will not go fully off and this will result in higher power
consumption and inability to wake the device with RTC alarm.

The solution is to enable pm_power_off_prepare function, which will
configure SLEEP pin for OFF function.

Signed-off-by: Stefan Mavrodiev <stefan@olimex.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>

Showing 2 changed files with 36 additions and 15 deletions Side-by-side Diff

... ... @@ -474,35 +474,44 @@
474 474 int ret;
475 475 struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
476 476  
477   - if (!rk808) {
478   - dev_warn(&rk808_i2c_client->dev,
479   - "have no rk805, so do nothing here\n");
  477 + if (!rk808)
480 478 return;
481   - }
482 479  
483 480 ret = regmap_update_bits(rk808->regmap,
484 481 RK805_DEV_CTRL_REG,
485 482 DEV_OFF, DEV_OFF);
486 483 if (ret)
487   - dev_err(&rk808_i2c_client->dev, "power off error!\n");
  484 + dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n");
488 485 }
489 486  
  487 +static void rk805_device_shutdown_prepare(void)
  488 +{
  489 + int ret;
  490 + struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
  491 +
  492 + if (!rk808)
  493 + return;
  494 +
  495 + ret = regmap_update_bits(rk808->regmap,
  496 + RK805_GPIO_IO_POL_REG,
  497 + SLP_SD_MSK, SHUTDOWN_FUN);
  498 + if (ret)
  499 + dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n");
  500 +}
  501 +
490 502 static void rk808_device_shutdown(void)
491 503 {
492 504 int ret;
493 505 struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
494 506  
495   - if (!rk808) {
496   - dev_warn(&rk808_i2c_client->dev,
497   - "have no rk808, so do nothing here\n");
  507 + if (!rk808)
498 508 return;
499   - }
500 509  
501 510 ret = regmap_update_bits(rk808->regmap,
502 511 RK808_DEVCTRL_REG,
503 512 DEV_OFF_RST, DEV_OFF_RST);
504 513 if (ret)
505   - dev_err(&rk808_i2c_client->dev, "power off error!\n");
  514 + dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n");
506 515 }
507 516  
508 517 static void rk818_device_shutdown(void)
509 518  
510 519  
... ... @@ -510,17 +519,14 @@
510 519 int ret;
511 520 struct rk808 *rk808 = i2c_get_clientdata(rk808_i2c_client);
512 521  
513   - if (!rk808) {
514   - dev_warn(&rk808_i2c_client->dev,
515   - "have no rk818, so do nothing here\n");
  522 + if (!rk808)
516 523 return;
517   - }
518 524  
519 525 ret = regmap_update_bits(rk808->regmap,
520 526 RK818_DEVCTRL_REG,
521 527 DEV_OFF, DEV_OFF);
522 528 if (ret)
523   - dev_err(&rk808_i2c_client->dev, "power off error!\n");
  529 + dev_err(&rk808_i2c_client->dev, "Failed to shutdown device!\n");
524 530 }
525 531  
526 532 static void rk8xx_syscore_shutdown(void)
... ... @@ -609,6 +615,7 @@
609 615 cells = rk805s;
610 616 nr_cells = ARRAY_SIZE(rk805s);
611 617 rk808->pm_pwroff_fn = rk805_device_shutdown;
  618 + rk808->pm_pwroff_prep_fn = rk805_device_shutdown_prepare;
612 619 break;
613 620 case RK808_ID:
614 621 rk808->regmap_cfg = &rk808_regmap_config;
... ... @@ -694,6 +701,12 @@
694 701 pm_power_off = rk808->pm_pwroff_fn;
695 702 }
696 703  
  704 + if (pm_off && !pm_power_off_prepare) {
  705 + if (!rk808_i2c_client)
  706 + rk808_i2c_client = client;
  707 + pm_power_off_prepare = rk808->pm_pwroff_prep_fn;
  708 + }
  709 +
697 710 return 0;
698 711  
699 712 err_irq:
... ... @@ -713,6 +726,13 @@
713 726 */
714 727 if (rk808->pm_pwroff_fn && pm_power_off == rk808->pm_pwroff_fn)
715 728 pm_power_off = NULL;
  729 +
  730 + /**
  731 + * As above, check if the pointer is set by us before overwrite.
  732 + */
  733 + if (rk808->pm_pwroff_prep_fn &&
  734 + pm_power_off_prepare == rk808->pm_pwroff_prep_fn)
  735 + pm_power_off_prepare = NULL;
716 736  
717 737 return 0;
718 738 }
include/linux/mfd/rk808.h
... ... @@ -629,6 +629,7 @@
629 629 const struct regmap_config *regmap_cfg;
630 630 const struct regmap_irq_chip *regmap_irq_chip;
631 631 void (*pm_pwroff_fn)(void);
  632 + void (*pm_pwroff_prep_fn)(void);
632 633 };
633 634 #endif /* __LINUX_REGULATOR_RK808_H */