]>
Commit | Line | Data |
---|---|---|
516799f6 SS |
1 | /* |
2 | * (C) Copyright 2010 | |
3 | * Texas Instruments, <www.ti.com> | |
4 | * | |
1a459660 | 5 | * SPDX-License-Identifier: GPL-2.0+ |
516799f6 SS |
6 | */ |
7 | #include <config.h> | |
8 | #ifdef CONFIG_TWL6030_POWER | |
9 | ||
10 | #include <twl6030.h> | |
11 | ||
fc889503 OK |
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 | ||
340e6c83 OK |
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 | ||
3e664f6d B |
32 | static int twl6030_gpadc_read_channel(u8 channel_no) |
33 | { | |
34 | u8 lsb = 0; | |
35 | u8 msb = 0; | |
36 | int ret = 0; | |
37 | ||
345ef204 | 38 | ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC, |
fc889503 | 39 | twl->adc_rbase + channel_no * 2, &lsb); |
3e664f6d B |
40 | if (ret) |
41 | return ret; | |
42 | ||
345ef204 | 43 | ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC, |
fc889503 | 44 | twl->adc_rbase + 1 + channel_no * 2, &msb); |
3e664f6d B |
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 | ||
fc889503 OK |
56 | ret = twl6030_i2c_write_u8(TWL6030_CHIP_ADC, |
57 | twl->adc_ctrl, twl->adc_enable); | |
3e664f6d B |
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)))) { | |
fc889503 OK |
65 | ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC, |
66 | twl->adc_ctrl, &val); | |
3e664f6d B |
67 | if (ret) |
68 | return ret; | |
69 | udelay(1000); | |
70 | } | |
71 | ||
72 | return 0; | |
73 | } | |
74 | ||
75 | void twl6030_stop_usb_charging(void) | |
76 | { | |
345ef204 | 77 | twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CONTROLLER_CTRL1, 0); |
3e664f6d B |
78 | |
79 | return; | |
80 | } | |
81 | ||
516799f6 SS |
82 | void twl6030_start_usb_charging(void) |
83 | { | |
345ef204 NM |
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); | |
516799f6 | 97 | /* Enable USB charging */ |
345ef204 NM |
98 | twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, |
99 | CONTROLLER_CTRL1, CONTROLLER_CTRL1_EN_CHARGER); | |
516799f6 SS |
100 | return; |
101 | } | |
102 | ||
3e664f6d B |
103 | int twl6030_get_battery_current(void) |
104 | { | |
105 | int battery_current = 0; | |
106 | u8 msb = 0; | |
107 | u8 lsb = 0; | |
108 | ||
345ef204 NM |
109 | twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_11, &msb); |
110 | twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_10, &lsb); | |
3e664f6d B |
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; | |
340e6c83 OK |
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 | } | |
3e664f6d B |
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 */ | |
340e6c83 | 148 | battery_volt = twl6030_gpadc_read_channel(vbatch); |
3e664f6d B |
149 | if (battery_volt < 0) { |
150 | printf("Failed to read battery voltage\n"); | |
151 | return ret; | |
152 | } | |
fc889503 | 153 | battery_volt = (battery_volt * twl->vbat_mult) >> twl->vbat_shift; |
3e664f6d B |
154 | printf("Battery Voltage: %d mV\n", battery_volt); |
155 | ||
156 | return battery_volt; | |
157 | } | |
158 | ||
516799f6 SS |
159 | void twl6030_init_battery_charging(void) |
160 | { | |
340e6c83 | 161 | u8 val = 0; |
3e664f6d B |
162 | int battery_volt = 0; |
163 | int ret = 0; | |
164 | ||
340e6c83 OK |
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 | } | |
fc889503 | 178 | |
3e664f6d | 179 | /* Enable VBAT measurement */ |
340e6c83 OK |
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 | } | |
3e664f6d B |
190 | |
191 | /* Enable GPADC module */ | |
345ef204 | 192 | ret = twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, TOGGLE1, FGS | GPADCS); |
3e664f6d B |
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 */ | |
340e6c83 | 206 | twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, CONTROLLER_STAT1, &val); |
3e664f6d B |
207 | |
208 | /* check for battery presence indirectly via Fuel gauge */ | |
340e6c83 | 209 | if ((val & VBUS_DET) && (battery_volt < 3300)) |
3e664f6d B |
210 | twl6030_start_usb_charging(); |
211 | ||
516799f6 SS |
212 | return; |
213 | } | |
214 | ||
14fa2dd0 B |
215 | void twl6030_power_mmc_init() |
216 | { | |
217 | /* set voltage to 3.0 and turnon for APP */ | |
345ef204 NM |
218 | twl6030_i2c_write_u8(TWL6030_CHIP_PM, VMMC_CFG_VOLTATE, 0x15); |
219 | twl6030_i2c_write_u8(TWL6030_CHIP_PM, VMMC_CFG_STATE, 0x21); | |
14fa2dd0 B |
220 | } |
221 | ||
516799f6 SS |
222 | void twl6030_usb_device_settings() |
223 | { | |
224 | u8 data = 0; | |
225 | ||
226 | /* Select APP Group and set state to ON */ | |
345ef204 | 227 | twl6030_i2c_write_u8(TWL6030_CHIP_PM, VUSB_CFG_STATE, 0x21); |
516799f6 | 228 | |
345ef204 | 229 | twl6030_i2c_read_u8(TWL6030_CHIP_PM, MISC2, &data); |
516799f6 SS |
230 | data |= 0x10; |
231 | ||
232 | /* Select the input supply for VBUS regulator */ | |
345ef204 | 233 | twl6030_i2c_write_u8(TWL6030_CHIP_PM, MISC2, data); |
516799f6 SS |
234 | } |
235 | #endif |