1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2011-2013
4  * Texas Instruments, <www.ti.com>
5  */
6 
7 #include <common.h>
8 #include <i2c.h>
9 #include <power/tps65217.h>
10 
11 struct udevice *tps65217_dev __attribute__((section(".data"))) = NULL;
12 
13 /**
14  * tps65217_reg_read() - Generic function that can read a TPS65217 register
15  * @src_reg:		 Source register address
16  * @src_val:		 Address of destination variable
17  * @return:		 0 for success, not 0 on failure.
18  */
19 int tps65217_reg_read(uchar src_reg, uchar *src_val)
20 {
21 #ifndef CONFIG_DM_I2C
22 	return i2c_read(TPS65217_CHIP_PM, src_reg, 1, src_val, 1);
23 #else
24 	return dm_i2c_read(tps65217_dev, src_reg,  src_val, 1);
25 #endif
26 }
27 
28 /**
29  *  tps65217_reg_write() - Generic function that can write a TPS65217 PMIC
30  *			   register or bit field regardless of protection
31  *			   level.
32  *
33  *  @prot_level:	   Register password protection.  Use
34  *			   TPS65217_PROT_LEVEL_NONE,
35  *			   TPS65217_PROT_LEVEL_1 or TPS65217_PROT_LEVEL_2
36  *  @dest_reg:		   Register address to write.
37  *  @dest_val:		   Value to write.
38  *  @mask:		   Bit mask (8 bits) to be applied.  Function will only
39  *			   change bits that are set in the bit mask.
40  *
41  *  @return:		   0 for success, not 0 on failure, as per the i2c API
42  */
43 int tps65217_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val,
44 		       uchar mask)
45 {
46 	uchar read_val;
47 	uchar xor_reg;
48 	int ret;
49 
50 	/*
51 	 * If we are affecting only a bit field, read dest_reg and apply the
52 	 * mask
53 	 */
54 	if (mask != TPS65217_MASK_ALL_BITS) {
55 #ifndef CONFIG_DM_I2C
56 		ret = i2c_read(TPS65217_CHIP_PM, dest_reg, 1, &read_val, 1);
57 #else
58 		ret = dm_i2c_read(tps65217_dev, dest_reg, &read_val, 1);
59 #endif
60 		if (ret)
61 			return ret;
62 
63 		read_val &= (~mask);
64 		read_val |= (dest_val & mask);
65 		dest_val = read_val;
66 	}
67 
68 	if (prot_level > 0) {
69 		xor_reg = dest_reg ^ TPS65217_PASSWORD_UNLOCK;
70 #ifndef CONFIG_DM_I2C
71 		ret = i2c_write(TPS65217_CHIP_PM, TPS65217_PASSWORD, 1,
72 				&xor_reg, 1);
73 #else
74 		ret = dm_i2c_write(tps65217_dev, TPS65217_PASSWORD,
75 				   &xor_reg, 1);
76 #endif
77 		if (ret)
78 			return ret;
79 	}
80 #ifndef CONFIG_DM_I2C
81 	ret = i2c_write(TPS65217_CHIP_PM, dest_reg, 1, &dest_val, 1);
82 #else
83 	ret = dm_i2c_write(tps65217_dev, dest_reg, &dest_val, 1);
84 #endif
85 	if (ret)
86 		return ret;
87 
88 	if (prot_level == TPS65217_PROT_LEVEL_2) {
89 #ifndef CONFIG_DM_I2C
90 		ret = i2c_write(TPS65217_CHIP_PM, TPS65217_PASSWORD, 1,
91 				&xor_reg, 1);
92 #else
93 		ret = dm_i2c_write(tps65217_dev, TPS65217_PASSWORD,
94 				   &xor_reg, 1);
95 #endif
96 		if (ret)
97 			return ret;
98 
99 #ifndef CONFIG_DM_I2C
100 		ret = i2c_write(TPS65217_CHIP_PM, dest_reg, 1, &dest_val, 1);
101 #else
102 		ret = dm_i2c_write(tps65217_dev, dest_reg, &dest_val, 1);
103 #endif
104 		if (ret)
105 			return ret;
106 	}
107 
108 	return 0;
109 }
110 
111 /**
112  * tps65217_voltage_update() - Function to change a voltage level, as this
113  *			       is a multi-step process.
114  * @dc_cntrl_reg:	       DC voltage control register to change.
115  * @volt_sel:		       New value for the voltage register
116  * @return:		       0 for success, not 0 on failure.
117  */
118 int tps65217_voltage_update(uchar dc_cntrl_reg, uchar volt_sel)
119 {
120 	if ((dc_cntrl_reg != TPS65217_DEFDCDC1) &&
121 	    (dc_cntrl_reg != TPS65217_DEFDCDC2) &&
122 	    (dc_cntrl_reg != TPS65217_DEFDCDC3))
123 		return 1;
124 
125 	/* set voltage level */
126 	if (tps65217_reg_write(TPS65217_PROT_LEVEL_2, dc_cntrl_reg, volt_sel,
127 			       TPS65217_MASK_ALL_BITS))
128 		return 1;
129 
130 	/* set GO bit to initiate voltage transition */
131 	if (tps65217_reg_write(TPS65217_PROT_LEVEL_2, TPS65217_DEFSLEW,
132 			       TPS65217_DCDC_GO, TPS65217_DCDC_GO))
133 		return 1;
134 
135 	return 0;
136 }
137 
138 int power_tps65217_init(unsigned char bus)
139 {
140 #ifdef CONFIG_DM_I2C
141 	struct udevice *dev = NULL;
142 	int rc;
143 
144 	rc = i2c_get_chip_for_busnum(bus, TPS65217_CHIP_PM, 1, &dev);
145 	if (rc)
146 		return rc;
147 	tps65217_dev = dev;
148 #endif
149 	return 0;
150 }
151