USB OTG power, take 2

bq27541, smb345, pm8921 (all in drivers/powr) and ektf3k (drivers/input/touchscreen) seem to know when power state changes. The latter relates to slimport hdmi and receiving power through it.

drivers/usb/otg/msm_otg is the other spot the work happens

The BQ27541 is a 'fuel-gauge' and the data sheet shows it is not involved in decisions about charging. There is a callback there for cable-state change tho, bq27541_battery_callback(). This in turn calls power_supply_changed(). Not part of the charging, but notifies the system (to e.g. change scheduler etc).

CONFIG_PM8921_CHARGER is not set in kernel config. And i suspect there is a reason.

One can see the registers of the smb345 in real time through the sysfs:

cd /sys/bus/i2c/drivers/smb345/0-006a; cat reg_status

and there is no register difference between power in or power out when OTG cable is inserted.

I note that CONFIG_USB_MSM_ACA is not set. Will try setting it.

if I look @ the ACA (accessory charger adapter) in /sys/kernel/debug/msm_otg/aca, it is 'disabled'. If i echo 'enabled' there, it doesn't have any affect.

I would think that something like this would work (it does not):

diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 54603bb..bf2d872 100755
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -38,7 +38,12 @@
 #include <linux/usb/msm_hsusb.h>
 #include <linux/usb/msm_hsusb_hw.h>
 #include <linux/regulator/consumer.h>
+#include <linux/smb345-charger.h>
 #include <linux/mfd/pm8xxx/pm8921-charger.h>
 #include <linux/mfd/pm8xxx/misc.h>
 #include <linux/power_supply.h>
 #include <linux/mhl_8334.h>
@@ -97,6 +102,7 @@ static int global_id_pin_suspend_status;
 #define APQ_AP_ACOK 23
 #define APQ_OTG_ID_PIN 77

 enum msm_otg_smb345_chg_type {
@@ -106,6 +112,7 @@ enum msm_otg_smb345_chg_type {

 extern int usb_cable_type_detect(unsigned int chgr_type);
 extern void smb345_otg_status(bool on);
@@ -135,10 +142,12 @@ static void asus_chg_set_chg_mode(enum usb_chg_type chg_src)
 int chg_type = chg_src;

+#if 0 /* DAB */
 if (old_chg_type == chg_type) {
 printk(KERN_INFO "The USB charging type is same : return\n");

 switch (chg_type) {
@@ -1154,11 +1163,12 @@ psy_not_supported:

 static int msm_otg_notify_chg_type(struct msm_otg *motg)
- int charger_type;
+ int charger_type, ret;
 * Unify OTG driver charger types and power supply charger types
+ printk("DAB: [usb_otg] chg_type %d\r\n", motg->chg_type);

 if (motg->chg_type == USB_SDP_CHARGER)
 charger_type = POWER_SUPPLY_TYPE_USB;
@@ -1175,7 +1185,15 @@ static int msm_otg_notify_chg_type(struct msm_otg *motg)

- return pm8921_set_usb_power_supply_type(charger_type);
+ printk("DAB: call smb345_charger_enable(%d)", motg->chg_type == USB_INVALID_CHARGER ? false : true);
+ ret = smb345_charger_enable(motg->chg_type == USB_INVALID_CHARGER ? false : true);
+ printk("DAB: smb345_charger_enable() returned %d", ret);
+ ret = pm8921_set_usb_power_supply_type(charger_type);
+ printk("DAB: pm8921_set_usb_power_supply_type(%d) returned %d\r\n", charger_type, ret);
+ return ret;

 static int msm_otg_notify_power_supply(struct msm_otg *motg, unsigned mA)
@@ -1231,7 +1249,11 @@ static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA)

 dev_info(motg->, "Avail curr from USB = %u\n", mA);

+ printk("DAB: not setting smb345 vbus_draw...");
 msm_otg_notify_power_supply(motg, mA);

 motg->cur_power = mA;

Would seem to be correct, but its not.

Leave a Reply

Your email address will not be published. Required fields are marked *