Port USB Fastcharge : originally ported by showp1984
https://github.com/showp1984/bricked-pyramid-3.0/commit/9074f71ce46a984ad790e1b6ffb2ff4221d7afd1
https://github.com/showp1984/bricked-pyramid-3.0/commit/515dedcf5fa3268942b282f0ecbb36533d4245da
USB forced fast charge v2
Use sysfs interface to change behaviour :
* /sys/kernel/fast_charge/force_fast_charge (rw)
*
* 0 - disabled (default)
* 1 - substitute AC to USB charging always
* 2 - substitute AC to USB charging only if no USB peripheral is detected
For informational purposes I've also added a read-only sysfs file that indicates the current USB state :
* /sys/kernel/fast_charge/USB_peripheral_detected (ro)
*
* The state will be returned in clear text (Yes/No).
For informational purposes I've also added a read-only sysfs file that indicates the detected USB port type :
* /sys/kernel/fast_charge/USB_porttype_detected (ro)
*
* The port type will be returned in clear text.
Change-Id: Iccd151e5bcd07af74859f5fe177312a12fb891c7
diff --git a/arch/arm/configs/pyramid_defconfig b/arch/arm/configs/pyramid_defconfig
index 46cf943..c1f1c31 100644
--- a/arch/arm/configs/pyramid_defconfig
+++ b/arch/arm/configs/pyramid_defconfig
@@ -409,6 +409,7 @@
CONFIG_HTC_HEADSET_GPIO=y
CONFIG_HTC_HEADSET_8X60=y
CONFIG_HTC_WAKE_ON_VOL=y
+CONFIG_FORCE_FAST_CHARGE=y
#
# HP Board Selection
diff --git a/arch/arm/mach-msm/htc/Kconfig b/arch/arm/mach-msm/htc/Kconfig
index 1030a1c..2115bc2 100644
--- a/arch/arm/mach-msm/htc/Kconfig
+++ b/arch/arm/mach-msm/htc/Kconfig
@@ -76,4 +76,12 @@
help
Provides support for HTC GPIO headset detection.
+config FORCE_FAST_CHARGE
+ bool "Force AC charge mode at will"
+ depends on ARCH_MSM8X60
+ default n
+ help
+ A simple sysfs interface to force adapters that
+ are detected as USB to charge as AC.
+
endmenu
diff --git a/arch/arm/mach-msm/htc/Makefile b/arch/arm/mach-msm/htc/Makefile
index dbd31e0..647a51c 100644
--- a/arch/arm/mach-msm/htc/Makefile
+++ b/arch/arm/mach-msm/htc/Makefile
@@ -23,6 +23,7 @@
obj-$(CONFIG_HTC_BATT_CORE) += htc_battery_core.o
obj-$(CONFIG_HTC_BATT_8x60) += htc_battery_8x60.o
obj-$(CONFIG_HTC_BATT_8960) += htc_battery_8960.o htc_battery_cell.o
+obj-$(CONFIG_FORCE_FAST_CHARGE) += fastchg.o
obj-$(CONFIG_MSM_NATIVE_RESTART) += htc_restart_handler.o
obj-$(CONFIG_HTC_HEADSET_MGR) += htc_headset_mgr.o
diff --git a/arch/arm/mach-msm/htc/fastchg.c b/arch/arm/mach-msm/htc/fastchg.c
new file mode 100644
index 0000000..9b8f1f9
--- /dev/null
+++ b/arch/arm/mach-msm/htc/fastchg.c
@@ -0,0 +1,180 @@
+/*
+ * Author: Chad Froebel <chadfroebel@gmail.com>
+ *
+ * Ported to Sensation and extended : Jean-Pierre Rasquin <yank555.lu@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*
+ * Possible values for "force_fast_charge" are :
+ *
+ * 0 - disabled (default)
+ * 1 - substitute AC to USB unconditional
+ * 2 - substitute AC to USB only if no USB peripheral is detected
+ *
+ * Possible values for "USB_peripheral_detected" are :
+ *
+ * 0 - No USB accessory currently attached (default)
+ * 1 - USB accessory currently attached
+ *
+ * Possible values for "USB_porttype_detected" are :
+ *
+ * 0 - invalid USB port
+ * 1 - standard downstream port
+ * 2 - dedicated charging port
+ * 3 - charging downstream port
+ * 4 - accessory charger adapter A
+ * 5 - accessory charger adapter B
+ * 6 - accessory charger adapter C
+ * 7 - accessory charger adapter dock
+ * 10 - nothing attached (default)
+ */
+
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include <linux/fastchg.h>
+
+int force_fast_charge;
+int USB_peripheral_detected;
+int USB_porttype_detected;
+
+/* sysfs interface for "force_fast_charge" */
+static ssize_t force_fast_charge_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+return sprintf(buf, "%d\n", force_fast_charge);
+}
+
+static ssize_t force_fast_charge_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
+{
+
+int new_force_fast_charge;
+
+sscanf(buf, "%du", &new_force_fast_charge);
+
+if (new_force_fast_charge >= FAST_CHARGE_DISABLED && new_force_fast_charge <= FAST_CHARGE_FORCE_AC_IF_NO_USB) {
+
+ /* update only if valid value provided */
+ force_fast_charge = new_force_fast_charge;
+
+}
+
+return count;
+}
+
+static struct kobj_attribute force_fast_charge_attribute =
+__ATTR(force_fast_charge, 0666, force_fast_charge_show, force_fast_charge_store);
+
+static struct attribute *force_fast_charge_attrs[] = {
+&force_fast_charge_attribute.attr,
+NULL,
+};
+
+static struct attribute_group force_fast_charge_attr_group = {
+.attrs = force_fast_charge_attrs,
+};
+
+/* sysfs interface for "USB_peripheral_detected" */
+static ssize_t USB_peripheral_detected_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ switch (USB_peripheral_detected) {
+ case USB_ACC_NOT_DETECTED: return sprintf(buf, "No\n");
+ case USB_ACC_DETECTED: return sprintf(buf, "Yes\n");
+ default: return sprintf(buf, "something went wrong\n");
+ }
+}
+
+static ssize_t USB_peripheral_detected_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
+{
+/* no user change allowed */
+return count;
+}
+
+static struct kobj_attribute USB_peripheral_detected_attribute =
+__ATTR(USB_peripheral_detected, 0444, USB_peripheral_detected_show, USB_peripheral_detected_store);
+
+static struct attribute *USB_peripheral_detected_attrs[] = {
+&USB_peripheral_detected_attribute.attr,
+NULL,
+};
+
+static struct attribute_group USB_peripheral_detected_attr_group = {
+.attrs = USB_peripheral_detected_attrs,
+};
+
+/* sysfs interface for "USB_porttype_detected" */
+static ssize_t USB_porttype_detected_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ switch (USB_porttype_detected) {
+ case USB_INVALID_DETECTED: return sprintf(buf, "Invalid Port\n");
+ case USB_SDP_DETECTED: return sprintf(buf, "Standard Downstream Port\n");
+ case USB_DCP_DETECTED: return sprintf(buf, "Dedicated Charging Port\n");
+ case USB_CDP_DETECTED: return sprintf(buf, "Charging Downstream Port\n");
+ case USB_ACA_A_DETECTED: return sprintf(buf, "Accessory Charger Adapter A\n");
+ case USB_ACA_B_DETECTED: return sprintf(buf, "Accessory Charger Adapter B\n");
+ case USB_ACA_C_DETECTED: return sprintf(buf, "Accessory Charger Adapter C\n");
+ case USB_ACA_DOCK_DETECTED: return sprintf(buf, "Accessory Charger Adapter Dock\n");
+ case NO_USB_DETECTED: return sprintf(buf, "No Port\n");
+ default: return sprintf(buf, "something went wrong\n");
+ }
+}
+
+static ssize_t USB_porttype_detected_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count)
+{
+/* no user change allowed */
+return count;
+}
+
+static struct kobj_attribute USB_porttype_detected_attribute =
+__ATTR(USB_porttype_detected, 0444, USB_porttype_detected_show, USB_porttype_detected_store);
+
+static struct attribute *USB_porttype_detected_attrs[] = {
+&USB_porttype_detected_attribute.attr,
+NULL,
+};
+
+static struct attribute_group USB_porttype_detected_attr_group = {
+.attrs = USB_porttype_detected_attrs,
+};
+
+/* Initialize fast charge sysfs folder */
+static struct kobject *force_fast_charge_kobj;
+
+int force_fast_charge_init(void)
+{
+ int force_fast_charge_retval;
+ int USB_peripheral_detected_retval;
+ int USB_porttype_detected_retval;
+
+ force_fast_charge = FAST_CHARGE_DISABLED; /* Forced fast charge disabled by default */
+ USB_peripheral_detected = USB_ACC_NOT_DETECTED; /* Consider no USB accessory detected so far */
+ USB_porttype_detected = NO_USB_DETECTED; /* Consider no USB port is yet detected */
+
+ force_fast_charge_kobj = kobject_create_and_add("fast_charge", kernel_kobj);
+ if (!force_fast_charge_kobj) {
+ return -ENOMEM;
+ }
+ force_fast_charge_retval = sysfs_create_group(force_fast_charge_kobj, &force_fast_charge_attr_group);
+ USB_peripheral_detected_retval = sysfs_create_group(force_fast_charge_kobj, &USB_peripheral_detected_attr_group);
+ USB_porttype_detected_retval = sysfs_create_group(force_fast_charge_kobj, &USB_porttype_detected_attr_group);
+ if (force_fast_charge_retval && USB_peripheral_detected_retval && USB_porttype_detected_retval)
+ kobject_put(force_fast_charge_kobj);
+ return (force_fast_charge_retval && USB_peripheral_detected_retval && USB_porttype_detected_retval);
+}
+/* end sysfs interface */
+
+void force_fast_charge_exit(void)
+{
+ kobject_put(force_fast_charge_kobj);
+}
+
+module_init(force_fast_charge_init);
+module_exit(force_fast_charge_exit);
diff --git a/arch/arm/mach-msm/htc/htc_battery_8x60.c b/arch/arm/mach-msm/htc/htc_battery_8x60.c
index 9cbd4db..a9e1303 100644
--- a/arch/arm/mach-msm/htc/htc_battery_8x60.c
+++ b/arch/arm/mach-msm/htc/htc_battery_8x60.c
@@ -39,6 +39,10 @@
#include <linux/earlysuspend.h>
#include <mach/rpm.h>
+#ifdef CONFIG_FORCE_FAST_CHARGE
+#include <linux/fastchg.h>
+#endif
+
#define BATT_SUSPEND_CHECK_TIME 3600
#define BATT_SUSPEND_HIGHFREQ_CHECK_TIME (300)
#define BATT_TIMER_CHECK_TIME 360
@@ -308,9 +312,24 @@
switch (online) {
case CONNECT_TYPE_USB:
+#ifdef CONFIG_FORCE_FAST_CHARGE
+ /* If forced fast charge is enabled "always" or if no USB device detected, go AC */
+ if ((force_fast_charge == FAST_CHARGE_FORCE_AC) ||
+ (force_fast_charge == FAST_CHARGE_FORCE_AC_IF_NO_USB &&
+ USB_peripheral_detected == USB_ACC_NOT_DETECTED )) {
+ BATT_LOG("cable USB forced to AC");
+ htc_batt_info.rep.charging_source = CHARGER_AC;
+ radio_set_cable_status(CHARGER_AC);
+ } else {
+ BATT_LOG("cable USB not forced to AC");
+ htc_batt_info.rep.charging_source = CHARGER_USB;
+ radio_set_cable_status(CHARGER_USB);
+ }
+#else
BATT_LOG("cable USB");
htc_batt_info.rep.charging_source = CHARGER_USB;
radio_set_cable_status(CHARGER_USB);
+#endif
break;
case CONNECT_TYPE_AC:
case CONNECT_TYPE_MHL_AC:
diff --git a/drivers/usb/otg/msm_otg_htc.c b/drivers/usb/otg/msm_otg_htc.c
index 6fc9595..8030220 100644
--- a/drivers/usb/otg/msm_otg_htc.c
+++ b/drivers/usb/otg/msm_otg_htc.c
@@ -50,6 +50,10 @@
#include <mach/board.h>
#include <mach/board_htc.h>
+#ifdef CONFIG_FORCE_FAST_CHARGE
+#include <linux/fastchg.h>
+#endif
+
#define MSM_USB_BASE (motg->regs)
#define DRIVER_NAME "msm_otg"
@@ -73,6 +77,15 @@
motg->connect_type_ready = 1;
USBH_INFO("send connect type %d\n", motg->connect_type);
+#ifdef CONFIG_FORCE_FAST_CHARGE
+ if (motg->connect_type == CONNECT_TYPE_USB) {
+ USB_peripheral_detected = USB_ACC_DETECTED; /* Inform forced fast charge that a USB accessory has been attached */
+ USBH_INFO("USB forced fast charge : USB device currently attached");
+ } else {
+ USB_peripheral_detected = USB_ACC_NOT_DETECTED; /* Inform forced fast charge that a USB accessory has not been attached */
+ USBH_INFO("USB forced fast charge : No USB device currently attached");
+ }
+#endif
mutex_lock(¬ify_sem);
list_for_each_entry(notifier, &g_lh_usb_notifier_list, notifier_link) {
if (notifier->func != NULL) {
@@ -653,6 +666,10 @@
u32 ulpi_val = 0;
USBH_INFO("%s\n", __func__);
+#ifdef CONFIG_FORCE_FAST_CHARGE
+ USB_porttype_detected = NO_USB_DETECTED; /* No USB plugged, clear fast charge detected port value */
+#endif
+
/*
* USB PHY and Link reset also reset the USB BAM.
* Thus perform reset operation only once to avoid
@@ -2225,6 +2242,27 @@
msm_chg_enable_aca_intr(motg);
USBH_INFO("chg_type = %s\n",
chg_to_string(motg->chg_type));
+
+#ifdef CONFIG_FORCE_FAST_CHARGE
+ switch (motg->chg_type) {
+ case USB_SDP_CHARGER: USB_porttype_detected = USB_SDP_DETECTED;
+ break;
+ case USB_DCP_CHARGER: USB_porttype_detected = USB_DCP_DETECTED;
+ break;
+ case USB_CDP_CHARGER: USB_porttype_detected = USB_CDP_DETECTED;
+ break;
+ case USB_ACA_A_CHARGER: USB_porttype_detected = USB_ACA_A_DETECTED;
+ break;
+ case USB_ACA_B_CHARGER: USB_porttype_detected = USB_ACA_B_DETECTED;
+ break;
+ case USB_ACA_C_CHARGER: USB_porttype_detected = USB_ACA_C_DETECTED;
+ break;
+ case USB_ACA_DOCK_CHARGER: USB_porttype_detected = USB_ACA_DOCK_DETECTED;
+ break;
+ default: USB_porttype_detected = USB_INVALID_DETECTED;
+ break;
+ }
+#endif
queue_work(system_nrt_wq, &motg->sm_work);
queue_work(motg->usb_wq, &motg->notifier_work);
return;
diff --git a/include/linux/fastchg.h b/include/linux/fastchg.h
new file mode 100644
index 0000000..f300c4a
--- /dev/null
+++ b/include/linux/fastchg.h
@@ -0,0 +1,42 @@
+/*
+ * Author: Chad Froebel <chadfroebel@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+
+#ifndef _LINUX_FASTCHG_H
+#define _LINUX_FASTCHG_H
+
+extern int force_fast_charge;
+
+#define FAST_CHARGE_DISABLED 0 /* default */
+#define FAST_CHARGE_FORCE_AC 1
+#define FAST_CHARGE_FORCE_AC_IF_NO_USB 2
+
+extern int USB_peripheral_detected;
+
+#define USB_ACC_NOT_DETECTED 0 /* default */
+#define USB_ACC_DETECTED 1
+
+#define USB_INVALID_DETECTED 0
+#define USB_SDP_DETECTED 1
+#define USB_DCP_DETECTED 2
+#define USB_CDP_DETECTED 3
+#define USB_ACA_A_DETECTED 4
+#define USB_ACA_B_DETECTED 5
+#define USB_ACA_C_DETECTED 6
+#define USB_ACA_DOCK_DETECTED 7
+#define NO_USB_DETECTED 10 /* default */
+
+extern int USB_porttype_detected;
+
+#endif