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 <linux/errno.h>
10#include <power/pmic.h>
11#include <power/tps65218.h>
12
13#if !CONFIG_IS_ENABLED(DM_I2C)
14int tps65218_reg_read(uchar dest_reg, uchar *dest_val)
15{
16	uchar read_val;
17	int ret;
18
19	ret = i2c_read(TPS65218_CHIP_PM, dest_reg, 1, &read_val, 1);
20	if (ret)
21		return ret;
22
23	*dest_val = read_val;
24
25	return 0;
26}
27
28/**
29 *  tps65218_reg_write() - Generic function that can write a TPS65218 PMIC
30 *			   register or bit field regardless of protection
31 *			   level.
32 *
33 *  @prot_level:	   Register password protection.  Use
34 *			   TPS65218_PROT_LEVEL_NONE,
35 *			   TPS65218_PROT_LEVEL_1 or TPS65218_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 */
43int tps65218_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 != TPS65218_MASK_ALL_BITS) {
55		ret = i2c_read(TPS65218_CHIP_PM, dest_reg, 1, &read_val, 1);
56		if (ret)
57			return ret;
58		read_val &= (~mask);
59		read_val |= (dest_val & mask);
60		dest_val = read_val;
61	}
62
63	if (prot_level > 0) {
64		xor_reg = dest_reg ^ TPS65218_PASSWORD_UNLOCK;
65		ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1,
66				&xor_reg, 1);
67		if (ret)
68			return ret;
69	}
70
71	ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1);
72	if (ret)
73		return ret;
74
75	if (prot_level == TPS65218_PROT_LEVEL_2) {
76		ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1,
77				&xor_reg, 1);
78		if (ret)
79			return ret;
80
81		ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1);
82		if (ret)
83			return ret;
84	}
85
86	return 0;
87}
88#else
89struct udevice *tps65218_dev __section(".data") = NULL;
90
91int tps65218_reg_read(uchar dest_reg, uchar *dest_val)
92{
93	uchar read_val;
94	int ret;
95
96	if (!tps65218_dev)
97		return -ENODEV;
98
99	ret = dm_i2c_read(tps65218_dev, dest_reg,  &read_val, 1);
100	if (ret)
101		return ret;
102
103	*dest_val = read_val;
104
105	return 0;
106}
107
108int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val,
109		       uchar mask)
110{
111	uchar read_val;
112	uchar xor_reg;
113	int ret;
114
115	if (!tps65218_dev)
116		return -ENODEV;
117
118	/*
119	 * If we are affecting only a bit field, read dest_reg and apply the
120	 * mask
121	 */
122	if (mask != TPS65218_MASK_ALL_BITS) {
123		ret = dm_i2c_read(tps65218_dev, dest_reg, &read_val, 1);
124		if (ret)
125			return ret;
126
127		read_val &= (~mask);
128		read_val |= (dest_val & mask);
129		dest_val = read_val;
130	}
131
132	if (prot_level > 0) {
133		xor_reg = dest_reg ^ TPS65218_PASSWORD_UNLOCK;
134		ret = dm_i2c_write(tps65218_dev, TPS65218_PASSWORD, &xor_reg,
135				   1);
136		if (ret)
137			return ret;
138	}
139
140	ret = dm_i2c_write(tps65218_dev, dest_reg, &dest_val, 1);
141	if (ret)
142		return ret;
143
144	if (prot_level == TPS65218_PROT_LEVEL_2) {
145		ret = dm_i2c_write(tps65218_dev, TPS65218_PASSWORD, &xor_reg,
146				   1);
147		if (ret)
148			return ret;
149
150		ret = dm_i2c_write(tps65218_dev, dest_reg, &dest_val, 1);
151		if (ret)
152			return ret;
153	}
154
155	return 0;
156}
157#endif
158
159/**
160 * tps65218_voltage_update() - Function to change a voltage level, as this
161 *			       is a multi-step process.
162 * @dc_cntrl_reg:	       DC voltage control register to change.
163 * @volt_sel:		       New value for the voltage register
164 * @return:		       0 for success, not 0 on failure.
165 */
166int tps65218_voltage_update(uchar dc_cntrl_reg, uchar volt_sel)
167{
168	if ((dc_cntrl_reg != TPS65218_DCDC1) &&
169	    (dc_cntrl_reg != TPS65218_DCDC2) &&
170	    (dc_cntrl_reg != TPS65218_DCDC3))
171		return 1;
172
173	/* set voltage level */
174	if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, dc_cntrl_reg, volt_sel,
175			       TPS65218_DCDC_VSEL_MASK))
176		return 1;
177
178	/* set GO bit to initiate voltage transition */
179	if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, TPS65218_SLEW,
180			       TPS65218_DCDC_GO, TPS65218_DCDC_GO))
181		return 1;
182
183	return 0;
184}
185
186/**
187 * tps65218_toggle_fseal() - Perform the sequence that toggles the FSEAL bit.
188 *
189 * @return:		     0 on success, -EBADE if the sequence was broken
190 */
191int tps65218_toggle_fseal(void)
192{
193	if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD,
194			       0xb1, TPS65218_MASK_ALL_BITS))
195		return -EBADE;
196
197	if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD,
198			       0xfe, TPS65218_MASK_ALL_BITS))
199		return -EBADE;
200
201	if (tps65218_reg_write(TPS65218_PROT_LEVEL_NONE, TPS65218_PASSWORD,
202			       0xa3, TPS65218_MASK_ALL_BITS))
203		return -EBADE;
204
205	return 0;
206}
207
208/**
209 * tps65218_lock_fseal() - Perform the sequence that locks the FSEAL bit to 1.
210 *
211 * The FSEAL bit prevents the PMIC from turning off DCDC5 and DCDC6. It can be
212 * toggled at most 3 times: 0->1, 1->0, and finally 0->1. After the third switch
213 * its value is locked and can only be reset by powering off the PMIC entirely.
214 *
215 * @return:		   0 on success, -EBADE if the sequence was broken
216 */
217int tps65218_lock_fseal(void)
218{
219	int i;
220
221	for (i = 0; i < 3; i++)
222		if (tps65218_toggle_fseal())
223			return -EBADE;
224
225	return 0;
226}
227
228#if !CONFIG_IS_ENABLED(DM_I2C)
229int power_tps65218_init(unsigned char bus)
230{
231	static const char name[] = "TPS65218_PMIC";
232	struct pmic *p = pmic_alloc();
233
234	if (!p) {
235		printf("%s: POWER allocation error!\n", __func__);
236		return -ENOMEM;
237	}
238
239	p->name = name;
240	p->interface = PMIC_I2C;
241	p->number_of_regs = TPS65218_PMIC_NUM_OF_REGS;
242	p->hw.i2c.addr = TPS65218_CHIP_PM;
243	p->hw.i2c.tx_num = 1;
244	p->bus = bus;
245
246	return 0;
247}
248#else
249int power_tps65218_init(unsigned char bus)
250{
251	struct udevice *dev = NULL;
252	int rc;
253
254	rc = i2c_get_chip_for_busnum(bus, TPS65218_CHIP_PM, 1, &dev);
255	if (rc)
256		return rc;
257	tps65218_dev = dev;
258	return 0;
259}
260#endif
261