2018-11-12 10:53:45

by Baolin Wang

[permalink] [raw]
Subject: [PATCH 1/4] power: supply: sc2731_charger: Add one work to charge/discharge

Since the USB notifier context is atomic, we can not start or stop charging
in atomic context. Thus this patch adds one work to help to charge or
discharge.

Signed-off-by: Baolin Wang <[email protected]>
---
drivers/power/supply/sc2731_charger.c | 30 ++++++++++++++++++++++--------
1 file changed, 22 insertions(+), 8 deletions(-)

diff --git a/drivers/power/supply/sc2731_charger.c b/drivers/power/supply/sc2731_charger.c
index 525a820..393ba98 100644
--- a/drivers/power/supply/sc2731_charger.c
+++ b/drivers/power/supply/sc2731_charger.c
@@ -57,9 +57,11 @@ struct sc2731_charger_info {
struct usb_phy *usb_phy;
struct notifier_block usb_notify;
struct power_supply *psy_usb;
+ struct work_struct work;
struct mutex lock;
bool charging;
u32 base;
+ u32 limit;
};

static void sc2731_charger_stop_charge(struct sc2731_charger_info *info)
@@ -318,22 +320,21 @@ static int sc2731_charger_property_is_writeable(struct power_supply *psy,
.property_is_writeable = sc2731_charger_property_is_writeable,
};

-static int sc2731_charger_usb_change(struct notifier_block *nb,
- unsigned long limit, void *data)
+static void sc2731_charger_work(struct work_struct *data)
{
struct sc2731_charger_info *info =
- container_of(nb, struct sc2731_charger_info, usb_notify);
- int ret = 0;
+ container_of(data, struct sc2731_charger_info, work);
+ int ret;

mutex_lock(&info->lock);

- if (limit > 0) {
+ if (info->limit > 0) {
/* set current limitation and start to charge */
- ret = sc2731_charger_set_current_limit(info, limit);
+ ret = sc2731_charger_set_current_limit(info, info->limit);
if (ret)
goto out;

- ret = sc2731_charger_set_current(info, limit);
+ ret = sc2731_charger_set_current(info, info->limit);
if (ret)
goto out;

@@ -350,7 +351,19 @@ static int sc2731_charger_usb_change(struct notifier_block *nb,

out:
mutex_unlock(&info->lock);
- return ret;
+}
+
+static int sc2731_charger_usb_change(struct notifier_block *nb,
+ unsigned long limit, void *data)
+{
+ struct sc2731_charger_info *info =
+ container_of(nb, struct sc2731_charger_info, usb_notify);
+
+ info->limit = limit;
+
+ schedule_work(&info->work);
+
+ return NOTIFY_OK;
}

static int sc2731_charger_hw_init(struct sc2731_charger_info *info)
@@ -432,6 +445,7 @@ static int sc2731_charger_probe(struct platform_device *pdev)

mutex_init(&info->lock);
info->dev = &pdev->dev;
+ INIT_WORK(&info->work, sc2731_charger_work);

info->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!info->regmap) {
--
1.7.9.5



2018-11-12 10:53:50

by Baolin Wang

[permalink] [raw]
Subject: [PATCH 2/4] power: supply: sc2731_charger: Add charger status detection

The USB charger status can be notified before the charger driver registers
the USB phy notifier, so we should check the charger status in probe() in
case we missed the USB charger notification.

Signed-off-by: Baolin Wang <[email protected]>
---
drivers/power/supply/sc2731_charger.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)

diff --git a/drivers/power/supply/sc2731_charger.c b/drivers/power/supply/sc2731_charger.c
index 393ba98..a012d6c 100644
--- a/drivers/power/supply/sc2731_charger.c
+++ b/drivers/power/supply/sc2731_charger.c
@@ -432,6 +432,24 @@ static int sc2731_charger_hw_init(struct sc2731_charger_info *info)
return ret;
}

+static void sc2731_charger_detect_status(struct sc2731_charger_info *info)
+{
+ unsigned int min, max;
+
+ /*
+ * If the USB charger status has been USB_CHARGER_PRESENT before
+ * registering the notifier, we should start to charge with getting
+ * the charge current.
+ */
+ if (info->usb_phy->chg_state != USB_CHARGER_PRESENT)
+ return;
+
+ usb_phy_get_charger_current(info->usb_phy, &min, &max);
+ info->limit = min;
+
+ schedule_work(&info->work);
+}
+
static int sc2731_charger_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -486,6 +504,8 @@ static int sc2731_charger_probe(struct platform_device *pdev)
return ret;
}

+ sc2731_charger_detect_status(info);
+
return 0;
}

--
1.7.9.5


2018-11-12 10:53:52

by Baolin Wang

[permalink] [raw]
Subject: [PATCH 3/4] power: supply: sc2731_charger: Avoid repeated charge/discharge

Add info->charging validation to avoid repeated charge or discharge
operation.

Signed-off-by: Baolin Wang <[email protected]>
---
drivers/power/supply/sc2731_charger.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/power/supply/sc2731_charger.c b/drivers/power/supply/sc2731_charger.c
index a012d6c..49b3f0c 100644
--- a/drivers/power/supply/sc2731_charger.c
+++ b/drivers/power/supply/sc2731_charger.c
@@ -328,7 +328,7 @@ static void sc2731_charger_work(struct work_struct *data)

