[PATCH] usb: phy: add dedicated notifier for charger events

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
---
 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




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux