Пример #1
0
/*
 * Enable/disable hardware battery presence event notifications.
 */
static int twl4030battery_hw_presence_en(int enable)
{
	int ret;

	if (enable) {
		/* unmask BATSTS interrupt for INT1 */
		ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_IMR1,
			0, REG_BCIIMR1A);
		if (ret)
			return ret;

		/* configuring interrupt edge for BATSTS */
		ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
			BATSTS_EDRRISIN | BATSTS_EDRFALLING, REG_BCIEDR2);
		if (ret)
			return ret;
	} else {
		/* mask BATSTS interrupt for INT1 */
        ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
                BATSTS_IMR1, REG_BCIIMR1A);
		if (ret)
			return ret;
	}

	return 0;
}
Пример #2
0
/*
 * Enable/Disable AC Charge funtionality.
 */
static int twl4030charger_ac_en(int enable)
{
	int ret;

	if (enable) {
		/* Set the charging current for AC */
		ret = twl4030charger_cur_setup(AC_CURRENT,
			bci_charging_current);
		if (ret)
			return ret;
		/* forcing the field BCIAUTOAC (BOOT_BCI[0) to 1 */
		ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
			(CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC),
			REG_BOOT_BCI);
		if (ret)
			return ret;
	} else {
		/* forcing the field BCIAUTOAC (BOOT_BCI[0) to 0*/
		ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOAC,
			(CONFIG_DONE | BCIAUTOWEN),
			REG_BOOT_BCI);
		if (ret)
			return ret;
	}

	return 0;
}
Пример #3
0
/*
 * Enable/Disable hardware battery level event notifications.
 */
static int twl4030battery_hw_level_en(int enable)
{
	int ret;

	if (enable) {
		/* unmask VBATOV interrupt for INT1 */
		ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, VBATLVL_IMR1,
			0, REG_BCIIMR2A);
		if (ret)
			return ret;

		/* configuring interrupt edge detection for VBATOv */
		ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
			VBATLVL_EDRRISIN, REG_BCIEDR3);
		if (ret)
			return ret;
	} else {
		/* mask VBATOV interrupt for INT1 */
        ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, 0,
                VBATLVL_IMR1, REG_BCIIMR2A);

		if (ret)
			return ret;
	}

	return 0;
}
Пример #4
0
static int read_bci_val(u8 reg)
{
	int ret, temp;
	u8 val = 0;

// 20100816 [email protected] Set TWL4030 register for MADC voltage check [START_LGE]
    ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, USBFASTMCHG, REG_BCIMFSTS4);
// 20100816 [email protected] Set TWL4030 register for MADC voltage check [END_LGE]

	/* reading MSB */
	ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
		reg + 1);
	if (ret)
		return ret;

	temp = ((int)(val & 0x03)) << 8;

	/* reading LSB */
	ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
		reg);
	if (ret)
		return ret;

	return temp | val;
}
Пример #5
0
/*
 * Report and clear the charger presence event.
 */
static inline int twl4030charger_presence_evt(void)
{
	int ret = 0;
	u8 chg_sts = 0, set = 0, clear = 0;

	/* read charger power supply status */
	ret = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &chg_sts,
		REG_STS_HW_CONDITIONS);
	if (ret)
		return IRQ_NONE;

	if (chg_sts & STS_CHG) { /* If the AC charger have been connected */
		/* configuring falling edge detection for CHG_PRES */
		set = CHG_PRES_FALLING;
		clear = CHG_PRES_RISING;
	} else { /* If the AC charger have been disconnected */
		/* configuring rising edge detection for CHG_PRES */
		set = CHG_PRES_RISING;
		clear = CHG_PRES_FALLING;
	}

	/* Update the interrupt edge detection register */
	clear_n_set(TWL4030_MODULE_INT, clear, set, REG_PWR_EDR1);

	return 0;
}
Пример #6
0
static int twl4030battery_presence_evt(void)
{
	int ret;
	u8 batstsmchg, batstspchg;
	
	/* In case of invalid service event function abandon */
	if (twl4030battery_event.battery_presence == NULL)
		return -ENXIO;		
	
	/* checking for battery presence in main charge*/		
	if ((ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, 
			&batstsmchg, REG_BCIMFSTS3)))
		return ret;
			
	/* checking for battery presence in precharge*/		
	if ((ret = twl4030_i2c_read_u8(TWL4030_MODULE_PRECHARGE,
			&batstspchg, REG_BCIMFSTS1)))
		return ret;
	
	/* In case of the battery insertion event */
	if ((batstspchg & BATSTSPCHG) || (batstsmchg & BATSTSMCHG))
	{			
		/* calling the battery presence event service function */
		twl4030battery_event.battery_presence(EVT_BATTSTS_CONN);
		
		ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_EDRRISIN,
			BATSTS_EDRFALLING, REG_BCIEDR2);
		if (ret)
			return ret;
	}
	
	/* In case of the battery removal event */
	else
	{	
		/* calling the battery presence event service function */
		twl4030battery_event.battery_presence(EVT_BATTSTS_DISC);
		
		ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_EDRFALLING,
			BATSTS_EDRRISIN, REG_BCIEDR2);
		if (ret)
			return ret;
	}	
	
	return 0;
}
Пример #7
0
/*
 * Settup the twl4030 BCI module to enable backup
 * battery charging.
 */
