aboutsummaryrefslogtreecommitdiff
path: root/drivers/power/pmic/pmic_tps65217.c
blob: c839e3189055a22f439cbe99e7e02caad2ebface (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// SPDX-License-Identifier: GPL-2.0+
/*
 * (C) Copyright 2011-2013
 * Texas Instruments, <www.ti.com>
 */

#include <common.h>
#include <i2c.h>
#include <power/tps65217.h>

struct udevice *tps65217_dev __attribute__((section(".data"))) = NULL;

/**
 * tps65217_reg_read() - Generic function that can read a TPS65217 register
 * @src_reg:		 Source register address
 * @src_val:		 Address of destination variable
 * @return:		 0 for success, not 0 on failure.
 */
int tps65217_reg_read(uchar src_reg, uchar *src_val)
{
#ifndef CONFIG_DM_I2C
	return i2c_read(TPS65217_CHIP_PM, src_reg, 1, src_val, 1);
#else
	return dm_i2c_read(tps65217_dev, src_reg,  src_val, 1);
#endif
}

/**
 *  tps65217_reg_write() - Generic function that can write a TPS65217 PMIC
 *			   register or bit field regardless of protection
 *			   level.
 *
 *  @prot_level:	   Register password protection.  Use
 *			   TPS65217_PROT_LEVEL_NONE,
 *			   TPS65217_PROT_LEVEL_1 or TPS65217_PROT_LEVEL_2
 *  @dest_reg:		   Register address to write.
 *  @dest_val:		   Value to write.
 *  @mask:		   Bit mask (8 bits) to be applied.  Function will only
 *			   change bits that are set in the bit mask.
 *
 *  @return:		   0 for success, not 0 on failure, as per the i2c API
 */
int tps65217_reg_write(uchar prot_level, uchar dest_reg, uchar dest_val,
		       uchar mask)
{
	uchar read_val;
	uchar xor_reg;
	int ret;

	/*
	 * If we are affecting only a bit field, read dest_reg and apply the
	 * mask
	 */
	if (mask != TPS65217_MASK_ALL_BITS) {
#ifndef CONFIG_DM_I2C
		ret = i2c_read(TPS65217_CHIP_PM, dest_reg, 1, &read_val, 1);
#else
		ret = dm_i2c_read(tps65217_dev, dest_reg, &read_val, 1);
#endif
		if (ret)
			return ret;

		read_val &= (~mask);
		read_val |= (dest_val & mask);
		dest_val = read_val;
	}

	if (prot_level > 0) {
		xor_reg = dest_reg ^ TPS65217_PASSWORD_UNLOCK;
#ifndef CONFIG_DM_I2C
		ret = i2c_write(TPS65217_CHIP_PM, TPS65217_PASSWORD, 1,
				&xor_reg, 1);
#else
		ret = dm_i2c_write(tps65217_dev, TPS65217_PASSWORD,
				   &xor_reg, 1);
#endif
		if (ret)
			return ret;
	}
#ifndef CONFIG_DM_I2C
	ret = i2c_write(TPS65217_CHIP_PM, dest_reg, 1, &dest_val, 1);
#else
	ret = dm_i2c_write(tps65217_dev, dest_reg, &dest_val, 1);
#endif
	if (ret)
		return ret;

	if (prot_level == TPS65217_PROT_LEVEL_2) {
#ifndef CONFIG_DM_I2C
		ret = i2c_write(TPS65217_CHIP_PM, TPS65217_PASSWORD, 1,
				&xor_reg, 1);
#else
		ret = dm_i2c_write(tps65217_dev, TPS65217_PASSWORD,
				   &xor_reg, 1);
#endif
		if (ret)
			return ret;

#ifndef CONFIG_DM_I2C
		ret = i2c_write(TPS65217_CHIP_PM, dest_reg, 1, &dest_val, 1);
#else
		ret = dm_i2c_write(tps65217_dev, dest_reg, &dest_val, 1);
#endif
		if (ret)
			return ret;
	}

	return 0;
}

/**
 * tps65217_voltage_update() - Function to change a voltage level, as this
 *			       is a multi-step process.
 * @dc_cntrl_reg:	       DC voltage control register to change.
 * @volt_sel:		       New value for the voltage register
 * @return:		       0 for success, not 0 on failure.
 */
int tps65217_voltage_update(uchar dc_cntrl_reg, uchar volt_sel)
{
	if ((dc_cntrl_reg != TPS65217_DEFDCDC1) &&
	    (dc_cntrl_reg != TPS65217_DEFDCDC2) &&
	    (dc_cntrl_reg != TPS65217_DEFDCDC3))
		return 1;

	/* set voltage level */
	if (tps65217_reg_write(TPS65217_PROT_LEVEL_2, dc_cntrl_reg, volt_sel,
			       TPS65217_MASK_ALL_BITS))
		return 1;

	/* set GO bit to initiate voltage transition */
	if (tps65217_reg_write(TPS65217_PROT_LEVEL_2, TPS65217_DEFSLEW,
			       TPS65217_DCDC_GO, TPS65217_DCDC_GO))
		return 1;

	return 0;
}

int power_tps65217_init(unsigned char bus)
{
#ifdef CONFIG_DM_I2C
	struct udevice *dev = NULL;
	int rc;

	rc = i2c_get_chip_for_busnum(bus, TPS65217_CHIP_PM, 1, &dev);
	if (rc)
		return rc;
	tps65217_dev = dev;
#endif
	return 0;
}