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 9 #include <twl6030.h> 10 11 static struct twl6030_data *twl; 12 13 static struct twl6030_data twl6030_info = { 14 .chip_type = chip_TWL6030, 15 .adc_rbase = GPCH0_LSB, 16 .adc_ctrl = CTRL_P2, 17 .adc_enable = CTRL_P2_SP2, 18 .vbat_mult = TWL6030_VBAT_MULT, 19 .vbat_shift = TWL6030_VBAT_SHIFT, 20 }; 21 22 static struct twl6030_data twl6032_info = { 23 .chip_type = chip_TWL6032, 24 .adc_rbase = TWL6032_GPCH0_LSB, 25 .adc_ctrl = TWL6032_CTRL_P1, 26 .adc_enable = CTRL_P1_SP1, 27 .vbat_mult = TWL6032_VBAT_MULT, 28 .vbat_shift = TWL6032_VBAT_SHIFT, 29 }; 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_power_off(void) 76 { 77 twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_PHOENIX_DEV_ON, 78 TWL6030_PHOENIX_APP_DEVOFF | TWL6030_PHOENIX_CON_DEVOFF | 79 TWL6030_PHOENIX_MOD_DEVOFF); 80 } 81 82 void twl6030_stop_usb_charging(void) 83 { 84 twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CONTROLLER_CTRL1, 0); 85 86 return; 87 } 88 89 void twl6030_start_usb_charging(void) 90 { 91 twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 92 CHARGERUSB_VICHRG, CHARGERUSB_VICHRG_1500); 93 twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 94 CHARGERUSB_CINLIMIT, CHARGERUSB_CIN_LIMIT_NONE); 95 twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 96 CONTROLLER_INT_MASK, MBAT_TEMP); 97 twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 98 CHARGERUSB_INT_MASK, MASK_MCHARGERUSB_THMREG); 99 twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 100 CHARGERUSB_VOREG, CHARGERUSB_VOREG_4P0); 101 twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 102 CHARGERUSB_CTRL2, CHARGERUSB_CTRL2_VITERM_400); 103 twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CHARGERUSB_CTRL1, TERM); 104 /* Enable USB charging */ 105 twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 106 CONTROLLER_CTRL1, CONTROLLER_CTRL1_EN_CHARGER); 107 return; 108 } 109 110 int twl6030_get_battery_current(void) 111 { 112 int battery_current = 0; 113 u8 msb = 0; 114 u8 lsb = 0; 115 116 twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_11, &msb); 117 twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_10, &lsb); 118 battery_current = ((msb << 8) | lsb); 119 120 /* convert 10 bit signed number to 16 bit signed number */ 121 if (battery_current >= 0x2000) 122 battery_current = (battery_current - 0x4000); 123 124 battery_current = battery_current * 3000 / 4096; 125 printf("Battery Current: %d mA\n", battery_current); 126 127 return battery_current; 128 } 129 130 int twl6030_get_battery_voltage(void) 131 { 132 int battery_volt = 0; 133 int ret = 0; 134 u8 vbatch; 135 136 if (twl->chip_type == chip_TWL6030) { 137 vbatch = TWL6030_GPADC_VBAT_CHNL; 138 } else { 139 ret = twl6030_i2c_write_u8(TWL6030_CHIP_ADC, 140 TWL6032_GPSELECT_ISB, 141 TWL6032_GPADC_VBAT_CHNL); 142 if (ret) 143 return ret; 144 vbatch = 0; 145 } 146 147 /* Start GPADC SW conversion */ 148 ret = twl6030_gpadc_sw2_trigger(); 149 if (ret) { 150 printf("Failed to convert battery voltage\n"); 151 return ret; 152 } 153 154 /* measure Vbat voltage */ 155 battery_volt = twl6030_gpadc_read_channel(vbatch); 156 if (battery_volt < 0) { 157 printf("Failed to read battery voltage\n"); 158 return ret; 159 } 160 battery_volt = (battery_volt * twl->vbat_mult) >> twl->vbat_shift; 161 printf("Battery Voltage: %d mV\n", battery_volt); 162 163 return battery_volt; 164 } 165 166 void twl6030_init_battery_charging(void) 167 { 168 u8 val = 0; 169 int battery_volt = 0; 170 int ret = 0; 171 172 ret = twl6030_i2c_read_u8(TWL6030_CHIP_USB, USB_PRODUCT_ID_LSB, &val); 173 if (ret) { 174 puts("twl6030_init_battery_charging(): could not determine chip!\n"); 175 return; 176 } 177 if (val == 0x30) { 178 twl = &twl6030_info; 179 } else if (val == 0x32) { 180 twl = &twl6032_info; 181 } else { 182 puts("twl6030_init_battery_charging(): unsupported chip type\n"); 183 return; 184 } 185 186 /* Enable VBAT measurement */ 187 if (twl->chip_type == chip_TWL6030) { 188 twl6030_i2c_write_u8(TWL6030_CHIP_PM, MISC1, VBAT_MEAS); 189 twl6030_i2c_write_u8(TWL6030_CHIP_ADC, 190 TWL6030_GPADC_CTRL, 191 GPADC_CTRL_SCALER_DIV4); 192 } else { 193 twl6030_i2c_write_u8(TWL6030_CHIP_ADC, 194 TWL6032_GPADC_CTRL2, 195 GPADC_CTRL2_CH18_SCALER_EN); 196 } 197 198 /* Enable GPADC module */ 199 ret = twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, TOGGLE1, FGS | GPADCS); 200 if (ret) { 201 printf("Failed to enable GPADC\n"); 202 return; 203 } 204 205 battery_volt = twl6030_get_battery_voltage(); 206 if (battery_volt < 0) 207 return; 208 209 if (battery_volt < 3000) 210 printf("Main battery voltage too low!\n"); 211 212 /* Check for the presence of USB charger */ 213 twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, CONTROLLER_STAT1, &val); 214 215 /* check for battery presence indirectly via Fuel gauge */ 216 if ((val & VBUS_DET) && (battery_volt < 3300)) 217 twl6030_start_usb_charging(); 218 219 return; 220 } 221 222 void twl6030_power_mmc_init(int dev_index) 223 { 224 u8 value = 0; 225 226 if (dev_index == 0) { 227 /* 3.0V voltage output for VMMC */ 228 twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VMMC_CFG_VOLTAGE, 229 TWL6030_CFG_VOLTAGE_30); 230 231 /* Enable P1 output for VMMC */ 232 twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VMMC_CFG_STATE, 233 TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON); 234 235 twl6030_i2c_read_u8(TWL6030_CHIP_PM, TWL6030_PH_STS_BOOT, &value); 236 } else if (dev_index == 1) { 237 /* BOOT2 indicates 1.8V/2.8V VAUX1 for eMMC */ 238 if (value & TWL6030_PH_STS_BOOT2) { 239 /* 1.8V voltage output for VAUX1 */ 240 twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_VOLTAGE, 241 TWL6030_CFG_VOLTAGE_18); 242 } else { 243 /* 2.8V voltage output for VAUX1 */ 244 twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_VOLTAGE, 245 TWL6030_CFG_VOLTAGE_28); 246 } 247 248 /* Enable P1 output for VAUX */ 249 twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_STATE, 250 TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON); 251 } 252 } 253 254 void twl6030_usb_device_settings() 255 { 256 u8 value = 0; 257 258 /* 3.3V voltage output for VUSB */ 259 twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VUSB_CFG_VOLTAGE, 260 TWL6030_CFG_VOLTAGE_33); 261 262 /* Enable P1 output for VUSB */ 263 twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VUSB_CFG_STATE, 264 TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON); 265 266 /* Select the input supply for VUSB regulator */ 267 twl6030_i2c_read_u8(TWL6030_CHIP_PM, TWL6030_MISC2, &value); 268 value |= TWL6030_MISC2_VUSB_IN_VSYS; 269 value &= ~TWL6030_MISC2_VUSB_IN_PMID; 270 twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_MISC2, value); 271 } 272