static int twl4030backupbatt_voltage_setup(void)
{
	int ret;

	/* Starting backup batery charge */
	ret = clear_n_set(TWL4030_MODULE_PM_RECEIVER, 0, BBCHEN,
		REG_BB_CFG);
	if (ret)
		return ret;

	return 0;
}
Пример #8
0
/*
 * Settup the twl4030 BCI module to measure battery
 * temperature
 */
static int twl4030battery_temp_setup(void)
{
	int ret;

	/* Enabling thermistor current */
	ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, ITHEN,
		REG_BCICTL1);
	if (ret)
		return ret;

	return 0;
}
Пример #9
0
/*
 * Enable/Disable AC Charge funtionality.
 */
static int twl4030charger_ac_en(int enable)
{
	int ret;

	if (enable) {
		/* forcing the field BCIAUTOAC (BOOT_BCI[0) to 1 */
		ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
			(CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC),
			REG_BOOT_BCI);
		if (ret)
			return ret;
	} else {
		/* forcing the field BCIAUTOAC (BOOT_BCI[0) to 0*/
		ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOAC,
			(CONFIG_DONE | BCIAUTOWEN),
			REG_BOOT_BCI);
		if (ret)
			return ret;
	}

	return 0;
}
Пример #10
0
/*
 * This function handles the twl4030 battery presence interrupt
 */
static int twl4030battery_presence_evt(void)
{
	int ret;
	u8 batstsmchg = 0, batstspchg = 0;

	/* check for the battery presence in main charge*/
	ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
			&batstsmchg, REG_BCIMFSTS3);
	if (ret)
		return ret;

	/* check for the battery presence in precharge */
	ret = twl_i2c_read_u8(TWL4030_MODULE_PRECHARGE,
			&batstspchg, REG_BCIMFSTS1);
	if (ret)
		return ret;

	/*
	 * REVISIT: Physically inserting/removing the batt
	 * does not seem to generate an int on 3430ES2 SDP.
	 */
	if ((batstspchg & BATSTSPCHG) || (batstsmchg & BATSTSMCHG)) {
		/* In case of the battery insertion event */
		ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_EDRRISIN,
			BATSTS_EDRFALLING, REG_BCIEDR2);
		if (ret)
			return ret;
	} else {
		/* In case of the battery removal event */
		ret = clear_n_set(TWL4030_MODULE_INTERRUPTS, BATSTS_EDRFALLING,
			BATSTS_EDRRISIN, REG_BCIEDR2);
		if (ret)
			return ret;
	}

	return 0;
}
Пример #11
0
/*
 * Enable/Disable USB Charge funtionality.
 */
