I got myself a PureGear Extreme USB Wall Charger few months ago. It’s Quick Charge 2.0 (QC2.0) enabled. But it didn’t live up to the claims made by Qualcomm to charge from 0% to 60% in 30 minutes. So I figured either the charger wasn’t doing what it promised to, or my phone was the culprit. Gotta find out which.
In a non-QC2.0 charger that conforms to USB Charging Specification, a certain resistance is connected across the USB data lines. When a phone is plugged in, the phone measures this resistance to find out how much current it’s allowed to draw from the charger. The voltage is always 5V. Lower the resistance means higher maximum current draw allowed. A resistance of 0Ω means draw as much as you want.
In QC2.0 chargers, there is an interface chip that takes commands from the phone over the USB data lines. The commands only tell the charger what voltage to supply. Choices are 5V, 9V, 12V and 20V. The protocol is simple. After the phone is plugged in, it asserts certain voltages on the USB data lines. The charger measures the voltage on the data pins and sets the output voltage accordingly. The details can be found in the datasheet of a QC2.0 charger IC (CHY100) that I found with a bit of googling. Note that a higher maximum current cannot damage a phone (a phone only draws what it needs), but a higher input voltage regardless of maximum current can damage the phone.
Now the fun part. I stripped a mid section of a USB cable and hooked up probes to each lead to measure voltages on all lines. Then I plugged my HTC One M8 with initial charge of 5%. I then ran adb connect 10.1.1.216:5555 followed by adb shell to open a terminal session to the phone. The IBAT(uA) line in /sys/devices/platform/htc_battery/power_supply/battery/batt_attr_text gives the current draw. At 5% charge, my phone was drawing 1400mA. Assuming the battery is charged at this rate all the way to 100% (not the case by the way), charging a 2600mAh battery to 60% will take longer than an hour. Not the 30 minutes I was promised.
So I measured the voltage on the USB data lines to see if the phone was indeed talking to the charger block over QC2.0 protocol. Turns out it did. It was asking it for 5V, by pulling the D+ pin to 0.7V and D- to GND. I kind of wish it didn’t talk QC2.0 so that it could be enabled somewhere. Now the odds are: either the phone isn’t asking for more voltage because it can’t handle it; or that the kernel is not configured to ask for more. I really hope it’s the latter.
I will update this post as I find more info about this.
2015-01-08: OK. I can confirm that the issue is the ROM I’m using (Cyanogenmod 11 Nightly). I just restored the stock recovery and plugged in the phone while in recovery and it now configures the charger for 9V output. Now I know where to dig.
2015-01-09: Upgraded to CM 12 Nightly. Issue still there. I noticed that sometimes the phone puts 3V on D+ but 0V on D-. I suspect CM uses outdated device tree.
2015-01-13: Got it. The problem was that CM didn’t have a daemon called hvdcp which configures the DCP circuitry of the phone and requests 9V input. After some time of hacking, I managed to fix it all up and submitted a patch to CM for review. The battery now charges at 2500mA compared to 1400mA before the change. That means, 60% of the battery will be charged in 37 minutes which is pretty close to Qualcomm’s promise of 30 minutes.