xref: /aosp_15_r20/external/coreboot/src/drivers/ti/tps65090/tps65090.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: BSD-3-Clause or GPL-2.0-only */
2 
3 #include <delay.h>
4 #include <types.h>
5 #include <console/console.h>
6 #include <device/i2c_simple.h>
7 #include "tps65090.h"
8 
9 /* TPS65090 register addresses */
10 enum {
11 	REG_CG_CTRL0 = 4,
12 	REG_CG_STATUS1 = 0xa,
13 };
14 
15 enum {
16 	CG_CTRL0_ENC_MASK	= 0x01,
17 
18 	MAX_FET_NUM	= 7,
19 	MAX_CTRL_READ_TRIES = 5,
20 
21 	/* TPS65090 FET_CTRL register values */
22 	FET_CTRL_TOFET		= 1 << 7,  /* Timeout, startup, overload */
23 	FET_CTRL_PGFET		= 1 << 4,  /* Power good for FET status */
24 	FET_CTRL_WAIT		= 3 << 2,  /* Overcurrent timeout max */
25 	FET_CTRL_ADENFET	= 1 << 1,  /* Enable output auto discharge */
26 	FET_CTRL_ENFET		= 1 << 0,  /* Enable FET */
27 };
28 
tps65090_i2c_write(unsigned int bus,unsigned int reg_addr,unsigned char value)29 static int tps65090_i2c_write(unsigned int bus,
30 		unsigned int reg_addr, unsigned char value)
31 {
32 	int ret;
33 
34 	ret = i2c_writeb(bus, TPS65090_I2C_ADDR, reg_addr, value);
35 	printk(BIOS_DEBUG, "%s: reg=%#x, value=%#x, ret=%d\n",
36 			__func__, reg_addr, value, ret);
37 	return ret;
38 }
39 
tps65090_i2c_read(unsigned int bus,unsigned int reg_addr,unsigned char * value)40 static int tps65090_i2c_read(unsigned int bus,
41 		unsigned int reg_addr, unsigned char *value)
42 {
43 	int ret;
44 
45 	printk(BIOS_DEBUG, "%s: reg=%#x, ", __func__, reg_addr);
46 	ret = i2c_readb(bus, TPS65090_I2C_ADDR, reg_addr, value);
47 	if (ret)
48 		printk(BIOS_DEBUG, "fail, ret=%d\n", ret);
49 	else
50 		printk(BIOS_DEBUG, "value=%#x, ret=%d\n", *value, ret);
51 	return ret;
52 }
53 
54 /**
55  * Set the power state for a FET
56  *
57  * @param bus
58  * @param fet_id		Fet number to set (1..MAX_FET_NUM)
59  * @param set			1 to power on FET, 0 to power off
60  * @return FET_ERR_COMMS if we got a comms error, FET_ERR_NOT_READY if the
61  * FET failed to change state. If all is ok, returns 0.
62  */
tps65090_fet_set(unsigned int bus,enum fet_id fet_id,int set)63 static int tps65090_fet_set(unsigned int bus, enum fet_id fet_id, int set)
64 {
65 	int retry, value;
66 	uint8_t reg;
67 
68 	value = FET_CTRL_ADENFET | FET_CTRL_WAIT;
69 	if (set)
70 		value |= FET_CTRL_ENFET;
71 
72 	if (tps65090_i2c_write(bus, fet_id, value))
73 		return FET_ERR_COMMS;
74 	/* Try reading until we get a result */
75 	for (retry = 0; retry < MAX_CTRL_READ_TRIES; retry++) {
76 		if (tps65090_i2c_read(bus, fet_id, &reg))
77 			return FET_ERR_COMMS;
78 
79 		/* Check that the fet went into the expected state */
80 		if (!!(reg & FET_CTRL_PGFET) == set)
81 			return 0;
82 
83 		/* If we got a timeout, there is no point in waiting longer */
84 		if (reg & FET_CTRL_TOFET)
85 			break;
86 
87 		udelay(1000);
88 	}
89 
90 	printk(BIOS_DEBUG, "FET %d: Power good should have set to %d but "
91 			"reg=%#02x\n", fet_id, set, reg);
92 	return FET_ERR_NOT_READY;
93 }
94 
tps65090_fet_enable(unsigned int bus,enum fet_id fet_id)95 int tps65090_fet_enable(unsigned int bus, enum fet_id fet_id)
96 {
97 	int loops;
98 	int ret = 0;
99 
100 	for (loops = 0; loops < 100; loops++) {
101 		ret = tps65090_fet_set(bus, fet_id, 1);
102 		if (!ret)
103 			break;
104 
105 		/* Turn it off and try again until we time out */
106 		tps65090_fet_set(bus, fet_id, 0);
107 		udelay(1000);
108 	}
109 
110 	if (ret) {
111 		printk(BIOS_DEBUG, "%s: FET%d failed to power on\n",
112 				__func__, fet_id);
113 	} else if (loops) {
114 		printk(BIOS_DEBUG, "%s: FET%d powered on\n",
115 				__func__, fet_id);
116 	}
117 	/*
118 	 * Unfortunately, there are some conditions where the power
119 	 * good bit will be 0, but the fet still comes up. One such
120 	 * case occurs with the lcd backlight. We'll just return 0 here
121 	 * and assume that the fet will eventually come up.
122 	 */
123 	if (ret == FET_ERR_NOT_READY)
124 		ret = 0;
125 
126 	return ret;
127 }
128 
tps65090_fet_disable(unsigned int bus,enum fet_id fet_id)129 int tps65090_fet_disable(unsigned int bus, enum fet_id fet_id)
130 {
131 	return tps65090_fet_set(bus, fet_id, 0);
132 }
133 
tps65090_fet_is_enabled(unsigned int bus,enum fet_id fet_id)134 int tps65090_fet_is_enabled(unsigned int bus, enum fet_id fet_id)
135 {
136 	unsigned char reg;
137 	int ret;
138 
139 	ret = tps65090_i2c_read(bus, fet_id, &reg);
140 	if (ret) {
141 		printk(BIOS_DEBUG, "fail to read FET%u_CTRL", fet_id);
142 		return -2;
143 	}
144 
145 	return reg & FET_CTRL_ENFET;
146 }
147 
tps65090_is_charging(unsigned int bus)148 int tps65090_is_charging(unsigned int bus)
149 {
150 	unsigned char val;
151 	int ret;
152 
153 	ret = tps65090_i2c_read(bus, REG_CG_CTRL0, &val);
154 	if (ret)
155 		return ret;
156 	return val & CG_CTRL0_ENC_MASK ? 1 : 0;
157 }
158 
tps65090_set_charge_enable(unsigned int bus,int enable)159 int tps65090_set_charge_enable(unsigned int bus, int enable)
160 {
161 	unsigned char val;
162 	int ret;
163 
164 	ret = tps65090_i2c_read(bus, REG_CG_CTRL0, &val);
165 	if (!ret) {
166 		if (enable)
167 			val |= CG_CTRL0_ENC_MASK;
168 		else
169 			val &= ~CG_CTRL0_ENC_MASK;
170 		ret = tps65090_i2c_write(bus, REG_CG_CTRL0, val);
171 	}
172 	if (ret) {
173 		printk(BIOS_DEBUG, "%s: Failed to enable\n", __func__);
174 		return ret;
175 	}
176 	return 0;
177 }
178 
tps65090_get_status(unsigned int bus)179 int tps65090_get_status(unsigned int bus)
180 {
181 	unsigned char val;
182 	int ret;
183 
184 	ret = tps65090_i2c_read(bus, REG_CG_STATUS1, &val);
185 	if (ret)
186 		return ret;
187 	return val;
188 }
189