All of lore.kernel.org
 help / color / mirror / Atom feed
* USB charging over TPS65950 BCI
@ 2009-07-31 13:49 pramod gurav
  2009-08-01  6:41 ` Gregoire Gentil
  2009-08-02 15:44 ` Grazvydas Ignotas
  0 siblings, 2 replies; 7+ messages in thread
From: pramod gurav @ 2009-07-31 13:49 UTC (permalink / raw)
  To: linux-omap

Hi All,
I was trying to get the USB battery charging working over TPS65950 BCI
on the OMAP3430 custom board. I am working with linux-omap-2.6
v2.6.28-omap1 tag. I enabled the TWL4030 MADC and TWL4030 BCI drivers.
I passed interrupt details to these drivers from platform_device
structure from my board file. I could get the AC charging working. The
AC and USB detection worked. However the USB charging is not
happening.
I read through the TPS TRM and took the dumps of the registers from
BCI and some from TWL USB module and BOOT_BCI whenever I plug in the
USB charger between host and the board. The register settings seem to
be fine. But the battery is not charging. I am using BQ27000 chip for
battery monitoring and I can see the battery voltage is decreasing.

Following are the register dumps of TWL with and without USB plugged in:

These are the register contents when USB charger is plugged in:
BCIMDEN         = 0x11
REG_BOOT_BCI    = 0x37
REG_POWER_CTRL  = 0x20
REG_BCIMFSTS4   = 0xf4
REG_BCIMFSTS1   = 0x13
REG_BCIIREF1    = 0x68
REG_BCIIREF2    = 0x3
REG_BCIMFEN4    = 0x6f
REG_BCIMFSTS2   = 0x0
REG_BCIMSTATEC  = 0x12
REG_STS_HW_CONDITIONS= 0x90


These are the register contents when USB charger is plugged out:
BCIMDEN         = 0x0
REG_BOOT_BCI    = 0x35
REG_POWER_CTRL  = 0x20
REG_BCIMFSTS4   = 0xf0
REG_BCIMFSTS1   = 0xaa
REG_BCIIREF1    = 0x68
REG_BCIIREF2    = 0x3
REG_BCIMFEN4    = 0x68
REG_BCIMFSTS2   = 0x0
REG_BCIMSTATEC  =0x0
REG_STS_HW_CONDITIONS= 0x10

Is there anything more I need to support to get BCI USB charging
working? Need I follow any USB Communication protocol between Host and
the board.
I have pasted the kernel boot logs for reference at the end.
Can any one please guide me to some pointers?

-- 
Best Regards
Pramod


Starting kernel ...

Uncompressing Linux...................................................................................................................................
done, boo.
Linux version 2.6.28-omap1-(gpramod@gpramod.mistral.in) (gcc version
4.2.1 (CodeSourcery Sourcery G++ Lite 2007q3-51)) #25 Fri Jul 31
15:48:37 I9
CPU: ARMv7 Processor [411fc083] revision 3 (ARMv7), cr=10c5387f
CPU: VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
Machine: OMAP3430 Main Board
Memory policy: ECC disabled, Data cache writeback
OMAP3430 Unknown revision

SRAM: Mapped pa 0x40200000 to va 0xd7000000 size: 0x100000
Reserving 4194304 bytes SDRAM for VRAM
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 65024
Kernel command line: console=ttyS2,115200n8 root=/dev/mmcblk0p2
rootfstype=ext3 rootdelay=3 android.ril=pts/0 init=/init
Unknown boot option `android.ril=pts/0': ignoring
Clocking rate (Crystal/DPLL/ARM core): 26.0/332/500 MHz
Reprogramming SDRC
GPMC revision 5.0
IRQ: Found an INTC at 0xd8200000 (revision 4.0) with 96 interrupts
Total of 96 interrupts on 1 active controller
OMAP34xx GPIO hardware version 2.5
PID hash table entries: 1024 (order: 10, 4096 bytes)
OMAP clockevent source: GPTIMER12 at 32768 Hz
Console: colour dummy device 80x30
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 128MB 128MB = 256MB total
Memory: 250880KB available (3580K code, 755K data, 300K init)
Calibrating delay loop... 494.72 BogoMIPS (lpj=1933312)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
net_namespace: 312 bytes
NET: Registered protocol family 16
Found NAND on CS0
Registering NAND on CS0
OMAP DMA hardware revision 4.0
USB: No board-specific platform config found
OMAP DSS rev 2.0
OMAP DISPC rev 3.0
OMAP VENC rev 2
i2c_omap i2c_omap.1: bus 1 rev3.12 at 400 kHz
Skipping twl4030 internal clock init and using bootloader value
(unknown osc rate)
twl4030: PIH (irq 7) chaining IRQs 368..375
twl4030: power (irq 373) chaining IRQs 376..383
twl4030: gpio (irq 368) chaining IRQs 384..401
i2c_omap i2c_omap.2: bus 2 rev3.12 at 400 kHz
i2c_omap i2c_omap.3: bus 3 rev3.12 at 400 kHz
SCSI subsystem initialized
twl4030_usb twl4030_usb: Initialized TWL4030 USB module
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
musb_hdrc: version 6.0, musb-dma, otg (peripheral+host), debug=0
musb_hdrc: USB OTG mode controller at d80ab000 using DMA, IRQ 92
NET: Registered protocol family 2
IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
TCP established hash table entries: 8192 (order: 4, 65536 bytes)
TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP reno registered
NET: Registered protocol family 1
NetWinder Floating Point Emulator V0.97 (double precision)
ashmem: initialized
VFS: Disk quotas dquot_6.5.1
Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
JFFS2 version 2.2. (NAND) �© 2001-2006 Red Hat, Inc.
msgmni has been set to 490
alg: No test for stdrng (krng)
io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
io scheduler cfq registered
Allocating static major number 255 to omap3custum_bl driver
Serial: 8250/16550 driver4 ports, IRQ sharing enabled
serial8250.0: ttyS0 at MMIO 0x4806a000 (irq = 72) is a ST16654
serial8250.0: ttyS1 at MMIO 0x4806c000 (irq = 73) is a ST16654
serial8250.0: ttyS2 at MMIO 0x49020000 (irq = 74) is a ST16654
console [ttyS2] enabled
brd: module loaded
loop: module loaded
logger: created 64K log 'log_main'
logger: created 256K log 'log_events'
logger: created 64K log 'log_radio'
Created /proc/audio
PPP generic driver version 2.4.2
PPP Deflate Compression module registered
PPP BSD Compression module registered
PPP MPPE Compression module registered
NET: Registered protocol family 24
PPPoL2TP kernel driver, V1.0
i2c /dev entries driver
input: triton2-pwrbutton as /devices/virtual/input/input0
triton2 power button driver initialized
3-Axis AK8973 Compass Driver : version : 0.0
Client [AK8973_Compass] registered with bus id (3) with slave address 0x1c
input: ak8973 as /devices/virtual/input/input1
Installing 'vibrator' driver
3-Axis lis302dl Accelerometer : version : 0.0
Client [lis302dl] registered with bus id (3) with slave address 0x1d
Driver 'sd' needs updating - please use bus_type methods
omap2-nand driver initializing
NAND device: Manufacturer ID: 0x2c, Chip ID: 0xba (Micron NAND 256MiB
1,8V 16-bit)
cmdlinepart partition parsing not available
Creating 10 MTD partitions on "omap2-nand":
0x00000000-0x00020000 : "X-Loader(1)"
0x00020000-0x00040000 : "X-Loader(2)"
0x00040000-0x00060000 : "X-Loader(3)"
0x00060000-0x00080000 : "X-Loader(4)"
0x00080000-0x00100000 : "U-Boot"
0x00100000-0x00120000 : "U-Boot Environment"
0x00120000-0x00320000 : "Kernel(1)"
0x00320000-0x00520000 : "Kernel(2)"
0x00520000-0x06920000 : "File System(1)"
0x06920000-0x10000000 : "File System(2)"
android adb driver
musb_hdrc musb_hdrc: MUSB HDRC host driver
musb_hdrc musb_hdrc: new USB bus registered, assigned bus number 1
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
mice: PS/2 mouse device common for all mice
input: omap_twl4030keypad as
/devices/platform/i2c_omap.1/i2c-adapter/i2c-1/1-004a/twl4030_keypad/input/input2
Register Mapped Interface Data Layer Driver
    Allocation Stats Enabled
RMI TouchPad Driver
input: RMI Touchpad as /devices/virtual/input/input3
Registering app driver rmi_touchpad
Registered app driver rmi_touchpad (cf9bb960)
i2c-adapter i2c-1: Invalid probe address 0x00
detect(): Detect: 00000020, 00000000
rmi: Registering phys driver rmi_i2c
rmi: RMI Protocol: 0.1
rmi: Manufacturer: 1 (Synaptics)

rmi: Physical Interface Version: 0.1
rmi: Properties:
rmi:    Can doze
rmi: Product Versions: 1.2.0.1
rmi: Product ID: TM1172
rmi: Functions:
rmi:    2-D Sensor
rmi:         SFPL: 1, Sources: 3, EDR: 7
rmi:         Function Version: 0.1
rmi: rmi_touchpad bound to rmi_i2c
Config function
  Number of extra positions: 0
  Has 2D Scroll: 0
  Has Scroller: 0
  Has gestures: 1
  Has Multifing: 1
  Has Palm Det: 1
  Sensor Max X: 3975, MAX_X=3975
  Sensor Max Y: 5952, MAX_Y=5952
  Sensor Resolution: 77
  Interrupt Driven
Registered phys driver rmi_i2c
i2c-adapter i2c-2: Invalid probe address 0x00
i2c-adapter i2c-3: Invalid probe address 0x00
twl4030_rtc twl4030_rtc: rtc core: registered twl4030_rtc as rtc0
twl4030_rtc twl4030_rtc: Power up reset detected.
twl4030_rtc twl4030_rtc: Enabling TWL4030-RTC.
Driver for 1-wire Dallas network protocol.
omap_hdq omap_hdq.0: OMAP HDQ Hardware Rev 0.5. Driver in Interrupt mode
w1_master_driver w1_bus_master1: Family 1 for 01.000000000000.3d is
not registered.
mmci-omap-hs mmci-omap-hs.0: Failed to get debounce clock
mmci-omap-hs mmci-omap-hs.1: Failed to get debounce clock
Advanced Linux Sound Architecture Driver Version 1.0.18rc3.
ASoC version 0.13.2
omap3custum SoC init
TWL4030 Audio Codec init
asoc: twl4030 <-> omap-mcbsp-dai-(link_id) mapping ok
ALSA device list:
  #0: OMAP3430 (twl4030)
TCP cubic registered
NET: Registered protocol family 17
NET: Registered protocol family 15
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
ThumbEE CPU extension supported.
Power Management for TI OMAP3.
clock: dpll5_ck failed transition to 'locked'
VFP support v0.3: implementor 41 architecture 3 part 30 variant c rev 1
Console: switching to colour frame buffer device 40x30
mmc0: new SD card at address e624
mmcblk0: mmc0:e624 SU02G 1.89 GiB
 mmcblk0:<6>twl4030_rtc twl4030_rtc: setting system clock to
2000-01-01 00:00:02 UTC (946684802)
Waiting 3sec before mounting root device...
 p1 p2
kjournald starting.  Commit interval 5 seconds
EXT3-fs warning: maximal mount count reached, running e2fsck is recommended
EXT3 FS on mmcblk0p2, internal journal
EXT3-fs: mounted filesystem with ordered data mode.
VFS: Mounted root (ext3 filesystem).
Freeing init memory: 300K
Failed to execute /init.  Attempting defaults...

****************************************************
Starting System Init for OMAP3430 1.0
****************************************************

Mounting Filesystem...
Starting inetd...
Starting syslogd...

Please press Enter to activate this console.

Processing /etc/profile... Done

--
Best Regards
Pramod
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: USB charging over TPS65950 BCI
  2009-07-31 13:49 USB charging over TPS65950 BCI pramod gurav
@ 2009-08-01  6:41 ` Gregoire Gentil
       [not found]   ` <1249489092.24549.9.camel@gregoire-laptop>
  2009-08-02 15:44 ` Grazvydas Ignotas
  1 sibling, 1 reply; 7+ messages in thread
From: Gregoire Gentil @ 2009-08-01  6:41 UTC (permalink / raw)
  To: pramod gurav; +Cc: linux-omap

[-- Attachment #1: Type: text/plain, Size: 12918 bytes --]

On Fri, 2009-07-31 at 19:19 +0530, pramod gurav wrote:
> Hi All,
> I was trying to get the USB battery charging working over TPS65950 BCI
> on the OMAP3430 custom board. I am working with linux-omap-2.6
> v2.6.28-omap1 tag. I enabled the TWL4030 MADC and TWL4030 BCI drivers.
> I passed interrupt details to these drivers from platform_device
> structure from my board file. I could get the AC charging working. The
> AC and USB detection worked. However the USB charging is not
> happening.
> I read through the TPS TRM and took the dumps of the registers from
> BCI and some from TWL USB module and BOOT_BCI whenever I plug in the
> USB charger between host and the board. The register settings seem to
> be fine. But the battery is not charging. I am using BQ27000 chip for
> battery monitoring and I can see the battery voltage is decreasing.
> 
> Following are the register dumps of TWL with and without USB plugged in:
> 
> These are the register contents when USB charger is plugged in:
> BCIMDEN         = 0x11
> REG_BOOT_BCI    = 0x37
> REG_POWER_CTRL  = 0x20
> REG_BCIMFSTS4   = 0xf4
> REG_BCIMFSTS1   = 0x13
> REG_BCIIREF1    = 0x68
> REG_BCIIREF2    = 0x3
> REG_BCIMFEN4    = 0x6f
> REG_BCIMFSTS2   = 0x0
> REG_BCIMSTATEC  = 0x12
> REG_STS_HW_CONDITIONS= 0x90
> 
> 
> These are the register contents when USB charger is plugged out:
> BCIMDEN         = 0x0
> REG_BOOT_BCI    = 0x35
> REG_POWER_CTRL  = 0x20
> REG_BCIMFSTS4   = 0xf0
> REG_BCIMFSTS1   = 0xaa
> REG_BCIIREF1    = 0x68
> REG_BCIIREF2    = 0x3
> REG_BCIMFEN4    = 0x68
> REG_BCIMFSTS2   = 0x0
> REG_BCIMSTATEC  =0x0
> REG_STS_HW_CONDITIONS= 0x10
> 
> Is there anything more I need to support to get BCI USB charging
> working? Need I follow any USB Communication protocol between Host and
> the board.
> I have pasted the kernel boot logs for reference at the end.
> Can any one please guide me to some pointers?
> 
> -- 
> Best Regards
> Pramod
I'm experiencing some problems with TWL4030 DC charging and I'm
interested by this kind of problem. Basically, the values reported by
our patch is different from the current going to the battery. We wrote
the attached enhanced patch so as to edit at run-time the charging mode
and various values including charge_current. It's against 2.6.29 but I
think that it should work again 2.6.28. Unfortunately, starting 2.6.30,
Tony has removed all the BCI battery code and has asked for updated code
against mainline but I've not seen anything so far.

Pramod, can you try the attached patch (perhaps, it will help you) and
can you tell if you see the exact current going to the battery reported
by the driver?

Grégoire





--- a/drivers/power/twl4030_bci_battery.c	2009-07-22 18:27:16.000000000
-0700
+++ b/drivers/power/twl4030_bci_battery.c	2009-07-22 18:30:22.000000000
-0700
@@ -15,6 +15,9 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+/* Boot with automatic charge */
+#define CHARGE_MODE 1
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/device.h>
@@ -50,6 +53,7 @@
 /* Boot BCI flag bits */
 #define BCIAUTOWEN		0x020
 #define CONFIG_DONE		0x010
+#define CVENAC			0x004
 #define BCIAUTOUSB		0x002
 #define BCIAUTOAC		0x001
 #define BCIMSTAT_MASK		0x03F
@@ -81,6 +85,11 @@
 #define REG_BB_CFG		0x012
 #define BBCHEN			0x010
 
+/* GPBR */
+#define REG_GPBR1		0x0c
+#define MADC_HFCLK_EN		0x80
+#define DEFAULT_MADC_CLK_EN	0x10
+
 /* Power supply charge interrupt */
 #define REG_PWR_ISR1		0x00
 #define REG_PWR_IMR1		0x01
@@ -125,6 +134,18 @@
 /* BCIEDR3 */
 #define	VBATLVL_EDRRISIN	0x02
 
+/* BCIIREF1 */
+#define REG_BCIIREF1		0x027
+#define REG_BCIIREF2		0x028
+
+/* BCIMFTH1 */
+#define REG_BCIMFTH1		0x016
+
+/* Key */
+#define KEY_IIREF		0xE7
+#define KEY_FTH1		0xD2
+#define REG_BCIMFKEY		0x011
+
 /* Step size and prescaler ratio */
 #define TEMP_STEP_SIZE		147
 #define TEMP_PSR_R		100
@@ -142,9 +163,6 @@
 #define ENABLE		1
 #define DISABLE		1
 
-/* Ptr to thermistor table */
-int *therm_tbl;
-
 struct twl4030_bci_device_info {
 	struct device		*dev;
 
@@ -160,6 +178,8 @@
 	struct power_supply	bk_bat;
 	struct delayed_work	twl4030_bci_monitor_work;
 	struct delayed_work	twl4030_bk_bci_monitor_work;
+
+	struct twl4030_bci_platform_data *pdata;
 };
 
 static int usb_charger_flag;
@@ -425,15 +445,21 @@
 /*
  * Enable/Disable AC Charge funtionality.
  */
-static int twl4030charger_ac_en(int enable)
+static int twl4030charger_ac_en(int enable, int automatic)
 {
 	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(!automatic) {
+			ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOAC | CVENAC,
+				(CONFIG_DONE | BCIAUTOWEN),
+				REG_BOOT_BCI);
+		} else {
+			ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
+				(CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC | CVENAC),
+				REG_BOOT_BCI);
+		}
 		if (ret)
 			return ret;
 	} else {
@@ -518,11 +544,15 @@
  * Return battery temperature
  * Or < 0 on failure.
  */
-static int twl4030battery_temperature(void)
+static int twl4030battery_temperature(struct twl4030_bci_device_info
*di)
 {
 	u8 val;
 	int temp, curr, volt, res, ret;
 
+	/* Is a temperature table specified? */
+	if (!di->pdata->tblsize)
+		return 0;
+
 	/* Getting and calculating the thermistor voltage */
 	ret = read_bci_val(T2_BATTERY_TEMP);
 	if (ret < 0)
@@ -543,7 +573,7 @@
 
 	/*calculating temperature*/
 	for (temp = 58; temp >= 0; temp--) {
-		int actual = therm_tbl[temp];
+		int actual = di->pdata->battery_tmp_tbl[temp];
 		if ((actual - res) >= 0)
 			break;
 	}
@@ -661,6 +691,9 @@
 		return ret;
 	}
 
+#ifdef DEBUG
+	printk("BCI DEBUG: BCIMSTATEC Charge state is 0x%x\n", status);
+#endif
 	return (int) (status & BCIMSTAT_MASK);
 }
 
