/*
 * (C) Copyright 2010
 * Texas Instruments, <www.ti.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */
#include <config.h>
#ifdef CONFIG_TWL6030_POWER

#include <twl6030.h>

static struct twl6030_data *twl;

static struct twl6030_data twl6030_info = {
	.chip_type	= chip_TWL6030,
	.adc_rbase	= GPCH0_LSB,
	.adc_ctrl	= CTRL_P2,
	.adc_enable	= CTRL_P2_SP2,
	.vbat_mult	= TWL6030_VBAT_MULT,
	.vbat_shift	= TWL6030_VBAT_SHIFT,
};

static struct twl6030_data twl6032_info = {
	.chip_type	= chip_TWL6032,
	.adc_rbase	= TWL6032_GPCH0_LSB,
	.adc_ctrl	= TWL6032_CTRL_P1,
	.adc_enable	= CTRL_P1_SP1,
	.vbat_mult	= TWL6032_VBAT_MULT,
	.vbat_shift	= TWL6032_VBAT_SHIFT,
};

static int twl6030_gpadc_read_channel(u8 channel_no)
{
	u8 lsb = 0;
	u8 msb = 0;
	int ret = 0;

	ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC,
				  twl->adc_rbase + channel_no * 2, &lsb);
	if (ret)
		return ret;

	ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC,
				  twl->adc_rbase + 1 + channel_no * 2, &msb);
	if (ret)
		return ret;

	return (msb << 8) | lsb;
}

static int twl6030_gpadc_sw2_trigger(void)
{
	u8 val;
	int ret = 0;

	ret = twl6030_i2c_write_u8(TWL6030_CHIP_ADC,
				   twl->adc_ctrl, twl->adc_enable);
	if (ret)
		return ret;

	/* Waiting until the SW1 conversion ends*/
	val =  CTRL_P2_BUSY;

	while (!((val & CTRL_P2_EOCP2) && (!(val & CTRL_P2_BUSY)))) {
		ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC,
					  twl->adc_ctrl, &val);
		if (ret)
			return ret;
		udelay(1000);
	}

	return 0;
}

void twl6030_stop_usb_charging(void)
{
	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CONTROLLER_CTRL1, 0);

	return;
}

void twl6030_start_usb_charging(void)
{
	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
			     CHARGERUSB_VICHRG, CHARGERUSB_VICHRG_1500);
	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
			     CHARGERUSB_CINLIMIT, CHARGERUSB_CIN_LIMIT_NONE);
	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
			     CONTROLLER_INT_MASK, MBAT_TEMP);
	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
			     CHARGERUSB_INT_MASK, MASK_MCHARGERUSB_THMREG);
	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
			     CHARGERUSB_VOREG, CHARGERUSB_VOREG_4P0);
	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
			     CHARGERUSB_CTRL2, CHARGERUSB_CTRL2_VITERM_400);
	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CHARGERUSB_CTRL1, TERM);
	/* Enable USB charging */
	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER,
			     CONTROLLER_CTRL1, CONTROLLER_CTRL1_EN_CHARGER);
	return;
}

int twl6030_get_battery_current(void)
{
	int battery_current = 0;
	u8 msb = 0;
	u8 lsb = 0;

	twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_11, &msb);
	twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, FG_REG_10, &lsb);
	battery_current = ((msb << 8) | lsb);

	/* convert 10 bit signed number to 16 bit signed number */
	if (battery_current >= 0x2000)
		battery_current = (battery_current - 0x4000);

	battery_current = battery_current * 3000 / 4096;
	printf("Battery Current: %d mA\n", battery_current);

	return battery_current;
}

int twl6030_get_battery_voltage(void)
{
	int battery_volt = 0;
	int ret = 0;
	u8 vbatch;

	if (twl->chip_type == chip_TWL6030) {
		vbatch = TWL6030_GPADC_VBAT_CHNL;
	} else {
		ret = twl6030_i2c_write_u8(TWL6030_CHIP_ADC,
					   TWL6032_GPSELECT_ISB,
					   TWL6032_GPADC_VBAT_CHNL);
		if (ret)
			return ret;
		vbatch = 0;
	}

	/* Start GPADC SW conversion */
	ret = twl6030_gpadc_sw2_trigger();
	if (ret) {
		printf("Failed to convert battery voltage\n");
		return ret;
	}

	/* measure Vbat voltage */
	battery_volt = twl6030_gpadc_read_channel(vbatch);
	if (battery_volt < 0) {
		printf("Failed to read battery voltage\n");
		return ret;
	}
	battery_volt = (battery_volt * twl->vbat_mult) >> twl->vbat_shift;
	printf("Battery Voltage: %d mV\n", battery_volt);

	return battery_volt;
}

void twl6030_init_battery_charging(void)
{
	u8 val = 0;
	int battery_volt = 0;
	int ret = 0;

	ret = twl6030_i2c_read_u8(TWL6030_CHIP_USB, USB_PRODUCT_ID_LSB, &val);
	if (ret) {
		puts("twl6030_init_battery_charging(): could not determine chip!\n");
		return;
	}
	if (val == 0x30) {
		twl = &twl6030_info;
	} else if (val == 0x32) {
		twl = &twl6032_info;
	} else {
		puts("twl6030_init_battery_charging(): unsupported chip type\n");
		return;
	}

	/* Enable VBAT measurement */
	if (twl->chip_type == chip_TWL6030) {
		twl6030_i2c_write_u8(TWL6030_CHIP_PM, MISC1, VBAT_MEAS);
		twl6030_i2c_write_u8(TWL6030_CHIP_ADC,
				     TWL6030_GPADC_CTRL,
				     GPADC_CTRL_SCALER_DIV4);
	} else {
		twl6030_i2c_write_u8(TWL6030_CHIP_ADC,
				     TWL6032_GPADC_CTRL2,
				     GPADC_CTRL2_CH18_SCALER_EN);
	}

	/* Enable GPADC module */
	ret = twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, TOGGLE1, FGS | GPADCS);
	if (ret) {
		printf("Failed to enable GPADC\n");
		return;
	}

	battery_volt = twl6030_get_battery_voltage();
	if (battery_volt < 0)
		return;

	if (battery_volt < 3000)
		printf("Main battery voltage too low!\n");

	/* Check for the presence of USB charger */
	twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, CONTROLLER_STAT1, &val);

	/* check for battery presence indirectly via Fuel gauge */
	if ((val & VBUS_DET) && (battery_volt < 3300))
		twl6030_start_usb_charging();

	return;
}

void twl6030_power_mmc_init()
{
	/* set voltage to 3.0 and turnon for APP */
	twl6030_i2c_write_u8(TWL6030_CHIP_PM, VMMC_CFG_VOLTATE, 0x15);
	twl6030_i2c_write_u8(TWL6030_CHIP_PM, VMMC_CFG_STATE, 0x21);
}

void twl6030_usb_device_settings()
{
	u8 data = 0;

	/* Select APP Group and set state to ON */
	twl6030_i2c_write_u8(TWL6030_CHIP_PM, VUSB_CFG_STATE, 0x21);

	twl6030_i2c_read_u8(TWL6030_CHIP_PM, MISC2, &data);
	data |= 0x10;

	/* Select the input supply for VBUS regulator */
	twl6030_i2c_write_u8(TWL6030_CHIP_PM, MISC2, data);
}
#endif
