1616 * more details.
1717 */
1818
19+ #include <linux/delay.h>
1920#include <linux/i2c.h>
2021#include <linux/interrupt.h>
2122#include <linux/kernel.h>
2425#include <linux/module.h>
2526#include <linux/of_device.h>
2627#include <linux/regmap.h>
28+ #include <linux/syscore_ops.h>
2729
2830struct rk808_reg_data {
2931 int addr ;
@@ -812,7 +814,7 @@ static void rk808_device_shutdown_prepare(void)
812814 }
813815}
814816
815- static void rk808_device_shutdown (void )
817+ static void rk808_syscore_shutdown (void )
816818{
817819 int ret ;
818820 struct rk808 * rk808 = i2c_get_clientdata (rk808_i2c_client );
@@ -830,13 +832,35 @@ static void rk808_device_shutdown(void)
830832 regmap_update_bits (rk808 -> regmap ,
831833 RK808_RTC_INT_REG ,
832834 (0x3 << 2 ), (0x0 << 2 ));
833- if (pm_shutdown ) {
834- ret = pm_shutdown (rk808 -> regmap );
835- if (ret )
836- dev_err (& rk808_i2c_client -> dev , "power off error!\n" );
835+ /*
836+ * For PMIC that power off supplies by write register via i2c bus,
837+ * it's better to do power off at syscore shutdown here.
838+ *
839+ * Because when run to kernel's "pm_power_off" call, i2c may has
840+ * been stopped or PMIC may not be able to get i2c transfer while
841+ * there are too many devices are competiting.
842+ */
843+ if (system_state == SYSTEM_POWER_OFF ) {
844+ /* power off supplies ! */
845+ if (pm_shutdown ) {
846+ dev_info (& rk808_i2c_client -> dev , "System power off\n" );
847+ ret = pm_shutdown (rk808 -> regmap );
848+ if (ret )
849+ dev_err (& rk808_i2c_client -> dev ,
850+ "System power off error!\n" );
851+ mdelay (10 );
852+ dev_info (& rk808_i2c_client -> dev ,
853+ "Cpu should never reach here, stop!\n" );
854+ while (1 )
855+ ;
856+ }
837857 }
838858}
839859
860+ static struct syscore_ops rk808_syscore_ops = {
861+ .shutdown = rk808_syscore_shutdown ,
862+ };
863+
840864static ssize_t rk8xx_dbg_store (struct device * dev ,
841865 struct device_attribute * attr ,
842866 const char * buf , size_t count )
@@ -1104,7 +1128,7 @@ static int rk808_probe(struct i2c_client *client,
11041128 }
11051129 if (pm_shutdown_fn ) {
11061130 pm_shutdown = pm_shutdown_fn ;
1107- pm_power_off = rk808_device_shutdown ;
1131+ register_syscore_ops ( & rk808_syscore_ops ) ;
11081132 }
11091133 }
11101134
@@ -1170,10 +1194,11 @@ static int rk808_remove(struct i2c_client *client)
11701194
11711195 regmap_del_irq_chip (client -> irq , rk808 -> irq_data );
11721196 mfd_remove_devices (& client -> dev );
1173- if (pm_power_off == rk808_device_shutdown )
1174- pm_power_off = NULL ;
1197+
11751198 if (pm_power_off_prepare == rk808_device_shutdown_prepare )
11761199 pm_power_off_prepare = NULL ;
1200+ if (pm_shutdown )
1201+ unregister_syscore_ops (& rk808_syscore_ops );
11771202
11781203 return 0 ;
11791204}
0 commit comments