@@ -709,14 +742,43 @@
  */
 static int twl4030battery_temp_setup(void)
 {
-	int ret;
+#ifdef DEBUG
+	u8 i;
+#endif
+	u8 ret;
 
 	/* Enabling thermistor current */
-	ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, ITHEN,
+	ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, 0x1B,
 		REG_BCICTL1);
 	if (ret)
 		return ret;
 
+#ifdef DEBUG
+	twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret, REG_BOOT_BCI);
+	printk("BCI DEBUG: BOOT_BCI Value is 0x%x\n", ret);
+
+	twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret,
REG_STS_HW_CONDITIONS);
+	printk("BCI DEBUG: STS_HW_CONDITIONS Value is 0x%x\n", ret);
+
+	twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL1);
+	printk("BCI DEBUG: BCICTL1 Value is 0x%x\n", ret);
+
+	twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL2);
+	printk("BCI DEBUG: BCICTL2 Value is 0x%x\n", ret);
+
+	twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, 0x0);
+	printk("BCI DEBUG: BCIMDEN Value is 0x%x\n", ret);
+
+	twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &ret, REG_GPBR1);
+	printk("BCI DEBUG: GPBR1 Value is 0x%x\n", ret);
+
+	for(i = 0x0; i <= 0x32; i++)
+	{
+		twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, i);
+		printk("BCI DEBUG: BCI 0x%x Value is 0x%x\n", i, ret);
+	}
+#endif
+
 	return 0;
 }
 
@@ -732,7 +794,6 @@
 	ret = twl4030_i2c_read_u8(mod_no, &val, reg);
 	if (ret)
 		return ret;
-
 	/* Clearing all those bits to clear */
 	val &= ~(clear);
 
@@ -772,13 +833,14 @@
 		struct twl4030_bci_device_info,
 		twl4030_bk_bci_monitor_work.work);
 
-	twl4030_bk_bci_battery_read_status(di);
+	if(!di->pdata->no_backup_battery)
+		twl4030_bk_bci_battery_read_status(di);
 	schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
 }
 
 static void twl4030_bci_battery_read_status(struct
twl4030_bci_device_info *di)
 {
-	di->temp_C = twl4030battery_temperature();
+	di->temp_C = twl4030battery_temperature(di);
 	di->voltage_uV = twl4030battery_voltage();
 	di->current_uA = twl4030battery_current();
 }
@@ -819,6 +881,87 @@
 #define to_twl4030_bk_bci_device_info(x) container_of((x), \
 		struct twl4030_bci_device_info, bk_bat);
 
+static ssize_t
+show_charge_current(struct device *dev, struct device_attribute *attr,
char *buf)
+{
+	u8  ctl;
+	int ret = read_bci_val(REG_BCIIREF1) & 0x1FF;
+	twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ctl, REG_BCICTL1);
+
+	if (ctl & CGAIN)
+		ret |= 0x200;
+
+#ifdef DEBUG
+	/* Dump debug */
+	twl4030battery_temp_setup();
+#endif
+
+	return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t
+set_charge_current(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
+{
+	unsigned long newCurrent;
+	int ret;
+
+	ret = strict_strtoul(buf, 10, &newCurrent);
+	if (ret)
+		return -EINVAL;
+
+	ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF,
REG_BCIMFKEY);
+	if (ret)
+		return ret;
+
+	ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, newCurrent &
0xff, REG_BCIIREF1);
+	if (ret)
+		return ret;
+
+	ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF,
REG_BCIMFKEY);
+	if (ret)
+		return ret;
+
+	ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, (newCurrent >>
8) & 0x1, REG_BCIIREF2);
+	if (ret)
+		return ret;
+
+	/* Set software-controlled charge */
+	twl4030charger_ac_en(ENABLE, 0);
+
+	/* Set CGAIN = 0 or 1 */
+	if(newCurrent > 511) {
+		u8 tmp;
+
+		/* Set CGAIN = 1 -- need to wait until automatic charge turns off */
+		while(!ret) {
+			clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, CGAIN | 0x1B,
REG_BCICTL1);
+			twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
+
+			ret = tmp & CGAIN;
+			if(!ret)
+				mdelay(50);
+		}
+	} else {
+		u8 tmp;
+
+		/* Set CGAIN = 0 -- need to wait until automatic charge turns off */
+		while(!ret) {
+			clear_n_set(TWL4030_MODULE_MAIN_CHARGE, CGAIN, 0x1B, REG_BCICTL1);
+			twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
+
+			ret = !(tmp & CGAIN);
+			if(!ret)
+				mdelay(50);
+		}
+	}
+
+	/* Set automatic charge (CGAIN = 0/1 persists) */
+	twl4030charger_ac_en(ENABLE, 1);
+
+	return count;
+}
+static DEVICE_ATTR(charge_current, S_IRUGO | S_IWUSR,
show_charge_current, set_charge_current);
+
 static int twl4030_bk_bci_battery_get_property(struct power_supply
*psy,
 					enum power_supply_property psp,
 					union power_supply_propval *val)
@@ -912,8 +1055,6 @@
 	int irq;
 	int ret;
 
-	therm_tbl = pdata->battery_tmp_tbl;
-
 	di = kzalloc(sizeof(*di), GFP_KERNEL);
 	if (!di)
 		return -ENOMEM;
@@ -937,8 +1078,12 @@
 	di->bk_bat.num_properties = ARRAY_SIZE(twl4030_bk_bci_battery_props);
 	di->bk_bat.get_property = twl4030_bk_bci_battery_get_property;
 	di->bk_bat.external_power_changed = NULL;
+	di->pdata = pdata;
 
-	twl4030charger_ac_en(ENABLE);
+	/* Set up clocks */
+	twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, MADC_HFCLK_EN |
DEFAULT_MADC_CLK_EN, REG_GPBR1);
+
+	twl4030charger_ac_en(ENABLE, CHARGE_MODE);
 	twl4030charger_usb_en(ENABLE);
 	twl4030battery_hw_level_en(ENABLE);
 	twl4030battery_hw_presence_en(ENABLE);
@@ -951,9 +1096,12 @@
 		goto temp_setup_fail;
 
 	/* enabling GPCH09 for read back battery voltage */
-	ret = twl4030backupbatt_voltage_setup();
-	if (ret)
-		goto voltage_setup_fail;
+	if(!di->pdata->no_backup_battery)
+	{
+		ret = twl4030backupbatt_voltage_setup();
+		if (ret)
+			goto voltage_setup_fail;
+	}
 
 	/* REVISIT do we need to request both IRQs ?? */
 
@@ -988,9 +1136,18 @@
 				twl4030_bci_battery_work);
 	schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
 
-	ret = power_supply_register(&pdev->dev, &di->bk_bat);
+	if(!pdata->no_backup_battery)
+	{
+		ret = power_supply_register(&pdev->dev, &di->bk_bat);
+		if (ret) {
+			dev_dbg(&pdev->dev, "failed to register backup battery\n");
+			goto bk_batt_failed;
+		}
+	}
+
+	ret = device_create_file(di->bat.dev, &dev_attr_charge_current);
 	if (ret) {
-		dev_dbg(&pdev->dev, "failed to register backup battery\n");
+		dev_err(&pdev->dev, "failed to create sysfs entries\n");
 		goto bk_batt_failed;
 	}
 
@@ -1001,7 +1158,8 @@
 	return 0;
 
 bk_batt_failed:
-	power_supply_unregister(&di->bat);
+	if(!pdata->no_backup_battery)
+		power_supply_unregister(&di->bat);
 batt_failed:
 	free_irq(irq, di);
 chg_irq_fail:
@@ -1010,7 +1168,7 @@
 batt_irq_fail:
 voltage_setup_fail:
 temp_setup_fail:
-	twl4030charger_ac_en(DISABLE);
+	twl4030charger_ac_en(DISABLE, CHARGE_MODE);
 	twl4030charger_usb_en(DISABLE);
 	twl4030battery_hw_level_en(DISABLE);
 	twl4030battery_hw_presence_en(DISABLE);
@@ -1024,7 +1182,7 @@
 	struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
 	int irq;
 
-	twl4030charger_ac_en(DISABLE);
+	twl4030charger_ac_en(DISABLE, CHARGE_MODE);
 	twl4030charger_usb_en(DISABLE);
 	twl4030battery_hw_level_en(DISABLE);
 	twl4030battery_hw_presence_en(DISABLE);
--- a/include/linux/i2c/twl4030.h
+++ b/include/linux/i2c/twl4030.h
@@ -299,6 +299,8 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg,
unsigned num_bytes);
 struct twl4030_bci_platform_data {
 	int *battery_tmp_tbl;
 	unsigned int tblsize;
+
+	bool no_backup_battery;
 };
 
 /* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */


[-- Attachment #2: twl4030_bci_battery.patch --]
[-- Type: text/x-patch, Size: 10277 bytes --]

--- a/drivers/power/twl4030_bci_battery.c	2009-07-22 18:27:16.000000000 -0700
+++ b/drivers/power/twl4030_bci_battery.c	2009-07-22 18:30:22.000000000 -0700
@@ -15,6 +15,9 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+/* Boot with automatic charge */
+#define CHARGE_MODE 1
+
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/device.h>
@@ -50,6 +53,7 @@
 /* Boot BCI flag bits */
 #define BCIAUTOWEN		0x020
 #define CONFIG_DONE		0x010
+#define CVENAC			0x004
 #define BCIAUTOUSB		0x002
 #define BCIAUTOAC		0x001
 #define BCIMSTAT_MASK		0x03F
@@ -81,6 +85,11 @@
 #define REG_BB_CFG		0x012
 #define BBCHEN			0x010
 
+/* GPBR */
+#define REG_GPBR1		0x0c
+#define MADC_HFCLK_EN		0x80
+#define DEFAULT_MADC_CLK_EN	0x10
+
 /* Power supply charge interrupt */
 #define REG_PWR_ISR1		0x00
 #define REG_PWR_IMR1		0x01
@@ -125,6 +134,18 @@
 /* BCIEDR3 */
 #define	VBATLVL_EDRRISIN	0x02
 
+/* BCIIREF1 */
+#define REG_BCIIREF1		0x027
+#define REG_BCIIREF2		0x028
+
+/* BCIMFTH1 */
+#define REG_BCIMFTH1		0x016
+
+/* Key */
+#define KEY_IIREF		0xE7
+#define KEY_FTH1		0xD2
+#define REG_BCIMFKEY		0x011
+
 /* Step size and prescaler ratio */
 #define TEMP_STEP_SIZE		147
 #define TEMP_PSR_R		100
@@ -142,9 +163,6 @@
 #define ENABLE		1
 #define DISABLE		1
 
-/* Ptr to thermistor table */
-int *therm_tbl;
-
 struct twl4030_bci_device_info {
 	struct device		*dev;
 
@@ -160,6 +178,8 @@
 	struct power_supply	bk_bat;
 	struct delayed_work	twl4030_bci_monitor_work;
 	struct delayed_work	twl4030_bk_bci_monitor_work;
+
+	struct twl4030_bci_platform_data *pdata;
 };
 
 static int usb_charger_flag;
@@ -425,15 +445,21 @@
 /*
  * Enable/Disable AC Charge funtionality.
  */
-static int twl4030charger_ac_en(int enable)
+static int twl4030charger_ac_en(int enable, int automatic)
 {
 	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(!automatic) {
+			ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOAC | CVENAC,
+				(CONFIG_DONE | BCIAUTOWEN),
+				REG_BOOT_BCI);
+		} else {
+			ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
+				(CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC | CVENAC),
+				REG_BOOT_BCI);
+		}
 		if (ret)
 			return ret;
 	} else {
@@ -518,11 +544,15 @@
  * Return battery temperature
  * Or < 0 on failure.
  */
-static int twl4030battery_temperature(void)
+static int twl4030battery_temperature(struct twl4030_bci_device_info *di)
 {
 	u8 val;
 	int temp, curr, volt, res, ret;
 
+	/* Is a temperature table specified? */
+	if (!di->pdata->tblsize)
+		return 0;
+
 	/* Getting and calculating the thermistor voltage */
 	ret = read_bci_val(T2_BATTERY_TEMP);
 	if (ret < 0)
@@ -543,7 +573,7 @@
 
 	/*calculating temperature*/
 	for (temp = 58; temp >= 0; temp--) {
-		int actual = therm_tbl[temp];
+		int actual = di->pdata->battery_tmp_tbl[temp];
 		if ((actual - res) >= 0)
 			break;
 	}
@@ -661,6 +691,9 @@
 		return ret;
 	}
 
+#ifdef DEBUG
+	printk("BCI DEBUG: BCIMSTATEC Charge state is 0x%x\n", status);
+#endif
 	return (int) (status & BCIMSTAT_MASK);
 }
 
@@ -709,14 +742,43 @@
  */
 static int twl4030battery_temp_setup(void)
 {
-	int ret;
+#ifdef DEBUG
+	u8 i;
+#endif
+	u8 ret;
 
 	/* Enabling thermistor current */
-	ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, ITHEN,
+	ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, 0x1B,
 		REG_BCICTL1);
 	if (ret)
 		return ret;
 
+#ifdef DEBUG
+	twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret, REG_BOOT_BCI);
+	printk("BCI DEBUG: BOOT_BCI Value is 0x%x\n", ret);
+
+	twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret, REG_STS_HW_CONDITIONS);
+	printk("BCI DEBUG: STS_HW_CONDITIONS Value is 0x%x\n", ret);
+
+	twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL1);
+	printk("BCI DEBUG: BCICTL1 Value is 0x%x\n", ret);
+
+	twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL2);
+	printk("BCI DEBUG: BCICTL2 Value is 0x%x\n", ret);
+
+	twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, 0x0);
+	printk("BCI DEBUG: BCIMDEN Value is 0x%x\n", ret);
+
+	twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &ret, REG_GPBR1);
+	printk("BCI DEBUG: GPBR1 Value is 0x%x\n", ret);
+
+	for(i = 0x0; i <= 0x32; i++)
+	{
+		twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, i);
+		printk("BCI DEBUG: BCI 0x%x Value is 0x%x\n", i, ret);
+	}
+#endif
+
 	return 0;
 }
 
@@ -732,7 +794,6 @@
 	ret = twl4030_i2c_read_u8(mod_no, &val, reg);
 	if (ret)
 		return ret;
-
 	/* Clearing all those bits to clear */
 	val &= ~(clear);
 
@@ -772,13 +833,14 @@
 		struct twl4030_bci_device_info,
 		twl4030_bk_bci_monitor_work.work);
 
-	twl4030_bk_bci_battery_read_status(di);
+	if(!di->pdata->no_backup_battery)
+		twl4030_bk_bci_battery_read_status(di);
 	schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
 }
 
 static void twl4030_bci_battery_read_status(struct twl4030_bci_device_info *di)
 {
-	di->temp_C = twl4030battery_temperature();
+	di->temp_C = twl4030battery_temperature(di);
 	di->voltage_uV = twl4030battery_voltage();
 	di->current_uA = twl4030battery_current();
 }
