All of lore.kernel.org
 help / color / mirror / Atom feed
From: Steve Sakoman <steve@sakoman.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH] ARMV7: OMAP4: twl6030 add battery charging support
Date: Sun, 28 Nov 2010 20:50:31 -0800	[thread overview]
Message-ID: <1291006231.30938.2.camel@quadra> (raw)

From: Balaji T K <balajitk@ti.com>

Add battery charging support twl6030 driver.
Add support for battery voltage and current measurements.
Add command to get battery status and start/stop battery charging from USB.

Signed-off-by: Balaji T K <balajitk@ti.com>
Tested-by: Steve Sakoman <steve.sakoman@linaro.org>
---
 board/ti/sdp4430/Makefile       |    2 +-
 board/ti/sdp4430/cmd_bat.c      |   58 ++++++++++++++++++
 board/ti/sdp4430/sdp.c          |    4 +
 drivers/power/twl6030.c         |  124 ++++++++++++++++++++++++++++++++++++++-
 include/configs/omap4_sdp4430.h |    1 +
 include/twl6030.h               |   45 +++++++++++++-
 6 files changed, 229 insertions(+), 5 deletions(-)
 create mode 100644 board/ti/sdp4430/cmd_bat.c

diff --git a/board/ti/sdp4430/Makefile b/board/ti/sdp4430/Makefile
index bce8534..f1ee544 100644
--- a/board/ti/sdp4430/Makefile
+++ b/board/ti/sdp4430/Makefile
@@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(BOARD).o
 
-COBJS	:= sdp.o
+COBJS	:= sdp.o cmd_bat.o
 
 SRCS	:= $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS))
diff --git a/board/ti/sdp4430/cmd_bat.c b/board/ti/sdp4430/cmd_bat.c
new file mode 100644
index 0000000..fe33538
--- /dev/null
+++ b/board/ti/sdp4430/cmd_bat.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+
+#ifdef CONFIG_CMD_BAT
+#include <twl6030.h>
+
+int do_vbat(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	if (argc == 2) {
+		if (strncmp(argv[1], "startcharge", 12) == 0)
+			twl6030_start_usb_charging();
+		else if (strncmp(argv[1], "stopcharge", 11) == 0)
+			twl6030_stop_usb_charging();
+		else if (strncmp(argv[1], "status", 7) == 0) {
+			twl6030_get_battery_voltage();
+			twl6030_get_battery_current();
+		} else {
+			goto bat_cmd_usage;
+		}
+	} else {
+		goto bat_cmd_usage;
+	}
+	return 0;
+
+bat_cmd_usage:
+	return cmd_usage(cmdtp);
+}
+
+U_BOOT_CMD(
+	bat, 2, 1, do_vbat,
+	"battery charging, voltage/current measurements",
+	"status - display battery voltage and current\n"
+	"bat startcharge - start charging via USB\n"
+	"bat stopcharge - stop charging\n"
+);
+#endif /* CONFIG_BAT_CMD */
diff --git a/board/ti/sdp4430/sdp.c b/board/ti/sdp4430/sdp.c
index 01d5ce4..b13c4c5 100644
--- a/board/ti/sdp4430/sdp.c
+++ b/board/ti/sdp4430/sdp.c
@@ -23,6 +23,7 @@
  * MA 02111-1307 USA
  */
 #include <common.h>
+#include <twl6030.h>
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/mmc_host_def.h>
 
@@ -63,6 +64,9 @@ int board_eth_init(bd_t *bis)
  */
 int misc_init_r(void)
 {
+#ifdef CONFIG_TWL6030_POWER
+	twl6030_init_battery_charging();
+#endif
 	return 0;
 }
 
diff --git a/drivers/power/twl6030.c b/drivers/power/twl6030.c
index cf1da6b..fef57b4 100644
--- a/drivers/power/twl6030.c
+++ b/drivers/power/twl6030.c
@@ -36,6 +36,54 @@ static inline int twl6030_i2c_read_u8(u8 chip_no, u8 *val, u8 reg)
 	return i2c_read(chip_no, reg, 1, val, 1);
 }
 
+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, &lsb,
+				GPCH0_LSB + channel_no * 2);
+	if (ret)
+		return ret;
+
+	ret = twl6030_i2c_read_u8(TWL6030_CHIP_ADC, &msb,
+				GPCH0_MSB + channel_no * 2);
+	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, CTRL_P2_SP2, CTRL_P2);
+	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, &val, CTRL_P2);
+		if (ret)
+			return ret;
+		udelay(1000);
+	}
+
+	return 0;
+}
+
+void twl6030_stop_usb_charging(void)
+{
+	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, 0, CONTROLLER_CTRL1);
+
+	return;
+}
+
 void twl6030_start_usb_charging(void)
 {
 	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CHARGERUSB_VICHRG_1500,
@@ -48,17 +96,89 @@ void twl6030_start_usb_charging(void)
 							CHARGERUSB_INT_MASK);
 	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CHARGERUSB_VOREG_4P0,
 							CHARGERUSB_VOREG);
-	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CHARGERUSB_CTRL2_VITERM_100,
+	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CHARGERUSB_CTRL2_VITERM_400,
 							CHARGERUSB_CTRL2);
+	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, TERM, CHARGERUSB_CTRL1);
 	/* Enable USB charging */
 	twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, CONTROLLER_CTRL1_EN_CHARGER,
 							CONTROLLER_CTRL1);
 	return;
 }
 
