blob: dbc7a73a7235eb090efccb350238eebba8f31f3f [file] [log] [blame]
Tom Rini86db5502014-06-05 11:15:29 -04001/*
2 * (C) Copyright 2011-2013
3 * Texas Instruments, <www.ti.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8#include <common.h>
9#include <i2c.h>
Tom Rini7aa55982014-06-23 16:06:29 -040010#include <asm/errno.h>
11#include <power/pmic.h>
Tom Rini86db5502014-06-05 11:15:29 -040012#include <power/tps65218.h>
13
14/**
15 * tps65218_reg_write() - Generic function that can write a TPS65218 PMIC
16 * register or bit field regardless of protection
17 * level.
18 *
19 * @prot_level: Register password protection. Use
20 * TPS65218_PROT_LEVEL_NONE,
21 * TPS65218_PROT_LEVEL_1 or TPS65218_PROT_LEVEL_2
22 * @dest_reg: Register address to write.
23 * @dest_val: Value to write.
24 * @mask: Bit mask (8 bits) to be applied. Function will only
25 * change bits that are set in the bit mask.
26 *
27 * @return: 0 for success, not 0 on failure, as per the i2c API
28 */
29int tps65218_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val,
30 uchar mask)
31{
32 uchar read_val;
33 uchar xor_reg;
34 int ret;
35
36 /*
37 * If we are affecting only a bit field, read dest_reg and apply the
38 * mask
39 */
40 if (mask != TPS65218_MASK_ALL_BITS) {
41 ret = i2c_read(TPS65218_CHIP_PM, dest_reg, 1, &read_val, 1);
42 if (ret)
43 return ret;
44 read_val &= (~mask);
45 read_val |= (dest_val & mask);
46 dest_val = read_val;
47 }
48
49 if (prot_level > 0) {
50 xor_reg = dest_reg ^ TPS65218_PASSWORD_UNLOCK;
51 ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1,
52 &xor_reg, 1);
53 if (ret)
54 return ret;
55 }
56
57 ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1);
58 if (ret)
59 return ret;
60
61 if (prot_level == TPS65218_PROT_LEVEL_2) {
62 ret = i2c_write(TPS65218_CHIP_PM, TPS65218_PASSWORD, 1,
63 &xor_reg, 1);
64 if (ret)
65 return ret;
66
67 ret = i2c_write(TPS65218_CHIP_PM, dest_reg, 1, &dest_val, 1);
68 if (ret)
69 return ret;
70 }
71
72 return 0;
73}
74
75/**
76 * tps65218_voltage_update() - Function to change a voltage level, as this
77 * is a multi-step process.
78 * @dc_cntrl_reg: DC voltage control register to change.
79 * @volt_sel: New value for the voltage register
80 * @return: 0 for success, not 0 on failure.
81 */
82int tps65218_voltage_update(uchar dc_cntrl_reg, uchar volt_sel)
83{
84 if ((dc_cntrl_reg != TPS65218_DCDC1) &&
85 (dc_cntrl_reg != TPS65218_DCDC2))
86 return 1;
87
88 /* set voltage level */
89 if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, dc_cntrl_reg, volt_sel,
90 TPS65218_MASK_ALL_BITS))
91 return 1;
92
93 /* set GO bit to initiate voltage transition */
94 if (tps65218_reg_write(TPS65218_PROT_LEVEL_2, TPS65218_SLEW,
95 TPS65218_DCDC_GO, TPS65218_DCDC_GO))
96 return 1;
97
98 return 0;
99}
Tom Rini7aa55982014-06-23 16:06:29 -0400100
101int power_tps65218_init(unsigned char bus)
102{
103 static const char name[] = "TPS65218_PMIC";
104 struct pmic *p = pmic_alloc();
105
106 if (!p) {
107 printf("%s: POWER allocation error!\n", __func__);
108 return -ENOMEM;
109 }
110
111 p->name = name;
112 p->interface = PMIC_I2C;
113 p->number_of_regs = TPS65218_PMIC_NUM_OF_REGS;
114 p->hw.i2c.addr = TPS65218_CHIP_PM;
115 p->hw.i2c.tx_num = 1;
116 p->bus = bus;
117
118 return 0;
119}