lkml.org 
[lkml]   [2022]   [Nov]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH] usb: phy: add dedicated notifier for charger events
Date
usb_phy::notifier is already used by various PHY drivers (including
phy_generic) to report VBUS status changes and its usage conflicts with
charger current limit changes reporting.

Fix that by introducing a second notifier that is dedicated to usb charger
notifications. Add usb_charger_XXX_notifier functions. Fix charger drivers
that currently (ab)use usb_XXX_notifier() to use the new API.

Fixes: a9081a008f84 ("usb: phy: Add USB charger support")

Signed-off-by: Ivaylo Dimitrov <ivo.g.dimitrov.75@gmail.com>
---
drivers/power/supply/sc2731_charger.c | 4 ++--
drivers/power/supply/wm831x_power.c | 7 ++++---
drivers/usb/phy/phy.c | 7 +++++--
include/linux/usb/phy.h | 14 ++++++++++++++
4 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/drivers/power/supply/sc2731_charger.c b/drivers/power/supply/sc2731_charger.c
index 9ac17cf..e3fa0e2 100644
--- a/drivers/power/supply/sc2731_charger.c
+++ b/drivers/power/supply/sc2731_charger.c
@@ -500,7 +500,7 @@ static int sc2731_charger_probe(struct platform_device *pdev)
}

info->usb_notify.notifier_call = sc2731_charger_usb_change;
- ret = usb_register_notifier(info->usb_phy, &info->usb_notify);
+ ret = usb_charger_register_notifier(info->usb_phy, &info->usb_notify);
if (ret) {
dev_err(&pdev->dev, "failed to register notifier: %d\n", ret);
return ret;
@@ -515,7 +515,7 @@ static int sc2731_charger_remove(struct platform_device *pdev)
{
struct sc2731_charger_info *info = platform_get_drvdata(pdev);

- usb_unregister_notifier(info->usb_phy, &info->usb_notify);
+ usb_charger_unregister_notifier(info->usb_phy, &info->usb_notify);

return 0;
}
diff --git a/drivers/power/supply/wm831x_power.c b/drivers/power/supply/wm831x_power.c
index 82e3106..0744167 100644
--- a/drivers/power/supply/wm831x_power.c
+++ b/drivers/power/supply/wm831x_power.c
@@ -650,7 +650,8 @@ static int wm831x_power_probe(struct platform_device *pdev)
switch (ret) {
case 0:
power->usb_notify.notifier_call = wm831x_usb_limit_change;
- ret = usb_register_notifier(power->usb_phy, &power->usb_notify);
+ ret = usb_charger_register_notifier(power->usb_phy,
+ &power->usb_notify);
if (ret) {
dev_err(&pdev->dev, "Failed to register notifier: %d\n",
ret);
@@ -701,8 +702,8 @@ static int wm831x_power_remove(struct platform_device *pdev)
int irq, i;

if (wm831x_power->usb_phy) {
- usb_unregister_notifier(wm831x_power->usb_phy,
- &wm831x_power->usb_notify);
+ usb_charger_unregister_notifier(wm831x_power->usb_phy,
+ &wm831x_power->usb_notify);
}

for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c
index 1b24492..6b8bf05 100644
--- a/drivers/usb/phy/phy.c
+++ b/drivers/usb/phy/phy.c
@@ -129,12 +129,13 @@ static void usb_phy_notify_charger_work(struct work_struct *work)
case USB_CHARGER_PRESENT:
usb_phy_get_charger_current(usb_phy, &min, &max);

- atomic_notifier_call_chain(&usb_phy->notifier, max, usb_phy);
+ atomic_notifier_call_chain(&usb_phy->chg_notifier, max,
+ usb_phy);
break;
case USB_CHARGER_ABSENT:
usb_phy_set_default_current(usb_phy);

- atomic_notifier_call_chain(&usb_phy->notifier, 0, usb_phy);
+ atomic_notifier_call_chain(&usb_phy->chg_notifier, 0, usb_phy);
break;
default:
dev_warn(usb_phy->dev, "Unknown USB charger state: %d\n",
@@ -678,6 +679,7 @@ int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
return ret;

ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier);
+ ATOMIC_INIT_NOTIFIER_HEAD(&x->chg_notifier);

spin_lock_irqsave(&phy_lock, flags);

@@ -730,6 +732,7 @@ int usb_add_phy_dev(struct usb_phy *x)
x->dev->type = &usb_phy_dev_type;

ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier);
+ ATOMIC_INIT_NOTIFIER_HEAD(&x->chg_notifier);

spin_lock_irqsave(&phy_lock, flags);
list_add_tail(&x->head, &phy_list);
diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h
index e4de6bc..23db554 100644
--- a/include/linux/usb/phy.h
+++ b/include/linux/usb/phy.h
@@ -111,6 +111,7 @@ struct usb_phy {
enum usb_charger_state chg_state;
struct usb_charger_current chg_cur;
struct work_struct chg_work;
+ struct atomic_notifier_head chg_notifier;

/* for notification of usb_phy_events */
struct atomic_notifier_head notifier;
@@ -347,6 +348,19 @@ static inline void usb_phy_set_charger_state(struct usb_phy *usb_phy,
atomic_notifier_chain_unregister(&x->notifier, nb);
}

+/* notifiers */
+static inline int
+usb_charger_register_notifier(struct usb_phy *x, struct notifier_block *nb)
+{
+ return atomic_notifier_chain_register(&x->chg_notifier, nb);
+}
+
+static inline void
+usb_charger_unregister_notifier(struct usb_phy *x, struct notifier_block *nb)
+{
+ atomic_notifier_chain_unregister(&x->chg_notifier, nb);
+}
+
static inline const char *usb_phy_type_string(enum usb_phy_type type)
{
switch (type) {
--
1.9.1
\
 
 \ /
  Last update: 2022-11-14 13:57    [W:0.082 / U:0.056 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site