xref: /openbmc/u-boot/drivers/power/twl6030.c (revision 940db16d)
1 /*
2  * (C) Copyright 2010
3  * Texas Instruments, <www.ti.com>
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 #include <config.h>
8 #ifdef CONFIG_TWL6030_POWER
9 
10 #include <twl6030.h>
11 
12 static struct twl6030_data *twl;
13 
14 static struct twl6030_data twl6030_info = {
15 	.chip_type	= chip_TWL6030,
16 	.adc_rbase	= GPCH0_LSB,
17 	.adc_ctrl	= CTRL_P2,
18 	.adc_enable	= CTRL_P2_SP2,
19 	.vbat_mult	= TWL6030_VBAT_MULT,
20 	.vbat_shift	= TWL6030_VBAT_SHIFT,
21 };
22 
23 static struct twl6030_data twl6032_info = {
24 	.chip_type	= chip_TWL6032,
25 	.adc_rbase	= TWL6032_GPCH0_LSB,
26 	.adc_ctrl	= TWL6032_CTRL_P1,
27 	.adc_enable	= CTRL_P1_SP1,
28 	.vbat_mult	= TWL6032_VBAT_MULT,
29 	.vbat_shift	= TWL6032_VBAT_SHIFT,
30 };
31 
32 static int twl6030_gpadc_read_channel(u8 channel_no)
33 {
34 	u8 lsb = 0;
35 	u8 msb = 0;
36 	int ret = 0;
37 
38 	ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC,
39 				  twl->adc_rbase + channel_no * 2, &lsb);
40 	if (ret)
41 		return ret;
42 
43 	ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC,
44 				  twl->adc_rbase + 1 + channel_no * 2, &msb);
45 	if (ret)
46 		return ret;
47 
48 	return (msb << 8) | lsb;
49 }
50 
51 static int twl6030_gpadc_sw2_trigger(void)
52 {
53 	u8 val;
54 	int ret = 0;
55 
56 	ret = twl6030_i2c_write_u8(TWL6030_CHIP_ADC,
57 				   twl->adc_ctrl, twl->adc_enable);
58 	if (ret)
59 		return ret;
60 
61 	/* Waiting until the SW1 conversion ends*/
62 	val =  CTRL_P2_BUSY;
63 
64 	while (!((val & CTRL_P2_EOCP2) && (!(val & CTRL_P2_BUSY)))) {
65 		ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC,
66 					  twl->adc_ctrl, &val);
67 		if (ret)
68 			return ret;
69 		udelay(1000);
70 	}
71 
72 	return 0;
73 }
74 
75 void twl6030_stop_usb_charging(void)
76 {
77 	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CONTROLLER_CTRL1, 0);
78 
79 	return;
80 }
81 
82 void twl6030_start_usb_charging(void)
83 {
84 	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
85 			     CHARGERUSB_VICHRG, CHARGERUSB_VICHRG_1500);
86 	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
87 			     CHARGERUSB_CINLIMIT, CHARGERUSB_CIN_LIMIT_NONE);
88 	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
89 			     CONTROLLER_INT_MASK, MBAT_TEMP);
90 	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
91 			     CHARGERUSB_INT_MASK, MASK_MCHARGERUSB_THMREG);
92 	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
93 			     CHARGERUSB_VOREG, CHARGERUSB_VOREG_4P0);
94 	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
95 			     CHARGERUSB_CTRL2, CHARGERUSB_CTRL2_VITERM_400);
96 	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CHARGERUSB_CTRL1, TERM);
97 	/* Enable USB charging */
98 	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
99 			     CONTROLLER_CTRL1, CONTROLLER_CTRL1_EN_CHARGER);
100 	return;
101 }
102 
103 int twl6030_get_battery_current(void)
104 {
105 	int battery_current = 0;
106 	u8 msb = 0;
107 	u8 lsb = 0;
108 
109 	twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_11, &msb);
110 	twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_10, &lsb);
111 	battery_current = ((msb << 8) | lsb);
112 
113 	/* convert 10 bit signed number to 16 bit signed number */
114 	if (battery_current >= 0x2000)
115 		battery_current = (battery_current - 0x4000);
116 
117 	battery_current = battery_current * 3000 / 4096;
118 	printf("Battery Current: %d mA\n", battery_current);
119 
120 	return battery_current;
121 }
122 
123 int twl6030_get_battery_voltage(void)
124 {
125 	int battery_volt = 0;
126 	int ret = 0;
127 	u8 vbatch;
128 
129 	if (twl->chip_type == chip_TWL6030) {
130 		vbatch = TWL6030_GPADC_VBAT_CHNL;
131 	} else {
132 		ret = twl6030_i2c_write_u8(TWL6030_CHIP_ADC,
133 					   TWL6032_GPSELECT_ISB,
134 					   TWL6032_GPADC_VBAT_CHNL);
135 		if (ret)
136 			return ret;
137 		vbatch = 0;
138 	}
139 
140 	/* Start GPADC SW conversion */
141 	ret = twl6030_gpadc_sw2_trigger();
142 	if (ret) {
143 		printf("Failed to convert battery voltage\n");
144 		return ret;
145 	}
146 
147 	/* measure Vbat voltage */
148 	battery_volt = twl6030_gpadc_read_channel(vbatch);
149 	if (battery_volt < 0) {
150 		printf("Failed to read battery voltage\n");
151 		return ret;
152 	}
153 	battery_volt = (battery_volt * twl->vbat_mult) >> twl->vbat_shift;
154 	printf("Battery Voltage: %d mV\n", battery_volt);
155 
156 	return battery_volt;
157 }
158 
159 void twl6030_init_battery_charging(void)
160 {
161 	u8 val = 0;
162 	int battery_volt = 0;
163 	int ret = 0;
164 
165 	ret = twl6030_i2c_read_u8(TWL6030_CHIP_USB, USB_PRODUCT_ID_LSB, &val);
166 	if (ret) {
167 		puts("twl6030_init_battery_charging(): could not determine chip!\n");
168 		return;
169 	}
170 	if (val == 0x30) {
171 		twl = &twl6030_info;
172 	} else if (val == 0x32) {
173 		twl = &twl6032_info;
174 	} else {
175 		puts("twl6030_init_battery_charging(): unsupported chip type\n");
176 		return;
177 	}
178 
179 	/* Enable VBAT measurement */
180 	if (twl->chip_type == chip_TWL6030) {
181 		twl6030_i2c_write_u8(TWL6030_CHIP_PM, MISC1, VBAT_MEAS);
182 		twl6030_i2c_write_u8(TWL6030_CHIP_ADC,
183 				     TWL6030_GPADC_CTRL,
184 				     GPADC_CTRL_SCALER_DIV4);
185 	} else {
186 		twl6030_i2c_write_u8(TWL6030_CHIP_ADC,
187 				     TWL6032_GPADC_CTRL2,
188 				     GPADC_CTRL2_CH18_SCALER_EN);
189 	}
190 
191 	/* Enable GPADC module */
192 	ret = twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, TOGGLE1, FGS | GPADCS);
193 	if (ret) {
194 		printf("Failed to enable GPADC\n");
195 		return;
196 	}
197 
198 	battery_volt = twl6030_get_battery_voltage();
199 	if (battery_volt < 0)
200 		return;
201 
202 	if (battery_volt < 3000)
203 		printf("Main battery voltage too low!\n");
204 
205 	/* Check for the presence of USB charger */
206 	twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, CONTROLLER_STAT1, &val);
207 
208 	/* check for battery presence indirectly via Fuel gauge */
209 	if ((val & VBUS_DET) && (battery_volt < 3300))
210 		twl6030_start_usb_charging();
211 
212 	return;
213 }
214 
215 void twl6030_power_mmc_init()
216 {
217 	/* set voltage to 3.0 and turnon for APP */
218 	twl6030_i2c_write_u8(TWL6030_CHIP_PM, VMMC_CFG_VOLTATE, 0x15);
219 	twl6030_i2c_write_u8(TWL6030_CHIP_PM, VMMC_CFG_STATE, 0x21);
220 }
221 
222 void twl6030_usb_device_settings()
223 {
224 	u8 data = 0;
225 
226 	/* Select APP Group and set state to ON */
227 	twl6030_i2c_write_u8(TWL6030_CHIP_PM, VUSB_CFG_STATE, 0x21);
228 
229 	twl6030_i2c_read_u8(TWL6030_CHIP_PM, MISC2, &data);
230 	data |= 0x10;
231 
232 	/* Select the input supply for VBUS regulator */
233 	twl6030_i2c_write_u8(TWL6030_CHIP_PM, MISC2, data);
234 }
235 #endif
236