@@ -819,6 +881,87 @@
 #define to_twl4030_bk_bci_device_info(x) container_of((x), \
 		struct twl4030_bci_device_info, bk_bat);
 
+static ssize_t
+show_charge_current(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	u8  ctl;
+	int ret = read_bci_val(REG_BCIIREF1) & 0x1FF;
+	twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ctl, REG_BCICTL1);
+
+	if (ctl & CGAIN)
+		ret |= 0x200;
+
+#ifdef DEBUG
+	/* Dump debug */
+	twl4030battery_temp_setup();
+#endif
+
+	return sprintf(buf, "%d\n", ret);
+}
+
+static ssize_t
+set_charge_current(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long newCurrent;
+	int ret;
+
+	ret = strict_strtoul(buf, 10, &newCurrent);
+	if (ret)
+		return -EINVAL;
+
+	ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF, REG_BCIMFKEY);
+	if (ret)
+		return ret;
+
+	ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, newCurrent & 0xff, REG_BCIIREF1);
+	if (ret)
+		return ret;
+
+	ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF, REG_BCIMFKEY);
+	if (ret)
+		return ret;
+
+	ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, (newCurrent >> 8) & 0x1, REG_BCIIREF2);
+	if (ret)
+		return ret;
+
+	/* Set software-controlled charge */
+	twl4030charger_ac_en(ENABLE, 0);
+
+	/* Set CGAIN = 0 or 1 */
+	if(newCurrent > 511) {
+		u8 tmp;
+
+		/* Set CGAIN = 1 -- need to wait until automatic charge turns off */
+		while(!ret) {
+			clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, CGAIN | 0x1B, REG_BCICTL1);
+			twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
+
+			ret = tmp & CGAIN;
+			if(!ret)
+				mdelay(50);
+		}
+	} else {
+		u8 tmp;
+
+		/* Set CGAIN = 0 -- need to wait until automatic charge turns off */
+		while(!ret) {
+			clear_n_set(TWL4030_MODULE_MAIN_CHARGE, CGAIN, 0x1B, REG_BCICTL1);
+			twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
+
+			ret = !(tmp & CGAIN);
+			if(!ret)
+				mdelay(50);
+		}
+	}
+
+	/* Set automatic charge (CGAIN = 0/1 persists) */
+	twl4030charger_ac_en(ENABLE, 1);
+
+	return count;
+}
+static DEVICE_ATTR(charge_current, S_IRUGO | S_IWUSR, show_charge_current, set_charge_current);
+
 static int twl4030_bk_bci_battery_get_property(struct power_supply *psy,
 					enum power_supply_property psp,
 					union power_supply_propval *val)
@@ -912,8 +1055,6 @@
 	int irq;
 	int ret;
 
-	therm_tbl = pdata->battery_tmp_tbl;
-
 	di = kzalloc(sizeof(*di), GFP_KERNEL);
 	if (!di)
 		return -ENOMEM;
@@ -937,8 +1078,12 @@
 	di->bk_bat.num_properties = ARRAY_SIZE(twl4030_bk_bci_battery_props);
 	di->bk_bat.get_property = twl4030_bk_bci_battery_get_property;
 	di->bk_bat.external_power_changed = NULL;
+	di->pdata = pdata;
 
-	twl4030charger_ac_en(ENABLE);
+	/* Set up clocks */
+	twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, MADC_HFCLK_EN | DEFAULT_MADC_CLK_EN, REG_GPBR1);
+
+	twl4030charger_ac_en(ENABLE, CHARGE_MODE);
 	twl4030charger_usb_en(ENABLE);
 	twl4030battery_hw_level_en(ENABLE);
 	twl4030battery_hw_presence_en(ENABLE);
@@ -951,9 +1096,12 @@
 		goto temp_setup_fail;
 
 	/* enabling GPCH09 for read back battery voltage */
-	ret = twl4030backupbatt_voltage_setup();
-	if (ret)
-		goto voltage_setup_fail;
+	if(!di->pdata->no_backup_battery)
+	{
+		ret = twl4030backupbatt_voltage_setup();
+		if (ret)
+			goto voltage_setup_fail;
+	}
 
 	/* REVISIT do we need to request both IRQs ?? */
 
@@ -988,9 +1136,18 @@
 				twl4030_bci_battery_work);
 	schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
 
-	ret = power_supply_register(&pdev->dev, &di->bk_bat);
+	if(!pdata->no_backup_battery)
+	{
+		ret = power_supply_register(&pdev->dev, &di->bk_bat);
+		if (ret) {
+			dev_dbg(&pdev->dev, "failed to register backup battery\n");
+			goto bk_batt_failed;
+		}
+	}
+
+	ret = device_create_file(di->bat.dev, &dev_attr_charge_current);
 	if (ret) {
-		dev_dbg(&pdev->dev, "failed to register backup battery\n");
+		dev_err(&pdev->dev, "failed to create sysfs entries\n");
 		goto bk_batt_failed;
 	}
 
@@ -1001,7 +1158,8 @@
 	return 0;
 
 bk_batt_failed:
-	power_supply_unregister(&di->bat);
+	if(!pdata->no_backup_battery)
+		power_supply_unregister(&di->bat);
 batt_failed:
 	free_irq(irq, di);
 chg_irq_fail:
@@ -1010,7 +1168,7 @@
 batt_irq_fail:
 voltage_setup_fail:
 temp_setup_fail:
-	twl4030charger_ac_en(DISABLE);
+	twl4030charger_ac_en(DISABLE, CHARGE_MODE);
 	twl4030charger_usb_en(DISABLE);
 	twl4030battery_hw_level_en(DISABLE);
 	twl4030battery_hw_presence_en(DISABLE);
@@ -1024,7 +1182,7 @@
 	struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
 	int irq;
 
-	twl4030charger_ac_en(DISABLE);
+	twl4030charger_ac_en(DISABLE, CHARGE_MODE);
 	twl4030charger_usb_en(DISABLE);
 	twl4030battery_hw_level_en(DISABLE);
 	twl4030battery_hw_presence_en(DISABLE);
