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 9516799f6SSteve Sakoman #include <twl6030.h> 10516799f6SSteve Sakoman 11fc889503SOleg Kosheliev static struct twl6030_data *twl; 12fc889503SOleg Kosheliev 13fc889503SOleg Kosheliev static struct twl6030_data twl6030_info = { 14fc889503SOleg Kosheliev .chip_type = chip_TWL6030, 15fc889503SOleg Kosheliev .adc_rbase = GPCH0_LSB, 16fc889503SOleg Kosheliev .adc_ctrl = CTRL_P2, 17fc889503SOleg Kosheliev .adc_enable = CTRL_P2_SP2, 18fc889503SOleg Kosheliev .vbat_mult = TWL6030_VBAT_MULT, 19fc889503SOleg Kosheliev .vbat_shift = TWL6030_VBAT_SHIFT, 20fc889503SOleg Kosheliev }; 21fc889503SOleg Kosheliev 22340e6c83SOleg Kosheliev static struct twl6030_data twl6032_info = { 23340e6c83SOleg Kosheliev .chip_type = chip_TWL6032, 24340e6c83SOleg Kosheliev .adc_rbase = TWL6032_GPCH0_LSB, 25340e6c83SOleg Kosheliev .adc_ctrl = TWL6032_CTRL_P1, 26340e6c83SOleg Kosheliev .adc_enable = CTRL_P1_SP1, 27340e6c83SOleg Kosheliev .vbat_mult = TWL6032_VBAT_MULT, 28340e6c83SOleg Kosheliev .vbat_shift = TWL6032_VBAT_SHIFT, 29340e6c83SOleg Kosheliev }; 30340e6c83SOleg Kosheliev 31d6a2042dSPaul Kocialkowski 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 75d6a2042dSPaul Kocialkowski void twl6030_power_off(void) 76d6a2042dSPaul Kocialkowski { 77d6a2042dSPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_PHOENIX_DEV_ON, 78d6a2042dSPaul Kocialkowski TWL6030_PHOENIX_APP_DEVOFF | TWL6030_PHOENIX_CON_DEVOFF | 79d6a2042dSPaul Kocialkowski TWL6030_PHOENIX_MOD_DEVOFF); 80d6a2042dSPaul Kocialkowski } 81d6a2042dSPaul Kocialkowski 823e664f6dSBalaji T K void twl6030_stop_usb_charging(void) 833e664f6dSBalaji T K { 84345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CONTROLLER_CTRL1, 0); 853e664f6dSBalaji T K 863e664f6dSBalaji T K return; 873e664f6dSBalaji T K } 883e664f6dSBalaji T K 89516799f6SSteve Sakoman void twl6030_start_usb_charging(void) 90516799f6SSteve Sakoman { 91345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 92345ef204SNishanth Menon CHARGERUSB_VICHRG, CHARGERUSB_VICHRG_1500); 93345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 94345ef204SNishanth Menon CHARGERUSB_CINLIMIT, CHARGERUSB_CIN_LIMIT_NONE); 95345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 96345ef204SNishanth Menon CONTROLLER_INT_MASK, MBAT_TEMP); 97345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 98345ef204SNishanth Menon CHARGERUSB_INT_MASK, MASK_MCHARGERUSB_THMREG); 99345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 100345ef204SNishanth Menon CHARGERUSB_VOREG, CHARGERUSB_VOREG_4P0); 101345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 102345ef204SNishanth Menon CHARGERUSB_CTRL2, CHARGERUSB_CTRL2_VITERM_400); 103345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CHARGERUSB_CTRL1, TERM); 104516799f6SSteve Sakoman /* Enable USB charging */ 105345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 106345ef204SNishanth Menon CONTROLLER_CTRL1, CONTROLLER_CTRL1_EN_CHARGER); 107516799f6SSteve Sakoman return; 108516799f6SSteve Sakoman } 109516799f6SSteve Sakoman 1103e664f6dSBalaji T K int twl6030_get_battery_current(void) 1113e664f6dSBalaji T K { 1123e664f6dSBalaji T K int battery_current = 0; 1133e664f6dSBalaji T K u8 msb = 0; 1143e664f6dSBalaji T K u8 lsb = 0; 1153e664f6dSBalaji T K 116345ef204SNishanth Menon twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_11, &msb); 117345ef204SNishanth Menon twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_10, &lsb); 1183e664f6dSBalaji T K battery_current = ((msb << 8) | lsb); 1193e664f6dSBalaji T K 1203e664f6dSBalaji T K /* convert 10 bit signed number to 16 bit signed number */ 1213e664f6dSBalaji T K if (battery_current >= 0x2000) 1223e664f6dSBalaji T K battery_current = (battery_current - 0x4000); 1233e664f6dSBalaji T K 1243e664f6dSBalaji T K battery_current = battery_current * 3000 / 4096; 1253e664f6dSBalaji T K printf("Battery Current: %d mA\n", battery_current); 1263e664f6dSBalaji T K 1273e664f6dSBalaji T K return battery_current; 1283e664f6dSBalaji T K } 1293e664f6dSBalaji T K 1303e664f6dSBalaji T K int twl6030_get_battery_voltage(void) 1313e664f6dSBalaji T K { 1323e664f6dSBalaji T K int battery_volt = 0; 1333e664f6dSBalaji T K int ret = 0; 134340e6c83SOleg Kosheliev u8 vbatch; 135340e6c83SOleg Kosheliev 136340e6c83SOleg Kosheliev if (twl->chip_type == chip_TWL6030) { 137340e6c83SOleg Kosheliev vbatch = TWL6030_GPADC_VBAT_CHNL; 138340e6c83SOleg Kosheliev } else { 139340e6c83SOleg Kosheliev ret = twl6030_i2c_write_u8(TWL6030_CHIP_ADC, 140340e6c83SOleg Kosheliev TWL6032_GPSELECT_ISB, 141340e6c83SOleg Kosheliev TWL6032_GPADC_VBAT_CHNL); 142340e6c83SOleg Kosheliev if (ret) 143340e6c83SOleg Kosheliev return ret; 144340e6c83SOleg Kosheliev vbatch = 0; 145340e6c83SOleg Kosheliev } 1463e664f6dSBalaji T K 1473e664f6dSBalaji T K /* Start GPADC SW conversion */ 1483e664f6dSBalaji T K ret = twl6030_gpadc_sw2_trigger(); 1493e664f6dSBalaji T K if (ret) { 1503e664f6dSBalaji T K printf("Failed to convert battery voltage\n"); 1513e664f6dSBalaji T K return ret; 1523e664f6dSBalaji T K } 1533e664f6dSBalaji T K 1543e664f6dSBalaji T K /* measure Vbat voltage */ 155340e6c83SOleg Kosheliev battery_volt = twl6030_gpadc_read_channel(vbatch); 1563e664f6dSBalaji T K if (battery_volt < 0) { 1573e664f6dSBalaji T K printf("Failed to read battery voltage\n"); 1583e664f6dSBalaji T K return ret; 1593e664f6dSBalaji T K } 160fc889503SOleg Kosheliev battery_volt = (battery_volt * twl->vbat_mult) >> twl->vbat_shift; 1613e664f6dSBalaji T K printf("Battery Voltage: %d mV\n", battery_volt); 1623e664f6dSBalaji T K 1633e664f6dSBalaji T K return battery_volt; 1643e664f6dSBalaji T K } 1653e664f6dSBalaji T K 166516799f6SSteve Sakoman void twl6030_init_battery_charging(void) 167516799f6SSteve Sakoman { 168340e6c83SOleg Kosheliev u8 val = 0; 1693e664f6dSBalaji T K int battery_volt = 0; 1703e664f6dSBalaji T K int ret = 0; 1713e664f6dSBalaji T K 172340e6c83SOleg Kosheliev ret = twl6030_i2c_read_u8(TWL6030_CHIP_USB, USB_PRODUCT_ID_LSB, &val); 173340e6c83SOleg Kosheliev if (ret) { 174340e6c83SOleg Kosheliev puts("twl6030_init_battery_charging(): could not determine chip!\n"); 175340e6c83SOleg Kosheliev return; 176340e6c83SOleg Kosheliev } 177340e6c83SOleg Kosheliev if (val == 0x30) { 178fc889503SOleg Kosheliev twl = &twl6030_info; 179340e6c83SOleg Kosheliev } else if (val == 0x32) { 180340e6c83SOleg Kosheliev twl = &twl6032_info; 181340e6c83SOleg Kosheliev } else { 182340e6c83SOleg Kosheliev puts("twl6030_init_battery_charging(): unsupported chip type\n"); 183340e6c83SOleg Kosheliev return; 184340e6c83SOleg Kosheliev } 185fc889503SOleg Kosheliev 1863e664f6dSBalaji T K /* Enable VBAT measurement */ 187340e6c83SOleg Kosheliev if (twl->chip_type == chip_TWL6030) { 188345ef204SNishanth Menon twl6030_i2c_write_u8(TWL6030_CHIP_PM, MISC1, VBAT_MEAS); 189340e6c83SOleg Kosheliev twl6030_i2c_write_u8(TWL6030_CHIP_ADC, 190340e6c83SOleg Kosheliev TWL6030_GPADC_CTRL, 191340e6c83SOleg Kosheliev GPADC_CTRL_SCALER_DIV4); 192340e6c83SOleg Kosheliev } else { 193340e6c83SOleg Kosheliev twl6030_i2c_write_u8(TWL6030_CHIP_ADC, 194340e6c83SOleg Kosheliev TWL6032_GPADC_CTRL2, 195340e6c83SOleg Kosheliev GPADC_CTRL2_CH18_SCALER_EN); 196340e6c83SOleg Kosheliev } 1973e664f6dSBalaji T K 1983e664f6dSBalaji T K /* Enable GPADC module */ 199345ef204SNishanth Menon ret = twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, TOGGLE1, FGS | GPADCS); 2003e664f6dSBalaji T K if (ret) { 2013e664f6dSBalaji T K printf("Failed to enable GPADC\n"); 2023e664f6dSBalaji T K return; 2033e664f6dSBalaji T K } 2043e664f6dSBalaji T K 2053e664f6dSBalaji T K battery_volt = twl6030_get_battery_voltage(); 2063e664f6dSBalaji T K if (battery_volt < 0) 2073e664f6dSBalaji T K return; 2083e664f6dSBalaji T K 2093e664f6dSBalaji T K if (battery_volt < 3000) 2103e664f6dSBalaji T K printf("Main battery voltage too low!\n"); 2113e664f6dSBalaji T K 2123e664f6dSBalaji T K /* Check for the presence of USB charger */ 213340e6c83SOleg Kosheliev twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, CONTROLLER_STAT1, &val); 2143e664f6dSBalaji T K 2153e664f6dSBalaji T K /* check for battery presence indirectly via Fuel gauge */ 216340e6c83SOleg Kosheliev if ((val & VBUS_DET) && (battery_volt < 3300)) 217516799f6SSteve Sakoman twl6030_start_usb_charging(); 2183e664f6dSBalaji T K 219516799f6SSteve Sakoman return; 220516799f6SSteve Sakoman } 221516799f6SSteve Sakoman 222a85362fbSPaul Kocialkowski void twl6030_power_mmc_init(int dev_index) 22314fa2dd0SBalaji T K { 224d7b6a754SPaul Kocialkowski u8 value = 0; 225d7b6a754SPaul Kocialkowski 226a85362fbSPaul Kocialkowski if (dev_index == 0) { 227c5dbae7cSPaul Kocialkowski /* 3.0V voltage output for VMMC */ 228c5dbae7cSPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VMMC_CFG_VOLTAGE, 229c5dbae7cSPaul Kocialkowski TWL6030_CFG_VOLTAGE_30); 230c5dbae7cSPaul Kocialkowski 231c5dbae7cSPaul Kocialkowski /* Enable P1 output for VMMC */ 232c5dbae7cSPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VMMC_CFG_STATE, 233c5dbae7cSPaul Kocialkowski TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON); 234a85362fbSPaul Kocialkowski } else if (dev_index == 1) { 235*28a3a43dSNicolae Rosia twl6030_i2c_read_u8(TWL6030_CHIP_PM, TWL6030_PH_STS_BOOT, 236*28a3a43dSNicolae Rosia &value); 237d7b6a754SPaul Kocialkowski /* BOOT2 indicates 1.8V/2.8V VAUX1 for eMMC */ 238d7b6a754SPaul Kocialkowski if (value & TWL6030_PH_STS_BOOT2) { 239d7b6a754SPaul Kocialkowski /* 1.8V voltage output for VAUX1 */ 240d7b6a754SPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_VOLTAGE, 241d7b6a754SPaul Kocialkowski TWL6030_CFG_VOLTAGE_18); 242d7b6a754SPaul Kocialkowski } else { 243d7b6a754SPaul Kocialkowski /* 2.8V voltage output for VAUX1 */ 244d7b6a754SPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_VOLTAGE, 245d7b6a754SPaul Kocialkowski TWL6030_CFG_VOLTAGE_28); 246d7b6a754SPaul Kocialkowski } 247d7b6a754SPaul Kocialkowski 248d7b6a754SPaul Kocialkowski /* Enable P1 output for VAUX */ 249d7b6a754SPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VAUX1_CFG_STATE, 250d7b6a754SPaul Kocialkowski TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON); 25114fa2dd0SBalaji T K } 252a85362fbSPaul Kocialkowski } 25314fa2dd0SBalaji T K 254516799f6SSteve Sakoman void twl6030_usb_device_settings() 255516799f6SSteve Sakoman { 256c5dbae7cSPaul Kocialkowski u8 value = 0; 257516799f6SSteve Sakoman 2580343f71fSPaul Kocialkowski /* 3.3V voltage output for VUSB */ 2590343f71fSPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VUSB_CFG_VOLTAGE, 2600343f71fSPaul Kocialkowski TWL6030_CFG_VOLTAGE_33); 2610343f71fSPaul Kocialkowski 262c5dbae7cSPaul Kocialkowski /* Enable P1 output for VUSB */ 263c5dbae7cSPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_VUSB_CFG_STATE, 264c5dbae7cSPaul Kocialkowski TWL6030_CFG_STATE_P1 | TWL6030_CFG_STATE_ON); 265516799f6SSteve Sakoman 266c5dbae7cSPaul Kocialkowski /* Select the input supply for VUSB regulator */ 267c5dbae7cSPaul Kocialkowski twl6030_i2c_read_u8(TWL6030_CHIP_PM, TWL6030_MISC2, &value); 268c5dbae7cSPaul Kocialkowski value |= TWL6030_MISC2_VUSB_IN_VSYS; 2696313c650SPaul Kocialkowski value &= ~TWL6030_MISC2_VUSB_IN_PMID; 270c5dbae7cSPaul Kocialkowski twl6030_i2c_write_u8(TWL6030_CHIP_PM, TWL6030_MISC2, value); 271516799f6SSteve Sakoman } 272