1516799f6SSteve Sakoman /* 2516799f6SSteve Sakoman * (C) Copyright 2010 3516799f6SSteve Sakoman * Texas Instruments, <www.ti.com> 4516799f6SSteve Sakoman * 51a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 6516799f6SSteve Sakoman */ 7516799f6SSteve Sakoman #include <config.h> 8516799f6SSteve Sakoman #ifdef CONFIG_TWL6030_POWER 9516799f6SSteve Sakoman 10516799f6SSteve Sakoman #include <twl6030.h> 11516799f6SSteve Sakoman 12fc889503SOleg Kosheliev static struct twl6030_data *twl; 13fc889503SOleg Kosheliev 14fc889503SOleg Kosheliev static struct twl6030_data twl6030_info = { 15fc889503SOleg Kosheliev .chip_type = chip_TWL6030, 16fc889503SOleg Kosheliev .adc_rbase = GPCH0_LSB, 17fc889503SOleg Kosheliev .adc_ctrl = CTRL_P2, 18fc889503SOleg Kosheliev .adc_enable = CTRL_P2_SP2, 19fc889503SOleg Kosheliev .vbat_mult = TWL6030_VBAT_MULT, 20fc889503SOleg Kosheliev .vbat_shift = TWL6030_VBAT_SHIFT, 21fc889503SOleg Kosheliev }; 22fc889503SOleg Kosheliev 23*340e6c83SOleg Kosheliev static struct twl6030_data twl6032_info = { 24*340e6c83SOleg Kosheliev .chip_type = chip_TWL6032, 25*340e6c83SOleg Kosheliev .adc_rbase = TWL6032_GPCH0_LSB, 26*340e6c83SOleg Kosheliev .adc_ctrl = TWL6032_CTRL_P1, 27*340e6c83SOleg Kosheliev .adc_enable = CTRL_P1_SP1, 28*340e6c83SOleg Kosheliev .vbat_mult = TWL6032_VBAT_MULT, 29*340e6c83SOleg Kosheliev .vbat_shift = TWL6032_VBAT_SHIFT, 30*340e6c83SOleg Kosheliev }; 31*340e6c83SOleg Kosheliev 323e664f6dSBalaji T K static int twl6030_gpadc_read_channel(u8 channel_no) 333e664f6dSBalaji T K { 343e664f6dSBalaji T K u8 lsb = 0; 353e664f6dSBalaji T K u8 msb = 0; 363e664f6dSBalaji T K int ret = 0; 373e664f6dSBalaji T K 38345ef204SNishanth Menon ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC, 39fc889503SOleg Kosheliev twl->adc_rbase + channel_no * 2, &lsb); 403e664f6dSBalaji T K if (ret) 413e664f6dSBalaji T K return ret; 423e664f6dSBalaji T K 43345ef204SNishanth Menon ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC, 44fc889503SOleg Kosheliev twl->adc_rbase + 1 + channel_no * 2, &msb); 453e664f6dSBalaji T K if (ret) 463e664f6dSBalaji T K return ret; 473e664f6dSBalaji T K 483e664f6dSBalaji T K return (msb << 8) | lsb; 493e664f6dSBalaji T K } 503e664f6dSBalaji T K 513e664f6dSBalaji T K static int twl6030_gpadc_sw2_trigger(void) 523e664f6dSBalaji T K { 533e664f6dSBalaji T K u8 val; 543e664f6dSBalaji T K int ret = 0; 553e664f6dSBalaji T K 56fc889503SOleg Kosheliev ret = twl6030_i2c_write_u8(TWL6030_CHIP_ADC, 57fc889503SOleg Kosheliev twl->adc_ctrl, twl->adc_enable); 583e664f6dSBalaji T K if (ret) 593e664f6dSBalaji T K return ret; 603e664f6dSBalaji T K 613e664f6dSBalaji T K /* Waiting until the SW1 conversion ends*/ 623e664f6dSBalaji T K val = CTRL_P2_BUSY; 633e664f6dSBalaji T K 643e664f6dSBalaji T K while (!((val & CTRL_P2_EOCP2) && (!(val & CTRL_P2_BUSY)))) { 65fc889503SOleg Kosheliev ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC, 66fc889503SOleg Kosheliev twl->adc_ctrl, &val); 673e664f6dSBalaji T K if (ret) 683e664f6dSBalaji T K return ret; 693e664f6dSBalaji T K udelay(1000); 703e664f6dSBalaji T K } 713e664f6dSBalaji T K 723e664f6dSBalaji T K return 0; 733e664f6dSBalaji T K } 743e664f6dSBalaji T K 753e664f6dSBalaji T K void twl6030_stop_usb_charging(void) 763e664f6dSBalaji T K { 77345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CONTROLLER_CTRL1, 0); 783e664f6dSBalaji T K 793e664f6dSBalaji T K return; 803e664f6dSBalaji T K } 813e664f6dSBalaji T K 82516799f6SSteve Sakoman void twl6030_start_usb_charging(void) 83516799f6SSteve Sakoman { 84345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 85345ef204SNishanth Menon CHARGERUSB_VICHRG, CHARGERUSB_VICHRG_1500); 86345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 87345ef204SNishanth Menon CHARGERUSB_CINLIMIT, CHARGERUSB_CIN_LIMIT_NONE); 88345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 89345ef204SNishanth Menon CONTROLLER_INT_MASK, MBAT_TEMP); 90345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 91345ef204SNishanth Menon CHARGERUSB_INT_MASK, MASK_MCHARGERUSB_THMREG); 92345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 93345ef204SNishanth Menon CHARGERUSB_VOREG, CHARGERUSB_VOREG_4P0); 94345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 95345ef204SNishanth Menon CHARGERUSB_CTRL2, CHARGERUSB_CTRL2_VITERM_400); 96345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CHARGERUSB_CTRL1, TERM); 97516799f6SSteve Sakoman /* Enable USB charging */ 98345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 99345ef204SNishanth Menon CONTROLLER_CTRL1, CONTROLLER_CTRL1_EN_CHARGER); 100516799f6SSteve Sakoman return; 101516799f6SSteve Sakoman } 102516799f6SSteve Sakoman 1033e664f6dSBalaji T K int twl6030_get_battery_current(void) 1043e664f6dSBalaji T K { 1053e664f6dSBalaji T K int battery_current = 0; 1063e664f6dSBalaji T K u8 msb = 0; 1073e664f6dSBalaji T K u8 lsb = 0; 1083e664f6dSBalaji T K 109345ef204SNishanth Menon twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_11, &msb); 110345ef204SNishanth Menon twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_10, &lsb); 1113e664f6dSBalaji T K battery_current = ((msb << 8) | lsb); 1123e664f6dSBalaji T K 1133e664f6dSBalaji T K /* convert 10 bit signed number to 16 bit signed number */ 1143e664f6dSBalaji T K if (battery_current >= 0x2000) 1153e664f6dSBalaji T K battery_current = (battery_current - 0x4000); 1163e664f6dSBalaji T K 1173e664f6dSBalaji T K battery_current = battery_current * 3000 / 4096; 1183e664f6dSBalaji T K printf("Battery Current: %d mA\n", battery_current); 1193e664f6dSBalaji T K 1203e664f6dSBalaji T K return battery_current; 1213e664f6dSBalaji T K } 1223e664f6dSBalaji T K 1233e664f6dSBalaji T K int twl6030_get_battery_voltage(void) 1243e664f6dSBalaji T K { 1253e664f6dSBalaji T K int battery_volt = 0; 1263e664f6dSBalaji T K int ret = 0; 127*340e6c83SOleg Kosheliev u8 vbatch; 128*340e6c83SOleg Kosheliev 129*340e6c83SOleg Kosheliev if (twl->chip_type == chip_TWL6030) { 130*340e6c83SOleg Kosheliev vbatch = TWL6030_GPADC_VBAT_CHNL; 131*340e6c83SOleg Kosheliev } else { 132*340e6c83SOleg Kosheliev ret = twl6030_i2c_write_u8(TWL6030_CHIP_ADC, 133*340e6c83SOleg Kosheliev TWL6032_GPSELECT_ISB, 134*340e6c83SOleg Kosheliev TWL6032_GPADC_VBAT_CHNL); 135*340e6c83SOleg Kosheliev if (ret) 136*340e6c83SOleg Kosheliev return ret; 137*340e6c83SOleg Kosheliev vbatch = 0; 138*340e6c83SOleg Kosheliev } 1393e664f6dSBalaji T K 1403e664f6dSBalaji T K /* Start GPADC SW conversion */ 1413e664f6dSBalaji T K ret = twl6030_gpadc_sw2_trigger(); 1423e664f6dSBalaji T K if (ret) { 1433e664f6dSBalaji T K printf("Failed to convert battery voltage\n"); 1443e664f6dSBalaji T K return ret; 1453e664f6dSBalaji T K } 1463e664f6dSBalaji T K 1473e664f6dSBalaji T K /* measure Vbat voltage */ 148*340e6c83SOleg Kosheliev battery_volt = twl6030_gpadc_read_channel(vbatch); 1493e664f6dSBalaji T K if (battery_volt < 0) { 1503e664f6dSBalaji T K printf("Failed to read battery voltage\n"); 1513e664f6dSBalaji T K return ret; 1523e664f6dSBalaji T K } 153fc889503SOleg Kosheliev battery_volt = (battery_volt * twl->vbat_mult) >> twl->vbat_shift; 1543e664f6dSBalaji T K printf("Battery Voltage: %d mV\n", battery_volt); 1553e664f6dSBalaji T K 1563e664f6dSBalaji T K return battery_volt; 1573e664f6dSBalaji T K } 1583e664f6dSBalaji T K 159516799f6SSteve Sakoman void twl6030_init_battery_charging(void) 160516799f6SSteve Sakoman { 161*340e6c83SOleg Kosheliev u8 val = 0; 1623e664f6dSBalaji T K int battery_volt = 0; 1633e664f6dSBalaji T K int ret = 0; 1643e664f6dSBalaji T K 165*340e6c83SOleg Kosheliev ret = twl6030_i2c_read_u8(TWL6030_CHIP_USB, USB_PRODUCT_ID_LSB, &val); 166*340e6c83SOleg Kosheliev if (ret) { 167*340e6c83SOleg Kosheliev puts("twl6030_init_battery_charging(): could not determine chip!\n"); 168*340e6c83SOleg Kosheliev return; 169*340e6c83SOleg Kosheliev } 170*340e6c83SOleg Kosheliev if (val == 0x30) { 171fc889503SOleg Kosheliev twl = &twl6030_info; 172*340e6c83SOleg Kosheliev } else if (val == 0x32) { 173*340e6c83SOleg Kosheliev twl = &twl6032_info; 174*340e6c83SOleg Kosheliev } else { 175*340e6c83SOleg Kosheliev puts("twl6030_init_battery_charging(): unsupported chip type\n"); 176*340e6c83SOleg Kosheliev return; 177*340e6c83SOleg Kosheliev } 178fc889503SOleg Kosheliev 1793e664f6dSBalaji T K /* Enable VBAT measurement */ 180*340e6c83SOleg Kosheliev if (twl->chip_type == chip_TWL6030) { 181345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_PM, MISC1, VBAT_MEAS); 182*340e6c83SOleg Kosheliev twl6030_i2c_write_u8(TWL6030_CHIP_ADC, 183*340e6c83SOleg Kosheliev TWL6030_GPADC_CTRL, 184*340e6c83SOleg Kosheliev GPADC_CTRL_SCALER_DIV4); 185*340e6c83SOleg Kosheliev } else { 186*340e6c83SOleg Kosheliev twl6030_i2c_write_u8(TWL6030_CHIP_ADC, 187*340e6c83SOleg Kosheliev TWL6032_GPADC_CTRL2, 188*340e6c83SOleg Kosheliev GPADC_CTRL2_CH18_SCALER_EN); 189*340e6c83SOleg Kosheliev } 1903e664f6dSBalaji T K 1913e664f6dSBalaji T K /* Enable GPADC module */ 192345ef204SNishanth Menon ret = twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, TOGGLE1, FGS | GPADCS); 1933e664f6dSBalaji T K if (ret) { 1943e664f6dSBalaji T K printf("Failed to enable GPADC\n"); 1953e664f6dSBalaji T K return; 1963e664f6dSBalaji T K } 1973e664f6dSBalaji T K 1983e664f6dSBalaji T K battery_volt = twl6030_get_battery_voltage(); 1993e664f6dSBalaji T K if (battery_volt < 0) 2003e664f6dSBalaji T K return; 2013e664f6dSBalaji T K 2023e664f6dSBalaji T K if (battery_volt < 3000) 2033e664f6dSBalaji T K printf("Main battery voltage too low!\n"); 2043e664f6dSBalaji T K 2053e664f6dSBalaji T K /* Check for the presence of USB charger */ 206*340e6c83SOleg Kosheliev twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, CONTROLLER_STAT1, &val); 2073e664f6dSBalaji T K 2083e664f6dSBalaji T K /* check for battery presence indirectly via Fuel gauge */ 209*340e6c83SOleg Kosheliev if ((val & VBUS_DET) && (battery_volt < 3300)) 210516799f6SSteve Sakoman twl6030_start_usb_charging(); 2113e664f6dSBalaji T K 212516799f6SSteve Sakoman return; 213516799f6SSteve Sakoman } 214516799f6SSteve Sakoman 21514fa2dd0SBalaji T K void twl6030_power_mmc_init() 21614fa2dd0SBalaji T K { 21714fa2dd0SBalaji T K /* set voltage to 3.0 and turnon for APP */ 218345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_PM, VMMC_CFG_VOLTATE, 0x15); 219345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_PM, VMMC_CFG_STATE, 0x21); 22014fa2dd0SBalaji T K } 22114fa2dd0SBalaji T K 222516799f6SSteve Sakoman void twl6030_usb_device_settings() 223516799f6SSteve Sakoman { 224516799f6SSteve Sakoman u8 data = 0; 225516799f6SSteve Sakoman 226516799f6SSteve Sakoman /* Select APP Group and set state to ON */ 227345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_PM, VUSB_CFG_STATE, 0x21); 228516799f6SSteve Sakoman 229345ef204SNishanth Menon twl6030_i2c_read_u8(TWL6030_CHIP_PM, MISC2, &data); 230516799f6SSteve Sakoman data |= 0x10; 231516799f6SSteve Sakoman 232516799f6SSteve Sakoman /* Select the input supply for VBUS regulator */ 233345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_PM, MISC2, data); 234516799f6SSteve Sakoman } 235516799f6SSteve Sakoman #endif 236