xref: /openbmc/u-boot/drivers/power/pmic/pmic_tps65218.c (revision 7ff485c68b7e5573e5a4a877066e98398283a24f)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
286db550bSTom Rini /*
386db550bSTom Rini  * (C) Copyright 2011-2013
486db550bSTom Rini  * Texas Instruments, <www.ti.com>
586db550bSTom Rini  */
686db550bSTom Rini 
786db550bSTom Rini #include <common.h>
886db550bSTom Rini #include <i2c.h>
91221ce45SMasahiro Yamada #include <linux/errno.h>
107aa5598aSTom Rini #include <power/pmic.h>
1186db550bSTom Rini #include <power/tps65218.h>
1286db550bSTom Rini 
13*fb1b7712SJean-Jacques Hiblot #ifndef CONFIG_DM_I2C
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 }
88*fb1b7712SJean-Jacques Hiblot #else
89*fb1b7712SJean-Jacques Hiblot struct udevice *tps65218_dev __attribute__((section(".data"))) = NULL;
90*fb1b7712SJean-Jacques Hiblot 
tps65218_reg_read(uchar dest_reg,uchar * dest_val)91*fb1b7712SJean-Jacques Hiblot int tps65218_reg_read(uchar dest_reg, uchar *dest_val)
92*fb1b7712SJean-Jacques Hiblot {
93*fb1b7712SJean-Jacques Hiblot 	uchar read_val;
94*fb1b7712SJean-Jacques Hiblot 	int ret;
95*fb1b7712SJean-Jacques Hiblot 
96*fb1b7712SJean-Jacques Hiblot 	if (!tps65218_dev)
97*fb1b7712SJean-Jacques Hiblot 		return -ENODEV;
98*fb1b7712SJean-Jacques Hiblot 
99*fb1b7712SJean-Jacques Hiblot 	ret = dm_i2c_read(tps65218_dev, dest_reg,  &read_val, 1);
100*fb1b7712SJean-Jacques Hiblot 	if (ret)
101*fb1b7712SJean-Jacques Hiblot 		return ret;
102*fb1b7712SJean-Jacques Hiblot 
103*fb1b7712SJean-Jacques Hiblot 	*dest_val = read_val;
104*fb1b7712SJean-Jacques Hiblot 
105*fb1b7712SJean-Jacques Hiblot 	return 0;
106*fb1b7712SJean-Jacques Hiblot }
107*fb1b7712SJean-Jacques Hiblot 
tps65218_reg_write(uchar prot_level,uchar dest_reg,uchar dest_val,uchar mask)108*fb1b7712SJean-Jacques Hiblot int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val,
109*fb1b7712SJean-Jacques Hiblot 		       uchar mask)
110*fb1b7712SJean-Jacques Hiblot {
111*fb1b7712SJean-Jacques Hiblot 	uchar read_val;
112*fb1b7712SJean-Jacques Hiblot 	uchar xor_reg;
113*fb1b7712SJean-Jacques Hiblot 	int ret;
114*fb1b7712SJean-Jacques Hiblot 
115*fb1b7712SJean-Jacques Hiblot 	if (!tps65218_dev)
116*fb1b7712SJean-Jacques Hiblot 		return -ENODEV;
117*fb1b7712SJean-Jacques Hiblot 
118*fb1b7712SJean-Jacques Hiblot 	/*
119*fb1b7712SJean-Jacques Hiblot 	 * If we are affecting only a bit field, read dest_reg and apply the
120*fb1b7712SJean-Jacques Hiblot 	 * mask
121*fb1b7712SJean-Jacques Hiblot 	 */
122*fb1b7712SJean-Jacques Hiblot 	if (mask != TPS65218_MASK_ALL_BITS) {
123*fb1b7712SJean-Jacques Hiblot 		ret = dm_i2c_read(tps65218_dev, dest_reg, &read_val, 1);
124*fb1b7712SJean-Jacques Hiblot 		if (ret)
125*fb1b7712SJean-Jacques Hiblot 			return ret;
126*fb1b7712SJean-Jacques Hiblot 
127*fb1b7712SJean-Jacques Hiblot 		read_val &= (~mask);
128*fb1b7712SJean-Jacques Hiblot 		read_val |= (dest_val & mask);
129*fb1b7712SJean-Jacques Hiblot 		dest_val = read_val;
130*fb1b7712SJean-Jacques Hiblot 	}
131*fb1b7712SJean-Jacques Hiblot 
132*fb1b7712SJean-Jacques Hiblot 	if (prot_level > 0) {
133*fb1b7712SJean-Jacques Hiblot 		xor_reg = dest_reg ^ TPS65218_PASSWORD_UNLOCK;
134*fb1b7712SJean-Jacques Hiblot 		ret = dm_i2c_write(tps65218_dev, TPS65218_PASSWORD, &xor_reg,
135*fb1b7712SJean-Jacques Hiblot 				   1);
136*fb1b7712SJean-Jacques Hiblot 		if (ret)
137*fb1b7712SJean-Jacques Hiblot 			return ret;
138*fb1b7712SJean-Jacques Hiblot 	}
139*fb1b7712SJean-Jacques Hiblot 
140*fb1b7712SJean-Jacques Hiblot 	ret = dm_i2c_write(tps65218_dev, dest_reg, &dest_val, 1);
141*fb1b7712SJean-Jacques Hiblot 	if (ret)
142*fb1b7712SJean-Jacques Hiblot 		return ret;
143*fb1b7712SJean-Jacques Hiblot 
144*fb1b7712SJean-Jacques Hiblot 	if (prot_level == TPS65218_PROT_LEVEL_2) {
145*fb1b7712SJean-Jacques Hiblot 		ret = dm_i2c_write(tps65218_dev, TPS65218_PASSWORD, &xor_reg,
146*fb1b7712SJean-Jacques Hiblot 				   1);
147*fb1b7712SJean-Jacques Hiblot 		if (ret)
148*fb1b7712SJean-Jacques Hiblot 			return ret;
149*fb1b7712SJean-Jacques Hiblot 
150*fb1b7712SJean-Jacques Hiblot 		ret = dm_i2c_write(tps65218_dev, dest_reg, &dest_val, 1);
151*fb1b7712SJean-Jacques Hiblot 		if (ret)
152*fb1b7712SJean-Jacques Hiblot 			return ret;
153*fb1b7712SJean-Jacques Hiblot 	}
154*fb1b7712SJean-Jacques Hiblot 
155*fb1b7712SJean-Jacques Hiblot 	return 0;
156*fb1b7712SJean-Jacques Hiblot }
157*fb1b7712SJean-Jacques Hiblot #endif
15886db550bSTom Rini 
15986db550bSTom Rini /**
16086db550bSTom Rini  * tps65218_voltage_update() - Function to change a voltage level, as this
16186db550bSTom Rini  *			       is a multi-step process.
16286db550bSTom Rini  * @dc_cntrl_reg:	       DC voltage control register to change.
16386db550bSTom Rini  * @volt_sel:		       New value for the voltage register
16486db550bSTom Rini  * @return:		       0 for success, not 0 on failure.
16586db550bSTom Rini  */
tps65218_voltage_update(uchar dc_cntrl_reg,uchar volt_sel)16686db550bSTom Rini int tps65218_voltage_update(uchar dc_cntrl_reg, uchar volt_sel)
16786db550bSTom Rini {
16886db550bSTom Rini 	if ((dc_cntrl_reg != TPS65218_DCDC1) &&
169e395b884SKeerthy 	    (dc_cntrl_reg != TPS65218_DCDC2) &&
170e395b884SKeerthy 	    (dc_cntrl_reg != TPS65218_DCDC3))
17186db550bSTom Rini 		return 1;
17286db550bSTom Rini 
17386db550bSTom Rini 	/* set voltage level */
17486db550bSTom Rini 	if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, dc_cntrl_reg, volt_sel,
1756183b295SKeerthy 			       TPS65218_DCDC_VSEL_MASK))
17686db550bSTom Rini 		return 1;
17786db550bSTom Rini 
17886db550bSTom Rini 	/* set GO bit to initiate voltage transition */
17986db550bSTom Rini 	if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, TPS65218_SLEW,
18086db550bSTom Rini 			       TPS65218_DCDC_GO, TPS65218_DCDC_GO))
18186db550bSTom Rini 		return 1;
18286db550bSTom Rini 
18386db550bSTom Rini 	return 0;
18486db550bSTom Rini }
1857aa5598aSTom Rini 
1869bcfca12SNikita Kiryanov /**
1879bcfca12SNikita Kiryanov  * tps65218_toggle_fseal() - Perform the sequence that toggles the FSEAL bit.
1889bcfca12SNikita Kiryanov  *
1899bcfca12SNikita Kiryanov  * @return:		     0 on success, -EBADE if the sequence was broken
1909bcfca12SNikita Kiryanov  */
tps65218_toggle_fseal(void)1919bcfca12SNikita Kiryanov int tps65218_toggle_fseal(void)
1929bcfca12SNikita Kiryanov {
1939bcfca12SNikita Kiryanov 	if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD,
1949bcfca12SNikita Kiryanov 			       0xb1, TPS65218_MASK_ALL_BITS))
1959bcfca12SNikita Kiryanov 		return -EBADE;
1969bcfca12SNikita Kiryanov 
1979bcfca12SNikita Kiryanov 	if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD,
1989bcfca12SNikita Kiryanov 			       0xfe, TPS65218_MASK_ALL_BITS))
1999bcfca12SNikita Kiryanov 		return -EBADE;
2009bcfca12SNikita Kiryanov 
2019bcfca12SNikita Kiryanov 	if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD,
2029bcfca12SNikita Kiryanov 			       0xa3, TPS65218_MASK_ALL_BITS))
2039bcfca12SNikita Kiryanov 		return -EBADE;
2049bcfca12SNikita Kiryanov 
2059bcfca12SNikita Kiryanov 	return 0;
2069bcfca12SNikita Kiryanov }
2079bcfca12SNikita Kiryanov 
2089bcfca12SNikita Kiryanov /**
2099bcfca12SNikita Kiryanov  * tps65218_lock_fseal() - Perform the sequence that locks the FSEAL bit to 1.
2109bcfca12SNikita Kiryanov  *
2119bcfca12SNikita Kiryanov  * The FSEAL bit prevents the PMIC from turning off DCDC5 and DCDC6. It can be
2129bcfca12SNikita Kiryanov  * toggled at most 3 times: 0->1, 1->0, and finally 0->1. After the third switch
2139bcfca12SNikita Kiryanov  * its value is locked and can only be reset by powering off the PMIC entirely.
2149bcfca12SNikita Kiryanov  *
2159bcfca12SNikita Kiryanov  * @return:		   0 on success, -EBADE if the sequence was broken
2169bcfca12SNikita Kiryanov  */
tps65218_lock_fseal(void)2179bcfca12SNikita Kiryanov int tps65218_lock_fseal(void)
2189bcfca12SNikita Kiryanov {
2199bcfca12SNikita Kiryanov 	int i;
2209bcfca12SNikita Kiryanov 
2219bcfca12SNikita Kiryanov 	for (i = 0; i < 3; i++)
2229bcfca12SNikita Kiryanov 		if (tps65218_toggle_fseal())
2239bcfca12SNikita Kiryanov 			return -EBADE;
2249bcfca12SNikita Kiryanov 
2259bcfca12SNikita Kiryanov 	return 0;
2269bcfca12SNikita Kiryanov }
2279bcfca12SNikita Kiryanov 
228*fb1b7712SJean-Jacques Hiblot #ifndef CONFIG_DM_I2C
power_tps65218_init(unsigned char bus)2297aa5598aSTom Rini int power_tps65218_init(unsigned char bus)
2307aa5598aSTom Rini {
2317aa5598aSTom Rini 	static const char name[] = "TPS65218_PMIC";
2327aa5598aSTom Rini 	struct pmic *p = pmic_alloc();
2337aa5598aSTom Rini 
2347aa5598aSTom Rini 	if (!p) {
2357aa5598aSTom Rini 		printf("%s: POWER allocation error!\n", __func__);
2367aa5598aSTom Rini 		return -ENOMEM;
2377aa5598aSTom Rini 	}
2387aa5598aSTom Rini 
2397aa5598aSTom Rini 	p->name = name;
2407aa5598aSTom Rini 	p->interface = PMIC_I2C;
2417aa5598aSTom Rini 	p->number_of_regs = TPS65218_PMIC_NUM_OF_REGS;
2427aa5598aSTom Rini 	p->hw.i2c.addr = TPS65218_CHIP_PM;
2437aa5598aSTom Rini 	p->hw.i2c.tx_num = 1;
2447aa5598aSTom Rini 	p->bus = bus;
2457aa5598aSTom Rini 
2467aa5598aSTom Rini 	return 0;
2477aa5598aSTom Rini }
248*fb1b7712SJean-Jacques Hiblot #else
power_tps65218_init(unsigned char bus)249*fb1b7712SJean-Jacques Hiblot int power_tps65218_init(unsigned char bus)
250*fb1b7712SJean-Jacques Hiblot {
251*fb1b7712SJean-Jacques Hiblot 	struct udevice *dev = NULL;
252*fb1b7712SJean-Jacques Hiblot 	int rc;
253*fb1b7712SJean-Jacques Hiblot 
254*fb1b7712SJean-Jacques Hiblot 	rc = i2c_get_chip_for_busnum(bus, TPS65218_CHIP_PM, 1, &dev);
255*fb1b7712SJean-Jacques Hiblot 	if (rc)
256*fb1b7712SJean-Jacques Hiblot 		return rc;
257*fb1b7712SJean-Jacques Hiblot 	tps65218_dev = dev;
258*fb1b7712SJean-Jacques Hiblot 	return 0;
259*fb1b7712SJean-Jacques Hiblot }
260*fb1b7712SJean-Jacques Hiblot #endif
261