[Gta04-owner] [PATCH 14/15] twl4030_charger: Increase current carefully while watching voltage.
EdorFaus
edorfaus at xepher.net
Wed Feb 25 04:11:10 CET 2015
On 02/24/2015 05:33 AM, NeilBrown wrote:
> The USB Battery Charging spec (BC1.2) suggests a dedicated
> charging port can deliver from 0.5 to 5.0A at between 4.75 and 5.25
> volts.
>
> To choose the "correct" current voltage setting requires a trial
> and error approach: try to draw current and see if the voltage drops
> too low.
>
> Even with a configure Standard Downstream Port, it may not be possible
> to reliably pull 500mA - depending on cable quality and source
> quality I have reports of charging failure due to the voltage dropping
> too low.
>
> To address both these concern, this patch introduce incremental
> current setting.
> The current pull from VBUS is increased in steps of 20mA every 100ms
> until the target is reached or until the measure voltage drops below
> 4.75V. If the voltage does go too long, the target current is reduced
> by 20mA and kept there.
>
> This applies to currents selected automatically, or to values
> set via sysfs. So setting a large value will cause the maximum
> available to be used - up to the limit of 1.7mA imposed by the
> hardware.
As 1.7mA makes little sense here, I assume this should say 1.7A?
The relative values of USB_CUR_STEP and USB_MAX_CURRENT seem to agree.
>
> Signed-off-by: NeilBrown <neilb at suse.de>
> ---
> drivers/power/twl4030_charger.c | 54 ++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 53 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
> index e5a0225ea87e..7ad6b4b531d7 100644
> --- a/drivers/power/twl4030_charger.c
> +++ b/drivers/power/twl4030_charger.c
> @@ -117,6 +117,18 @@ struct twl4030_bci {
> #define CHARGE_AUTO 1
> #define CHARGE_LINEAR 2
>
> + /* When setting the USB current we slowly increase the
> + * requested current until target is reached or the voltage
> + * drops below 4.75V. In the latter case we set back one
> + * step.
> + */
> + int usb_cur_actual;
> + struct delayed_work current_worker;
> +#define USB_CUR_STEP 20000 /* 20mA at a time */
> +#define USB_MIN_VOLT 4750000 /* 4.75V */
> +#define USB_CUR_DELAY msecs_to_jiffies(100)
> +#define USB_MAX_CURRENT 1700000 /* TWL4030 caps at 1.7mA */
As above, this comment should probably say 1.7A, or 1700mA, not 1.7mA.
By the way, I agree with Boudewijn: even though I don't really know what
I'm doing when it comes to kernel code, it's still interesting, so
thanks for posting the patches here. :)
Best regards,
Frode Austvik
> +
> unsigned long event;
> };
>
> @@ -249,8 +261,14 @@ static int twl4030_charger_update_current(struct twl4030_bci *bci)
> cur = bci->ac_cur;
> bci->ac_is_active = 1;
> } else {
> - cur = bci->usb_cur;
> + cur = bci->usb_cur_actual;
> bci->ac_is_active = 0;
> + if (cur > bci->usb_cur) {
> + cur = bci->usb_cur;
> + bci->usb_cur_actual = cur;
> + }
> + if (cur < bci->usb_cur)
> + schedule_delayed_work(&bci->current_worker, USB_CUR_DELAY);
> }
>
> /* First, check thresholds and see if cgain is needed */
> @@ -379,6 +397,38 @@ static int twl4030_charger_update_current(struct twl4030_bci *bci)
> return 0;
> }
>
> +static void twl4030_current_worker(struct work_struct *data)
> +{
> + int v;
> + int res;
> + struct twl4030_bci *bci = container_of(data, struct twl4030_bci,
> + current_worker.work);
> +
> + res = twl4030bci_read_adc_val(TWL4030_BCIVBUS);
> + if (res < 0)
> + v = 0;
> + else
> + /* BCIVBUS uses ADCIN8, 7/1023 V/step */
> + v = res * 6843;
> +
> + printk("v=%d cur=%d target=%d\n", v, bci->usb_cur_actual,
> + bci->usb_cur);
> +
> + if (v < USB_MIN_VOLT) {
> + /* Back up and stop adjusting. */
> + bci->usb_cur_actual -= USB_CUR_STEP;
> + bci->usb_cur = bci->usb_cur_actual;
> + } else if (bci->usb_cur_actual >= bci->usb_cur ||
> + bci->usb_cur_actual + USB_CUR_STEP > USB_MAX_CURRENT) {
> + /* Reach target and volts are OK - stop */
> + return;
> + } else {
> + bci->usb_cur_actual += USB_CUR_STEP;
> + schedule_delayed_work(&bci->current_worker, USB_CUR_DELAY);
> + }
> + twl4030_charger_update_current(bci);
> +}
> +
> /*
> * Enable/Disable USB Charge functionality.
> */
> @@ -441,6 +491,7 @@ static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
> pm_runtime_put_autosuspend(bci->transceiver->dev);
> bci->usb_enabled = 0;
> }
> + bci->usb_cur_actual = 0;
> }
>
> return ret;
> @@ -972,6 +1023,7 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
> }
>
> INIT_WORK(&bci->work, twl4030_bci_usb_work);
> + INIT_DELAYED_WORK(&bci->current_worker, twl4030_current_worker);
>
> bci->usb_nb.notifier_call = twl4030_bci_usb_ncb;
> if (bci->dev->of_node) {
>
>
> _______________________________________________
> Gta04-owner mailing list
> Gta04-owner at goldelico.com
> http://lists.goldelico.com/mailman/listinfo.cgi/gta04-owner
>
More information about the Gta04-owner
mailing list