1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 2516799f6SSteve Sakoman /* 3516799f6SSteve Sakoman * (C) Copyright 2010 4516799f6SSteve Sakoman * Texas Instruments, <www.ti.com> 5516799f6SSteve Sakoman */ 6516799f6SSteve Sakoman #include <config.h> 7516799f6SSteve Sakoman 8516799f6SSteve Sakoman #include <twl6030.h> 9516799f6SSteve Sakoman 10fc889503SOleg Kosheliev static struct twl6030_data *twl; 11fc889503SOleg Kosheliev 12fc889503SOleg Kosheliev static struct twl6030_data twl6030_info = { 13fc889503SOleg Kosheliev .chip_type = chip_TWL6030, 14fc889503SOleg Kosheliev .adc_rbase = GPCH0_LSB, 15fc889503SOleg Kosheliev .adc_ctrl = CTRL_P2, 16fc889503SOleg Kosheliev .adc_enable = CTRL_P2_SP2, 17fc889503SOleg Kosheliev .vbat_mult = TWL6030_VBAT_MULT, 18fc889503SOleg Kosheliev .vbat_shift = TWL6030_VBAT_SHIFT, 19fc889503SOleg Kosheliev }; 20fc889503SOleg Kosheliev 21340e6c83SOleg Kosheliev static struct twl6030_data twl6032_info = { 22340e6c83SOleg Kosheliev .chip_type = chip_TWL6032, 23340e6c83SOleg Kosheliev .adc_rbase = TWL6032_GPCH0_LSB, 24340e6c83SOleg Kosheliev .adc_ctrl = TWL6032_CTRL_P1, 25340e6c83SOleg Kosheliev .adc_enable = CTRL_P1_SP1, 26340e6c83SOleg Kosheliev .vbat_mult = TWL6032_VBAT_MULT, 27340e6c83SOleg Kosheliev .vbat_shift = TWL6032_VBAT_SHIFT, 28340e6c83SOleg Kosheliev }; 29340e6c83SOleg Kosheliev 30d6a2042dSPaul Kocialkowski 313e664f6dSBalaji T K static int twl6030_gpadc_read_channel(u8 channel_no) 323e664f6dSBalaji T K { 333e664f6dSBalaji T K u8 lsb = 0; 343e664f6dSBalaji T K u8 msb = 0; 353e664f6dSBalaji T K int ret = 0; 363e664f6dSBalaji T K 37345ef204SNishanth Menon ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC, 38fc889503SOleg Kosheliev twl->adc_rbase + channel_no * 2, &lsb); 393e664f6dSBalaji T K if (ret) 403e664f6dSBalaji T K return ret; 413e664f6dSBalaji T K 42345ef204SNishanth Menon ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC, 43fc889503SOleg Kosheliev twl->adc_rbase + 1 + channel_no * 2, &msb); 443e664f6dSBalaji T K if (ret) 453e664f6dSBalaji T K return ret; 463e664f6dSBalaji T K 473e664f6dSBalaji T K return (msb << 8) | lsb; 483e664f6dSBalaji T K } 493e664f6dSBalaji T K 503e664f6dSBalaji T K static int twl6030_gpadc_sw2_trigger(void) 513e664f6dSBalaji T K { 523e664f6dSBalaji T K u8 val; 533e664f6dSBalaji T K int ret = 0; 543e664f6dSBalaji T K 55fc889503SOleg Kosheliev ret = twl6030_i2c_write_u8(TWL6030_CHIP_ADC, 56fc889503SOleg Kosheliev twl->adc_ctrl, twl->adc_enable); 573e664f6dSBalaji T K if (ret) 583e664f6dSBalaji T K return ret; 593e664f6dSBalaji T K 603e664f6dSBalaji T K /* Waiting until the SW1 conversion ends*/ 613e664f6dSBalaji T K val = CTRL_P2_BUSY; 623e664f6dSBalaji T K 633e664f6dSBalaji T K while (!((val & CTRL_P2_EOCP2) && (!(val & CTRL_P2_BUSY)))) { 64fc889503SOleg Kosheliev ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC, 65fc889503SOleg Kosheliev twl->adc_ctrl, &val); 663e664f6dSBalaji T K if (ret) 673e664f6dSBalaji T K return ret; 683e664f6dSBalaji T K udelay(1000); 693e664f6dSBalaji T K } 703e664f6dSBalaji T K 713e664f6dSBalaji T K return 0; 723e664f6dSBalaji T K } 733e664f6dSBalaji T K 74d6a2042dSPaul Kocialkowski void twl6030_power_off(void) 75d6a2042dSPaul Kocialkowski { 76d6a2042dSPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_PHOENIX_DEV_ON, 77d6a2042dSPaul Kocialkowski TWL6030_PHOENIX_APP_DEVOFF | TWL6030_PHOENIX_CON_DEVOFF | 78d6a2042dSPaul Kocialkowski TWL6030_PHOENIX_MOD_DEVOFF); 79d6a2042dSPaul Kocialkowski } 80d6a2042dSPaul Kocialkowski 813e664f6dSBalaji T K void twl6030_stop_usb_charging(void) 823e664f6dSBalaji T K { 83345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CONTROLLER_CTRL1, 0); 843e664f6dSBalaji T K 853e664f6dSBalaji T K return; 863e664f6dSBalaji T K } 873e664f6dSBalaji T K 88516799f6SSteve Sakoman void twl6030_start_usb_charging(void) 89516799f6SSteve Sakoman { 90345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 91345ef204SNishanth Menon CHARGERUSB_VICHRG, CHARGERUSB_VICHRG_1500); 92345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 93345ef204SNishanth Menon CHARGERUSB_CINLIMIT, CHARGERUSB_CIN_LIMIT_NONE); 94345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 95345ef204SNishanth Menon CONTROLLER_INT_MASK, MBAT_TEMP); 96345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 97345ef204SNishanth Menon CHARGERUSB_INT_MASK, MASK_MCHARGERUSB_THMREG); 98345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 99345ef204SNishanth Menon CHARGERUSB_VOREG, CHARGERUSB_VOREG_4P0); 100345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 101345ef204SNishanth Menon CHARGERUSB_CTRL2, CHARGERUSB_CTRL2_VITERM_400); 102345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CHARGERUSB_CTRL1, TERM); 103516799f6SSteve Sakoman /* Enable USB charging */ 104345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 105345ef204SNishanth Menon CONTROLLER_CTRL1, CONTROLLER_CTRL1_EN_CHARGER); 106516799f6SSteve Sakoman return; 107516799f6SSteve Sakoman } 108516799f6SSteve Sakoman 1093e664f6dSBalaji T K int twl6030_get_battery_current(void) 1103e664f6dSBalaji T K { 1113e664f6dSBalaji T K int battery_current = 0; 1123e664f6dSBalaji T K u8 msb = 0; 1133e664f6dSBalaji T K u8 lsb = 0; 1143e664f6dSBalaji T K 115345ef204SNishanth Menon twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_11, &msb); 116345ef204SNishanth Menon twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_10, &lsb); 1173e664f6dSBalaji T K battery_current = ((msb << 8) | lsb); 1183e664f6dSBalaji T K 1193e664f6dSBalaji T K /* convert 10 bit signed number to 16 bit signed number */ 1203e664f6dSBalaji T K if (battery_current >= 0x2000) 1213e664f6dSBalaji T K battery_current = (battery_current - 0x4000); 1223e664f6dSBalaji T K 1233e664f6dSBalaji T K battery_current = battery_current * 3000 / 4096; 1243e664f6dSBalaji T K printf("Battery Current: %d mA\n", battery_current); 1253e664f6dSBalaji T K 1263e664f6dSBalaji T K return battery_current; 1273e664f6dSBalaji T K } 1283e664f6dSBalaji T K 1293e664f6dSBalaji T K int twl6030_get_battery_voltage(void) 1303e664f6dSBalaji T K { 1313e664f6dSBalaji T K int battery_volt = 0; 1323e664f6dSBalaji T K int ret = 0; 133340e6c83SOleg Kosheliev u8 vbatch; 134340e6c83SOleg Kosheliev 135340e6c83SOleg Kosheliev if (twl->chip_type == chip_TWL6030) { 136340e6c83SOleg Kosheliev vbatch = TWL6030_GPADC_VBAT_CHNL; 137340e6c83SOleg Kosheliev } else { 138340e6c83SOleg Kosheliev ret = twl6030_i2c_write_u8(TWL6030_CHIP_ADC, 139340e6c83SOleg Kosheliev TWL6032_GPSELECT_ISB, 140340e6c83SOleg Kosheliev TWL6032_GPADC_VBAT_CHNL); 141340e6c83SOleg Kosheliev if (ret) 142340e6c83SOleg Kosheliev return ret; 143340e6c83SOleg Kosheliev vbatch = 0; 144340e6c83SOleg Kosheliev } 1453e664f6dSBalaji T K 1463e664f6dSBalaji T K /* Start GPADC SW conversion */ 1473e664f6dSBalaji T K ret = twl6030_gpadc_sw2_trigger(); 1483e664f6dSBalaji T K if (ret) { 1493e664f6dSBalaji T K printf("Failed to convert battery voltage\n"); 1503e664f6dSBalaji T K return ret; 1513e664f6dSBalaji T K } 1523e664f6dSBalaji T K 1533e664f6dSBalaji T K /* measure Vbat voltage */ 154340e6c83SOleg Kosheliev battery_volt = twl6030_gpadc_read_channel(vbatch); 1553e664f6dSBalaji T K if (battery_volt < 0) { 1563e664f6dSBalaji T K printf("Failed to read battery voltage\n"); 1573e664f6dSBalaji T K return ret; 1583e664f6dSBalaji T K } 159fc889503SOleg Kosheliev battery_volt = (battery_volt * twl->vbat_mult) >> twl->vbat_shift; 1603e664f6dSBalaji T K printf("Battery Voltage: %d mV\n", battery_volt); 1613e664f6dSBalaji T K 1623e664f6dSBalaji T K return battery_volt; 1633e664f6dSBalaji T K } 1643e664f6dSBalaji T K 165516799f6SSteve Sakoman void twl6030_init_battery_charging(void) 166516799f6SSteve Sakoman { 167340e6c83SOleg Kosheliev u8 val = 0; 1683e664f6dSBalaji T K int battery_volt = 0; 1693e664f6dSBalaji T K int ret = 0; 1703e664f6dSBalaji T K 171340e6c83SOleg Kosheliev ret = twl6030_i2c_read_u8(TWL6030_CHIP_USB, USB_PRODUCT_ID_LSB, &val); 172340e6c83SOleg Kosheliev if (ret) { 173340e6c83SOleg Kosheliev puts("twl6030_init_battery_charging(): could not determine chip!\n"); 174340e6c83SOleg Kosheliev return; 175340e6c83SOleg Kosheliev } 176340e6c83SOleg Kosheliev if (val == 0x30) { 177fc889503SOleg Kosheliev twl = &twl6030_info; 178340e6c83SOleg Kosheliev } else if (val == 0x32) { 179340e6c83SOleg Kosheliev twl = &twl6032_info; 180340e6c83SOleg Kosheliev } else { 181340e6c83SOleg Kosheliev puts("twl6030_init_battery_charging(): unsupported chip type\n"); 182340e6c83SOleg Kosheliev return; 183340e6c83SOleg Kosheliev } 184fc889503SOleg Kosheliev 1853e664f6dSBalaji T K /* Enable VBAT measurement */ 186340e6c83SOleg Kosheliev if (twl->chip_type == chip_TWL6030) { 187345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_PM, MISC1, VBAT_MEAS); 188340e6c83SOleg Kosheliev twl6030_i2c_write_u8(TWL6030_CHIP_ADC, 189340e6c83SOleg Kosheliev TWL6030_GPADC_CTRL, 190340e6c83SOleg Kosheliev GPADC_CTRL_SCALER_DIV4); 191340e6c83SOleg Kosheliev } else { 192340e6c83SOleg Kosheliev twl6030_i2c_write_u8(TWL6030_CHIP_ADC, 193340e6c83SOleg Kosheliev TWL6032_GPADC_CTRL2, 194340e6c83SOleg Kosheliev GPADC_CTRL2_CH18_SCALER_EN); 195340e6c83SOleg Kosheliev } 1963e664f6dSBalaji T K 1973e664f6dSBalaji T K /* Enable GPADC module */ 198345ef204SNishanth Menon ret = twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, TOGGLE1, FGS | GPADCS); 1993e664f6dSBalaji T K if (ret) { 2003e664f6dSBalaji T K printf("Failed to enable GPADC\n"); 2013e664f6dSBalaji T K return; 2023e664f6dSBalaji T K } 2033e664f6dSBalaji T K 2043e664f6dSBalaji T K battery_volt = twl6030_get_battery_voltage(); 2053e664f6dSBalaji T K if (battery_volt < 0) 2063e664f6dSBalaji T K return; 2073e664f6dSBalaji T K 2083e664f6dSBalaji T K if (battery_volt < 3000) 2093e664f6dSBalaji T K printf("Main battery voltage too low!\n"); 2103e664f6dSBalaji T K 2113e664f6dSBalaji T K /* Check for the presence of USB charger */ 212340e6c83SOleg Kosheliev twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, CONTROLLER_STAT1, &val); 2133e664f6dSBalaji T K 2143e664f6dSBalaji T K /* check for battery presence indirectly via Fuel gauge */ 215340e6c83SOleg Kosheliev if ((val & VBUS_DET) && (battery_volt < 3300)) 216516799f6SSteve Sakoman twl6030_start_usb_charging(); 2173e664f6dSBalaji T K 218516799f6SSteve Sakoman return; 219516799f6SSteve Sakoman } 220516799f6SSteve Sakoman 221a85362fbSPaul Kocialkowski void twl6030_power_mmc_init(int dev_index) 22214fa2dd0SBalaji T K { 223d7b6a754SPaul Kocialkowski u8 value = 0; 224d7b6a754SPaul Kocialkowski 225a85362fbSPaul Kocialkowski if (dev_index == 0) { 226c5dbae7cSPaul Kocialkowski /* 3.0V voltage output for VMMC */ 227c5dbae7cSPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VMMC_CFG_VOLTAGE, 228c5dbae7cSPaul Kocialkowski TWL6030_CFG_VOLTAGE_30); 229c5dbae7cSPaul Kocialkowski 230c5dbae7cSPaul Kocialkowski /* Enable P1 output for VMMC */ 231c5dbae7cSPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VMMC_CFG_STATE, 232c5dbae7cSPaul Kocialkowski TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON); 233a85362fbSPaul Kocialkowski } else if (dev_index == 1) { 23428a3a43dSNicolae Rosia twl6030_i2c_read_u8(TWL6030_CHIP_PM, TWL6030_PH_STS_BOOT, 23528a3a43dSNicolae Rosia &value); 236d7b6a754SPaul Kocialkowski /* BOOT2 indicates 1.8V/2.8V VAUX1 for eMMC */ 237d7b6a754SPaul Kocialkowski if (value & TWL6030_PH_STS_BOOT2) { 238d7b6a754SPaul Kocialkowski /* 1.8V voltage output for VAUX1 */ 239d7b6a754SPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_VOLTAGE, 240d7b6a754SPaul Kocialkowski TWL6030_CFG_VOLTAGE_18); 241d7b6a754SPaul Kocialkowski } else { 242d7b6a754SPaul Kocialkowski /* 2.8V voltage output for VAUX1 */ 243d7b6a754SPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_VOLTAGE, 244d7b6a754SPaul Kocialkowski TWL6030_CFG_VOLTAGE_28); 245d7b6a754SPaul Kocialkowski } 246d7b6a754SPaul Kocialkowski 247d7b6a754SPaul Kocialkowski /* Enable P1 output for VAUX */ 248d7b6a754SPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_STATE, 249d7b6a754SPaul Kocialkowski TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON); 25014fa2dd0SBalaji T K } 251a85362fbSPaul Kocialkowski } 25214fa2dd0SBalaji T K 253516799f6SSteve Sakoman void twl6030_usb_device_settings() 254516799f6SSteve Sakoman { 255c5dbae7cSPaul Kocialkowski u8 value = 0; 256516799f6SSteve Sakoman 2570343f71fSPaul Kocialkowski /* 3.3V voltage output for VUSB */ 2580343f71fSPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VUSB_CFG_VOLTAGE, 2590343f71fSPaul Kocialkowski TWL6030_CFG_VOLTAGE_33); 2600343f71fSPaul Kocialkowski 261c5dbae7cSPaul Kocialkowski /* Enable P1 output for VUSB */ 262c5dbae7cSPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VUSB_CFG_STATE, 263c5dbae7cSPaul Kocialkowski TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON); 264516799f6SSteve Sakoman 265c5dbae7cSPaul Kocialkowski /* Select the input supply for VUSB regulator */ 266c5dbae7cSPaul Kocialkowski twl6030_i2c_read_u8(TWL6030_CHIP_PM, TWL6030_MISC2, &value); 267c5dbae7cSPaul Kocialkowski value |= TWL6030_MISC2_VUSB_IN_VSYS; 2686313c650SPaul Kocialkowski value &= ~TWL6030_MISC2_VUSB_IN_PMID; 269c5dbae7cSPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_MISC2, value); 270516799f6SSteve Sakoman } 271