+int twl6030_get_battery_current(void)
+{
+	int battery_current = 0;
+	u8 msb = 0;
+	u8 lsb = 0;
+
+	twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, &msb, FG_REG_11);
+	twl6030_i2c_read_u8(TWL6030_CHIP_CHARGER, &lsb, FG_REG_10);
+	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;
+
+	/* 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(7);
+	if (battery_volt < 0) {
+		printf("Failed to read battery voltage\n");
+		return ret;
+	}
+	battery_volt = (battery_volt * 25 * 1000) >> (10 + 2);
+	printf("Battery Voltage: %d mV\n", battery_volt);
+
+	return battery_volt;
+}
+
 void twl6030_init_battery_charging(void)
 {
-	twl6030_start_usb_charging();
+	u8 stat1 = 0;
+	int battery_volt = 0;
+	int ret = 0;
+
+	/* Enable VBAT measurement */
+	twl6030_i2c_write_u8(TWL6030_CHIP_PM, VBAT_MEAS, MISC1);
+
+	/* Enable GPADC module */
+	ret = twl6030_i2c_write_u8(TWL6030_CHIP_CHARGER, FGS | GPADCS, TOGGLE1);
+	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, &stat1, CONTROLLER_STAT1);
+
+	/* check for battery presence indirectly via Fuel gauge */
+	if ((stat1 & VBUS_DET) && (battery_volt < 3300))
+		twl6030_start_usb_charging();
+
 	return;
 }
 
diff --git a/include/configs/omap4_sdp4430.h b/include/configs/omap4_sdp4430.h
index ed0bd41..bdd330a 100644
--- a/include/configs/omap4_sdp4430.h
+++ b/include/configs/omap4_sdp4430.h
@@ -102,6 +102,7 @@
 
 /* TWL6030 */
 #define CONFIG_TWL6030_POWER		1
+#define CONFIG_CMD_BAT			1
 
 /* MMC */
 #define CONFIG_GENERIC_MMC		1
diff --git a/include/twl6030.h b/include/twl6030.h
index 54923ab..6ed68a0 100644
--- a/include/twl6030.h
+++ b/include/twl6030.h
@@ -32,6 +32,18 @@
 #define TWL6030_CHIP_CHARGER	0x49
 #define TWL6030_CHIP_PWM	0x49
 
+/* Slave Address 0x48 */
+#define VUSB_CFG_STATE		0xA2
+
+#define MISC1			0xE4
+#define VAC_MEAS		(1 << 2)
+#define VBAT_MEAS		(1 << 1)
+#define BB_MEAS			(1 << 0)
+
+#define MISC2			0xE5
+
+/* Slave Address 0x49 */
+
 /* Battery CHARGER REGISTERS */
 #define CONTROLLER_INT_MASK	0xE0
 #define CONTROLLER_CTRL1	0xE1
@@ -76,16 +88,45 @@
 #define CHARGERUSB_VOREG_4P0		0x19
 #define CHARGERUSB_VOREG_4P2		0x23
 #define CHARGERUSB_VOREG_4P76		0x3F
+/* CHARGERUSB_CTRL1 */
+#define SUSPEND_BOOT		(1 << 7)
+#define OPA_MODE		(1 << 6)
+#define HZ_MODE			(1 << 5)
+#define TERM			(1 << 4)
 /* CHARGERUSB_CTRL2 */
 #define CHARGERUSB_CTRL2_VITERM_50	(0 << 5)
 #define CHARGERUSB_CTRL2_VITERM_100	(1 << 5)
 #define CHARGERUSB_CTRL2_VITERM_150	(2 << 5)
+#define CHARGERUSB_CTRL2_VITERM_400	(7 << 5)
 /* CONTROLLER_CTRL1 */
 #define CONTROLLER_CTRL1_EN_CHARGER	(1 << 4)
 #define CONTROLLER_CTRL1_SEL_CHARGER	(1 << 3)
+/* CONTROLLER_STAT1 */
+#define CHRG_EXTCHRG_STATZ	(1 << 7)
+#define CHRG_DET_N		(1 << 5)
+#define VAC_DET			(1 << 3)
+#define VBUS_DET		(1 << 2)
 
-#define VUSB_CFG_STATE		0xA2
-#define MISC2			0xE5
+#define FG_REG_10	0xCA
+#define FG_REG_11	0xCB
+
+#define TOGGLE1		0x90
+#define FGS		(1 << 5)
+#define FGR		(1 << 4)
+#define GPADCS		(1 << 1)
+#define GPADCR		(1 << 0)
+
+#define CTRL_P2		0x34
+#define CTRL_P2_SP2	(1 << 2)
+#define CTRL_P2_EOCP2	(1 << 1)
+#define CTRL_P2_BUSY	(1 << 0)
+
+#define GPCH0_LSB	0x57
+#define GPCH0_MSB	0x58
 
 void twl6030_init_battery_charging(void);
 void twl6030_usb_device_settings(void);
+void twl6030_start_usb_charging(void);
+void twl6030_stop_usb_charging(void);
+int twl6030_get_battery_voltage(void);
+int twl6030_get_battery_current(void);
-- 
1.7.0.4

                 reply	other threads:[~2010-11-29  4:50 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1291006231.30938.2.camel@quadra \
    --to=steve@sakoman.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.