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 23340e6c83SOleg Kosheliev static struct twl6030_data twl6032_info = { 24340e6c83SOleg Kosheliev .chip_type = chip_TWL6032, 25340e6c83SOleg Kosheliev .adc_rbase = TWL6032_GPCH0_LSB, 26340e6c83SOleg Kosheliev .adc_ctrl = TWL6032_CTRL_P1, 27340e6c83SOleg Kosheliev .adc_enable = CTRL_P1_SP1, 28340e6c83SOleg Kosheliev .vbat_mult = TWL6032_VBAT_MULT, 29340e6c83SOleg Kosheliev .vbat_shift = TWL6032_VBAT_SHIFT, 30340e6c83SOleg Kosheliev }; 31340e6c83SOleg 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; 127340e6c83SOleg Kosheliev u8 vbatch; 128340e6c83SOleg Kosheliev 129340e6c83SOleg Kosheliev if (twl->chip_type == chip_TWL6030) { 130340e6c83SOleg Kosheliev vbatch = TWL6030_GPADC_VBAT_CHNL; 131340e6c83SOleg Kosheliev } else { 132340e6c83SOleg Kosheliev ret = twl6030_i2c_write_u8(TWL6030_CHIP_ADC, 133340e6c83SOleg Kosheliev TWL6032_GPSELECT_ISB, 134340e6c83SOleg Kosheliev TWL6032_GPADC_VBAT_CHNL); 135340e6c83SOleg Kosheliev if (ret) 136340e6c83SOleg Kosheliev return ret; 137340e6c83SOleg Kosheliev vbatch = 0; 138340e6c83SOleg 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 */ 148340e6c83SOleg 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 { 161340e6c83SOleg Kosheliev u8 val = 0; 1623e664f6dSBalaji T K int battery_volt = 0; 1633e664f6dSBalaji T K int ret = 0; 1643e664f6dSBalaji T K 165340e6c83SOleg Kosheliev ret = twl6030_i2c_read_u8(TWL6030_CHIP_USB, USB_PRODUCT_ID_LSB, &val); 166340e6c83SOleg Kosheliev if (ret) { 167340e6c83SOleg Kosheliev puts("twl6030_init_battery_charging(): could not determine chip!\n"); 168340e6c83SOleg Kosheliev return; 169340e6c83SOleg Kosheliev } 170340e6c83SOleg Kosheliev if (val == 0x30) { 171fc889503SOleg Kosheliev twl = &twl6030_info; 172340e6c83SOleg Kosheliev } else if (val == 0x32) { 173340e6c83SOleg Kosheliev twl = &twl6032_info; 174340e6c83SOleg Kosheliev } else { 175340e6c83SOleg Kosheliev puts("twl6030_init_battery_charging(): unsupported chip type\n"); 176340e6c83SOleg Kosheliev return; 177340e6c83SOleg Kosheliev } 178fc889503SOleg Kosheliev 1793e664f6dSBalaji T K /* Enable VBAT measurement */ 180340e6c83SOleg Kosheliev if (twl->chip_type == chip_TWL6030) { 181345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_PM, MISC1, VBAT_MEAS); 182340e6c83SOleg Kosheliev twl6030_i2c_write_u8(TWL6030_CHIP_ADC, 183340e6c83SOleg Kosheliev TWL6030_GPADC_CTRL, 184340e6c83SOleg Kosheliev GPADC_CTRL_SCALER_DIV4); 185340e6c83SOleg Kosheliev } else { 186340e6c83SOleg Kosheliev twl6030_i2c_write_u8(TWL6030_CHIP_ADC, 187340e6c83SOleg Kosheliev TWL6032_GPADC_CTRL2, 188340e6c83SOleg Kosheliev GPADC_CTRL2_CH18_SCALER_EN); 189340e6c83SOleg 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 */ 206340e6c83SOleg 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 */ 209340e6c83SOleg Kosheliev if ((val & VBUS_DET) && (battery_volt < 3300)) 210516799f6SSteve Sakoman twl6030_start_usb_charging(); 2113e664f6dSBalaji T K 212516799f6SSteve Sakoman return; 213516799f6SSteve Sakoman } 214516799f6SSteve Sakoman 215a85362fbSPaul Kocialkowski void twl6030_power_mmc_init(int dev_index) 21614fa2dd0SBalaji T K { 217d7b6a754SPaul Kocialkowski u8 value = 0; 218d7b6a754SPaul Kocialkowski 219a85362fbSPaul Kocialkowski if (dev_index == 0) { 220c5dbae7cSPaul Kocialkowski /* 3.0V voltage output for VMMC */ 221c5dbae7cSPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VMMC_CFG_VOLTAGE, 222c5dbae7cSPaul Kocialkowski TWL6030_CFG_VOLTAGE_30); 223c5dbae7cSPaul Kocialkowski 224c5dbae7cSPaul Kocialkowski /* Enable P1 output for VMMC */ 225c5dbae7cSPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VMMC_CFG_STATE, 226c5dbae7cSPaul Kocialkowski TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON); 227d7b6a754SPaul Kocialkowski 228d7b6a754SPaul Kocialkowski twl6030_i2c_read_u8(TWL6030_CHIP_PM, TWL6030_PH_STS_BOOT, &value); 229a85362fbSPaul Kocialkowski } else if (dev_index == 1) { 230d7b6a754SPaul Kocialkowski /* BOOT2 indicates 1.8V/2.8V VAUX1 for eMMC */ 231d7b6a754SPaul Kocialkowski if (value & TWL6030_PH_STS_BOOT2) { 232d7b6a754SPaul Kocialkowski /* 1.8V voltage output for VAUX1 */ 233d7b6a754SPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_VOLTAGE, 234d7b6a754SPaul Kocialkowski TWL6030_CFG_VOLTAGE_18); 235d7b6a754SPaul Kocialkowski } else { 236d7b6a754SPaul Kocialkowski /* 2.8V voltage output for VAUX1 */ 237d7b6a754SPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_VOLTAGE, 238d7b6a754SPaul Kocialkowski TWL6030_CFG_VOLTAGE_28); 239d7b6a754SPaul Kocialkowski } 240d7b6a754SPaul Kocialkowski 241d7b6a754SPaul Kocialkowski /* Enable P1 output for VAUX */ 242d7b6a754SPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_STATE, 243d7b6a754SPaul Kocialkowski TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON); 24414fa2dd0SBalaji T K } 245a85362fbSPaul Kocialkowski } 24614fa2dd0SBalaji T K 247516799f6SSteve Sakoman void twl6030_usb_device_settings() 248516799f6SSteve Sakoman { 249c5dbae7cSPaul Kocialkowski u8 value = 0; 250516799f6SSteve Sakoman 251*0343f71fSPaul Kocialkowski /* 3.3V voltage output for VUSB */ 252*0343f71fSPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VUSB_CFG_VOLTAGE, 253*0343f71fSPaul Kocialkowski TWL6030_CFG_VOLTAGE_33); 254*0343f71fSPaul Kocialkowski 255c5dbae7cSPaul Kocialkowski /* Enable P1 output for VUSB */ 256c5dbae7cSPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VUSB_CFG_STATE, 257c5dbae7cSPaul Kocialkowski TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON); 258516799f6SSteve Sakoman 259c5dbae7cSPaul Kocialkowski /* Select the input supply for VUSB regulator */ 260c5dbae7cSPaul Kocialkowski twl6030_i2c_read_u8(TWL6030_CHIP_PM, TWL6030_MISC2, &value); 261c5dbae7cSPaul Kocialkowski value |= TWL6030_MISC2_VUSB_IN_VSYS; 262c5dbae7cSPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_MISC2, value); 263516799f6SSteve Sakoman } 264516799f6SSteve Sakoman #endif 265