int twl4030charger_usb_en(int enable)
{
	u8 value;
	int ret;
	unsigned long timeout;

	if (enable) {
		/* Check for USB charger conneted */
		ret = twl4030charger_presence();
		if (ret < 0)
			return ret;

		if (!(ret & USB_PW_CONN))
			return -ENXIO;

		/* Set the charging current for USB */
		ret = twl4030charger_cur_setup(USB_CURRENT,
			bci_charging_current);
		if (ret)
			return ret;

		/* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */
		ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
			(CONFIG_DONE | BCIAUTOWEN | BCIAUTOUSB),
			REG_BOOT_BCI);
		if (ret)
			return ret;

		ret = clear_n_set(TWL4030_MODULE_USB, 0, PHY_DPLL_CLK,
			REG_PHY_CLK_CTRL);
		if (ret)
			return ret;

		value = 0;
		timeout = jiffies + msecs_to_jiffies(50);

		while ((!(value & PHY_DPLL_CLK)) &&
			time_before(jiffies, timeout)) {
			udelay(10);
			ret = twl4030_i2c_read_u8(TWL4030_MODULE_USB, &value,
				REG_PHY_CLK_CTRL_STS);
			if (ret)
				return ret;
		}

		/* OTG_EN (POWER_CTRL[5]) to 1 */
		ret = clear_n_set(TWL4030_MODULE_USB, 0, OTG_EN,
			REG_POWER_CTRL);
		if (ret)
			return ret;

		mdelay(50);

		/* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */
		ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0,
			USBFASTMCHG, REG_BCIMFSTS4);
		if (ret)
			return ret;
	} else {
		twl4030charger_presence();
		ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOUSB,
			(CONFIG_DONE | BCIAUTOWEN), REG_BOOT_BCI);
		if (ret)
			return ret;
	}

	return 0;
}
Пример #12
0
static int twl4030charger_cur_setup(int charging_source,
	int bci_charging_current)
{
	int ret;
	u8 cgain = 0, bciref1 = 0, bciref2 = 0, value = 0;

	if (charging_source == AC_CURRENT) {
		/* Disable AutoAC till the CGAIN is setup */
		ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOAC,
			(CONFIG_DONE | BCIAUTOWEN),
			REG_BOOT_BCI);
		if (ret)
			return ret;
	} else {
		/* Disable AutoUSB till CGAIN is setup */
		ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOUSB,
			(CONFIG_DONE | BCIAUTOWEN), REG_BOOT_BCI);
		if (ret)
			return ret;
	}

	switch (bci_charging_current) {
	case 1100: /* 1100 mA */
		bciref1 = 0x58;
		bciref2 = 0x03;
		cgain	= 1;
		break;
	case 852: /* 852 mA */
		bciref1 = 0xFF;
		bciref2 = 0x03;
		cgain	= 0;
		break;
	case 100: /* 100 mA */
		bciref1 = 0x3C;
		bciref2 = 0x02;
		cgain	= 0;
		break;
	default:
		/* Charging current as per reset values i,e 600mA */
		printk(KERN_INFO "Unsupported charging current\n");
	}

	/* enable access to BCIIREF1 */
	ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
		0xE7, REG_BCIMFKEY);
	if (ret)
		return ret;

	ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
		bciref1, REG_BCIIREF1);
	if (ret)
		return ret;

	/* enable access to BCIIREF2 */
	ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
		0xE7, REG_BCIMFKEY);
	if (ret)
		return ret;

	ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
		bciref2, REG_BCIIREF2);
	if (ret)
		return ret;

	ret = twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &value,
		REG_BCICTL1);
	if (ret)
		return ret;

	if (cgain == 0)
		value = value & ~(CGAIN);
	else
		value = value | CGAIN;

	ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
		value, REG_BCICTL1);
	if (ret)
		return ret;

	return 0;
}
Пример #13
0
/*
 * Helper function
 * 
 * This fucntion drives charger power supply events
 */
static int twl4030charger_presence_evt (void)
{
	int ret, event = 0;
	u8 chg_sts, set = 0, clear = 0;

	/*
	 * if there is no event sevice routine there is no need to do 
	 * anything.
	 */
	if (twl4030battery_event.charger_presence == NULL)
		return -ENXIO;
	
	/* checking charger power supply status */
	ret = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER,&chg_sts, 
		REG_STS_HW_CONDITIONS);
	if (ret)
		return IRQ_NONE;
				
	/* If the AC charger have been connected*/
	if (chg_sts & STS_CHG)
	{
		/* configuring falling edge detection for CHG_PRES */
		set = CHG_PRES_FALLING;
		clear = CHG_PRES_RISING;
		event = EVT_PWSPLY_AC_CONN;
	}
	/* If the AC charger have been disconnected*/
	else
	{
		/* configuring rising edge detection for CHG_PRES */
		set = CHG_PRES_RISING;
		clear = CHG_PRES_FALLING;
		event = EVT_PWSPLY_AC_DISC;
	}		
	 
	/* If the USB charger have been connected*/
	if (chg_sts & STS_VBUS)
	{
		/* configuring falling edge detection for USB_PRES */
		set |= USB_PRES_FALLING;
		clear |= USB_PRES_RISING;
		event |= EVT_PWSPLY_USB_CONN;
	}
	/* If the USB charger have been disconnected*/
	else
	{	/*
		 * configuring interrupt edge detection
		 * for USB_PRES and CHG_PRES.
	 	 */
		set |= USB_PRES_RISING;
		clear |= USB_PRES_FALLING;
		event |= EVT_PWSPLY_USB_DISC;
	}	
	
	/* Update the interrupt edge detection register */
	ret = clear_n_set(TWL4030_MODULE_INT, clear, set, REG_PWR_EDR1);
	if (ret)
		return 0;
			
	/* Calling  to the charger presence event service routine */
	twl4030battery_event.charger_presence(event);
	
	return 0;
}