blob: 7c95e5e758093e7dcf10487867a8aca62fff4583 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Tom Rini86db5502014-06-05 11:15:29 -04002/*
3 * (C) Copyright 2011-2013
4 * Texas Instruments, <www.ti.com>
Tom Rini86db5502014-06-05 11:15:29 -04005 */
6
7#include <common.h>
8#include <i2c.h>
Masahiro Yamada1221ce42016-09-21 11:28:55 +09009#include <linux/errno.h>
Tom Rini7aa55982014-06-23 16:06:29 -040010#include <power/pmic.h>
Tom Rini86db5502014-06-05 11:15:29 -040011#include <power/tps65218.h>
12
Jean-Jacques Hiblotfb1b7712018-12-07 14:50:46 +010013#ifndef CONFIG_DM_I2C
Nikita Kiryanov9bcfca12016-02-19 19:19:46 +020014int 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
Tom Rini86db5502014-06-05 11:15:29 -040028/**
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}
Jean-Jacques Hiblotfb1b7712018-12-07 14:50:46 +010088#else
89struct udevice *tps65218_dev __attribute__((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
Tom Rini86db5502014-06-05 11:15:29 -0400158
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) &&
Keerthye395b882017-06-02 15:00:30 +0530169 (dc_cntrl_reg != TPS65218_DCDC2) &&
170 (dc_cntrl_reg != TPS65218_DCDC3))
Tom Rini86db5502014-06-05 11:15:29 -0400171 return 1;
172
173 /* set voltage level */
174 if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, dc_cntrl_reg, volt_sel,
Keerthy6183b292017-05-24 10:19:27 +0530175 TPS65218_DCDC_VSEL_MASK))
Tom Rini86db5502014-06-05 11:15:29 -0400176 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}
Tom Rini7aa55982014-06-23 16:06:29 -0400185
Nikita Kiryanov9bcfca12016-02-19 19:19:46 +0200186/**
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
Jean-Jacques Hiblotfb1b7712018-12-07 14:50:46 +0100228#ifndef CONFIG_DM_I2C
Tom Rini7aa55982014-06-23 16:06:29 -0400229int 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}
Jean-Jacques Hiblotfb1b7712018-12-07 14:50:46 +0100248#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