Hi Maxim,

Sorry for not responding, someone picked the right dependency
patch and submitted to stable so this should be fixed now.

Yours,
Linus Walleij

On Tue, Jul 27, 2021 at 11:05 AM Maxim Kuvyrkov
<maxim.kuvyr...@linaro.org> wrote:
>
> Hi Linus,
>
> Just in case you hadn’t this reported elsewhere ...
>
> --
> Maxim Kuvyrkov
> https://www.linaro.org
>
> > On 27 Jul 2021, at 03:40, ci_not...@linaro.org wrote:
> >
> > Successfully identified regression in *linux* in CI configuration 
> > tcwg_kernel/gnu-master-arm-stable-allyesconfig.  So far, this commit has 
> > regressed CI configurations:
> > - tcwg_kernel/gnu-master-arm-stable-allyesconfig
> >
> > Culprit:
> > <cut>
> > commit 341db343768bc44f3512facc464021730d64071c
> > Author: Linus Walleij <linus.wall...@linaro.org>
> > Date:   Sun May 23 00:50:39 2021 +0200
> >
> >    power: supply: ab8500: Move to componentized binding
> >
> >    [ Upstream commit 1c1f13a006ed0d71bb5664c8b7e3e77a28da3beb ]
> >
> >    The driver has problems with the different components of
> >    the charging code racing with each other to probe().
> >
> >    This results in all four subdrivers populating battery
> >    information to ascertain that it is populated for their
> >    own needs for example.
> >
> >    Fix this by using component probing and thus expressing
> >    to the kernel that these are dependent components.
> >    The probes can happen in any order and will only acquire
> >    resources such as state container, regulators and
> >    interrupts and initialize the data structures, but no
> >    execution happens until the .bind() callback is called.
> >
> >    The charging driver is the main component and binds
> >    first, then bind in order the three subcomponents:
> >    ab8500-fg, ab8500-btemp and ab8500-chargalg.
> >
> >    Do some housekeeping while we are moving the code around.
> >    Like use devm_* for IRQs so as to cut down on some
> >    boilerplate.
> >
> >    Signed-off-by: Linus Walleij <linus.wall...@linaro.org>
> >    Signed-off-by: Sebastian Reichel <sebastian.reic...@collabora.com>
> >    Signed-off-by: Sasha Levin <sas...@kernel.org>
> > </cut>
> >
> > Results regressed to (for first_bad == 
> > 341db343768bc44f3512facc464021730d64071c)
> > # reset_artifacts:
> > -10
> > # build_abe binutils:
> > -9
> > # build_abe stage1:
> > -5
> > # build_abe qemu:
> > -2
> > # linux_n_obj:
> > 19543
> > # First few build errors in logs:
> > # 00:19:50 drivers/power/supply/ab8500_fg.c:3061:39: error: ‘np’ undeclared 
> > (first use in this function); did you mean ‘up’?
> > # 00:19:50 make[3]: *** [scripts/Makefile.build:273: 
> > drivers/power/supply/ab8500_fg.o] Error 1
> > # 00:21:18 make[2]: *** [scripts/Makefile.build:516: drivers/power/supply] 
> > Error 2
> > # 00:21:18 make[1]: *** [scripts/Makefile.build:516: drivers/power] Error 2
> > # 00:30:44 make: *** [Makefile:1847: drivers] Error 2
> >
> > from (for last_good == dc72a15859b2e604abb8a4bff123fbac8a0be92a)
> > # reset_artifacts:
> > -10
> > # build_abe binutils:
> > -9
> > # build_abe stage1:
> > -5
> > # build_abe qemu:
> > -2
> > # linux_n_obj:
> > 19631
> > # linux build successful:
> > all
> >
> > Artifacts of last_good build: 
> > https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-arm-stable-allyesconfig/14/artifact/artifacts/build-dc72a15859b2e604abb8a4bff123fbac8a0be92a/
> > Artifacts of first_bad build: 
> > https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-arm-stable-allyesconfig/14/artifact/artifacts/build-341db343768bc44f3512facc464021730d64071c/
> > Build top page/logs: 
> > https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-arm-stable-allyesconfig/14/
> >
> > Configuration details:
> >
> >
> > Reproduce builds:
> > <cut>
> > mkdir investigate-linux-341db343768bc44f3512facc464021730d64071c
> > cd investigate-linux-341db343768bc44f3512facc464021730d64071c
> >
> > git clone https://git.linaro.org/toolchain/jenkins-scripts
> >
> > mkdir -p artifacts/manifests
> > curl -o artifacts/manifests/build-baseline.sh 
> > https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-arm-stable-allyesconfig/14/artifact/artifacts/manifests/build-baseline.sh
> >  --fail
> > curl -o artifacts/manifests/build-parameters.sh 
> > https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-arm-stable-allyesconfig/14/artifact/artifacts/manifests/build-parameters.sh
> >  --fail
> > curl -o artifacts/test.sh 
> > https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-arm-stable-allyesconfig/14/artifact/artifacts/test.sh
> >  --fail
> > chmod +x artifacts/test.sh
> >
> > # Reproduce the baseline build (build all pre-requisites)
> > ./jenkins-scripts/tcwg_kernel-build.sh @@ 
> > artifacts/manifests/build-baseline.sh
> >
> > # Save baseline build state (which is then restored in artifacts/test.sh)
> > mkdir -p ./bisect
> > rsync -a --del --delete-excluded --exclude /bisect/ --exclude /artifacts/ 
> > --exclude /linux/ ./ ./bisect/baseline/
> >
> > cd linux
> >
> > # Reproduce first_bad build
> > git checkout --detach 341db343768bc44f3512facc464021730d64071c
> > ../artifacts/test.sh
> >
> > # Reproduce last_good build
> > git checkout --detach dc72a15859b2e604abb8a4bff123fbac8a0be92a
> > ../artifacts/test.sh
> >
> > cd ..
> > </cut>
> >
> > History of pending regressions and results: 
> > https://git.linaro.org/toolchain/ci/base-artifacts.git/log/?h=linaro-local/ci/tcwg_kernel/gnu-master-arm-stable-allyesconfig
> >
> > Artifacts: 
> > https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-arm-stable-allyesconfig/14/artifact/artifacts/
> > Build log: 
> > https://ci.linaro.org/job/tcwg_kernel-gnu-bisect-gnu-master-arm-stable-allyesconfig/14/consoleText
> >
> > Full commit (up to 1000 lines):
> > <cut>
> > commit 341db343768bc44f3512facc464021730d64071c
> > Author: Linus Walleij <linus.wall...@linaro.org>
> > Date:   Sun May 23 00:50:39 2021 +0200
> >
> >    power: supply: ab8500: Move to componentized binding
> >
> >    [ Upstream commit 1c1f13a006ed0d71bb5664c8b7e3e77a28da3beb ]
> >
> >    The driver has problems with the different components of
> >    the charging code racing with each other to probe().
> >
> >    This results in all four subdrivers populating battery
> >    information to ascertain that it is populated for their
> >    own needs for example.
> >
> >    Fix this by using component probing and thus expressing
> >    to the kernel that these are dependent components.
> >    The probes can happen in any order and will only acquire
> >    resources such as state container, regulators and
> >    interrupts and initialize the data structures, but no
> >    execution happens until the .bind() callback is called.
> >
> >    The charging driver is the main component and binds
> >    first, then bind in order the three subcomponents:
> >    ab8500-fg, ab8500-btemp and ab8500-chargalg.
> >
> >    Do some housekeeping while we are moving the code around.
> >    Like use devm_* for IRQs so as to cut down on some
> >    boilerplate.
> >
> >    Signed-off-by: Linus Walleij <linus.wall...@linaro.org>
> >    Signed-off-by: Sebastian Reichel <sebastian.reic...@collabora.com>
> >    Signed-off-by: Sasha Levin <sas...@kernel.org>
> > ---
> > drivers/power/supply/ab8500-bm.h       |   4 +
> > drivers/power/supply/ab8500_btemp.c    | 118 +++++-------
> > drivers/power/supply/ab8500_charger.c  | 339 
> > +++++++++++++++++++--------------
> > drivers/power/supply/ab8500_fg.c       | 136 +++++++------
> > drivers/power/supply/abx500_chargalg.c | 116 ++++++-----
> > 5 files changed, 379 insertions(+), 334 deletions(-)
> >
> > diff --git a/drivers/power/supply/ab8500-bm.h 
> > b/drivers/power/supply/ab8500-bm.h
> > index 41c69a4f2a1f..012595a9d269 100644
> > --- a/drivers/power/supply/ab8500-bm.h
> > +++ b/drivers/power/supply/ab8500-bm.h
> > @@ -730,4 +730,8 @@ int ab8500_bm_of_probe(struct device *dev,
> >                      struct device_node *np,
> >                      struct abx500_bm_data *bm);
> >
> > +extern struct platform_driver ab8500_fg_driver;
> > +extern struct platform_driver ab8500_btemp_driver;
> > +extern struct platform_driver abx500_chargalg_driver;
> > +
> > #endif /* _AB8500_CHARGER_H_ */
> > diff --git a/drivers/power/supply/ab8500_btemp.c 
> > b/drivers/power/supply/ab8500_btemp.c
> > index fdfcd59fc43e..3598b5a748e7 100644
> > --- a/drivers/power/supply/ab8500_btemp.c
> > +++ b/drivers/power/supply/ab8500_btemp.c
> > @@ -13,6 +13,7 @@
> > #include <linux/init.h>
> > #include <linux/module.h>
> > #include <linux/device.h>
> > +#include <linux/component.h>
> > #include <linux/interrupt.h>
> > #include <linux/delay.h>
> > #include <linux/slab.h>
> > @@ -932,26 +933,6 @@ static int __maybe_unused ab8500_btemp_suspend(struct 
> > device *dev)
> >       return 0;
> > }
> >
> > -static int ab8500_btemp_remove(struct platform_device *pdev)
> > -{
> > -     struct ab8500_btemp *di = platform_get_drvdata(pdev);
> > -     int i, irq;
> > -
> > -     /* Disable interrupts */
> > -     for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) {
> > -             irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
> > -             free_irq(irq, di);
> > -     }
> > -
> > -     /* Delete the work queue */
> > -     destroy_workqueue(di->btemp_wq);
> > -
> > -     flush_scheduled_work();
> > -     power_supply_unregister(di->btemp_psy);
> > -
> > -     return 0;
> > -}
> > -
> > static char *supply_interface[] = {
> >       "ab8500_chargalg",
> >       "ab8500_fg",
> > @@ -966,6 +947,40 @@ static const struct power_supply_desc 
> > ab8500_btemp_desc = {
> >       .external_power_changed = ab8500_btemp_external_power_changed,
> > };
> >
> > +static int ab8500_btemp_bind(struct device *dev, struct device *master,
> > +                          void *data)
> > +{
> > +     struct ab8500_btemp *di = dev_get_drvdata(dev);
> > +
> > +     /* Create a work queue for the btemp */
> > +     di->btemp_wq =
> > +             alloc_workqueue("ab8500_btemp_wq", WQ_MEM_RECLAIM, 0);
> > +     if (di->btemp_wq == NULL) {
> > +             dev_err(dev, "failed to create work queue\n");
> > +             return -ENOMEM;
> > +     }
> > +
> > +     /* Kick off periodic temperature measurements */
> > +     ab8500_btemp_periodic(di, true);
> > +
> > +     return 0;
> > +}
> > +
> > +static void ab8500_btemp_unbind(struct device *dev, struct device *master,
> > +                             void *data)
> > +{
> > +     struct ab8500_btemp *di = dev_get_drvdata(dev);
> > +
> > +     /* Delete the work queue */
> > +     destroy_workqueue(di->btemp_wq);
> > +     flush_scheduled_work();
> > +}
> > +
> > +static const struct component_ops ab8500_btemp_component_ops = {
> > +     .bind = ab8500_btemp_bind,
> > +     .unbind = ab8500_btemp_unbind,
> > +};
> > +
> > static int ab8500_btemp_probe(struct platform_device *pdev)
> > {
> >       struct device_node *np = pdev->dev.of_node;
> > @@ -1011,14 +1026,6 @@ static int ab8500_btemp_probe(struct platform_device 
> > *pdev)
> >       psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
> >       psy_cfg.drv_data = di;
> >
> > -     /* Create a work queue for the btemp */
> > -     di->btemp_wq =
> > -             alloc_workqueue("ab8500_btemp_wq", WQ_MEM_RECLAIM, 0);
> > -     if (di->btemp_wq == NULL) {
> > -             dev_err(dev, "failed to create work queue\n");
> > -             return -ENOMEM;
> > -     }
> > -
> >       /* Init work for measuring temperature periodically */
> >       INIT_DEFERRABLE_WORK(&di->btemp_periodic_work,
> >               ab8500_btemp_periodic_work);
> > @@ -1031,7 +1038,7 @@ static int ab8500_btemp_probe(struct platform_device 
> > *pdev)
> >               AB8500_BTEMP_HIGH_TH, &val);
> >       if (ret < 0) {
> >               dev_err(dev, "%s ab8500 read failed\n", __func__);
> > -             goto free_btemp_wq;
> > +             return ret;
> >       }
> >       switch (val) {
> >       case BTEMP_HIGH_TH_57_0:
> > @@ -1050,30 +1057,28 @@ static int ab8500_btemp_probe(struct 
> > platform_device *pdev)
> >       }
> >
> >       /* Register BTEMP power supply class */
> > -     di->btemp_psy = power_supply_register(dev, &ab8500_btemp_desc,
> > -                                           &psy_cfg);
> > +     di->btemp_psy = devm_power_supply_register(dev, &ab8500_btemp_desc,
> > +                                                &psy_cfg);
> >       if (IS_ERR(di->btemp_psy)) {
> >               dev_err(dev, "failed to register BTEMP psy\n");
> > -             ret = PTR_ERR(di->btemp_psy);
> > -             goto free_btemp_wq;
> > +             return PTR_ERR(di->btemp_psy);
> >       }
> >
> >       /* Register interrupts */
> >       for (i = 0; i < ARRAY_SIZE(ab8500_btemp_irq); i++) {
> >               irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
> > -             if (irq < 0) {
> > -                     ret = irq;
> > -                     goto free_irq;
> > -             }
> > +             if (irq < 0)
> > +                     return irq;
> >
> > -             ret = request_threaded_irq(irq, NULL, ab8500_btemp_irq[i].isr,
> > +             ret = devm_request_threaded_irq(dev, irq, NULL,
> > +                     ab8500_btemp_irq[i].isr,
> >                       IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT,
> >                       ab8500_btemp_irq[i].name, di);
> >
> >               if (ret) {
> >                       dev_err(dev, "failed to request %s IRQ %d: %d\n"
> >                               , ab8500_btemp_irq[i].name, irq, ret);
> > -                     goto free_irq;
> > +                     return ret;
> >               }
> >               dev_dbg(dev, "Requested %s IRQ %d: %d\n",
> >                       ab8500_btemp_irq[i].name, irq, ret);
> > @@ -1081,23 +1086,16 @@ static int ab8500_btemp_probe(struct 
> > platform_device *pdev)
> >
> >       platform_set_drvdata(pdev, di);
> >
> > -     /* Kick off periodic temperature measurements */
> > -     ab8500_btemp_periodic(di, true);
> >       list_add_tail(&di->node, &ab8500_btemp_list);
> >
> > -     return ret;
> > +     return component_add(dev, &ab8500_btemp_component_ops);
> > +}
> >
> > -free_irq:
> > -     /* We also have to free all successfully registered irqs */
> > -     for (i = i - 1; i >= 0; i--) {
> > -             irq = platform_get_irq_byname(pdev, ab8500_btemp_irq[i].name);
> > -             free_irq(irq, di);
> > -     }
> > +static int ab8500_btemp_remove(struct platform_device *pdev)
> > +{
> > +     component_del(&pdev->dev, &ab8500_btemp_component_ops);
> >
> > -     power_supply_unregister(di->btemp_psy);
> > -free_btemp_wq:
> > -     destroy_workqueue(di->btemp_wq);
> > -     return ret;
> > +     return 0;
> > }
> >
> > static SIMPLE_DEV_PM_OPS(ab8500_btemp_pm_ops, ab8500_btemp_suspend, 
> > ab8500_btemp_resume);
> > @@ -1107,7 +1105,7 @@ static const struct of_device_id ab8500_btemp_match[] 
> > = {
> >       { },
> > };
> >
> > -static struct platform_driver ab8500_btemp_driver = {
> > +struct platform_driver ab8500_btemp_driver = {
> >       .probe = ab8500_btemp_probe,
> >       .remove = ab8500_btemp_remove,
> >       .driver = {
> > @@ -1116,20 +1114,6 @@ static struct platform_driver ab8500_btemp_driver = {
> >               .pm = &ab8500_btemp_pm_ops,
> >       },
> > };
> > -
> > -static int __init ab8500_btemp_init(void)
> > -{
> > -     return platform_driver_register(&ab8500_btemp_driver);
> > -}
> > -
> > -static void __exit ab8500_btemp_exit(void)
> > -{
> > -     platform_driver_unregister(&ab8500_btemp_driver);
> > -}
> > -
> > -device_initcall(ab8500_btemp_init);
> > -module_exit(ab8500_btemp_exit);
> > -
> > MODULE_LICENSE("GPL v2");
> > MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy");
> > MODULE_ALIAS("platform:ab8500-btemp");
> > diff --git a/drivers/power/supply/ab8500_charger.c 
> > b/drivers/power/supply/ab8500_charger.c
> > index a9be10eb2c22..af32cfae9f19 100644
> > --- a/drivers/power/supply/ab8500_charger.c
> > +++ b/drivers/power/supply/ab8500_charger.c
> > @@ -13,6 +13,7 @@
> > #include <linux/init.h>
> > #include <linux/module.h>
> > #include <linux/device.h>
> > +#include <linux/component.h>
> > #include <linux/interrupt.h>
> > #include <linux/delay.h>
> > #include <linux/notifier.h>
> > @@ -3276,10 +3277,74 @@ static struct notifier_block charger_nb = {
> >       .notifier_call = ab8500_external_charger_prepare,
> > };
> >
> > -static int ab8500_charger_remove(struct platform_device *pdev)
> > +static char *supply_interface[] = {
> > +     "ab8500_chargalg",
> > +     "ab8500_fg",
> > +     "ab8500_btemp",
> > +};
> > +
> > +static const struct power_supply_desc ab8500_ac_chg_desc = {
> > +     .name           = "ab8500_ac",
> > +     .type           = POWER_SUPPLY_TYPE_MAINS,
> > +     .properties     = ab8500_charger_ac_props,
> > +     .num_properties = ARRAY_SIZE(ab8500_charger_ac_props),
> > +     .get_property   = ab8500_charger_ac_get_property,
> > +};
> > +
> > +static const struct power_supply_desc ab8500_usb_chg_desc = {
> > +     .name           = "ab8500_usb",
> > +     .type           = POWER_SUPPLY_TYPE_USB,
> > +     .properties     = ab8500_charger_usb_props,
> > +     .num_properties = ARRAY_SIZE(ab8500_charger_usb_props),
> > +     .get_property   = ab8500_charger_usb_get_property,
> > +};
> > +
> > +static int ab8500_charger_bind(struct device *dev)
> > {
> > -     struct ab8500_charger *di = platform_get_drvdata(pdev);
> > -     int i, irq, ret;
> > +     struct ab8500_charger *di = dev_get_drvdata(dev);
> > +     int ch_stat;
> > +     int ret;
> > +
> > +     /* Create a work queue for the charger */
> > +     di->charger_wq = alloc_ordered_workqueue("ab8500_charger_wq",
> > +                                              WQ_MEM_RECLAIM);
> > +     if (di->charger_wq == NULL) {
> > +             dev_err(dev, "failed to create work queue\n");
> > +             return -ENOMEM;
> > +     }
> > +
> > +     ch_stat = ab8500_charger_detect_chargers(di, false);
> > +
> > +     if (ch_stat & AC_PW_CONN) {
> > +             if (is_ab8500(di->parent))
> > +                     queue_delayed_work(di->charger_wq,
> > +                                        &di->ac_charger_attached_work,
> > +                                        HZ);
> > +     }
> > +     if (ch_stat & USB_PW_CONN) {
> > +             if (is_ab8500(di->parent))
> > +                     queue_delayed_work(di->charger_wq,
> > +                                        &di->usb_charger_attached_work,
> > +                                        HZ);
> > +             di->vbus_detected = true;
> > +             di->vbus_detected_start = true;
> > +             queue_work(di->charger_wq,
> > +                        &di->detect_usb_type_work);
> > +     }
> > +
> > +     ret = component_bind_all(dev, di);
> > +     if (ret) {
> > +             dev_err(dev, "can't bind component devices\n");
> > +             return ret;
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +static void ab8500_charger_unbind(struct device *dev)
> > +{
> > +     struct ab8500_charger *di = dev_get_drvdata(dev);
> > +     int ret;
> >
> >       /* Disable AC charging */
> >       ab8500_charger_ac_en(&di->ac_chg, false, 0, 0);
> > @@ -3287,68 +3352,47 @@ static int ab8500_charger_remove(struct 
> > platform_device *pdev)
> >       /* Disable USB charging */
> >       ab8500_charger_usb_en(&di->usb_chg, false, 0, 0);
> >
> > -     /* Disable interrupts */
> > -     for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) {
> > -             irq = platform_get_irq_byname(pdev, 
> > ab8500_charger_irq[i].name);
> > -             free_irq(irq, di);
> > -     }
> > -
> >       /* Backup battery voltage and current disable */
> >       ret = abx500_mask_and_set_register_interruptible(di->dev,
> >               AB8500_RTC, AB8500_RTC_CTRL_REG, RTC_BUP_CH_ENA, 0);
> >       if (ret < 0)
> >               dev_err(di->dev, "%s mask and set failed\n", __func__);
> >
> > -     usb_unregister_notifier(di->usb_phy, &di->nb);
> > -     usb_put_phy(di->usb_phy);
> > -
> >       /* Delete the work queue */
> >       destroy_workqueue(di->charger_wq);
> >
> > -     /* Unregister external charger enable notifier */
> > -     if (!di->ac_chg.enabled)
> > -             blocking_notifier_chain_unregister(
> > -                     &charger_notifier_list, &charger_nb);
> > -
> >       flush_scheduled_work();
> > -     if (di->usb_chg.enabled)
> > -             power_supply_unregister(di->usb_chg.psy);
> > -
> > -     if (di->ac_chg.enabled && !di->ac_chg.external)
> > -             power_supply_unregister(di->ac_chg.psy);
> >
> > -     return 0;
> > +     /* Unbind fg, btemp, algorithm */
> > +     component_unbind_all(dev, di);
> > }
> >
> > -static char *supply_interface[] = {
> > -     "ab8500_chargalg",
> > -     "ab8500_fg",
> > -     "ab8500_btemp",
> > +static const struct component_master_ops ab8500_charger_comp_ops = {
> > +     .bind = ab8500_charger_bind,
> > +     .unbind = ab8500_charger_unbind,
> > };
> >
> > -static const struct power_supply_desc ab8500_ac_chg_desc = {
> > -     .name           = "ab8500_ac",
> > -     .type           = POWER_SUPPLY_TYPE_MAINS,
> > -     .properties     = ab8500_charger_ac_props,
> > -     .num_properties = ARRAY_SIZE(ab8500_charger_ac_props),
> > -     .get_property   = ab8500_charger_ac_get_property,
> > +static struct platform_driver *const ab8500_charger_component_drivers[] = {
> > +     &ab8500_fg_driver,
> > +     &ab8500_btemp_driver,
> > +     &abx500_chargalg_driver,
> > };
> >
> > -static const struct power_supply_desc ab8500_usb_chg_desc = {
> > -     .name           = "ab8500_usb",
> > -     .type           = POWER_SUPPLY_TYPE_USB,
> > -     .properties     = ab8500_charger_usb_props,
> > -     .num_properties = ARRAY_SIZE(ab8500_charger_usb_props),
> > -     .get_property   = ab8500_charger_usb_get_property,
> > -};
> > +static int ab8500_charger_compare_dev(struct device *dev, void *data)
> > +{
> > +     return dev == data;
> > +}
> >
> > static int ab8500_charger_probe(struct platform_device *pdev)
> > {
> > -     struct device_node *np = pdev->dev.of_node;
> > +     struct device *dev = &pdev->dev;
> > +     struct device_node *np = dev->of_node;
> > +     struct component_match *match = NULL;
> >       struct power_supply_config ac_psy_cfg = {}, usb_psy_cfg = {};
> >       struct ab8500_charger *di;
> > -     int irq, i, charger_status, ret = 0, ch_stat;
> > -     struct device *dev = &pdev->dev;
> > +     int charger_status;
> > +     int i, irq;
> > +     int ret;
> >
> >       di = devm_kzalloc(dev, sizeof(*di), GFP_KERNEL);
> >       if (!di)
> > @@ -3393,6 +3437,38 @@ static int ab8500_charger_probe(struct 
> > platform_device *pdev)
> >               return ret;
> >       }
> >
> > +     /*
> > +      * VDD ADC supply needs to be enabled from this driver when there
> > +      * is a charger connected to avoid erroneous BTEMP_HIGH/LOW
> > +      * interrupts during charging
> > +      */
> > +     di->regu = devm_regulator_get(dev, "vddadc");
> > +     if (IS_ERR(di->regu)) {
> > +             ret = PTR_ERR(di->regu);
> > +             dev_err(dev, "failed to get vddadc regulator\n");
> > +             return ret;
> > +     }
> > +
> > +     /* Request interrupts */
> > +     for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) {
> > +             irq = platform_get_irq_byname(pdev, 
> > ab8500_charger_irq[i].name);
> > +             if (irq < 0)
> > +                     return irq;
> > +
> > +             ret = devm_request_threaded_irq(dev,
> > +                     irq, NULL, ab8500_charger_irq[i].isr,
> > +                     IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT,
> > +                     ab8500_charger_irq[i].name, di);
> > +
> > +             if (ret != 0) {
> > +                     dev_err(dev, "failed to request %s IRQ %d: %d\n"
> > +                             , ab8500_charger_irq[i].name, irq, ret);
> > +                     return ret;
> > +             }
> > +             dev_dbg(dev, "Requested %s IRQ %d: %d\n",
> > +                     ab8500_charger_irq[i].name, irq, ret);
> > +     }
> > +
> >       /* initialize lock */
> >       spin_lock_init(&di->usb_state.usb_lock);
> >       mutex_init(&di->usb_ipt_crnt_lock);
> > @@ -3422,11 +3498,6 @@ static int ab8500_charger_probe(struct 
> > platform_device *pdev)
> >       di->ac_chg.enabled = di->bm->ac_enabled;
> >       di->ac_chg.external = false;
> >
> > -     /*notifier for external charger enabling*/
> > -     if (!di->ac_chg.enabled)
> > -             blocking_notifier_chain_register(
> > -                     &charger_notifier_list, &charger_nb);
> > -
> >       /* USB supply */
> >       /* ux500_charger sub-class */
> >       di->usb_chg.ops.enable = &ab8500_charger_usb_en;
> > @@ -3442,14 +3513,6 @@ static int ab8500_charger_probe(struct 
> > platform_device *pdev)
> >       di->usb_chg.external = false;
> >       di->usb_state.usb_current = -1;
> >
> > -     /* Create a work queue for the charger */
> > -     di->charger_wq = alloc_ordered_workqueue("ab8500_charger_wq",
> > -                                              WQ_MEM_RECLAIM);
> > -     if (di->charger_wq == NULL) {
> > -             dev_err(dev, "failed to create work queue\n");
> > -             return -ENOMEM;
> > -     }
> > -
> >       mutex_init(&di->charger_attached_mutex);
> >
> >       /* Init work for HW failure check */
> > @@ -3500,63 +3563,36 @@ static int ab8500_charger_probe(struct 
> > platform_device *pdev)
> >       INIT_WORK(&di->check_usb_thermal_prot_work,
> >               ab8500_charger_check_usb_thermal_prot_work);
> >
> > -     /*
> > -      * VDD ADC supply needs to be enabled from this driver when there
> > -      * is a charger connected to avoid erroneous BTEMP_HIGH/LOW
> > -      * interrupts during charging
> > -      */
> > -     di->regu = devm_regulator_get(dev, "vddadc");
> > -     if (IS_ERR(di->regu)) {
> > -             ret = PTR_ERR(di->regu);
> > -             dev_err(dev, "failed to get vddadc regulator\n");
> > -             goto free_charger_wq;
> > -     }
> > -
> >
> >       /* Initialize OVV, and other registers */
> >       ret = ab8500_charger_init_hw_registers(di);
> >       if (ret) {
> >               dev_err(dev, "failed to initialize ABB registers\n");
> > -             goto free_charger_wq;
> > +             return ret;
> >       }
> >
> >       /* Register AC charger class */
> >       if (di->ac_chg.enabled) {
> > -             di->ac_chg.psy = power_supply_register(dev,
> > +             di->ac_chg.psy = devm_power_supply_register(dev,
> >                                                      &ab8500_ac_chg_desc,
> >                                                      &ac_psy_cfg);
> >               if (IS_ERR(di->ac_chg.psy)) {
> >                       dev_err(dev, "failed to register AC charger\n");
> > -                     ret = PTR_ERR(di->ac_chg.psy);
> > -                     goto free_charger_wq;
> > +                     return PTR_ERR(di->ac_chg.psy);
> >               }
> >       }
> >
> >       /* Register USB charger class */
> >       if (di->usb_chg.enabled) {
> > -             di->usb_chg.psy = power_supply_register(dev,
> > +             di->usb_chg.psy = devm_power_supply_register(dev,
> >                                                       &ab8500_usb_chg_desc,
> >                                                       &usb_psy_cfg);
> >               if (IS_ERR(di->usb_chg.psy)) {
> >                       dev_err(dev, "failed to register USB charger\n");
> > -                     ret = PTR_ERR(di->usb_chg.psy);
> > -                     goto free_ac;
> > +                     return PTR_ERR(di->usb_chg.psy);
> >               }
> >       }
> >
> > -     di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
> > -     if (IS_ERR_OR_NULL(di->usb_phy)) {
> > -             dev_err(dev, "failed to get usb transceiver\n");
> > -             ret = -EINVAL;
> > -             goto free_usb;
> > -     }
> > -     di->nb.notifier_call = ab8500_charger_usb_notifier_call;
> > -     ret = usb_register_notifier(di->usb_phy, &di->nb);
> > -     if (ret) {
> > -             dev_err(dev, "failed to register usb notifier\n");
> > -             goto put_usb_phy;
> > -     }
> > -
> >       /* Identify the connected charger types during startup */
> >       charger_status = ab8500_charger_detect_chargers(di, true);
> >       if (charger_status & AC_PW_CONN) {
> > @@ -3566,78 +3602,86 @@ static int ab8500_charger_probe(struct 
> > platform_device *pdev)
> >               sysfs_notify(&di->ac_chg.psy->dev.kobj, NULL, "present");
> >       }
> >
> > -     if (charger_status & USB_PW_CONN) {
> > -             di->vbus_detected = true;
> > -             di->vbus_detected_start = true;
> > -             queue_work(di->charger_wq,
> > -                     &di->detect_usb_type_work);
> > -     }
> > -
> > -     /* Register interrupts */
> > -     for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) {
> > -             irq = platform_get_irq_byname(pdev, 
> > ab8500_charger_irq[i].name);
> > -             if (irq < 0) {
> > -                     ret = irq;
> > -                     goto free_irq;
> > -             }
> > +     platform_set_drvdata(pdev, di);
> >
> > -             ret = request_threaded_irq(irq, NULL, 
> > ab8500_charger_irq[i].isr,
> > -                     IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT,
> > -                     ab8500_charger_irq[i].name, di);
> > +     /* Create something that will match the subdrivers when we bind */
> > +     for (i = 0; i < ARRAY_SIZE(ab8500_charger_component_drivers); i++) {
> > +             struct device_driver *drv = 
> > &ab8500_charger_component_drivers[i]->driver;
> > +             struct device *p = NULL, *d;
> >
> > -             if (ret != 0) {
> > -                     dev_err(dev, "failed to request %s IRQ %d: %d\n"
> > -                             , ab8500_charger_irq[i].name, irq, ret);
> > -                     goto free_irq;
> > +             while ((d = platform_find_device_by_driver(p, drv))) {
> > +                     put_device(p);
> > +                     component_match_add(dev, &match,
> > +                                         ab8500_charger_compare_dev, d);
> > +                     p = d;
> >               }
> > -             dev_dbg(dev, "Requested %s IRQ %d: %d\n",
> > -                     ab8500_charger_irq[i].name, irq, ret);
> > +             put_device(p);
> > +     }
> > +     if (!match) {
> > +             dev_err(dev, "no matching components\n");
> > +             return -ENODEV;
> > +     }
> > +     if (IS_ERR(match)) {
> > +             dev_err(dev, "could not create component match\n");
> > +             return PTR_ERR(match);
> >       }
> >
> > -     platform_set_drvdata(pdev, di);
> > +     /* Notifier for external charger enabling */
> > +     if (!di->ac_chg.enabled)
> > +             blocking_notifier_chain_register(
> > +                     &charger_notifier_list, &charger_nb);
> >
> > -     mutex_lock(&di->charger_attached_mutex);
> >
> > -     ch_stat = ab8500_charger_detect_chargers(di, false);
> > -
> > -     if ((ch_stat & AC_PW_CONN) == AC_PW_CONN) {
> > -             if (is_ab8500(di->parent))
> > -                     queue_delayed_work(di->charger_wq,
> > -                                        &di->ac_charger_attached_work,
> > -                                        HZ);
> > +     di->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2);
> > +     if (IS_ERR_OR_NULL(di->usb_phy)) {
> > +             dev_err(dev, "failed to get usb transceiver\n");
> > +             ret = -EINVAL;
> > +             goto out_charger_notifier;
> >       }
> > -     if ((ch_stat & USB_PW_CONN) == USB_PW_CONN) {
> > -             if (is_ab8500(di->parent))
> > -                     queue_delayed_work(di->charger_wq,
> > -                                        &di->usb_charger_attached_work,
> > -                                        HZ);
> > +     di->nb.notifier_call = ab8500_charger_usb_notifier_call;
> > +     ret = usb_register_notifier(di->usb_phy, &di->nb);
> > +     if (ret) {
> > +             dev_err(dev, "failed to register usb notifier\n");
> > +             goto put_usb_phy;
> >       }
> >
> > -     mutex_unlock(&di->charger_attached_mutex);
> >
> > -     return ret;
> > +     ret = component_master_add_with_match(&pdev->dev,
> > +                                           &ab8500_charger_comp_ops,
> > +                                           match);
> > +     if (ret) {
> > +             dev_err(dev, "failed to add component master\n");
> > +             goto free_notifier;
> > +     }
> >
> > -free_irq:
> > -     usb_unregister_notifier(di->usb_phy, &di->nb);
> > +     return 0;
> >
> > -     /* We also have to free all successfully registered irqs */
> > -     for (i = i - 1; i >= 0; i--) {
> > -             irq = platform_get_irq_byname(pdev, 
> > ab8500_charger_irq[i].name);
> > -             free_irq(irq, di);
> > -     }
> > +free_notifier:
> > +     usb_unregister_notifier(di->usb_phy, &di->nb);
> > put_usb_phy:
> >       usb_put_phy(di->usb_phy);
> > -free_usb:
> > -     if (di->usb_chg.enabled)
> > -             power_supply_unregister(di->usb_chg.psy);
> > -free_ac:
> > -     if (di->ac_chg.enabled)
> > -             power_supply_unregister(di->ac_chg.psy);
> > -free_charger_wq:
> > -     destroy_workqueue(di->charger_wq);
> > +out_charger_notifier:
> > +     if (!di->ac_chg.enabled)
> > +             blocking_notifier_chain_unregister(
> > +                     &charger_notifier_list, &charger_nb);
> >       return ret;
> > }
> >
> > +static int ab8500_charger_remove(struct platform_device *pdev)
> > +{
> > +     struct ab8500_charger *di = platform_get_drvdata(pdev);
> > +
> > +     component_master_del(&pdev->dev, &ab8500_charger_comp_ops);
> > +
> > +     usb_unregister_notifier(di->usb_phy, &di->nb);
> > +     usb_put_phy(di->usb_phy);
> > +     if (!di->ac_chg.enabled)
> > +             blocking_notifier_chain_unregister(
> > +                     &charger_notifier_list, &charger_nb);
> > +
> > +     return 0;
> > +}
> > +
> > static SIMPLE_DEV_PM_OPS(ab8500_charger_pm_ops, ab8500_charger_suspend, 
> > ab8500_charger_resume);
> >
> > static const struct of_device_id ab8500_charger_match[] = {
> > @@ -3657,15 +3701,24 @@ static struct platform_driver ab8500_charger_driver 
> > = {
> >
> > static int __init ab8500_charger_init(void)
> > {
> > +     int ret;
> > +
> > +     ret = platform_register_drivers(ab8500_charger_component_drivers,
> > +                     ARRAY_SIZE(ab8500_charger_component_drivers));
> > +     if (ret)
> > +             return ret;
> > +
> >       return platform_driver_register(&ab8500_charger_driver);
> > }
> >
> > static void __exit ab8500_charger_exit(void)
> > {
> > +     platform_unregister_drivers(ab8500_charger_component_drivers,
> > +                     ARRAY_SIZE(ab8500_charger_component_drivers));
> >       platform_driver_unregister(&ab8500_charger_driver);
> > }
> >
> > -subsys_initcall_sync(ab8500_charger_init);
> > +module_init(ab8500_charger_init);
> > module_exit(ab8500_charger_exit);
> >
> > MODULE_LICENSE("GPL v2");
> > diff --git a/drivers/power/supply/ab8500_fg.c 
> > b/drivers/power/supply/ab8500_fg.c
> > index 0c7c01a0d979..acf0f2471c0b 100644
> > --- a/drivers/power/supply/ab8500_fg.c
> > +++ b/drivers/power/supply/ab8500_fg.c
> > @@ -17,6 +17,7 @@
> >
> > #include <linux/init.h>
> > #include <linux/module.h>
> > +#include <linux/component.h>
> > #include <linux/device.h>
> > #include <linux/interrupt.h>
> > #include <linux/platform_device.h>
> > @@ -2980,27 +2981,6 @@ static int __maybe_unused ab8500_fg_suspend(struct 
> > device *dev)
> >       return 0;
> > }
> >
> > -static int ab8500_fg_remove(struct platform_device *pdev)
> > -{
> > -     int ret = 0;
> > -     struct ab8500_fg *di = platform_get_drvdata(pdev);
> > -
> > -     list_del(&di->node);
> > -
> > -     /* Disable coulomb counter */
> > -     ret = ab8500_fg_coulomb_counter(di, false);
> > -     if (ret)
> > -             dev_err(di->dev, "failed to disable coulomb counter\n");
> > -
> > -     destroy_workqueue(di->fg_wq);
> > -     ab8500_fg_sysfs_exit(di);
> > -
> > -     flush_scheduled_work();
> > -     ab8500_fg_sysfs_psy_remove_attrs(di);
> > -     power_supply_unregister(di->fg_psy);
> > -     return ret;
> > -}
> > -
> > /* ab8500 fg driver interrupts and their respective isr */
> > static struct ab8500_fg_interrupts ab8500_fg_irq[] = {
> >       {"NCONV_ACCU", ab8500_fg_cc_convend_handler},
> > @@ -3024,11 +3004,50 @@ static const struct power_supply_desc 
> > ab8500_fg_desc = {
> >       .external_power_changed = ab8500_fg_external_power_changed,
> > };
> >
> > +static int ab8500_fg_bind(struct device *dev, struct device *master,
> > +                       void *data)
> > +{
> > +     struct ab8500_fg *di = dev_get_drvdata(dev);
> > +
> > +     /* Create a work queue for running the FG algorithm */
> > +     di->fg_wq = alloc_ordered_workqueue("ab8500_fg_wq", WQ_MEM_RECLAIM);
> > +     if (di->fg_wq == NULL) {
> > +             dev_err(dev, "failed to create work queue\n");
> > +             return -ENOMEM;
> > +     }
> > +
> > +     /* Start the coulomb counter */
> > +     ab8500_fg_coulomb_counter(di, true);
> > +     /* Run the FG algorithm */
> > +     queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0);
> > +
> > +     return 0;
> > +}
> > +
> > +static void ab8500_fg_unbind(struct device *dev, struct device *master,
> > +                          void *data)
> > +{
> > +     struct ab8500_fg *di = dev_get_drvdata(dev);
> > +     int ret;
> > +
> > +     /* Disable coulomb counter */
> > +     ret = ab8500_fg_coulomb_counter(di, false);
> > +     if (ret)
> > +             dev_err(dev, "failed to disable coulomb counter\n");
> > +
> > +     destroy_workqueue(di->fg_wq);
> > +     flush_scheduled_work();
> > +}
> > +
> > +static const struct component_ops ab8500_fg_component_ops = {
> > +     .bind = ab8500_fg_bind,
> > +     .unbind = ab8500_fg_unbind,
> > +};
> > +
> > static int ab8500_fg_probe(struct platform_device *pdev)
> > {
> > -     struct device_node *np = pdev->dev.of_node;
> > -     struct power_supply_config psy_cfg = {};
> >       struct device *dev = &pdev->dev;
> > +     struct power_supply_config psy_cfg = {};
> >       struct ab8500_fg *di;
> >       int i, irq;
> >       int ret = 0;
> > @@ -3074,13 +3093,6 @@ static int ab8500_fg_probe(struct platform_device 
> > *pdev)
> >       ab8500_fg_charge_state_to(di, AB8500_FG_CHARGE_INIT);
> >       ab8500_fg_discharge_state_to(di, AB8500_FG_DISCHARGE_INIT);
> >
> > -     /* Create a work queue for running the FG algorithm */
> > -     di->fg_wq = alloc_ordered_workqueue("ab8500_fg_wq", WQ_MEM_RECLAIM);
> > -     if (di->fg_wq == NULL) {
> > -             dev_err(dev, "failed to create work queue\n");
> > -             return -ENOMEM;
> > -     }
> > -
> >       /* Init work for running the fg algorithm instantly */
> >       INIT_WORK(&di->fg_work, ab8500_fg_instant_work);
> >
> > @@ -3113,7 +3125,7 @@ static int ab8500_fg_probe(struct platform_device 
> > *pdev)
> >       ret = ab8500_fg_init_hw_registers(di);
> >       if (ret) {
> >               dev_err(dev, "failed to initialize registers\n");
> > -             goto free_inst_curr_wq;
> > +             return ret;
> >       }
> >
> >       /* Consider battery unknown until we're informed otherwise */
> > @@ -3121,15 +3133,13 @@ static int ab8500_fg_probe(struct platform_device 
> > *pdev)
> >       di->flags.batt_id_received = false;
> >
> >       /* Register FG power supply class */
> > -     di->fg_psy = power_supply_register(dev, &ab8500_fg_desc, &psy_cfg);
> > +     di->fg_psy = devm_power_supply_register(dev, &ab8500_fg_desc, 
> > &psy_cfg);
> >       if (IS_ERR(di->fg_psy)) {
> >               dev_err(dev, "failed to register FG psy\n");
> > -             ret = PTR_ERR(di->fg_psy);
> > -             goto free_inst_curr_wq;
> > +             return PTR_ERR(di->fg_psy);
> >       }
> >
> >       di->fg_samples = SEC_TO_SAMPLE(di->bm->fg_params->init_timer);
> > -     ab8500_fg_coulomb_counter(di, true);
> >
> >       /*
> >        * Initialize completion used to notify completion and start
> > @@ -3141,19 +3151,18 @@ static int ab8500_fg_probe(struct platform_device 
> > *pdev)
> >       /* Register primary interrupt handlers */
> >       for (i = 0; i < ARRAY_SIZE(ab8500_fg_irq); i++) {
> >               irq = platform_get_irq_byname(pdev, ab8500_fg_irq[i].name);
> > -             if (irq < 0) {
> > -                     ret = irq;
> > -                     goto free_irq;
> > -             }
> > +             if (irq < 0)
> > +                     return irq;
> >
> > -             ret = request_threaded_irq(irq, NULL, ab8500_fg_irq[i].isr,
> > +             ret = devm_request_threaded_irq(dev, irq, NULL,
> > +                               ab8500_fg_irq[i].isr,
> >                                 IRQF_SHARED | IRQF_NO_SUSPEND | 
> > IRQF_ONESHOT,
> >                                 ab8500_fg_irq[i].name, di);
> >
> >               if (ret != 0) {
> >                       dev_err(dev, "failed to request %s IRQ %d: %d\n",
> >                               ab8500_fg_irq[i].name, irq, ret);
> > -                     goto free_irq;
> > +                     return ret;
> >               }
> >               dev_dbg(dev, "Requested %s IRQ %d: %d\n",
> >                       ab8500_fg_irq[i].name, irq, ret);
> > @@ -3168,14 +3177,14 @@ static int ab8500_fg_probe(struct platform_device 
> > *pdev)
> >       ret = ab8500_fg_sysfs_init(di);
> >       if (ret) {
> >               dev_err(dev, "failed to create sysfs entry\n");
> > -             goto free_irq;
> > +             return ret;
> >       }
> >
> >       ret = ab8500_fg_sysfs_psy_create_attrs(di);
> >       if (ret) {
> >               dev_err(dev, "failed to create FG psy\n");
> >               ab8500_fg_sysfs_exit(di);
> > -             goto free_irq;
> > +             return ret;
> >       }
> >
> >       /* Calibrate the fg first time */
> > @@ -3185,24 +3194,21 @@ static int ab8500_fg_probe(struct platform_device 
> > *pdev)
> >       /* Use room temp as default value until we get an update from driver. 
> > */
> >       di->bat_temp = 210;
> >
> > -     /* Run the FG algorithm */
> > -     queue_delayed_work(di->fg_wq, &di->fg_periodic_work, 0);
> > -
> >       list_add_tail(&di->node, &ab8500_fg_list);
> >
> > -     return ret;
> > +     return component_add(dev, &ab8500_fg_component_ops);
> > +}
> >
> > -free_irq:
> > -     /* We also have to free all registered irqs */
> > -     while (--i >= 0) {
> > -             /* Last assignment of i from primary interrupt handlers */
> > -             irq = platform_get_irq_byname(pdev, ab8500_fg_irq[i].name);
> > -             free_irq(irq, di);
> > -     }
> > +static int ab8500_fg_remove(struct platform_device *pdev)
> > +{
> > +     int ret = 0;
> > +     struct ab8500_fg *di = platform_get_drvdata(pdev);
> > +
> > +     component_del(&pdev->dev, &ab8500_fg_component_ops);
> > +     list_del(&di->node);
> > +     ab8500_fg_sysfs_exit(di);
> > +     ab8500_fg_sysfs_psy_remove_attrs(di);
> >
> > -     power_supply_unregister(di->fg_psy);
> > -free_inst_curr_wq:
> > -     destroy_workqueue(di->fg_wq);
> >       return ret;
> > }
> >
> > @@ -3213,7 +3219,7 @@ static const struct of_device_id ab8500_fg_match[] = {
> >       { },
> > };
> >
> > -static struct platform_driver ab8500_fg_driver = {
> > +struct platform_driver ab8500_fg_driver = {
> >       .probe = ab8500_fg_probe,
> >       .remove = ab8500_fg_remove,
> >       .driver = {
> > @@ -3222,20 +3228,6 @@ static struct platform_driver ab8500_fg_driver = {
> >               .pm = &ab8500_fg_pm_ops,
> >       },
> > };
> > -
> > -static int __init ab8500_fg_init(void)
> > -{
> > -     return platform_driver_register(&ab8500_fg_driver);
> > -}
> > -
> > -static void __exit ab8500_fg_exit(void)
> > -{
> > -     platform_driver_unregister(&ab8500_fg_driver);
> > -}
> > -
> > -subsys_initcall_sync(ab8500_fg_init);
> > -module_exit(ab8500_fg_exit);
> > -
> > MODULE_LICENSE("GPL v2");
> > MODULE_AUTHOR("Johan Palsson, Karl Komierowski");
> > MODULE_ALIAS("platform:ab8500-fg");
> > diff --git a/drivers/power/supply/abx500_chargalg.c 
> > b/drivers/power/supply/abx500_chargalg.c
> > index f5b792243727..599684ce0e4b 100644
> > --- a/drivers/power/supply/abx500_chargalg.c
> > +++ b/drivers/power/supply/abx500_chargalg.c
> > @@ -15,6 +15,7 @@
> > #include <linux/init.h>
> > #include <linux/module.h>
> > #include <linux/device.h>
> > +#include <linux/component.h>
> > #include <linux/hrtimer.h>
> > #include <linux/interrupt.h>
> > #include <linux/delay.h>
> > @@ -1943,13 +1944,44 @@ static int __maybe_unused 
> > abx500_chargalg_suspend(struct device *dev)
> >       return 0;
> > }
> >
> > -static int abx500_chargalg_remove(struct platform_device *pdev)
> > +static char *supply_interface[] = {
> > +     "ab8500_fg",
> > +};
> > +
> > </cut>
>
_______________________________________________
linaro-toolchain mailing list
linaro-toolchain@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/linaro-toolchain

Reply via email to