--- a/include/linux/i2c/twl4030.h
+++ b/include/linux/i2c/twl4030.h
@@ -299,6 +299,8 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
 struct twl4030_bci_platform_data {
 	int *battery_tmp_tbl;
 	unsigned int tblsize;
+
+	bool no_backup_battery;
 };
 
 /* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: USB charging over TPS65950 BCI
  2009-07-31 13:49 USB charging over TPS65950 BCI pramod gurav
  2009-08-01  6:41 ` Gregoire Gentil
@ 2009-08-02 15:44 ` Grazvydas Ignotas
  1 sibling, 0 replies; 7+ messages in thread
From: Grazvydas Ignotas @ 2009-08-02 15:44 UTC (permalink / raw)
  To: pramod gurav; +Cc: linux-omap

On Fri, Jul 31, 2009 at 4:49 PM, pramod gurav<pramodforum@gmail.com> wrote:
> Hi All,
> I was trying to get the USB battery charging working over TPS65950 BCI
> on the OMAP3430 custom board. I am working with linux-omap-2.6
> v2.6.28-omap1 tag. I enabled the TWL4030 MADC and TWL4030 BCI drivers.
> I passed interrupt details to these drivers from platform_device
> structure from my board file. I could get the AC charging working. The
> AC and USB detection worked. However the USB charging is not
> happening.
> I read through the TPS TRM and took the dumps of the registers from
> BCI and some from TWL USB module and BOOT_BCI whenever I plug in the
> USB charger between host and the board. The register settings seem to
> be fine. But the battery is not charging. I am using BQ27000 chip for
> battery monitoring and I can see the battery voltage is decreasing.

There seem to be USB related changes in Zoom git, you can try and see
if it helps:
http://git.omapzoom.org/?p=repo/omapkernel.git;a=blob;f=drivers/power/twl4030_bci_battery.c;hb=refs/heads/ti-2.6.27-omap3

Let us know if it helps.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: USB charging over TPS65950 BCI
       [not found]     ` <f502236f0909110651v1c323f7co1fc515654f236eda@mail.gmail.com>
@ 2009-09-11 14:01       ` pramod gurav
  2009-09-14 22:53         ` Gregoire Gentil
  0 siblings, 1 reply; 7+ messages in thread
From: pramod gurav @ 2009-09-11 14:01 UTC (permalink / raw)
  To: gregoire, linux-omap

hi gregoire,
i did not mention about charge current. the sysfs entry charge_current
always returns 360.


-- 
Best Regards
Pramod


On Fri, Sep 11, 2009 at 7:21 PM, pramod gurav <pramodforum@gmail.com> wrote:
> Hello gregoire,
>
> Really sorry I could not reply to your mail as I was busy with some other work.
> I applied your above patch tested. The sysfs entries return correct
> values for status, charger device(online), voltage_now. But the
> current across the battery is reported wrong. I compared the values
> returned by current_now sysfs entry with multimeter values across the
> battery. The values were varying whenever I remove AC and plug it
> back. But what I could see was the current_now value was approximately
> double the actual current across the battery.
> Without your patch the twl4030_bci gives wrong values for current_now,
> voltage_now, capacity etc.
> But your patch fixes this issue.
>
> But the USB charging did not work. Is USB charging functional with
> TWL4030 on any of the OMAP boards?
>
>
> Don't mind for the late reply. Thanks for your help.
>
> --
> Thanks and Best Regards
> Pramod
>
> On Wed, Aug 5, 2009 at 9:48 PM, Gregoire Gentil <gregoire@gentil.com> wrote:
>> Hello,
>>
>> Any feed-back on the patch I sent? Have you tried it? Have you fixed
>> your problem?
>>
>> Grégoire
>>
>>
>> On Fri, 2009-07-31 at 23:41 -0700, Gregoire Gentil wrote:
>>> On Fri, 2009-07-31 at 19:19 +0530, pramod gurav wrote:
>>> > Hi All,
>>> > I was trying to get the USB battery charging working over TPS65950 BCI
>>> > on the OMAP3430 custom board. I am working with linux-omap-2.6
>>> > v2.6.28-omap1 tag. I enabled the TWL4030 MADC and TWL4030 BCI drivers.
>>> > I passed interrupt details to these drivers from platform_device
>>> > structure from my board file. I could get the AC charging working. The
>>> > AC and USB detection worked. However the USB charging is not
>>> > happening.
>>> > I read through the TPS TRM and took the dumps of the registers from
>>> > BCI and some from TWL USB module and BOOT_BCI whenever I plug in the
>>> > USB charger between host and the board. The register settings seem to
>>> > be fine. But the battery is not charging. I am using BQ27000 chip for
>>> > battery monitoring and I can see the battery voltage is decreasing.
>>> >
>>> > Following are the register dumps of TWL with and without USB plugged in:
>>> >
>>> > These are the register contents when USB charger is plugged in:
>>> > BCIMDEN         = 0x11
>>> > REG_BOOT_BCI    = 0x37
>>> > REG_POWER_CTRL  = 0x20
>>> > REG_BCIMFSTS4   = 0xf4
>>> > REG_BCIMFSTS1   = 0x13
>>> > REG_BCIIREF1    = 0x68
>>> > REG_BCIIREF2    = 0x3
>>> > REG_BCIMFEN4    = 0x6f
>>> > REG_BCIMFSTS2   = 0x0
>>> > REG_BCIMSTATEC  = 0x12
>>> > REG_STS_HW_CONDITIONS= 0x90
>>> >
>>> >
>>> > These are the register contents when USB charger is plugged out:
>>> > BCIMDEN         = 0x0
>>> > REG_BOOT_BCI    = 0x35
>>> > REG_POWER_CTRL  = 0x20
>>> > REG_BCIMFSTS4   = 0xf0
>>> > REG_BCIMFSTS1   = 0xaa
>>> > REG_BCIIREF1    = 0x68
>>> > REG_BCIIREF2    = 0x3
>>> > REG_BCIMFEN4    = 0x68
>>> > REG_BCIMFSTS2   = 0x0
>>> > REG_BCIMSTATEC  =0x0
>>> > REG_STS_HW_CONDITIONS= 0x10
>>> >
>>> > Is there anything more I need to support to get BCI USB charging
>>> > working? Need I follow any USB Communication protocol between Host and
>>> > the board.
>>> > I have pasted the kernel boot logs for reference at the end.
>>> > Can any one please guide me to some pointers?
>>> >
>>> > --
>>> > Best Regards
>>> > Pramod
>>> I'm experiencing some problems with TWL4030 DC charging and I'm
>>> interested by this kind of problem. Basically, the values reported by
>>> our patch is different from the current going to the battery. We wrote
>>> the attached enhanced patch so as to edit at run-time the charging mode
>>> and various values including charge_current. It's against 2.6.29 but I
>>> think that it should work again 2.6.28. Unfortunately, starting 2.6.30,
>>> Tony has removed all the BCI battery code and has asked for updated code
>>> against mainline but I've not seen anything so far.
>>>
>>> Pramod, can you try the attached patch (perhaps, it will help you) and
>>> can you tell if you see the exact current going to the battery reported
>>> by the driver?
>>>
>>> Grégoire
>>>
>>>
>>>
>>>
>>>
>>> --- a/drivers/power/twl4030_bci_battery.c     2009-07-22 18:27:16.000000000
>>> -0700
>>> +++ b/drivers/power/twl4030_bci_battery.c     2009-07-22 18:30:22.000000000
>>> -0700
>>> @@ -15,6 +15,9 @@
>>>   * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
>>>   */
>>>
>>> +/* Boot with automatic charge */
>>> +#define CHARGE_MODE 1
>>> +
>>>  #include <linux/init.h>
>>>  #include <linux/module.h>
>>>  #include <linux/device.h>
>>> @@ -50,6 +53,7 @@
>>>  /* Boot BCI flag bits */
>>>  #define BCIAUTOWEN           0x020
>>>  #define CONFIG_DONE          0x010
>>> +#define CVENAC                       0x004
>>>  #define BCIAUTOUSB           0x002
>>>  #define BCIAUTOAC            0x001
>>>  #define BCIMSTAT_MASK                0x03F
>>> @@ -81,6 +85,11 @@
>>>  #define REG_BB_CFG           0x012
>>>  #define BBCHEN                       0x010
>>>
>>> +/* GPBR */
>>> +#define REG_GPBR1            0x0c
>>> +#define MADC_HFCLK_EN                0x80
>>> +#define DEFAULT_MADC_CLK_EN  0x10
>>> +
>>>  /* Power supply charge interrupt */
>>>  #define REG_PWR_ISR1         0x00
>>>  #define REG_PWR_IMR1         0x01
>>> @@ -125,6 +134,18 @@
>>>  /* BCIEDR3 */
>>>  #define      VBATLVL_EDRRISIN        0x02
>>>
>>> +/* BCIIREF1 */
>>> +#define REG_BCIIREF1         0x027
>>> +#define REG_BCIIREF2         0x028
>>> +
>>> +/* BCIMFTH1 */
>>> +#define REG_BCIMFTH1         0x016
>>> +
>>> +/* Key */
>>> +#define KEY_IIREF            0xE7
>>> +#define KEY_FTH1             0xD2
>>> +#define REG_BCIMFKEY         0x011
>>> +
>>>  /* Step size and prescaler ratio */
>>>  #define TEMP_STEP_SIZE               147
>>>  #define TEMP_PSR_R           100
>>> @@ -142,9 +163,6 @@
>>>  #define ENABLE               1
>>>  #define DISABLE              1
>>>
>>> -/* Ptr to thermistor table */
>>> -int *therm_tbl;
>>> -
>>>  struct twl4030_bci_device_info {
>>>       struct device           *dev;
>>>
>>> @@ -160,6 +178,8 @@
>>>       struct power_supply     bk_bat;
>>>       struct delayed_work     twl4030_bci_monitor_work;
>>>       struct delayed_work     twl4030_bk_bci_monitor_work;
>>> +
>>> +     struct twl4030_bci_platform_data *pdata;
>>>  };
>>>
>>>  static int usb_charger_flag;
>>> @@ -425,15 +445,21 @@
>>>  /*
>>>   * Enable/Disable AC Charge funtionality.
>>>   */
>>> -static int twl4030charger_ac_en(int enable)
>>> +static int twl4030charger_ac_en(int enable, int automatic)
>>>  {
>>>       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(!automatic) {
>>> +                     ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOAC | CVENAC,
>>> +                             (CONFIG_DONE | BCIAUTOWEN),
>>> +                             REG_BOOT_BCI);
>>> +             } else {
>>> +                     ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
>>> +                             (CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC | CVENAC),
>>> +                             REG_BOOT_BCI);
>>> +             }
>>>               if (ret)
>>>                       return ret;
>>>       } else {
>>> @@ -518,11 +544,15 @@
>>>   * Return battery temperature
>>>   * Or < 0 on failure.
>>>   */
>>> -static int twl4030battery_temperature(void)
>>> +static int twl4030battery_temperature(struct twl4030_bci_device_info
>>> *di)
>>>  {
>>>       u8 val;
>>>       int temp, curr, volt, res, ret;
>>>
>>> +     /* Is a temperature table specified? */
>>> +     if (!di->pdata->tblsize)
>>> +             return 0;
>>> +
>>>       /* Getting and calculating the thermistor voltage */
>>>       ret = read_bci_val(T2_BATTERY_TEMP);
>>>       if (ret < 0)
>>> @@ -543,7 +573,7 @@
>>>
>>>       /*calculating temperature*/
>>>       for (temp = 58; temp >= 0; temp--) {
>>> -             int actual = therm_tbl[temp];
>>> +             int actual = di->pdata->battery_tmp_tbl[temp];
>>>               if ((actual - res) >= 0)
>>>                       break;
>>>       }
>>> @@ -661,6 +691,9 @@
>>>               return ret;
>>>       }
>>>
>>> +#ifdef DEBUG
>>> +     printk("BCI DEBUG: BCIMSTATEC Charge state is 0x%x\n", status);
>>> +#endif
>>>       return (int) (status & BCIMSTAT_MASK);
>>>  }
>>>
>>> @@ -709,14 +742,43 @@
>>>   */
>>>  static int twl4030battery_temp_setup(void)
>>>  {
>>> -     int ret;
>>> +#ifdef DEBUG
>>> +     u8 i;
>>> +#endif
>>> +     u8 ret;
>>>
>>>       /* Enabling thermistor current */
>>> -     ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, ITHEN,
>>> +     ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, 0x1B,
>>>               REG_BCICTL1);
>>>       if (ret)
>>>               return ret;
>>>
>>> +#ifdef DEBUG
>>> +     twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret, REG_BOOT_BCI);
>>> +     printk("BCI DEBUG: BOOT_BCI Value is 0x%x\n", ret);
>>> +
>>> +     twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret,
>>> REG_STS_HW_CONDITIONS);
>>> +     printk("BCI DEBUG: STS_HW_CONDITIONS Value is 0x%x\n", ret);
>>> +
>>> +     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL1);
>>> +     printk("BCI DEBUG: BCICTL1 Value is 0x%x\n", ret);
>>> +
>>> +     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL2);
>>> +     printk("BCI DEBUG: BCICTL2 Value is 0x%x\n", ret);
>>> +
>>> +     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, 0x0);
>>> +     printk("BCI DEBUG: BCIMDEN Value is 0x%x\n", ret);
>>> +
>>> +     twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &ret, REG_GPBR1);
>>> +     printk("BCI DEBUG: GPBR1 Value is 0x%x\n", ret);
>>> +
>>> +     for(i = 0x0; i <= 0x32; i++)
>>> +     {
>>> +             twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, i);
>>> +             printk("BCI DEBUG: BCI 0x%x Value is 0x%x\n", i, ret);
>>> +     }
>>> +#endif
>>> +
>>>       return 0;
>>>  }
>>>
>>> @@ -732,7 +794,6 @@
>>>       ret = twl4030_i2c_read_u8(mod_no, &val, reg);
>>>       if (ret)
>>>               return ret;
>>> -
>>>       /* Clearing all those bits to clear */
>>>       val &= ~(clear);
>>>
>>> @@ -772,13 +833,14 @@
>>>               struct twl4030_bci_device_info,
>>>               twl4030_bk_bci_monitor_work.work);
>>>
>>> -     twl4030_bk_bci_battery_read_status(di);
>>> +     if(!di->pdata->no_backup_battery)
>>> +             twl4030_bk_bci_battery_read_status(di);
>>>       schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
>>>  }
>>>
>>>  static void twl4030_bci_battery_read_status(struct
>>> twl4030_bci_device_info *di)
>>>  {
>>> -     di->temp_C = twl4030battery_temperature();
>>> +     di->temp_C = twl4030battery_temperature(di);
>>>       di->voltage_uV = twl4030battery_voltage();
>>>       di->current_uA = twl4030battery_current();
>>>  }
>>> @@ -819,6 +881,87 @@
>>>  #define to_twl4030_bk_bci_device_info(x) container_of((x), \
>>>               struct twl4030_bci_device_info, bk_bat);
>>>
>>> +static ssize_t
>>> +show_charge_current(struct device *dev, struct device_attribute *attr,
>>> char *buf)
>>> +{
>>> +     u8  ctl;
>>> +     int ret = read_bci_val(REG_BCIIREF1) & 0x1FF;
>>> +     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ctl, REG_BCICTL1);
>>> +
>>> +     if (ctl & CGAIN)
>>> +             ret |= 0x200;
>>> +
>>> +#ifdef DEBUG
>>> +     /* Dump debug */
>>> +     twl4030battery_temp_setup();
>>> +#endif
>>> +
>>> +     return sprintf(buf, "%d\n", ret);
>>> +}
>>> +
>>> +static ssize_t
>>> +set_charge_current(struct device *dev, struct device_attribute *attr,
>>> const char *buf, size_t count)
>>> +{
>>> +     unsigned long newCurrent;
>>> +     int ret;
>>> +
>>> +     ret = strict_strtoul(buf, 10, &newCurrent);
>>> +     if (ret)
>>> +             return -EINVAL;
>>> +
>>> +     ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF,
>>> REG_BCIMFKEY);
>>> +     if (ret)
>>> +             return ret;
>>> +
>>> +     ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, newCurrent &
>>> 0xff, REG_BCIIREF1);
>>> +     if (ret)
>>> +             return ret;
>>> +
>>> +     ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF,
>>> REG_BCIMFKEY);
>>> +     if (ret)
>>> +             return ret;
>>> +
>>> +     ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, (newCurrent >>
>>> 8) & 0x1, REG_BCIIREF2);
>>> +     if (ret)
>>> +             return ret;
>>> +
>>> +     /* Set software-controlled charge */
>>> +     twl4030charger_ac_en(ENABLE, 0);
>>> +
>>> +     /* Set CGAIN = 0 or 1 */
>>> +     if(newCurrent > 511) {
>>> +             u8 tmp;
>>> +
>>> +             /* Set CGAIN = 1 -- need to wait until automatic charge turns off */
>>> +             while(!ret) {
>>> +                     clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, CGAIN | 0x1B,
>>> REG_BCICTL1);
>>> +                     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
>>> +
>>> +                     ret = tmp & CGAIN;
>>> +                     if(!ret)
>>> +                             mdelay(50);
>>> +             }
>>> +     } else {
>>> +             u8 tmp;
>>> +
>>> +             /* Set CGAIN = 0 -- need to wait until automatic charge turns off */
>>> +             while(!ret) {
>>> +                     clear_n_set(TWL4030_MODULE_MAIN_CHARGE, CGAIN, 0x1B, REG_BCICTL1);
>>> +                     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
>>> +
>>> +                     ret = !(tmp & CGAIN);
>>> +                     if(!ret)
>>> +                             mdelay(50);
>>> +             }
>>> +     }
>>> +
>>> +     /* Set automatic charge (CGAIN = 0/1 persists) */
>>> +     twl4030charger_ac_en(ENABLE, 1);
>>> +
>>> +     return count;
>>> +}
>>> +static DEVICE_ATTR(charge_current, S_IRUGO | S_IWUSR,
>>> show_charge_current, set_charge_current);
>>> +
>>>  static int twl4030_bk_bci_battery_get_property(struct power_supply
>>> *psy,
>>>                                       enum power_supply_property psp,
>>>                                       union power_supply_propval *val)
>>> @@ -912,8 +1055,6 @@
>>>       int irq;
>>>       int ret;
>>>
>>> -     therm_tbl = pdata->battery_tmp_tbl;
>>> -
>>>       di = kzalloc(sizeof(*di), GFP_KERNEL);
>>>       if (!di)
>>>               return -ENOMEM;
>>> @@ -937,8 +1078,12 @@
>>>       di->bk_bat.num_properties = ARRAY_SIZE(twl4030_bk_bci_battery_props);
>>>       di->bk_bat.get_property = twl4030_bk_bci_battery_get_property;
>>>       di->bk_bat.external_power_changed = NULL;
>>> +     di->pdata = pdata;
>>>
>>> -     twl4030charger_ac_en(ENABLE);
>>> +     /* Set up clocks */
>>> +     twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, MADC_HFCLK_EN |
>>> DEFAULT_MADC_CLK_EN, REG_GPBR1);
>>> +
>>> +     twl4030charger_ac_en(ENABLE, CHARGE_MODE);
>>>       twl4030charger_usb_en(ENABLE);
>>>       twl4030battery_hw_level_en(ENABLE);
>>>       twl4030battery_hw_presence_en(ENABLE);
>>> @@ -951,9 +1096,12 @@
>>>               goto temp_setup_fail;
>>>
>>>       /* enabling GPCH09 for read back battery voltage */
>>> -     ret = twl4030backupbatt_voltage_setup();
>>> -     if (ret)
>>> -             goto voltage_setup_fail;
>>> +     if(!di->pdata->no_backup_battery)
>>> +     {
>>> +             ret = twl4030backupbatt_voltage_setup();
>>> +             if (ret)
>>> +                     goto voltage_setup_fail;
>>> +     }
>>>
>>>       /* REVISIT do we need to request both IRQs ?? */
>>>
>>> @@ -988,9 +1136,18 @@
>>>                               twl4030_bci_battery_work);
>>>       schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
>>>
>>> -     ret = power_supply_register(&pdev->dev, &di->bk_bat);
>>> +     if(!pdata->no_backup_battery)
>>> +     {
>>> +             ret = power_supply_register(&pdev->dev, &di->bk_bat);
>>> +             if (ret) {
>>> +                     dev_dbg(&pdev->dev, "failed to register backup battery\n");
>>> +                     goto bk_batt_failed;
>>> +             }
>>> +     }
>>> +
>>> +     ret = device_create_file(di->bat.dev, &dev_attr_charge_current);
>>>       if (ret) {
>>> -             dev_dbg(&pdev->dev, "failed to register backup battery\n");
>>> +             dev_err(&pdev->dev, "failed to create sysfs entries\n");
>>>               goto bk_batt_failed;
>>>       }
>>>
>>> @@ -1001,7 +1158,8 @@
>>>       return 0;
>>>
>>>  bk_batt_failed:
>>> -     power_supply_unregister(&di->bat);
>>> +     if(!pdata->no_backup_battery)
>>> +             power_supply_unregister(&di->bat);
>>>  batt_failed:
>>>       free_irq(irq, di);
>>>  chg_irq_fail:
>>> @@ -1010,7 +1168,7 @@
>>>  batt_irq_fail:
>>>  voltage_setup_fail:
>>>  temp_setup_fail:
>>> -     twl4030charger_ac_en(DISABLE);
>>> +     twl4030charger_ac_en(DISABLE, CHARGE_MODE);
>>>       twl4030charger_usb_en(DISABLE);
>>>       twl4030battery_hw_level_en(DISABLE);
>>>       twl4030battery_hw_presence_en(DISABLE);
>>> @@ -1024,7 +1182,7 @@
>>>       struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
>>>       int irq;
>>>
>>> -     twl4030charger_ac_en(DISABLE);
>>> +     twl4030charger_ac_en(DISABLE, CHARGE_MODE);
>>>       twl4030charger_usb_en(DISABLE);
>>>       twl4030battery_hw_level_en(DISABLE);
>>>       twl4030battery_hw_presence_en(DISABLE);
>>> --- a/include/linux/i2c/twl4030.h
>>> +++ b/include/linux/i2c/twl4030.h
>>> @@ -299,6 +299,8 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg,
>>> unsigned num_bytes);
>>>  struct twl4030_bci_platform_data {
>>>       int *battery_tmp_tbl;
>>>       unsigned int tblsize;
>>> +
>>> +     bool no_backup_battery;
>>>  };
>>>
>>>  /* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */
>>>
>>
>>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: USB charging over TPS65950 BCI
  2009-09-11 14:01       ` pramod gurav
@ 2009-09-14 22:53         ` Gregoire Gentil
  2009-09-14 23:21           ` Syed Mohammed, Khasim
  0 siblings, 1 reply; 7+ messages in thread
From: Gregoire Gentil @ 2009-09-14 22:53 UTC (permalink / raw)
  To: pramod gurav; +Cc: linux-omap, Tim Yamin, Dighe, Gandhar

I don't know. I haven't seen yet a battery driver that works correctly
with the TPS65950 and I have ping multiple times various people at TI.
Perhaps Gandhar will have an idea. I think that it would be valuable for
the community that somebody at TI provides some patches to report
correctly everything around the battery,

Grégoire


On Fri, 2009-09-11 at 19:31 +0530, pramod gurav wrote: 
> hi gregoire,
> i did not mention about charge current. the sysfs entry charge_current
> always returns 360.
> 
> 
> -- 
> Best Regards
> Pramod
> 
> 
> On Fri, Sep 11, 2009 at 7:21 PM, pramod gurav <pramodforum@gmail.com> wrote:
> > Hello gregoire,
> >
> > Really sorry I could not reply to your mail as I was busy with some other work.
> > I applied your above patch tested. The sysfs entries return correct
> > values for status, charger device(online), voltage_now. But the
> > current across the battery is reported wrong. I compared the values
> > returned by current_now sysfs entry with multimeter values across the
> > battery. The values were varying whenever I remove AC and plug it
> > back. But what I could see was the current_now value was approximately
> > double the actual current across the battery.
> > Without your patch the twl4030_bci gives wrong values for current_now,
> > voltage_now, capacity etc.
> > But your patch fixes this issue.
> >
> > But the USB charging did not work. Is USB charging functional with
> > TWL4030 on any of the OMAP boards?
> >
> >
> > Don't mind for the late reply. Thanks for your help.
> >
> > --
> > Thanks and Best Regards
> > Pramod
> >
> > On Wed, Aug 5, 2009 at 9:48 PM, Gregoire Gentil <gregoire@gentil.com> wrote:
> >> Hello,
> >>
> >> Any feed-back on the patch I sent? Have you tried it? Have you fixed
> >> your problem?
> >>
> >> Grégoire
> >>
> >>
> >> On Fri, 2009-07-31 at 23:41 -0700, Gregoire Gentil wrote:
> >>> On Fri, 2009-07-31 at 19:19 +0530, pramod gurav wrote:
> >>> > Hi All,
> >>> > I was trying to get the USB battery charging working over TPS65950 BCI
> >>> > on the OMAP3430 custom board. I am working with linux-omap-2.6
> >>> > v2.6.28-omap1 tag. I enabled the TWL4030 MADC and TWL4030 BCI drivers.
> >>> > I passed interrupt details to these drivers from platform_device
> >>> > structure from my board file. I could get the AC charging working. The
> >>> > AC and USB detection worked. However the USB charging is not
> >>> > happening.
> >>> > I read through the TPS TRM and took the dumps of the registers from
> >>> > BCI and some from TWL USB module and BOOT_BCI whenever I plug in the
> >>> > USB charger between host and the board. The register settings seem to
> >>> > be fine. But the battery is not charging. I am using BQ27000 chip for
> >>> > battery monitoring and I can see the battery voltage is decreasing.
> >>> >
> >>> > Following are the register dumps of TWL with and without USB plugged in:
> >>> >
> >>> > These are the register contents when USB charger is plugged in:
> >>> > BCIMDEN         = 0x11
> >>> > REG_BOOT_BCI    = 0x37
> >>> > REG_POWER_CTRL  = 0x20
> >>> > REG_BCIMFSTS4   = 0xf4
> >>> > REG_BCIMFSTS1   = 0x13
> >>> > REG_BCIIREF1    = 0x68
> >>> > REG_BCIIREF2    = 0x3
> >>> > REG_BCIMFEN4    = 0x6f
> >>> > REG_BCIMFSTS2   = 0x0
> >>> > REG_BCIMSTATEC  = 0x12
> >>> > REG_STS_HW_CONDITIONS= 0x90
> >>> >
> >>> >
> >>> > These are the register contents when USB charger is plugged out:
> >>> > BCIMDEN         = 0x0
> >>> > REG_BOOT_BCI    = 0x35
> >>> > REG_POWER_CTRL  = 0x20
> >>> > REG_BCIMFSTS4   = 0xf0
> >>> > REG_BCIMFSTS1   = 0xaa
> >>> > REG_BCIIREF1    = 0x68
> >>> > REG_BCIIREF2    = 0x3
> >>> > REG_BCIMFEN4    = 0x68
> >>> > REG_BCIMFSTS2   = 0x0
> >>> > REG_BCIMSTATEC  =0x0
> >>> > REG_STS_HW_CONDITIONS= 0x10
> >>> >
> >>> > Is there anything more I need to support to get BCI USB charging
> >>> > working? Need I follow any USB Communication protocol between Host and
> >>> > the board.
> >>> > I have pasted the kernel boot logs for reference at the end.
> >>> > Can any one please guide me to some pointers?
> >>> >
> >>> > --
> >>> > Best Regards
> >>> > Pramod
> >>> I'm experiencing some problems with TWL4030 DC charging and I'm
> >>> interested by this kind of problem. Basically, the values reported by
> >>> our patch is different from the current going to the battery. We wrote
> >>> the attached enhanced patch so as to edit at run-time the charging mode
> >>> and various values including charge_current. It's against 2.6.29 but I
> >>> think that it should work again 2.6.28. Unfortunately, starting 2.6.30,
> >>> Tony has removed all the BCI battery code and has asked for updated code
> >>> against mainline but I've not seen anything so far.
> >>>
> >>> Pramod, can you try the attached patch (perhaps, it will help you) and
> >>> can you tell if you see the exact current going to the battery reported
> >>> by the driver?
> >>>
> >>> Grégoire
> >>>
> >>>
> >>>
> >>>
> >>>
> >>> --- a/drivers/power/twl4030_bci_battery.c     2009-07-22 18:27:16.000000000
> >>> -0700
> >>> +++ b/drivers/power/twl4030_bci_battery.c     2009-07-22 18:30:22.000000000
> >>> -0700
> >>> @@ -15,6 +15,9 @@
> >>>   * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> >>>   */
> >>>
> >>> +/* Boot with automatic charge */
> >>> +#define CHARGE_MODE 1
> >>> +
> >>>  #include <linux/init.h>
> >>>  #include <linux/module.h>
> >>>  #include <linux/device.h>
> >>> @@ -50,6 +53,7 @@
> >>>  /* Boot BCI flag bits */
> >>>  #define BCIAUTOWEN           0x020
> >>>  #define CONFIG_DONE          0x010
> >>> +#define CVENAC                       0x004
> >>>  #define BCIAUTOUSB           0x002
> >>>  #define BCIAUTOAC            0x001
> >>>  #define BCIMSTAT_MASK                0x03F
> >>> @@ -81,6 +85,11 @@
> >>>  #define REG_BB_CFG           0x012
> >>>  #define BBCHEN                       0x010
> >>>
> >>> +/* GPBR */
> >>> +#define REG_GPBR1            0x0c
> >>> +#define MADC_HFCLK_EN                0x80
> >>> +#define DEFAULT_MADC_CLK_EN  0x10
> >>> +
> >>>  /* Power supply charge interrupt */
> >>>  #define REG_PWR_ISR1         0x00
> >>>  #define REG_PWR_IMR1         0x01
> >>> @@ -125,6 +134,18 @@
> >>>  /* BCIEDR3 */
> >>>  #define      VBATLVL_EDRRISIN        0x02
> >>>
> >>> +/* BCIIREF1 */
> >>> +#define REG_BCIIREF1         0x027
> >>> +#define REG_BCIIREF2         0x028
> >>> +
> >>> +/* BCIMFTH1 */
> >>> +#define REG_BCIMFTH1         0x016
> >>> +
> >>> +/* Key */
> >>> +#define KEY_IIREF            0xE7
> >>> +#define KEY_FTH1             0xD2
> >>> +#define REG_BCIMFKEY         0x011
> >>> +
> >>>  /* Step size and prescaler ratio */
> >>>  #define TEMP_STEP_SIZE               147
> >>>  #define TEMP_PSR_R           100
> >>> @@ -142,9 +163,6 @@
> >>>  #define ENABLE               1
> >>>  #define DISABLE              1
> >>>
> >>> -/* Ptr to thermistor table */
> >>> -int *therm_tbl;
> >>> -
> >>>  struct twl4030_bci_device_info {
> >>>       struct device           *dev;
> >>>
> >>> @@ -160,6 +178,8 @@
> >>>       struct power_supply     bk_bat;
> >>>       struct delayed_work     twl4030_bci_monitor_work;
> >>>       struct delayed_work     twl4030_bk_bci_monitor_work;
> >>> +
> >>> +     struct twl4030_bci_platform_data *pdata;
> >>>  };
> >>>
> >>>  static int usb_charger_flag;
> >>> @@ -425,15 +445,21 @@
> >>>  /*
> >>>   * Enable/Disable AC Charge funtionality.
> >>>   */
> >>> -static int twl4030charger_ac_en(int enable)
> >>> +static int twl4030charger_ac_en(int enable, int automatic)
> >>>  {
> >>>       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(!automatic) {
> >>> +                     ret = clear_n_set(TWL4030_MODULE_PM_MASTER, BCIAUTOAC | CVENAC,
> >>> +                             (CONFIG_DONE | BCIAUTOWEN),
> >>> +                             REG_BOOT_BCI);
> >>> +             } else {
> >>> +                     ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
> >>> +                             (CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC | CVENAC),
> >>> +                             REG_BOOT_BCI);
> >>> +             }
> >>>               if (ret)
> >>>                       return ret;
> >>>       } else {
> >>> @@ -518,11 +544,15 @@
> >>>   * Return battery temperature
> >>>   * Or < 0 on failure.
> >>>   */
> >>> -static int twl4030battery_temperature(void)
> >>> +static int twl4030battery_temperature(struct twl4030_bci_device_info
> >>> *di)
> >>>  {
> >>>       u8 val;
> >>>       int temp, curr, volt, res, ret;
> >>>
> >>> +     /* Is a temperature table specified? */
> >>> +     if (!di->pdata->tblsize)
> >>> +             return 0;
> >>> +
> >>>       /* Getting and calculating the thermistor voltage */
> >>>       ret = read_bci_val(T2_BATTERY_TEMP);
> >>>       if (ret < 0)
> >>> @@ -543,7 +573,7 @@
> >>>
> >>>       /*calculating temperature*/
> >>>       for (temp = 58; temp >= 0; temp--) {
> >>> -             int actual = therm_tbl[temp];
> >>> +             int actual = di->pdata->battery_tmp_tbl[temp];
> >>>               if ((actual - res) >= 0)
> >>>                       break;
> >>>       }
> >>> @@ -661,6 +691,9 @@
> >>>               return ret;
> >>>       }
> >>>
> >>> +#ifdef DEBUG
> >>> +     printk("BCI DEBUG: BCIMSTATEC Charge state is 0x%x\n", status);
> >>> +#endif
> >>>       return (int) (status & BCIMSTAT_MASK);
> >>>  }
> >>>
> >>> @@ -709,14 +742,43 @@
> >>>   */
> >>>  static int twl4030battery_temp_setup(void)
> >>>  {
> >>> -     int ret;
> >>> +#ifdef DEBUG
> >>> +     u8 i;
> >>> +#endif
> >>> +     u8 ret;
> >>>
> >>>       /* Enabling thermistor current */
> >>> -     ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, ITHEN,
> >>> +     ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, 0x1B,
> >>>               REG_BCICTL1);
> >>>       if (ret)
> >>>               return ret;
> >>>
> >>> +#ifdef DEBUG
> >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret, REG_BOOT_BCI);
> >>> +     printk("BCI DEBUG: BOOT_BCI Value is 0x%x\n", ret);
> >>> +
> >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret,
> >>> REG_STS_HW_CONDITIONS);
> >>> +     printk("BCI DEBUG: STS_HW_CONDITIONS Value is 0x%x\n", ret);
> >>> +
> >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL1);
> >>> +     printk("BCI DEBUG: BCICTL1 Value is 0x%x\n", ret);
> >>> +
> >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, REG_BCICTL2);
> >>> +     printk("BCI DEBUG: BCICTL2 Value is 0x%x\n", ret);
> >>> +
> >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, 0x0);
> >>> +     printk("BCI DEBUG: BCIMDEN Value is 0x%x\n", ret);
> >>> +
> >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &ret, REG_GPBR1);
> >>> +     printk("BCI DEBUG: GPBR1 Value is 0x%x\n", ret);
> >>> +
> >>> +     for(i = 0x0; i <= 0x32; i++)
> >>> +     {
> >>> +             twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, i);
> >>> +             printk("BCI DEBUG: BCI 0x%x Value is 0x%x\n", i, ret);
> >>> +     }
> >>> +#endif
> >>> +
> >>>       return 0;
> >>>  }
> >>>
> >>> @@ -732,7 +794,6 @@
> >>>       ret = twl4030_i2c_read_u8(mod_no, &val, reg);
> >>>       if (ret)
> >>>               return ret;
> >>> -
> >>>       /* Clearing all those bits to clear */
> >>>       val &= ~(clear);
> >>>
> >>> @@ -772,13 +833,14 @@
> >>>               struct twl4030_bci_device_info,
> >>>               twl4030_bk_bci_monitor_work.work);
> >>>
> >>> -     twl4030_bk_bci_battery_read_status(di);
> >>> +     if(!di->pdata->no_backup_battery)
> >>> +             twl4030_bk_bci_battery_read_status(di);
> >>>       schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
> >>>  }
> >>>
> >>>  static void twl4030_bci_battery_read_status(struct
> >>> twl4030_bci_device_info *di)
> >>>  {
> >>> -     di->temp_C = twl4030battery_temperature();
> >>> +     di->temp_C = twl4030battery_temperature(di);
> >>>       di->voltage_uV = twl4030battery_voltage();
> >>>       di->current_uA = twl4030battery_current();
> >>>  }
> >>> @@ -819,6 +881,87 @@
> >>>  #define to_twl4030_bk_bci_device_info(x) container_of((x), \
> >>>               struct twl4030_bci_device_info, bk_bat);
> >>>
> >>> +static ssize_t
> >>> +show_charge_current(struct device *dev, struct device_attribute *attr,
> >>> char *buf)
> >>> +{
> >>> +     u8  ctl;
> >>> +     int ret = read_bci_val(REG_BCIIREF1) & 0x1FF;
> >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ctl, REG_BCICTL1);
> >>> +
> >>> +     if (ctl & CGAIN)
> >>> +             ret |= 0x200;
> >>> +
> >>> +#ifdef DEBUG
> >>> +     /* Dump debug */
> >>> +     twl4030battery_temp_setup();
> >>> +#endif
> >>> +
> >>> +     return sprintf(buf, "%d\n", ret);
> >>> +}
> >>> +
> >>> +static ssize_t
> >>> +set_charge_current(struct device *dev, struct device_attribute *attr,
> >>> const char *buf, size_t count)
> >>> +{
> >>> +     unsigned long newCurrent;
> >>> +     int ret;
> >>> +
> >>> +     ret = strict_strtoul(buf, 10, &newCurrent);
> >>> +     if (ret)
> >>> +             return -EINVAL;
> >>> +
> >>> +     ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF,
> >>> REG_BCIMFKEY);
> >>> +     if (ret)
> >>> +             return ret;
> >>> +
> >>> +     ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, newCurrent &
> >>> 0xff, REG_BCIIREF1);
> >>> +     if (ret)
> >>> +             return ret;
> >>> +
> >>> +     ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF,
> >>> REG_BCIMFKEY);
> >>> +     if (ret)
> >>> +             return ret;
> >>> +
> >>> +     ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, (newCurrent >>
> >>> 8) & 0x1, REG_BCIIREF2);
> >>> +     if (ret)
> >>> +             return ret;
> >>> +
> >>> +     /* Set software-controlled charge */
> >>> +     twl4030charger_ac_en(ENABLE, 0);
> >>> +
> >>> +     /* Set CGAIN = 0 or 1 */
> >>> +     if(newCurrent > 511) {
> >>> +             u8 tmp;
> >>> +
> >>> +             /* Set CGAIN = 1 -- need to wait until automatic charge turns off */
> >>> +             while(!ret) {
> >>> +                     clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, CGAIN | 0x1B,
> >>> REG_BCICTL1);
> >>> +                     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
> >>> +
> >>> +                     ret = tmp & CGAIN;
> >>> +                     if(!ret)
> >>> +                             mdelay(50);
> >>> +             }
> >>> +     } else {
> >>> +             u8 tmp;
> >>> +
> >>> +             /* Set CGAIN = 0 -- need to wait until automatic charge turns off */
> >>> +             while(!ret) {
> >>> +                     clear_n_set(TWL4030_MODULE_MAIN_CHARGE, CGAIN, 0x1B, REG_BCICTL1);
> >>> +                     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &tmp, REG_BCICTL1);
> >>> +
> >>> +                     ret = !(tmp & CGAIN);
> >>> +                     if(!ret)
> >>> +                             mdelay(50);
> >>> +             }
> >>> +     }
> >>> +
> >>> +     /* Set automatic charge (CGAIN = 0/1 persists) */
> >>> +     twl4030charger_ac_en(ENABLE, 1);
> >>> +
> >>> +     return count;
> >>> +}
> >>> +static DEVICE_ATTR(charge_current, S_IRUGO | S_IWUSR,
> >>> show_charge_current, set_charge_current);
> >>> +
> >>>  static int twl4030_bk_bci_battery_get_property(struct power_supply
> >>> *psy,
> >>>                                       enum power_supply_property psp,
> >>>                                       union power_supply_propval *val)
> >>> @@ -912,8 +1055,6 @@
> >>>       int irq;
> >>>       int ret;
> >>>
> >>> -     therm_tbl = pdata->battery_tmp_tbl;
> >>> -
> >>>       di = kzalloc(sizeof(*di), GFP_KERNEL);
> >>>       if (!di)
> >>>               return -ENOMEM;
> >>> @@ -937,8 +1078,12 @@
> >>>       di->bk_bat.num_properties = ARRAY_SIZE(twl4030_bk_bci_battery_props);
> >>>       di->bk_bat.get_property = twl4030_bk_bci_battery_get_property;
> >>>       di->bk_bat.external_power_changed = NULL;
> >>> +     di->pdata = pdata;
> >>>
> >>> -     twl4030charger_ac_en(ENABLE);
> >>> +     /* Set up clocks */
> >>> +     twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, MADC_HFCLK_EN |
> >>> DEFAULT_MADC_CLK_EN, REG_GPBR1);
> >>> +
> >>> +     twl4030charger_ac_en(ENABLE, CHARGE_MODE);
> >>>       twl4030charger_usb_en(ENABLE);
> >>>       twl4030battery_hw_level_en(ENABLE);
> >>>       twl4030battery_hw_presence_en(ENABLE);
> >>> @@ -951,9 +1096,12 @@
> >>>               goto temp_setup_fail;
> >>>
> >>>       /* enabling GPCH09 for read back battery voltage */
> >>> -     ret = twl4030backupbatt_voltage_setup();
> >>> -     if (ret)
> >>> -             goto voltage_setup_fail;
> >>> +     if(!di->pdata->no_backup_battery)
> >>> +     {
> >>> +             ret = twl4030backupbatt_voltage_setup();
> >>> +             if (ret)
> >>> +                     goto voltage_setup_fail;
> >>> +     }
> >>>
> >>>       /* REVISIT do we need to request both IRQs ?? */
> >>>
> >>> @@ -988,9 +1136,18 @@
> >>>                               twl4030_bci_battery_work);
> >>>       schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
> >>>
> >>> -     ret = power_supply_register(&pdev->dev, &di->bk_bat);
> >>> +     if(!pdata->no_backup_battery)
> >>> +     {
> >>> +             ret = power_supply_register(&pdev->dev, &di->bk_bat);
> >>> +             if (ret) {
> >>> +                     dev_dbg(&pdev->dev, "failed to register backup battery\n");
> >>> +                     goto bk_batt_failed;
> >>> +             }
> >>> +     }
> >>> +
> >>> +     ret = device_create_file(di->bat.dev, &dev_attr_charge_current);
> >>>       if (ret) {
> >>> -             dev_dbg(&pdev->dev, "failed to register backup battery\n");
> >>> +             dev_err(&pdev->dev, "failed to create sysfs entries\n");
> >>>               goto bk_batt_failed;
> >>>       }
> >>>
> >>> @@ -1001,7 +1158,8 @@
> >>>       return 0;
> >>>
> >>>  bk_batt_failed:
> >>> -     power_supply_unregister(&di->bat);
> >>> +     if(!pdata->no_backup_battery)
> >>> +             power_supply_unregister(&di->bat);
> >>>  batt_failed:
> >>>       free_irq(irq, di);
> >>>  chg_irq_fail:
> >>> @@ -1010,7 +1168,7 @@
> >>>  batt_irq_fail:
> >>>  voltage_setup_fail:
> >>>  temp_setup_fail:
> >>> -     twl4030charger_ac_en(DISABLE);
> >>> +     twl4030charger_ac_en(DISABLE, CHARGE_MODE);
> >>>       twl4030charger_usb_en(DISABLE);
> >>>       twl4030battery_hw_level_en(DISABLE);
> >>>       twl4030battery_hw_presence_en(DISABLE);
> >>> @@ -1024,7 +1182,7 @@
> >>>       struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
> >>>       int irq;
> >>>
> >>> -     twl4030charger_ac_en(DISABLE);
> >>> +     twl4030charger_ac_en(DISABLE, CHARGE_MODE);
> >>>       twl4030charger_usb_en(DISABLE);
> >>>       twl4030battery_hw_level_en(DISABLE);
> >>>       twl4030battery_hw_presence_en(DISABLE);
> >>> --- a/include/linux/i2c/twl4030.h
> >>> +++ b/include/linux/i2c/twl4030.h
> >>> @@ -299,6 +299,8 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg,
> >>> unsigned num_bytes);
> >>>  struct twl4030_bci_platform_data {
> >>>       int *battery_tmp_tbl;
> >>>       unsigned int tblsize;
> >>> +
> >>> +     bool no_backup_battery;
> >>>  };
> >>>
> >>>  /* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */
> >>>
> >>
> >>
> >

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: USB charging over TPS65950 BCI
  2009-09-14 22:53         ` Gregoire Gentil
