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