mutex_lock(&info->lock);

- if (info->limit > 0) {
+ if (info->limit > 0 && !info->charging) {
/* set current limitation and start to charge */
ret = sc2731_charger_set_current_limit(info, info->limit);
if (ret)
@@ -343,7 +343,7 @@ static void sc2731_charger_work(struct work_struct *data)
goto out;

info->charging = true;
- } else {
+ } else if (!info->limit && info->charging) {
/* Stop charging */
info->charging = false;
sc2731_charger_stop_charge(info);
--
1.7.9.5


2018-11-12 10:53:54

by Baolin Wang

[permalink] [raw]
Subject: [PATCH 4/4] power: supply: sc2731_charger: Free battery information

Free battery information in case of adding battery OCV tables.

Signed-off-by: Baolin Wang <[email protected]>
---
drivers/power/supply/sc2731_charger.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/drivers/power/supply/sc2731_charger.c b/drivers/power/supply/sc2731_charger.c
index 49b3f0c..335cb85 100644
--- a/drivers/power/supply/sc2731_charger.c
+++ b/drivers/power/supply/sc2731_charger.c
@@ -408,6 +408,8 @@ static int sc2731_charger_hw_init(struct sc2731_charger_info *info)
vol_val = (term_voltage - 4200) / 100;
else
vol_val = 0;
+
+ power_supply_put_battery_info(info->psy_usb, &bat_info);
}

/* Set charge termination current */
--
1.7.9.5


2018-12-05 23:10:17

by Sebastian Reichel

[permalink] [raw]
Subject: Re: [PATCH 1/4] power: supply: sc2731_charger: Add one work to charge/discharge

Hi,

On Mon, Nov 12, 2018 at 06:52:35PM +0800, Baolin Wang wrote:
> Since the USB notifier context is atomic, we can not start or stop charging
> in atomic context. Thus this patch adds one work to help to charge or
> discharge.
>
> Signed-off-by: Baolin Wang <[email protected]>
> ---

Thanks, patchset queued.

-- Sebastian

> drivers/power/supply/sc2731_charger.c | 30 ++++++++++++++++++++++--------
> 1 file changed, 22 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/power/supply/sc2731_charger.c b/drivers/power/supply/sc2731_charger.c
> index 525a820..393ba98 100644
> --- a/drivers/power/supply/sc2731_charger.c
> +++ b/drivers/power/supply/sc2731_charger.c
> @@ -57,9 +57,11 @@ struct sc2731_charger_info {
> struct usb_phy *usb_phy;
> struct notifier_block usb_notify;
> struct power_supply *psy_usb;
> + struct work_struct work;
> struct mutex lock;
> bool charging;
> u32 base;
> + u32 limit;
> };
>
> static void sc2731_charger_stop_charge(struct sc2731_charger_info *info)
> @@ -318,22 +320,21 @@ static int sc2731_charger_property_is_writeable(struct power_supply *psy,
> .property_is_writeable = sc2731_charger_property_is_writeable,
> };
>
> -static int sc2731_charger_usb_change(struct notifier_block *nb,
> - unsigned long limit, void *data)
> +static void sc2731_charger_work(struct work_struct *data)
> {
> struct sc2731_charger_info *info =
> - container_of(nb, struct sc2731_charger_info, usb_notify);
> - int ret = 0;
> + container_of(data, struct sc2731_charger_info, work);
> + int ret;
>
> mutex_lock(&info->lock);
>
> - if (limit > 0) {
> + if (info->limit > 0) {
> /* set current limitation and start to charge */
> - ret = sc2731_charger_set_current_limit(info, limit);
> + ret = sc2731_charger_set_current_limit(info, info->limit);
> if (ret)
> goto out;
>
> - ret = sc2731_charger_set_current(info, limit);
> + ret = sc2731_charger_set_current(info, info->limit);
> if (ret)
> goto out;
>
> @@ -350,7 +351,19 @@ static int sc2731_charger_usb_change(struct notifier_block *nb,
>
> out:
> mutex_unlock(&info->lock);
> - return ret;
> +}
> +
> +static int sc2731_charger_usb_change(struct notifier_block *nb,
> + unsigned long limit, void *data)
> +{
> + struct sc2731_charger_info *info =
> + container_of(nb, struct sc2731_charger_info, usb_notify);
> +
> + info->limit = limit;
> +
> + schedule_work(&info->work);
> +
> + return NOTIFY_OK;
> }
>
> static int sc2731_charger_hw_init(struct sc2731_charger_info *info)
> @@ -432,6 +445,7 @@ static int sc2731_charger_probe(struct platform_device *pdev)
>
> mutex_init(&info->lock);
> info->dev = &pdev->dev;
> + INIT_WORK(&info->work, sc2731_charger_work);
>
> info->regmap = dev_get_regmap(pdev->dev.parent, NULL);
> if (!info->regmap) {
> --
> 1.7.9.5
>


Attachments:
(No filename) (2.88 kB)
signature.asc (849.00 B)
Download all attachments