Skip to content

Commit e842b84

Browse files
neilbrownFelipe Balbi
authored andcommitted
usb: phy: Add interface to get phy give of device_node.
Split the "get phy from device_node" functionality out of "get phy by phandle" so it can be used directly. This is useful when a battery-charger is intimately associated with a particular phy but handled by a separate driver. The charger can find the device_node based on sibling relationships without the need for a redundant declaration in the devicetree description. As a peripheral that gets a phy will often want to register a notifier block, and de-register it later, that functionality is included so the de-registration is automatic. Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Felipe Balbi <balbi@ti.com>
1 parent 11bece5 commit e842b84

File tree

2 files changed

+72
-27
lines changed

2 files changed

+72
-27
lines changed

drivers/usb/phy/phy.c

Lines changed: 70 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ static LIST_HEAD(phy_list);
2222
static LIST_HEAD(phy_bind_list);
2323
static DEFINE_SPINLOCK(phy_lock);
2424

25+
struct phy_devm {
26+
struct usb_phy *phy;
27+
struct notifier_block *nb;
28+
};
29+
2530
static struct usb_phy *__usb_find_phy(struct list_head *list,
2631
enum usb_phy_type type)
2732
{
@@ -79,6 +84,15 @@ static void devm_usb_phy_release(struct device *dev, void *res)
7984
usb_put_phy(phy);
8085
}
8186

87+
static void devm_usb_phy_release2(struct device *dev, void *_res)
88+
{
89+
struct phy_devm *res = _res;
90+
91+
if (res->nb)
92+
usb_unregister_notifier(res->phy, res->nb);
93+
usb_put_phy(res->phy);
94+
}
95+
8296
static int devm_usb_phy_match(struct device *dev, void *res, void *match_data)
8397
{
8498
struct usb_phy **phy = res;
@@ -153,40 +167,30 @@ struct usb_phy *usb_get_phy(enum usb_phy_type type)
153167
EXPORT_SYMBOL_GPL(usb_get_phy);
154168

155169
/**
156-
* devm_usb_get_phy_by_phandle - find the USB PHY by phandle
170+
* devm_usb_get_phy_by_node - find the USB PHY by device_node
157171
* @dev - device that requests this phy
158-
* @phandle - name of the property holding the phy phandle value
159-
* @index - the index of the phy
172+
* @node - the device_node for the phy device.
173+
* @nb - a notifier_block to register with the phy.
160174
*
161-
* Returns the phy driver associated with the given phandle value,
175+
* Returns the phy driver associated with the given device_node,
162176
* after getting a refcount to it, -ENODEV if there is no such phy or
163-
* -EPROBE_DEFER if there is a phandle to the phy, but the device is
164-
* not yet loaded. While at that, it also associates the device with
177+
* -EPROBE_DEFER if the device is not yet loaded. While at that, it
178+
* also associates the device with
165179
* the phy using devres. On driver detach, release function is invoked
166180
* on the devres data, then, devres data is freed.
167181
*
168-
* For use by USB host and peripheral drivers.
182+
* For use by peripheral drivers for devices related to a phy,
183+
* such as a charger.
169184
*/
170-
struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
171-
const char *phandle, u8 index)
185+
struct usb_phy *devm_usb_get_phy_by_node(struct device *dev,
186+
struct device_node *node,
187+
struct notifier_block *nb)
172188
{
173-
struct usb_phy *phy = ERR_PTR(-ENOMEM), **ptr;
189+
struct usb_phy *phy = ERR_PTR(-ENOMEM);
190+
struct phy_devm *ptr;
174191
unsigned long flags;
175-
struct device_node *node;
176192

177-
if (!dev->of_node) {
178-
dev_dbg(dev, "device does not have a device node entry\n");
179-
return ERR_PTR(-EINVAL);
180-
}
181-
182-
node = of_parse_phandle(dev->of_node, phandle, index);
183-
if (!node) {
184-
dev_dbg(dev, "failed to get %s phandle in %s node\n", phandle,
185-
dev->of_node->full_name);
186-
return ERR_PTR(-ENODEV);
187-
}
188-
189-
ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL);
193+
ptr = devres_alloc(devm_usb_phy_release2, sizeof(*ptr), GFP_KERNEL);
190194
if (!ptr) {
191195
dev_dbg(dev, "failed to allocate memory for devres\n");
192196
goto err0;
@@ -205,8 +209,10 @@ struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
205209
devres_free(ptr);
206210
goto err1;
207211
}
208-
209-
*ptr = phy;
212+
if (nb)
213+
usb_register_notifier(phy, nb);
214+
ptr->phy = phy;
215+
ptr->nb = nb;
210216
devres_add(dev, ptr);
211217

212218
get_device(phy->dev);
@@ -215,10 +221,47 @@ struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
215221
spin_unlock_irqrestore(&phy_lock, flags);
216222

217223
err0:
218-
of_node_put(node);
219224

220225
return phy;
221226
}
227+
EXPORT_SYMBOL_GPL(devm_usb_get_phy_by_node);
228+
229+
/**
230+
* devm_usb_get_phy_by_phandle - find the USB PHY by phandle
231+
* @dev - device that requests this phy
232+
* @phandle - name of the property holding the phy phandle value
233+
* @index - the index of the phy
234+
*
235+
* Returns the phy driver associated with the given phandle value,
236+
* after getting a refcount to it, -ENODEV if there is no such phy or
237+
* -EPROBE_DEFER if there is a phandle to the phy, but the device is
238+
* not yet loaded. While at that, it also associates the device with
239+
* the phy using devres. On driver detach, release function is invoked
240+
* on the devres data, then, devres data is freed.
241+
*
242+
* For use by USB host and peripheral drivers.
243+
*/
244+
struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
245+
const char *phandle, u8 index)
246+
{
247+
struct device_node *node;
248+
struct usb_phy *phy;
249+
250+
if (!dev->of_node) {
251+
dev_dbg(dev, "device does not have a device node entry\n");
252+
return ERR_PTR(-EINVAL);
253+
}
254+
255+
node = of_parse_phandle(dev->of_node, phandle, index);
256+
if (!node) {
257+
dev_dbg(dev, "failed to get %s phandle in %s node\n", phandle,
258+
dev->of_node->full_name);
259+
return ERR_PTR(-ENODEV);
260+
}
261+
phy = devm_usb_get_phy_by_node(dev, node, NULL);
262+
of_node_put(node);
263+
return phy;
264+
}
222265
EXPORT_SYMBOL_GPL(devm_usb_get_phy_by_phandle);
223266

224267
/**

include/linux/usb/phy.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@ extern struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index);
205205
extern struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index);
206206
extern struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
207207
const char *phandle, u8 index);
208+
extern struct usb_phy *devm_usb_get_phy_by_node(struct device *dev,
209+
struct device_node *node, struct notifier_block *nb);
208210
extern void usb_put_phy(struct usb_phy *);
209211
extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x);
210212
extern int usb_bind_phy(const char *dev_name, u8 index,

0 commit comments

Comments
 (0)