xref: /rk3399_rockchip-uboot/drivers/power/pmic/pmic_tps65218.c (revision 75fd49c836d9a1750c9b6d86c0511b990fbe9fa8)
186db550bSTom Rini /*
286db550bSTom Rini  * (C) Copyright 2011-2013
386db550bSTom Rini  * Texas Instruments, <www.ti.com>
486db550bSTom Rini  *
586db550bSTom Rini  * SPDX-License-Identifier:	GPL-2.0+
686db550bSTom Rini  */
786db550bSTom Rini 
886db550bSTom Rini #include <common.h>
986db550bSTom Rini #include <i2c.h>
101221ce45SMasahiro Yamada #include <linux/errno.h>
117aa5598aSTom Rini #include <power/pmic.h>
1286db550bSTom Rini #include <power/tps65218.h>
1386db550bSTom Rini 
tps65218_reg_read(uchar dest_reg,uchar * dest_val)149bcfca12SNikita Kiryanov int tps65218_reg_read(uchar dest_reg, uchar *dest_val)
159bcfca12SNikita Kiryanov {
169bcfca12SNikita Kiryanov 	uchar read_val;
179bcfca12SNikita Kiryanov 	int ret;
189bcfca12SNikita Kiryanov 
199bcfca12SNikita Kiryanov 	ret = i2c_read(TPS65218_CHIP_PM, dest_reg, 1, &read_val, 1);
209bcfca12SNikita Kiryanov 	if (ret)
219bcfca12SNikita Kiryanov 		return ret;
229bcfca12SNikita Kiryanov 
239bcfca12SNikita Kiryanov 	*dest_val = read_val;
249bcfca12SNikita Kiryanov 
259bcfca12SNikita Kiryanov 	return 0;
269bcfca12SNikita Kiryanov }
279bcfca12SNikita Kiryanov 
2886db550bSTom Rini /**
2986db550bSTom Rini  *  tps65218_reg_write() - Generic function that can write a TPS65218 PMIC
3086db550bSTom Rini  *			   register or bit field regardless of protection
3186db550bSTom Rini  *			   level.
3286db550bSTom Rini  *
3386db550bSTom Rini  *  @prot_level:	   Register password protection.  Use
3486db550bSTom Rini  *			   TPS65218_PROT_LEVEL_NONE,
3586db550bSTom Rini  *			   TPS65218_PROT_LEVEL_1 or TPS65218_PROT_LEVEL_2
3686db550bSTom Rini  *  @dest_reg:		   Register address to write.
3786db550bSTom Rini  *  @dest_val:		   Value to write.
3886db550bSTom Rini  *  @mask:		   Bit mask (8 bits) to be applied.  Function will only
3986db550bSTom Rini  *			   change bits that are set in the bit mask.
4086db550bSTom Rini  *
4186db550bSTom Rini  *  @return:		   0 for success, not 0 on failure, as per the i2c API
4286db550bSTom Rini  */
tps65218_reg_write(uchar prot_level,uchar dest_reg,uchar dest_val,uchar mask)4386db550bSTom Rini int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val,
4486db550bSTom Rini 		       uchar mask)
4586db550bSTom Rini {
4686db550bSTom Rini 	uchar read_val;
4786db550bSTom Rini 	uchar xor_reg;
4886db550bSTom Rini 	int ret;
4986db550bSTom Rini 
5086db550bSTom Rini 	/*
5186db550bSTom Rini 	 * If we are affecting only a bit field, read dest_reg and apply the
5286db550bSTom Rini 	 * mask
5386db550bSTom Rini 	 */
5486db550bSTom Rini 	if (mask != TPS65218_MASK_ALL_BITS) {
5586db550bSTom Rini 		ret = i2c_read(TPS65218_CHIP_PM, dest_reg, 1, &read_val, 1);
5686db550bSTom Rini 		if (ret)
5786db550bSTom Rini 			return ret;
5886db550bSTom Rini 		read_val &= (~mask);
5986db550bSTom Rini 		read_val |= (dest_val & mask);
6086db550bSTom Rini 		dest_val = read_val;
6186db550bSTom Rini 	}
6286db550bSTom Rini 
6386db550bSTom Rini 	if (prot_level > 0) {
6486db550bSTom Rini 		xor_reg = dest_reg ^ TPS65218_PASSWORD_UNLOCK;
6586db550bSTom Rini 		ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1,
6686db550bSTom Rini 				&xor_reg, 1);
6786db550bSTom Rini 		if (ret)
6886db550bSTom Rini 			return ret;
6986db550bSTom Rini 	}
7086db550bSTom Rini 
7186db550bSTom Rini 	ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1);
7286db550bSTom Rini 	if (ret)
7386db550bSTom Rini 		return ret;
7486db550bSTom Rini 
7586db550bSTom Rini 	if (prot_level == TPS65218_PROT_LEVEL_2) {
7686db550bSTom Rini 		ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1,
7786db550bSTom Rini 				&xor_reg, 1);
7886db550bSTom Rini 		if (ret)
7986db550bSTom Rini 			return ret;
8086db550bSTom Rini 
8186db550bSTom Rini 		ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1);
8286db550bSTom Rini 		if (ret)
8386db550bSTom Rini 			return ret;
8486db550bSTom Rini 	}
8586db550bSTom Rini 
8686db550bSTom Rini 	return 0;
8786db550bSTom Rini }
8886db550bSTom Rini 
8986db550bSTom Rini /**
9086db550bSTom Rini  * tps65218_voltage_update() - Function to change a voltage level, as this
9186db550bSTom Rini  *			       is a multi-step process.
9286db550bSTom Rini  * @dc_cntrl_reg:	       DC voltage control register to change.
9386db550bSTom Rini  * @volt_sel:		       New value for the voltage register
9486db550bSTom Rini  * @return:		       0 for success, not 0 on failure.
9586db550bSTom Rini  */
tps65218_voltage_update(uchar dc_cntrl_reg,uchar volt_sel)9686db550bSTom Rini int tps65218_voltage_update(uchar dc_cntrl_reg, uchar volt_sel)
9786db550bSTom Rini {
9886db550bSTom Rini 	if ((dc_cntrl_reg != TPS65218_DCDC1) &&
99*e395b884SKeerthy 	    (dc_cntrl_reg != TPS65218_DCDC2) &&
100*e395b884SKeerthy 	    (dc_cntrl_reg != TPS65218_DCDC3))
10186db550bSTom Rini 		return 1;
10286db550bSTom Rini 
10386db550bSTom Rini 	/* set voltage level */
10486db550bSTom Rini 	if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, dc_cntrl_reg, volt_sel,
1056183b295SKeerthy 			       TPS65218_DCDC_VSEL_MASK))
10686db550bSTom Rini 		return 1;
10786db550bSTom Rini 
10886db550bSTom Rini 	/* set GO bit to initiate voltage transition */
10986db550bSTom Rini 	if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, TPS65218_SLEW,
11086db550bSTom Rini 			       TPS65218_DCDC_GO, TPS65218_DCDC_GO))
11186db550bSTom Rini 		return 1;
11286db550bSTom Rini 
11386db550bSTom Rini 	return 0;
11486db550bSTom Rini }
1157aa5598aSTom Rini 
1169bcfca12SNikita Kiryanov /**
1179bcfca12SNikita Kiryanov  * tps65218_toggle_fseal() - Perform the sequence that toggles the FSEAL bit.
1189bcfca12SNikita Kiryanov  *
1199bcfca12SNikita Kiryanov  * @return:		     0 on success, -EBADE if the sequence was broken
1209bcfca12SNikita Kiryanov  */
tps65218_toggle_fseal(void)1219bcfca12SNikita Kiryanov int tps65218_toggle_fseal(void)
1229bcfca12SNikita Kiryanov {
1239bcfca12SNikita Kiryanov 	if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD,
1249bcfca12SNikita Kiryanov 			       0xb1, TPS65218_MASK_ALL_BITS))
1259bcfca12SNikita Kiryanov 		return -EBADE;
1269bcfca12SNikita Kiryanov 
1279bcfca12SNikita Kiryanov 	if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD,
1289bcfca12SNikita Kiryanov 			       0xfe, TPS65218_MASK_ALL_BITS))
1299bcfca12SNikita Kiryanov 		return -EBADE;
1309bcfca12SNikita Kiryanov 
1319bcfca12SNikita Kiryanov 	if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD,
1329bcfca12SNikita Kiryanov 			       0xa3, TPS65218_MASK_ALL_BITS))
1339bcfca12SNikita Kiryanov 		return -EBADE;
1349bcfca12SNikita Kiryanov 
1359bcfca12SNikita Kiryanov 	return 0;
1369bcfca12SNikita Kiryanov }
1379bcfca12SNikita Kiryanov 
1389bcfca12SNikita Kiryanov /**
1399bcfca12SNikita Kiryanov  * tps65218_lock_fseal() - Perform the sequence that locks the FSEAL bit to 1.
1409bcfca12SNikita Kiryanov  *
1419bcfca12SNikita Kiryanov  * The FSEAL bit prevents the PMIC from turning off DCDC5 and DCDC6. It can be
1429bcfca12SNikita Kiryanov  * toggled at most 3 times: 0->1, 1->0, and finally 0->1. After the third switch
1439bcfca12SNikita Kiryanov  * its value is locked and can only be reset by powering off the PMIC entirely.
1449bcfca12SNikita Kiryanov  *
1459bcfca12SNikita Kiryanov  * @return:		   0 on success, -EBADE if the sequence was broken
1469bcfca12SNikita Kiryanov  */
tps65218_lock_fseal(void)1479bcfca12SNikita Kiryanov int tps65218_lock_fseal(void)
1489bcfca12SNikita Kiryanov {
1499bcfca12SNikita Kiryanov 	int i;
1509bcfca12SNikita Kiryanov 
1519bcfca12SNikita Kiryanov 	for (i = 0; i < 3; i++)
1529bcfca12SNikita Kiryanov 		if (tps65218_toggle_fseal())
1539bcfca12SNikita Kiryanov 			return -EBADE;
1549bcfca12SNikita Kiryanov 
1559bcfca12SNikita Kiryanov 	return 0;
1569bcfca12SNikita Kiryanov }
1579bcfca12SNikita Kiryanov 
power_tps65218_init(unsigned char bus)1587aa5598aSTom Rini int power_tps65218_init(unsigned char bus)
1597aa5598aSTom Rini {
1607aa5598aSTom Rini 	static const char name[] = "TPS65218_PMIC";
1617aa5598aSTom Rini 	struct pmic *p = pmic_alloc();
1627aa5598aSTom Rini 
1637aa5598aSTom Rini 	if (!p) {
1647aa5598aSTom Rini 		printf("%s: POWER allocation error!\n", __func__);
1657aa5598aSTom Rini 		return -ENOMEM;
1667aa5598aSTom Rini 	}
1677aa5598aSTom Rini 
1687aa5598aSTom Rini 	p->name = name;
1697aa5598aSTom Rini 	p->interface = PMIC_I2C;
1707aa5598aSTom Rini 	p->number_of_regs = TPS65218_PMIC_NUM_OF_REGS;
1717aa5598aSTom Rini 	p->hw.i2c.addr = TPS65218_CHIP_PM;
1727aa5598aSTom Rini 	p->hw.i2c.tx_num = 1;
1737aa5598aSTom Rini 	p->bus = bus;
1747aa5598aSTom Rini 
1757aa5598aSTom Rini 	return 0;
1767aa5598aSTom Rini }
177