diff --git a/drivers/power/pmic/pmic_tps65218.c b/drivers/power/pmic/pmic_tps65218.c index dbc7a73a72..0fd0ad478a 100644 --- a/drivers/power/pmic/pmic_tps65218.c +++ b/drivers/power/pmic/pmic_tps65218.c @@ -11,6 +11,20 @@ #include #include +int tps65218_reg_read(uchar dest_reg, uchar *dest_val) +{ + uchar read_val; + int ret; + + ret = i2c_read(TPS65218_CHIP_PM, dest_reg, 1, &read_val, 1); + if (ret) + return ret; + + *dest_val = read_val; + + return 0; +} + /** * tps65218_reg_write() - Generic function that can write a TPS65218 PMIC * register or bit field regardless of protection @@ -98,6 +112,48 @@ int tps65218_voltage_update(uchar dc_cntrl_reg, uchar volt_sel) return 0; } +/** + * tps65218_toggle_fseal() - Perform the sequence that toggles the FSEAL bit. + * + * @return: 0 on success, -EBADE if the sequence was broken + */ +int tps65218_toggle_fseal(void) +{ + if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD, + 0xb1, TPS65218_MASK_ALL_BITS)) + return -EBADE; + + if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD, + 0xfe, TPS65218_MASK_ALL_BITS)) + return -EBADE; + + if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD, + 0xa3, TPS65218_MASK_ALL_BITS)) + return -EBADE; + + return 0; +} + +/** + * tps65218_lock_fseal() - Perform the sequence that locks the FSEAL bit to 1. + * + * The FSEAL bit prevents the PMIC from turning off DCDC5 and DCDC6. It can be + * toggled at most 3 times: 0->1, 1->0, and finally 0->1. After the third switch + * its value is locked and can only be reset by powering off the PMIC entirely. + * + * @return: 0 on success, -EBADE if the sequence was broken + */ +int tps65218_lock_fseal(void) +{ + int i; + + for (i = 0; i < 3; i++) + if (tps65218_toggle_fseal()) + return -EBADE; + + return 0; +} + int power_tps65218_init(unsigned char bus) { static const char name[] = "TPS65218_PMIC"; diff --git a/include/power/tps65218.h b/include/power/tps65218.h index 63fc7b343f..4d68faacaf 100644 --- a/include/power/tps65218.h +++ b/include/power/tps65218.h @@ -8,6 +8,8 @@ #ifndef __POWER_TPS65218_H__ #define __POWER_TPS65218_H__ +#include + /* I2C chip address */ #define TPS65218_CHIP_PM 0x24 @@ -60,8 +62,18 @@ enum { #define TPS65218_DCDC_VOLT_SEL_1260MV 0x29 #define TPS65218_DCDC_VOLT_SEL_1330MV 0x30 +#define TPS65218_CC_STAT (BIT(0) | BIT(1)) +#define TPS65218_STATE (BIT(2) | BIT(3)) +#define TPS65218_PB_STATE BIT(4) +#define TPS65218_AC_STATE BIT(5) +#define TPS65218_EE BIT(6) +#define TPS65218_FSEAL BIT(7) + +int tps65218_reg_read(uchar dest_reg, uchar *dest_val); int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val, uchar mask); int tps65218_voltage_update(uchar dc_cntrl_reg, uchar volt_sel); +int tps65218_toggle_fseal(void); +int tps65218_lock_fseal(void); int power_tps65218_init(unsigned char bus); #endif /* __POWER_TPS65218_H__ */