@ 2009-09-14 23:21           ` Syed Mohammed, Khasim
  2009-09-15  5:04             ` Dighe, Gandhar
  0 siblings, 1 reply; 7+ messages in thread
From: Syed Mohammed, Khasim @ 2009-09-14 23:21 UTC (permalink / raw)
  To: gregoire, pramod gurav; +Cc: linux-omap, Tim Yamin, Dighe, Gandhar



> -----Original Message-----
> From: linux-omap-owner@vger.kernel.org [mailto:linux-omap-
> owner@vger.kernel.org] On Behalf Of Gregoire Gentil
> Sent: Tuesday, September 15, 2009 4:24 AM
> To: pramod gurav
> Cc: linux-omap@vger.kernel.org; Tim Yamin; Dighe, Gandhar
> Subject: Re: USB charging over TPS65950 BCI
>
> I don't know. I haven't seen yet a battery driver that works correctly
> with the TPS65950 and I have ping multiple times various people at TI.
Isn't this driver working for you? http://git.omapzoom.org/?p=repo/omapkernel.git;a=blob;f=drivers/power/twl4030_bci_battery.c;h=816db99e086f69d3efa46efd0ccbb60753a57b59;hb=android-2.6.27

I know OMAP Zoom has battery driver and it does support USB charging. It works on Open Pandora to an extent as well.

