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