> Perhaps Gandhar will have an idea. I think that it would be valuable for
> the community that somebody at TI provides some patches to report
> correctly everything around the battery,
No idea why it wasn’t published.

Regards,
Khasim

> Grégoire
>
>
> On Fri, 2009-09-11 at 19:31 +0530, pramod gurav wrote:
> > hi gregoire,
> > i did not mention about charge current. the sysfs entry charge_current
> > always returns 360.
> >
> >
> > --
> > Best Regards
> > Pramod
> >
> >
> > On Fri, Sep 11, 2009 at 7:21 PM, pramod gurav <pramodforum@gmail.com>
> wrote:
> > > Hello gregoire,
> > >
> > > Really sorry I could not reply to your mail as I was busy with some other
> work.
> > > I applied your above patch tested. The sysfs entries return correct
> > > values for status, charger device(online), voltage_now. But the
> > > current across the battery is reported wrong. I compared the values
> > > returned by current_now sysfs entry with multimeter values across the
> > > battery. The values were varying whenever I remove AC and plug it
> > > back. But what I could see was the current_now value was approximately
> > > double the actual current across the battery.
> > > Without your patch the twl4030_bci gives wrong values for current_now,
> > > voltage_now, capacity etc.
> > > But your patch fixes this issue.
> > >
> > > But the USB charging did not work. Is USB charging functional with
> > > TWL4030 on any of the OMAP boards?
> > >
> > >
> > > Don't mind for the late reply. Thanks for your help.
> > >
> > > --
> > > Thanks and Best Regards
> > > Pramod
> > >
> > > On Wed, Aug 5, 2009 at 9:48 PM, Gregoire Gentil <gregoire@gentil.com>
> wrote:
> > >> Hello,
> > >>
> > >> Any feed-back on the patch I sent? Have you tried it? Have you fixed
> > >> your problem?
> > >>
> > >> Grégoire
> > >>
> > >>
> > >> On Fri, 2009-07-31 at 23:41 -0700, Gregoire Gentil wrote:
> > >>> On Fri, 2009-07-31 at 19:19 +0530, pramod gurav wrote:
> > >>> > Hi All,
> > >>> > I was trying to get the USB battery charging working over TPS65950
> BCI
> > >>> > on the OMAP3430 custom board. I am working with linux-omap-2.6
> > >>> > v2.6.28-omap1 tag. I enabled the TWL4030 MADC and TWL4030 BCI drivers.
> > >>> > I passed interrupt details to these drivers from platform_device
> > >>> > structure from my board file. I could get the AC charging working.
> The
> > >>> > AC and USB detection worked. However the USB charging is not
> > >>> > happening.
> > >>> > I read through the TPS TRM and took the dumps of the registers from
> > >>> > BCI and some from TWL USB module and BOOT_BCI whenever I plug in the
> > >>> > USB charger between host and the board. The register settings seem to
> > >>> > be fine. But the battery is not charging. I am using BQ27000 chip for
> > >>> > battery monitoring and I can see the battery voltage is decreasing.
> > >>> >
> > >>> > Following are the register dumps of TWL with and without USB plugged
> in:
> > >>> >
> > >>> > These are the register contents when USB charger is plugged in:
> > >>> > BCIMDEN         = 0x11
> > >>> > REG_BOOT_BCI    = 0x37
> > >>> > REG_POWER_CTRL  = 0x20
> > >>> > REG_BCIMFSTS4   = 0xf4
> > >>> > REG_BCIMFSTS1   = 0x13
> > >>> > REG_BCIIREF1    = 0x68
> > >>> > REG_BCIIREF2    = 0x3
> > >>> > REG_BCIMFEN4    = 0x6f
> > >>> > REG_BCIMFSTS2   = 0x0
> > >>> > REG_BCIMSTATEC  = 0x12
> > >>> > REG_STS_HW_CONDITIONS= 0x90
> > >>> >
> > >>> >
> > >>> > These are the register contents when USB charger is plugged out:
> > >>> > BCIMDEN         = 0x0
> > >>> > REG_BOOT_BCI    = 0x35
> > >>> > REG_POWER_CTRL  = 0x20
> > >>> > REG_BCIMFSTS4   = 0xf0
> > >>> > REG_BCIMFSTS1   = 0xaa
> > >>> > REG_BCIIREF1    = 0x68
> > >>> > REG_BCIIREF2    = 0x3
> > >>> > REG_BCIMFEN4    = 0x68
> > >>> > REG_BCIMFSTS2   = 0x0
> > >>> > REG_BCIMSTATEC  =0x0
> > >>> > REG_STS_HW_CONDITIONS= 0x10
> > >>> >
> > >>> > Is there anything more I need to support to get BCI USB charging
> > >>> > working? Need I follow any USB Communication protocol between Host
> and
> > >>> > the board.
> > >>> > I have pasted the kernel boot logs for reference at the end.
> > >>> > Can any one please guide me to some pointers?
> > >>> >
> > >>> > --
> > >>> > Best Regards
> > >>> > Pramod
> > >>> I'm experiencing some problems with TWL4030 DC charging and I'm
> > >>> interested by this kind of problem. Basically, the values reported by
> > >>> our patch is different from the current going to the battery. We wrote
> > >>> the attached enhanced patch so as to edit at run-time the charging mode
> > >>> and various values including charge_current. It's against 2.6.29 but I
> > >>> think that it should work again 2.6.28. Unfortunately, starting 2.6.30,
> > >>> Tony has removed all the BCI battery code and has asked for updated
> code
> > >>> against mainline but I've not seen anything so far.
> > >>>
> > >>> Pramod, can you try the attached patch (perhaps, it will help you) and
> > >>> can you tell if you see the exact current going to the battery reported
> > >>> by the driver?
> > >>>
> > >>> Grégoire
> > >>>
> > >>>
> > >>>
> > >>>
> > >>>
> > >>> --- a/drivers/power/twl4030_bci_battery.c     2009-07-22
> 18:27:16.000000000
> > >>> -0700
> > >>> +++ b/drivers/power/twl4030_bci_battery.c     2009-07-22
> 18:30:22.000000000
> > >>> -0700
> > >>> @@ -15,6 +15,9 @@
> > >>>   * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> > >>>   */
> > >>>
> > >>> +/* Boot with automatic charge */
> > >>> +#define CHARGE_MODE 1
> > >>> +
> > >>>  #include <linux/init.h>
> > >>>  #include <linux/module.h>
> > >>>  #include <linux/device.h>
> > >>> @@ -50,6 +53,7 @@
> > >>>  /* Boot BCI flag bits */
> > >>>  #define BCIAUTOWEN           0x020
> > >>>  #define CONFIG_DONE          0x010
> > >>> +#define CVENAC                       0x004
> > >>>  #define BCIAUTOUSB           0x002
> > >>>  #define BCIAUTOAC            0x001
> > >>>  #define BCIMSTAT_MASK                0x03F
> > >>> @@ -81,6 +85,11 @@
> > >>>  #define REG_BB_CFG           0x012
> > >>>  #define BBCHEN                       0x010
> > >>>
> > >>> +/* GPBR */
> > >>> +#define REG_GPBR1            0x0c
> > >>> +#define MADC_HFCLK_EN                0x80
> > >>> +#define DEFAULT_MADC_CLK_EN  0x10
> > >>> +
> > >>>  /* Power supply charge interrupt */
> > >>>  #define REG_PWR_ISR1         0x00
> > >>>  #define REG_PWR_IMR1         0x01
> > >>> @@ -125,6 +134,18 @@
> > >>>  /* BCIEDR3 */
> > >>>  #define      VBATLVL_EDRRISIN        0x02
> > >>>
> > >>> +/* BCIIREF1 */
> > >>> +#define REG_BCIIREF1         0x027
> > >>> +#define REG_BCIIREF2         0x028
> > >>> +
> > >>> +/* BCIMFTH1 */
> > >>> +#define REG_BCIMFTH1         0x016
> > >>> +
> > >>> +/* Key */
> > >>> +#define KEY_IIREF            0xE7
> > >>> +#define KEY_FTH1             0xD2
> > >>> +#define REG_BCIMFKEY         0x011
> > >>> +
> > >>>  /* Step size and prescaler ratio */
> > >>>  #define TEMP_STEP_SIZE               147
> > >>>  #define TEMP_PSR_R           100
> > >>> @@ -142,9 +163,6 @@
> > >>>  #define ENABLE               1
> > >>>  #define DISABLE              1
> > >>>
> > >>> -/* Ptr to thermistor table */
> > >>> -int *therm_tbl;
> > >>> -
> > >>>  struct twl4030_bci_device_info {
> > >>>       struct device           *dev;
> > >>>
> > >>> @@ -160,6 +178,8 @@
> > >>>       struct power_supply     bk_bat;
> > >>>       struct delayed_work     twl4030_bci_monitor_work;
> > >>>       struct delayed_work     twl4030_bk_bci_monitor_work;
> > >>> +
> > >>> +     struct twl4030_bci_platform_data *pdata;
> > >>>  };
> > >>>
> > >>>  static int usb_charger_flag;
> > >>> @@ -425,15 +445,21 @@
> > >>>  /*
> > >>>   * Enable/Disable AC Charge funtionality.
> > >>>   */
> > >>> -static int twl4030charger_ac_en(int enable)
> > >>> +static int twl4030charger_ac_en(int enable, int automatic)
> > >>>  {
> > >>>       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(!automatic) {
> > >>> +                     ret = clear_n_set(TWL4030_MODULE_PM_MASTER,
> BCIAUTOAC | CVENAC,
> > >>> +                             (CONFIG_DONE | BCIAUTOWEN),
> > >>> +                             REG_BOOT_BCI);
> > >>> +             } else {
> > >>> +                     ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
> > >>> +                             (CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC |
> CVENAC),
> > >>> +                             REG_BOOT_BCI);
> > >>> +             }
> > >>>               if (ret)
> > >>>                       return ret;
> > >>>       } else {
> > >>> @@ -518,11 +544,15 @@
> > >>>   * Return battery temperature
> > >>>   * Or < 0 on failure.
> > >>>   */
> > >>> -static int twl4030battery_temperature(void)
> > >>> +static int twl4030battery_temperature(struct twl4030_bci_device_info
> > >>> *di)
> > >>>  {
> > >>>       u8 val;
> > >>>       int temp, curr, volt, res, ret;
> > >>>
> > >>> +     /* Is a temperature table specified? */
> > >>> +     if (!di->pdata->tblsize)
> > >>> +             return 0;
> > >>> +
> > >>>       /* Getting and calculating the thermistor voltage */
> > >>>       ret = read_bci_val(T2_BATTERY_TEMP);
> > >>>       if (ret < 0)
> > >>> @@ -543,7 +573,7 @@
> > >>>
> > >>>       /*calculating temperature*/
> > >>>       for (temp = 58; temp >= 0; temp--) {
> > >>> -             int actual = therm_tbl[temp];
> > >>> +             int actual = di->pdata->battery_tmp_tbl[temp];
> > >>>               if ((actual - res) >= 0)
> > >>>                       break;
> > >>>       }
> > >>> @@ -661,6 +691,9 @@
> > >>>               return ret;
> > >>>       }
> > >>>
> > >>> +#ifdef DEBUG
> > >>> +     printk("BCI DEBUG: BCIMSTATEC Charge state is 0x%x\n", status);
> > >>> +#endif
> > >>>       return (int) (status & BCIMSTAT_MASK);
> > >>>  }
> > >>>
> > >>> @@ -709,14 +742,43 @@
> > >>>   */
> > >>>  static int twl4030battery_temp_setup(void)
> > >>>  {
> > >>> -     int ret;
> > >>> +#ifdef DEBUG
> > >>> +     u8 i;
> > >>> +#endif
> > >>> +     u8 ret;
> > >>>
> > >>>       /* Enabling thermistor current */
> > >>> -     ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, ITHEN,
> > >>> +     ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, 0x1B,
> > >>>               REG_BCICTL1);
> > >>>       if (ret)
> > >>>               return ret;
> > >>>
> > >>> +#ifdef DEBUG
> > >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret,
> REG_BOOT_BCI);
> > >>> +     printk("BCI DEBUG: BOOT_BCI Value is 0x%x\n", ret);
> > >>> +
> > >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret,
> > >>> REG_STS_HW_CONDITIONS);
> > >>> +     printk("BCI DEBUG: STS_HW_CONDITIONS Value is 0x%x\n", ret);
> > >>> +
> > >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret,
> REG_BCICTL1);
> > >>> +     printk("BCI DEBUG: BCICTL1 Value is 0x%x\n", ret);
> > >>> +
> > >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret,
> REG_BCICTL2);
> > >>> +     printk("BCI DEBUG: BCICTL2 Value is 0x%x\n", ret);
> > >>> +
> > >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, 0x0);
> > >>> +     printk("BCI DEBUG: BCIMDEN Value is 0x%x\n", ret);
> > >>> +
> > >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &ret, REG_GPBR1);
> > >>> +     printk("BCI DEBUG: GPBR1 Value is 0x%x\n", ret);
> > >>> +
> > >>> +     for(i = 0x0; i <= 0x32; i++)
> > >>> +     {
> > >>> +             twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, i);
> > >>> +             printk("BCI DEBUG: BCI 0x%x Value is 0x%x\n", i, ret);
> > >>> +     }
> > >>> +#endif
> > >>> +
> > >>>       return 0;
> > >>>  }
> > >>>
> > >>> @@ -732,7 +794,6 @@
> > >>>       ret = twl4030_i2c_read_u8(mod_no, &val, reg);
> > >>>       if (ret)
> > >>>               return ret;
> > >>> -
> > >>>       /* Clearing all those bits to clear */
> > >>>       val &= ~(clear);
> > >>>
> > >>> @@ -772,13 +833,14 @@
> > >>>               struct twl4030_bci_device_info,
> > >>>               twl4030_bk_bci_monitor_work.work);
> > >>>
> > >>> -     twl4030_bk_bci_battery_read_status(di);
> > >>> +     if(!di->pdata->no_backup_battery)
> > >>> +             twl4030_bk_bci_battery_read_status(di);
> > >>>       schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
> > >>>  }
> > >>>
> > >>>  static void twl4030_bci_battery_read_status(struct
> > >>> twl4030_bci_device_info *di)
> > >>>  {
> > >>> -     di->temp_C = twl4030battery_temperature();
> > >>> +     di->temp_C = twl4030battery_temperature(di);
> > >>>       di->voltage_uV = twl4030battery_voltage();
> > >>>       di->current_uA = twl4030battery_current();
> > >>>  }
> > >>> @@ -819,6 +881,87 @@
> > >>>  #define to_twl4030_bk_bci_device_info(x) container_of((x), \
> > >>>               struct twl4030_bci_device_info, bk_bat);
> > >>>
> > >>> +static ssize_t
> > >>> +show_charge_current(struct device *dev, struct device_attribute *attr,
> > >>> char *buf)
> > >>> +{
> > >>> +     u8  ctl;
> > >>> +     int ret = read_bci_val(REG_BCIIREF1) & 0x1FF;
> > >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ctl,
> REG_BCICTL1);
> > >>> +
> > >>> +     if (ctl & CGAIN)
> > >>> +             ret |= 0x200;
> > >>> +
> > >>> +#ifdef DEBUG
> > >>> +     /* Dump debug */
> > >>> +     twl4030battery_temp_setup();
> > >>> +#endif
> > >>> +
> > >>> +     return sprintf(buf, "%d\n", ret);
> > >>> +}
> > >>> +
> > >>> +static ssize_t
> > >>> +set_charge_current(struct device *dev, struct device_attribute *attr,
> > >>> const char *buf, size_t count)
> > >>> +{
> > >>> +     unsigned long newCurrent;
> > >>> +     int ret;
> > >>> +
> > >>> +     ret = strict_strtoul(buf, 10, &newCurrent);
> > >>> +     if (ret)
> > >>> +             return -EINVAL;
> > >>> +
> > >>> +     ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF,
> > >>> REG_BCIMFKEY);
> > >>> +     if (ret)
> > >>> +             return ret;
> > >>> +
> > >>> +     ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, newCurrent
> &
> > >>> 0xff, REG_BCIIREF1);
> > >>> +     if (ret)
> > >>> +             return ret;
> > >>> +
> > >>> +     ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF,
> > >>> REG_BCIMFKEY);
> > >>> +     if (ret)
> > >>> +             return ret;
> > >>> +
> > >>> +     ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
> (newCurrent >>
> > >>> 8) & 0x1, REG_BCIIREF2);
> > >>> +     if (ret)
> > >>> +             return ret;
> > >>> +
> > >>> +     /* Set software-controlled charge */
> > >>> +     twl4030charger_ac_en(ENABLE, 0);
> > >>> +
> > >>> +     /* Set CGAIN = 0 or 1 */
> > >>> +     if(newCurrent > 511) {
> > >>> +             u8 tmp;
> > >>> +
> > >>> +             /* Set CGAIN = 1 -- need to wait until automatic charge
> turns off */
> > >>> +             while(!ret) {
> > >>> +                     clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, CGAIN
> | 0x1B,
> > >>> REG_BCICTL1);
> > >>> +                     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
> &tmp, REG_BCICTL1);
> > >>> +
> > >>> +                     ret = tmp & CGAIN;
> > >>> +                     if(!ret)
> > >>> +                             mdelay(50);
> > >>> +             }
> > >>> +     } else {
> > >>> +             u8 tmp;
> > >>> +
> > >>> +             /* Set CGAIN = 0 -- need to wait until automatic charge
> turns off */
> > >>> +             while(!ret) {
> > >>> +                     clear_n_set(TWL4030_MODULE_MAIN_CHARGE, CGAIN,
> 0x1B, REG_BCICTL1);
> > >>> +                     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
> &tmp, REG_BCICTL1);
> > >>> +
> > >>> +                     ret = !(tmp & CGAIN);
> > >>> +                     if(!ret)
> > >>> +                             mdelay(50);
> > >>> +             }
> > >>> +     }
> > >>> +
> > >>> +     /* Set automatic charge (CGAIN = 0/1 persists) */
> > >>> +     twl4030charger_ac_en(ENABLE, 1);
> > >>> +
> > >>> +     return count;
> > >>> +}
> > >>> +static DEVICE_ATTR(charge_current, S_IRUGO | S_IWUSR,
> > >>> show_charge_current, set_charge_current);
> > >>> +
> > >>>  static int twl4030_bk_bci_battery_get_property(struct power_supply
> > >>> *psy,
> > >>>                                       enum power_supply_property psp,
> > >>>                                       union power_supply_propval *val)
> > >>> @@ -912,8 +1055,6 @@
> > >>>       int irq;
> > >>>       int ret;
> > >>>
> > >>> -     therm_tbl = pdata->battery_tmp_tbl;
> > >>> -
> > >>>       di = kzalloc(sizeof(*di), GFP_KERNEL);
> > >>>       if (!di)
> > >>>               return -ENOMEM;
> > >>> @@ -937,8 +1078,12 @@
> > >>>       di->bk_bat.num_properties =
> ARRAY_SIZE(twl4030_bk_bci_battery_props);
> > >>>       di->bk_bat.get_property = twl4030_bk_bci_battery_get_property;
> > >>>       di->bk_bat.external_power_changed = NULL;
> > >>> +     di->pdata = pdata;
> > >>>
> > >>> -     twl4030charger_ac_en(ENABLE);
> > >>> +     /* Set up clocks */
> > >>> +     twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, MADC_HFCLK_EN |
> > >>> DEFAULT_MADC_CLK_EN, REG_GPBR1);
> > >>> +
> > >>> +     twl4030charger_ac_en(ENABLE, CHARGE_MODE);
> > >>>       twl4030charger_usb_en(ENABLE);
> > >>>       twl4030battery_hw_level_en(ENABLE);
> > >>>       twl4030battery_hw_presence_en(ENABLE);
> > >>> @@ -951,9 +1096,12 @@
> > >>>               goto temp_setup_fail;
> > >>>
> > >>>       /* enabling GPCH09 for read back battery voltage */
> > >>> -     ret = twl4030backupbatt_voltage_setup();
> > >>> -     if (ret)
> > >>> -             goto voltage_setup_fail;
> > >>> +     if(!di->pdata->no_backup_battery)
> > >>> +     {
> > >>> +             ret = twl4030backupbatt_voltage_setup();
> > >>> +             if (ret)
> > >>> +                     goto voltage_setup_fail;
> > >>> +     }
> > >>>
> > >>>       /* REVISIT do we need to request both IRQs ?? */
> > >>>
> > >>> @@ -988,9 +1136,18 @@
> > >>>                               twl4030_bci_battery_work);
> > >>>       schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
> > >>>
> > >>> -     ret = power_supply_register(&pdev->dev, &di->bk_bat);
> > >>> +     if(!pdata->no_backup_battery)
> > >>> +     {
> > >>> +             ret = power_supply_register(&pdev->dev, &di->bk_bat);
> > >>> +             if (ret) {
> > >>> +                     dev_dbg(&pdev->dev, "failed to register backup
> battery\n");
> > >>> +                     goto bk_batt_failed;
> > >>> +             }
> > >>> +     }
> > >>> +
> > >>> +     ret = device_create_file(di->bat.dev, &dev_attr_charge_current);
> > >>>       if (ret) {
> > >>> -             dev_dbg(&pdev->dev, "failed to register backup
> battery\n");
> > >>> +             dev_err(&pdev->dev, "failed to create sysfs entries\n");
> > >>>               goto bk_batt_failed;
> > >>>       }
> > >>>
> > >>> @@ -1001,7 +1158,8 @@
> > >>>       return 0;
> > >>>
> > >>>  bk_batt_failed:
> > >>> -     power_supply_unregister(&di->bat);
> > >>> +     if(!pdata->no_backup_battery)
> > >>> +             power_supply_unregister(&di->bat);
> > >>>  batt_failed:
> > >>>       free_irq(irq, di);
> > >>>  chg_irq_fail:
> > >>> @@ -1010,7 +1168,7 @@
> > >>>  batt_irq_fail:
> > >>>  voltage_setup_fail:
> > >>>  temp_setup_fail:
> > >>> -     twl4030charger_ac_en(DISABLE);
> > >>> +     twl4030charger_ac_en(DISABLE, CHARGE_MODE);
> > >>>       twl4030charger_usb_en(DISABLE);
> > >>>       twl4030battery_hw_level_en(DISABLE);
> > >>>       twl4030battery_hw_presence_en(DISABLE);
> > >>> @@ -1024,7 +1182,7 @@
> > >>>       struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
> > >>>       int irq;
> > >>>
> > >>> -     twl4030charger_ac_en(DISABLE);
> > >>> +     twl4030charger_ac_en(DISABLE, CHARGE_MODE);
> > >>>       twl4030charger_usb_en(DISABLE);
> > >>>       twl4030battery_hw_level_en(DISABLE);
> > >>>       twl4030battery_hw_presence_en(DISABLE);
> > >>> --- a/include/linux/i2c/twl4030.h
> > >>> +++ b/include/linux/i2c/twl4030.h
> > >>> @@ -299,6 +299,8 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg,
> > >>> unsigned num_bytes);
> > >>>  struct twl4030_bci_platform_data {
> > >>>       int *battery_tmp_tbl;
> > >>>       unsigned int tblsize;
> > >>> +
> > >>> +     bool no_backup_battery;
> > >>>  };
> > >>>
> > >>>  /* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */
> > >>>
> > >>
> > >>
> > >
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: USB charging over TPS65950 BCI
  2009-09-14 23:21           ` Syed Mohammed, Khasim
@ 2009-09-15  5:04             ` Dighe, Gandhar
  0 siblings, 0 replies; 7+ messages in thread
From: Dighe, Gandhar @ 2009-09-15  5:04 UTC (permalink / raw)
  To: Syed Mohammed, Khasim, gregoire, pramod gurav; +Cc: linux-omap, Tim Yamin

Hi Khasim,

Actually it works very well on Pandora. For some reasons he had problems with CV mode. When he switched his schematics to non-limited charger as in part (D) in the data manual he was able to use charger properly.


Regards,

Gandhar Dighe,
Texas Instruments Inc.
phone: (214)567-4146
TPS659xx Forum - http://community.ti.com/forums/107.aspx

My carbon footprint is 11 tons/yr and is reducing. What's your? Check here and join the rally!!
-----Original Message-----
From: Syed Mohammed, Khasim
Sent: Monday, September 14, 2009 6:21 PM
To: gregoire@gentil.com; pramod gurav
Cc: linux-omap@vger.kernel.org; Tim Yamin; Dighe, Gandhar
Subject: RE: USB charging over TPS65950 BCI



> -----Original Message-----
> From: linux-omap-owner@vger.kernel.org [mailto:linux-omap-
> owner@vger.kernel.org] On Behalf Of Gregoire Gentil
> Sent: Tuesday, September 15, 2009 4:24 AM
> To: pramod gurav
> Cc: linux-omap@vger.kernel.org; Tim Yamin; Dighe, Gandhar
> Subject: Re: USB charging over TPS65950 BCI
>
> I don't know. I haven't seen yet a battery driver that works correctly
> with the TPS65950 and I have ping multiple times various people at TI.
Isn't this driver working for you? http://git.omapzoom.org/?p=repo/omapkernel.git;a=blob;f=drivers/power/twl4030_bci_battery.c;h=816db99e086f69d3efa46efd0ccbb60753a57b59;hb=android-2.6.27

I know OMAP Zoom has battery driver and it does support USB charging. It works on Open Pandora to an extent as well.

> Perhaps Gandhar will have an idea. I think that it would be valuable for
> the community that somebody at TI provides some patches to report
> correctly everything around the battery,
No idea why it wasn't published.

Regards,
Khasim

> Grégoire
>
>
> On Fri, 2009-09-11 at 19:31 +0530, pramod gurav wrote:
> > hi gregoire,
> > i did not mention about charge current. the sysfs entry charge_current
> > always returns 360.
> >
> >
> > --
> > Best Regards
> > Pramod
> >
> >
> > On Fri, Sep 11, 2009 at 7:21 PM, pramod gurav <pramodforum@gmail.com>
> wrote:
> > > Hello gregoire,
> > >
> > > Really sorry I could not reply to your mail as I was busy with some other
> work.
> > > I applied your above patch tested. The sysfs entries return correct
> > > values for status, charger device(online), voltage_now. But the
> > > current across the battery is reported wrong. I compared the values
> > > returned by current_now sysfs entry with multimeter values across the
> > > battery. The values were varying whenever I remove AC and plug it
> > > back. But what I could see was the current_now value was approximately
> > > double the actual current across the battery.
> > > Without your patch the twl4030_bci gives wrong values for current_now,
> > > voltage_now, capacity etc.
> > > But your patch fixes this issue.
> > >
> > > But the USB charging did not work. Is USB charging functional with
> > > TWL4030 on any of the OMAP boards?
> > >
> > >
> > > Don't mind for the late reply. Thanks for your help.
> > >
> > > --
> > > Thanks and Best Regards
> > > Pramod
> > >
> > > On Wed, Aug 5, 2009 at 9:48 PM, Gregoire Gentil <gregoire@gentil.com>
> wrote:
> > >> Hello,
> > >>
> > >> Any feed-back on the patch I sent? Have you tried it? Have you fixed
> > >> your problem?
> > >>
> > >> Grégoire
> > >>
> > >>
> > >> On Fri, 2009-07-31 at 23:41 -0700, Gregoire Gentil wrote:
> > >>> On Fri, 2009-07-31 at 19:19 +0530, pramod gurav wrote:
> > >>> > Hi All,
> > >>> > I was trying to get the USB battery charging working over TPS65950
> BCI
> > >>> > on the OMAP3430 custom board. I am working with linux-omap-2.6
> > >>> > v2.6.28-omap1 tag. I enabled the TWL4030 MADC and TWL4030 BCI drivers.
> > >>> > I passed interrupt details to these drivers from platform_device
> > >>> > structure from my board file. I could get the AC charging working.
> The
> > >>> > AC and USB detection worked. However the USB charging is not
> > >>> > happening.
> > >>> > I read through the TPS TRM and took the dumps of the registers from
> > >>> > BCI and some from TWL USB module and BOOT_BCI whenever I plug in the
> > >>> > USB charger between host and the board. The register settings seem to
> > >>> > be fine. But the battery is not charging. I am using BQ27000 chip for
> > >>> > battery monitoring and I can see the battery voltage is decreasing.
> > >>> >
> > >>> > Following are the register dumps of TWL with and without USB plugged
> in:
> > >>> >
> > >>> > These are the register contents when USB charger is plugged in:
> > >>> > BCIMDEN         = 0x11
> > >>> > REG_BOOT_BCI    = 0x37
> > >>> > REG_POWER_CTRL  = 0x20
> > >>> > REG_BCIMFSTS4   = 0xf4
> > >>> > REG_BCIMFSTS1   = 0x13
> > >>> > REG_BCIIREF1    = 0x68
> > >>> > REG_BCIIREF2    = 0x3
> > >>> > REG_BCIMFEN4    = 0x6f
> > >>> > REG_BCIMFSTS2   = 0x0
> > >>> > REG_BCIMSTATEC  = 0x12
> > >>> > REG_STS_HW_CONDITIONS= 0x90
> > >>> >
> > >>> >
> > >>> > These are the register contents when USB charger is plugged out:
> > >>> > BCIMDEN         = 0x0
> > >>> > REG_BOOT_BCI    = 0x35
> > >>> > REG_POWER_CTRL  = 0x20
> > >>> > REG_BCIMFSTS4   = 0xf0
> > >>> > REG_BCIMFSTS1   = 0xaa
> > >>> > REG_BCIIREF1    = 0x68
> > >>> > REG_BCIIREF2    = 0x3
> > >>> > REG_BCIMFEN4    = 0x68
> > >>> > REG_BCIMFSTS2   = 0x0
> > >>> > REG_BCIMSTATEC  =0x0
> > >>> > REG_STS_HW_CONDITIONS= 0x10
> > >>> >
> > >>> > Is there anything more I need to support to get BCI USB charging
> > >>> > working? Need I follow any USB Communication protocol between Host
> and
> > >>> > the board.
> > >>> > I have pasted the kernel boot logs for reference at the end.
> > >>> > Can any one please guide me to some pointers?
> > >>> >
> > >>> > --
> > >>> > Best Regards
> > >>> > Pramod
> > >>> I'm experiencing some problems with TWL4030 DC charging and I'm
> > >>> interested by this kind of problem. Basically, the values reported by
> > >>> our patch is different from the current going to the battery. We wrote
> > >>> the attached enhanced patch so as to edit at run-time the charging mode
> > >>> and various values including charge_current. It's against 2.6.29 but I
> > >>> think that it should work again 2.6.28. Unfortunately, starting 2.6.30,
> > >>> Tony has removed all the BCI battery code and has asked for updated
> code
> > >>> against mainline but I've not seen anything so far.
> > >>>
> > >>> Pramod, can you try the attached patch (perhaps, it will help you) and
> > >>> can you tell if you see the exact current going to the battery reported
> > >>> by the driver?
> > >>>
> > >>> Grégoire
> > >>>
> > >>>
> > >>>
> > >>>
> > >>>
> > >>> --- a/drivers/power/twl4030_bci_battery.c     2009-07-22
> 18:27:16.000000000
> > >>> -0700
> > >>> +++ b/drivers/power/twl4030_bci_battery.c     2009-07-22
> 18:30:22.000000000
> > >>> -0700
> > >>> @@ -15,6 +15,9 @@
> > >>>   * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
> > >>>   */
> > >>>
> > >>> +/* Boot with automatic charge */
> > >>> +#define CHARGE_MODE 1
> > >>> +
> > >>>  #include <linux/init.h>
> > >>>  #include <linux/module.h>
> > >>>  #include <linux/device.h>
> > >>> @@ -50,6 +53,7 @@
> > >>>  /* Boot BCI flag bits */
> > >>>  #define BCIAUTOWEN           0x020
> > >>>  #define CONFIG_DONE          0x010
> > >>> +#define CVENAC                       0x004
> > >>>  #define BCIAUTOUSB           0x002
> > >>>  #define BCIAUTOAC            0x001
> > >>>  #define BCIMSTAT_MASK                0x03F
> > >>> @@ -81,6 +85,11 @@
> > >>>  #define REG_BB_CFG           0x012
> > >>>  #define BBCHEN                       0x010
> > >>>
> > >>> +/* GPBR */
> > >>> +#define REG_GPBR1            0x0c
> > >>> +#define MADC_HFCLK_EN                0x80
> > >>> +#define DEFAULT_MADC_CLK_EN  0x10
> > >>> +
> > >>>  /* Power supply charge interrupt */
> > >>>  #define REG_PWR_ISR1         0x00
> > >>>  #define REG_PWR_IMR1         0x01
> > >>> @@ -125,6 +134,18 @@
> > >>>  /* BCIEDR3 */
> > >>>  #define      VBATLVL_EDRRISIN        0x02
> > >>>
> > >>> +/* BCIIREF1 */
> > >>> +#define REG_BCIIREF1         0x027
> > >>> +#define REG_BCIIREF2         0x028
> > >>> +
> > >>> +/* BCIMFTH1 */
> > >>> +#define REG_BCIMFTH1         0x016
> > >>> +
> > >>> +/* Key */
> > >>> +#define KEY_IIREF            0xE7
> > >>> +#define KEY_FTH1             0xD2
> > >>> +#define REG_BCIMFKEY         0x011
> > >>> +
> > >>>  /* Step size and prescaler ratio */
> > >>>  #define TEMP_STEP_SIZE               147
> > >>>  #define TEMP_PSR_R           100
> > >>> @@ -142,9 +163,6 @@
> > >>>  #define ENABLE               1
> > >>>  #define DISABLE              1
> > >>>
> > >>> -/* Ptr to thermistor table */
> > >>> -int *therm_tbl;
> > >>> -
> > >>>  struct twl4030_bci_device_info {
> > >>>       struct device           *dev;
> > >>>
> > >>> @@ -160,6 +178,8 @@
> > >>>       struct power_supply     bk_bat;
> > >>>       struct delayed_work     twl4030_bci_monitor_work;
> > >>>       struct delayed_work     twl4030_bk_bci_monitor_work;
> > >>> +
> > >>> +     struct twl4030_bci_platform_data *pdata;
> > >>>  };
> > >>>
> > >>>  static int usb_charger_flag;
> > >>> @@ -425,15 +445,21 @@
> > >>>  /*
> > >>>   * Enable/Disable AC Charge funtionality.
> > >>>   */
> > >>> -static int twl4030charger_ac_en(int enable)
> > >>> +static int twl4030charger_ac_en(int enable, int automatic)
> > >>>  {
> > >>>       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(!automatic) {
> > >>> +                     ret = clear_n_set(TWL4030_MODULE_PM_MASTER,
> BCIAUTOAC | CVENAC,
> > >>> +                             (CONFIG_DONE | BCIAUTOWEN),
> > >>> +                             REG_BOOT_BCI);
> > >>> +             } else {
> > >>> +                     ret = clear_n_set(TWL4030_MODULE_PM_MASTER, 0,
> > >>> +                             (CONFIG_DONE | BCIAUTOWEN | BCIAUTOAC |
> CVENAC),
> > >>> +                             REG_BOOT_BCI);
> > >>> +             }
> > >>>               if (ret)
> > >>>                       return ret;
> > >>>       } else {
> > >>> @@ -518,11 +544,15 @@
> > >>>   * Return battery temperature
> > >>>   * Or < 0 on failure.
> > >>>   */
> > >>> -static int twl4030battery_temperature(void)
> > >>> +static int twl4030battery_temperature(struct twl4030_bci_device_info
> > >>> *di)
> > >>>  {
> > >>>       u8 val;
> > >>>       int temp, curr, volt, res, ret;
> > >>>
> > >>> +     /* Is a temperature table specified? */
> > >>> +     if (!di->pdata->tblsize)
> > >>> +             return 0;
> > >>> +
> > >>>       /* Getting and calculating the thermistor voltage */
> > >>>       ret = read_bci_val(T2_BATTERY_TEMP);
> > >>>       if (ret < 0)
> > >>> @@ -543,7 +573,7 @@
> > >>>
> > >>>       /*calculating temperature*/
> > >>>       for (temp = 58; temp >= 0; temp--) {
> > >>> -             int actual = therm_tbl[temp];
> > >>> +             int actual = di->pdata->battery_tmp_tbl[temp];
> > >>>               if ((actual - res) >= 0)
> > >>>                       break;
> > >>>       }
> > >>> @@ -661,6 +691,9 @@
> > >>>               return ret;
> > >>>       }
> > >>>
> > >>> +#ifdef DEBUG
> > >>> +     printk("BCI DEBUG: BCIMSTATEC Charge state is 0x%x\n", status);
> > >>> +#endif
> > >>>       return (int) (status & BCIMSTAT_MASK);
> > >>>  }
> > >>>
> > >>> @@ -709,14 +742,43 @@
> > >>>   */
> > >>>  static int twl4030battery_temp_setup(void)
> > >>>  {
> > >>> -     int ret;
> > >>> +#ifdef DEBUG
> > >>> +     u8 i;
> > >>> +#endif
> > >>> +     u8 ret;
> > >>>
> > >>>       /* Enabling thermistor current */
> > >>> -     ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, ITHEN,
> > >>> +     ret = clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, 0x1B,
> > >>>               REG_BCICTL1);
> > >>>       if (ret)
> > >>>               return ret;
> > >>>
> > >>> +#ifdef DEBUG
> > >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret,
> REG_BOOT_BCI);
> > >>> +     printk("BCI DEBUG: BOOT_BCI Value is 0x%x\n", ret);
> > >>> +
> > >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &ret,
> > >>> REG_STS_HW_CONDITIONS);
> > >>> +     printk("BCI DEBUG: STS_HW_CONDITIONS Value is 0x%x\n", ret);
> > >>> +
> > >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret,
> REG_BCICTL1);
> > >>> +     printk("BCI DEBUG: BCICTL1 Value is 0x%x\n", ret);
> > >>> +
> > >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret,
> REG_BCICTL2);
> > >>> +     printk("BCI DEBUG: BCICTL2 Value is 0x%x\n", ret);
> > >>> +
> > >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, 0x0);
> > >>> +     printk("BCI DEBUG: BCIMDEN Value is 0x%x\n", ret);
> > >>> +
> > >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &ret, REG_GPBR1);
> > >>> +     printk("BCI DEBUG: GPBR1 Value is 0x%x\n", ret);
> > >>> +
> > >>> +     for(i = 0x0; i <= 0x32; i++)
> > >>> +     {
> > >>> +             twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ret, i);
> > >>> +             printk("BCI DEBUG: BCI 0x%x Value is 0x%x\n", i, ret);
> > >>> +     }
> > >>> +#endif
> > >>> +
> > >>>       return 0;
> > >>>  }
> > >>>
> > >>> @@ -732,7 +794,6 @@
> > >>>       ret = twl4030_i2c_read_u8(mod_no, &val, reg);
> > >>>       if (ret)
> > >>>               return ret;
> > >>> -
> > >>>       /* Clearing all those bits to clear */
> > >>>       val &= ~(clear);
> > >>>
> > >>> @@ -772,13 +833,14 @@
> > >>>               struct twl4030_bci_device_info,
> > >>>               twl4030_bk_bci_monitor_work.work);
> > >>>
> > >>> -     twl4030_bk_bci_battery_read_status(di);
> > >>> +     if(!di->pdata->no_backup_battery)
> > >>> +             twl4030_bk_bci_battery_read_status(di);
> > >>>       schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);
> > >>>  }
> > >>>
> > >>>  static void twl4030_bci_battery_read_status(struct
> > >>> twl4030_bci_device_info *di)
> > >>>  {
> > >>> -     di->temp_C = twl4030battery_temperature();
> > >>> +     di->temp_C = twl4030battery_temperature(di);
> > >>>       di->voltage_uV = twl4030battery_voltage();
> > >>>       di->current_uA = twl4030battery_current();
> > >>>  }
> > >>> @@ -819,6 +881,87 @@
> > >>>  #define to_twl4030_bk_bci_device_info(x) container_of((x), \
> > >>>               struct twl4030_bci_device_info, bk_bat);
> > >>>
> > >>> +static ssize_t
> > >>> +show_charge_current(struct device *dev, struct device_attribute *attr,
> > >>> char *buf)
> > >>> +{
> > >>> +     u8  ctl;
> > >>> +     int ret = read_bci_val(REG_BCIIREF1) & 0x1FF;
> > >>> +     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &ctl,
> REG_BCICTL1);
> > >>> +
> > >>> +     if (ctl & CGAIN)
> > >>> +             ret |= 0x200;
> > >>> +
> > >>> +#ifdef DEBUG
> > >>> +     /* Dump debug */
> > >>> +     twl4030battery_temp_setup();
> > >>> +#endif
> > >>> +
> > >>> +     return sprintf(buf, "%d\n", ret);
> > >>> +}
> > >>> +
> > >>> +static ssize_t
> > >>> +set_charge_current(struct device *dev, struct device_attribute *attr,
> > >>> const char *buf, size_t count)
> > >>> +{
> > >>> +     unsigned long newCurrent;
> > >>> +     int ret;
> > >>> +
> > >>> +     ret = strict_strtoul(buf, 10, &newCurrent);
> > >>> +     if (ret)
> > >>> +             return -EINVAL;
> > >>> +
> > >>> +     ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF,
> > >>> REG_BCIMFKEY);
> > >>> +     if (ret)
> > >>> +             return ret;
> > >>> +
> > >>> +     ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, newCurrent
> &
> > >>> 0xff, REG_BCIIREF1);
> > >>> +     if (ret)
> > >>> +             return ret;
> > >>> +
> > >>> +     ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE, KEY_IIREF,
> > >>> REG_BCIMFKEY);
> > >>> +     if (ret)
> > >>> +             return ret;
> > >>> +
> > >>> +     ret = twl4030_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
> (newCurrent >>
> > >>> 8) & 0x1, REG_BCIIREF2);
> > >>> +     if (ret)
> > >>> +             return ret;
> > >>> +
> > >>> +     /* Set software-controlled charge */
> > >>> +     twl4030charger_ac_en(ENABLE, 0);
> > >>> +
> > >>> +     /* Set CGAIN = 0 or 1 */
> > >>> +     if(newCurrent > 511) {
> > >>> +             u8 tmp;
> > >>> +
> > >>> +             /* Set CGAIN = 1 -- need to wait until automatic charge
> turns off */
> > >>> +             while(!ret) {
> > >>> +                     clear_n_set(TWL4030_MODULE_MAIN_CHARGE, 0, CGAIN
> | 0x1B,
> > >>> REG_BCICTL1);
> > >>> +                     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
> &tmp, REG_BCICTL1);
> > >>> +
> > >>> +                     ret = tmp & CGAIN;
> > >>> +                     if(!ret)
> > >>> +                             mdelay(50);
> > >>> +             }
> > >>> +     } else {
> > >>> +             u8 tmp;
> > >>> +
> > >>> +             /* Set CGAIN = 0 -- need to wait until automatic charge
> turns off */
> > >>> +             while(!ret) {
> > >>> +                     clear_n_set(TWL4030_MODULE_MAIN_CHARGE, CGAIN,
> 0x1B, REG_BCICTL1);
> > >>> +                     twl4030_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
> &tmp, REG_BCICTL1);
> > >>> +
> > >>> +                     ret = !(tmp & CGAIN);
> > >>> +                     if(!ret)
> > >>> +                             mdelay(50);
> > >>> +             }
> > >>> +     }
> > >>> +
> > >>> +     /* Set automatic charge (CGAIN = 0/1 persists) */
> > >>> +     twl4030charger_ac_en(ENABLE, 1);
> > >>> +
> > >>> +     return count;
> > >>> +}
> > >>> +static DEVICE_ATTR(charge_current, S_IRUGO | S_IWUSR,
> > >>> show_charge_current, set_charge_current);
> > >>> +
> > >>>  static int twl4030_bk_bci_battery_get_property(struct power_supply
> > >>> *psy,
> > >>>                                       enum power_supply_property psp,
> > >>>                                       union power_supply_propval *val)
> > >>> @@ -912,8 +1055,6 @@
> > >>>       int irq;
> > >>>       int ret;
> > >>>
> > >>> -     therm_tbl = pdata->battery_tmp_tbl;
> > >>> -
> > >>>       di = kzalloc(sizeof(*di), GFP_KERNEL);
> > >>>       if (!di)
> > >>>               return -ENOMEM;
> > >>> @@ -937,8 +1078,12 @@
> > >>>       di->bk_bat.num_properties =
> ARRAY_SIZE(twl4030_bk_bci_battery_props);
> > >>>       di->bk_bat.get_property = twl4030_bk_bci_battery_get_property;
> > >>>       di->bk_bat.external_power_changed = NULL;
> > >>> +     di->pdata = pdata;
> > >>>
> > >>> -     twl4030charger_ac_en(ENABLE);
> > >>> +     /* Set up clocks */
> > >>> +     twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, MADC_HFCLK_EN |
> > >>> DEFAULT_MADC_CLK_EN, REG_GPBR1);
> > >>> +
> > >>> +     twl4030charger_ac_en(ENABLE, CHARGE_MODE);
> > >>>       twl4030charger_usb_en(ENABLE);
> > >>>       twl4030battery_hw_level_en(ENABLE);
> > >>>       twl4030battery_hw_presence_en(ENABLE);
> > >>> @@ -951,9 +1096,12 @@
> > >>>               goto temp_setup_fail;
> > >>>
> > >>>       /* enabling GPCH09 for read back battery voltage */
> > >>> -     ret = twl4030backupbatt_voltage_setup();
> > >>> -     if (ret)
> > >>> -             goto voltage_setup_fail;
> > >>> +     if(!di->pdata->no_backup_battery)
> > >>> +     {
> > >>> +             ret = twl4030backupbatt_voltage_setup();
> > >>> +             if (ret)
> > >>> +                     goto voltage_setup_fail;
> > >>> +     }
> > >>>
> > >>>       /* REVISIT do we need to request both IRQs ?? */
> > >>>
> > >>> @@ -988,9 +1136,18 @@
> > >>>                               twl4030_bci_battery_work);
> > >>>       schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);
> > >>>
> > >>> -     ret = power_supply_register(&pdev->dev, &di->bk_bat);
> > >>> +     if(!pdata->no_backup_battery)
> > >>> +     {
> > >>> +             ret = power_supply_register(&pdev->dev, &di->bk_bat);
> > >>> +             if (ret) {
> > >>> +                     dev_dbg(&pdev->dev, "failed to register backup
> battery\n");
> > >>> +                     goto bk_batt_failed;
> > >>> +             }
> > >>> +     }
> > >>> +
> > >>> +     ret = device_create_file(di->bat.dev, &dev_attr_charge_current);
> > >>>       if (ret) {
> > >>> -             dev_dbg(&pdev->dev, "failed to register backup
> battery\n");
> > >>> +             dev_err(&pdev->dev, "failed to create sysfs entries\n");
> > >>>               goto bk_batt_failed;
> > >>>       }
> > >>>
> > >>> @@ -1001,7 +1158,8 @@
> > >>>       return 0;
> > >>>
> > >>>  bk_batt_failed:
> > >>> -     power_supply_unregister(&di->bat);
> > >>> +     if(!pdata->no_backup_battery)
> > >>> +             power_supply_unregister(&di->bat);
> > >>>  batt_failed:
> > >>>       free_irq(irq, di);
> > >>>  chg_irq_fail:
> > >>> @@ -1010,7 +1168,7 @@
> > >>>  batt_irq_fail:
> > >>>  voltage_setup_fail:
> > >>>  temp_setup_fail:
> > >>> -     twl4030charger_ac_en(DISABLE);
> > >>> +     twl4030charger_ac_en(DISABLE, CHARGE_MODE);
> > >>>       twl4030charger_usb_en(DISABLE);
> > >>>       twl4030battery_hw_level_en(DISABLE);
> > >>>       twl4030battery_hw_presence_en(DISABLE);
> > >>> @@ -1024,7 +1182,7 @@
> > >>>       struct twl4030_bci_device_info *di = platform_get_drvdata(pdev);
> > >>>       int irq;
> > >>>
> > >>> -     twl4030charger_ac_en(DISABLE);
> > >>> +     twl4030charger_ac_en(DISABLE, CHARGE_MODE);
> > >>>       twl4030charger_usb_en(DISABLE);
> > >>>       twl4030battery_hw_level_en(DISABLE);
> > >>>       twl4030battery_hw_presence_en(DISABLE);
> > >>> --- a/include/linux/i2c/twl4030.h
> > >>> +++ b/include/linux/i2c/twl4030.h
> > >>> @@ -299,6 +299,8 @@ int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg,
> > >>> unsigned num_bytes);
> > >>>  struct twl4030_bci_platform_data {
> > >>>       int *battery_tmp_tbl;
> > >>>       unsigned int tblsize;
> > >>> +
> > >>> +     bool no_backup_battery;
> > >>>  };
> > >>>
> > >>>  /* TWL4030_GPIO_MAX (18) GPIOs, with interrupts */
> > >>>
> > >>
> > >>
> > >
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2009-09-15  5:04 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-07-31 13:49 USB charging over TPS65950 BCI pramod gurav
2009-08-01  6:41 ` Gregoire Gentil
     [not found]   ` <1249489092.24549.9.camel@gregoire-laptop>
     [not found]     ` <f502236f0909110651v1c323f7co1fc515654f236eda@mail.gmail.com>
2009-09-11 14:01       ` pramod gurav
2009-09-14 22:53         ` Gregoire Gentil
2009-09-14 23:21           ` Syed Mohammed, Khasim
2009-09-15  5:04             ` Dighe, Gandhar
2009-08-02 15:44 ` Grazvydas Ignotas

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.