USB: Add support for multiple PHYs of same type
Subsystems (6)
v2 cover USB: Add support for multiple PHYs of same type
This patch series adds support for adding multiple PHY's (of same type). The binding information has to be present in the PHY library (otg.c) in order for it to return the appropriate PHY whenever the USB controller request for the PHY. So added a new API usb_bind_phy() to pass the binding information. This API should be called by platform specific initialization code.
So the binding should be done something like usb_bind_phy("musb-hdrc.0.auto", 0, "omap-usb2.1.auto"); specifying the USB controller device name, index, and the PHY device name.
I have done this binding for OMAP platforms, but it should be done for all the platforms.
After this design, the phy can be got by passing the USB controller device pointer and the index.
Changes from v1:
* made *usb_bind_phy* return an interget instead of struct usb_phy_bind *
* made *__usb_find_phy_dev* return -EPROBE_DEFER if the usb_phy_bind entry has device names filled but phy is NULL.
* Added of_node_put(node) corresponding to of_parse_phandle.
Developed this patch series ongit://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git xceiv after applying "usb: musb: add driver for control module" patch series and "ARM: dts: omap: add dt data for MUSB"
I've kept this patch series and all the patch series to follow in a single branchgit://gitorious.org/linux-usb/linux-usb.git omap5-with-palmas (changes up to 23b4dfa2ab7052569cd88acc6383c4b1a8e8a482)
Did basic enumeration testing in omap4 panda and omap3 beagle.
Kishon Vijay Abraham I (6):
usb: otg: Add an API to bind the USB controller and PHY
usb: otg: utils: add facilities in phy lib to support multiple PHYs
of same type
ARM: OMAP: USB: Add phy binding information
drivers: usb: musb: omap: make use of the new PHY lib APIs
usb: otg: add device tree support to otg library
USB: MUSB: OMAP: get PHY by phandle for dt boot
arch/arm/mach-omap2/board-2430sdp.c | 2 + arch/arm/mach-omap2/board-3430sdp.c | 2 + arch/arm/mach-omap2/board-4430sdp.c | 2 + arch/arm/mach-omap2/board-cm-t35.c | 2 + arch/arm/mach-omap2/board-devkit8000.c | 2 + arch/arm/mach-omap2/board-igep0020.c | 2 + arch/arm/mach-omap2/board-ldp.c | 2 + arch/arm/mach-omap2/board-omap3beagle.c | 2 + arch/arm/mach-omap2/board-omap3evm.c | 2 + arch/arm/mach-omap2/board-omap3logic.c | 2 + arch/arm/mach-omap2/board-omap3pandora.c | 2 + arch/arm/mach-omap2/board-omap3stalker.c | 2 + arch/arm/mach-omap2/board-omap3touchbook.c | 2 + arch/arm/mach-omap2/board-omap4panda.c | 2 + arch/arm/mach-omap2/board-overo.c | 2 + arch/arm/mach-omap2/board-rm680.c | 2 + arch/arm/mach-omap2/board-zoom-peripherals.c | 2 + drivers/usb/musb/omap2430.c | 7 +- drivers/usb/otg/otg.c | 235 +++++++++++++++++++++++++- drivers/usb/otg/twl4030-usb.c | 3 +- drivers/usb/phy/omap-usb2.c | 3 +- include/linux/usb/phy.h | 43 +++++ 22 files changed, 321 insertions(+), 4 deletions(-)
Signature · 1 line
1.7.9.5
PATCH v2 1/6 usb: otg: Add an API to bind the USB controller and PHY
In order to support platforms which has multiple PHY's (of same type) and which has multiple USB controllers, a new design is adopted wherin the binding information (between the PHY and the USB controller) should be passed to the PHY library from platform specific file (board file).
So added a new API to pass the binding information.
--- drivers/usb/otg/otg.c | 37 +++++++++++++++++++++++++++++++++++++ include/linux/usb/phy.h | 22 ++++++++++++++++++++++ 2 files changed, 59 insertions(+)
drivers/usb/otg/otg.c +37 -0
@@ -18,6 +18,7 @@#include <linux/usb/otg.h> static LIST_HEAD (phy_list); +static LIST_HEAD (phy_bind_list);static DEFINE_SPINLOCK (phy_lock); static struct usb_phy *__usb_find_phy(struct list_head *list,
@@ -201,6 +202,42 @@ void usb_remove_phy(struct usb_phy *x) }EXPORT_SYMBOL (usb_remove_phy); +/** +* usb_bind_phy - bind the phy and the controller that uses the phy +* @dev_name: the device name of the device that will bind to the phy +* @index: index to specify the port number +* @phy_dev_name: the device name of the phy +* +* Fills the phy_bind structure with the dev_name and phy_dev_name. This will +* be used when the phy driver registers the phy and when the controller +* requests this phy. +* +* To be used by platform specific initialization code. +*/ +int __init usb_bind_phy (const char *dev_name,u8 index, +const char *phy_dev_name) +{ +struct usb_phy_bind *phy_bind; +unsigned long flags; + + phy_bind =kzalloc (sizeof (*phy_bind),GFP_KERNEL ); +if (!phy_bind) { +pr_err ("phy_bind(): No memory for phy_bind" ); +return -ENOMEM ; + } + + phy_bind->dev_name = dev_name; + phy_bind->phy_dev_name = phy_dev_name; + phy_bind->index = index; + +spin_lock_irqsave (&phy_lock, flags); +list_add_tail (&phy_bind->list, &phy_bind_list); +spin_unlock_irqrestore (&phy_lock, flags); + +return 0 ; +} +EXPORT_SYMBOL_GPL (usb_bind_phy); +const char *otg_state_string (enum usb_otg_state state) {switch (state) {
include/linux/usb/phy.h +22 -0
@@ -106,6 +106,21 @@ struct usb_phy { enum usb_device_speed speed); }; +/** +* struct usb_phy_bind - represent the binding for the phy +* @dev_name: the device name of the device that will bind to the phy +* @phy_dev_name: the device name of the phy +* @index: used if a single controller uses multiple phys +* @phy: reference to the phy +* @list: to maintain a linked list of the binding information +*/ +struct usb_phy_bind { +const char *dev_name; +const char *phy_dev_name; +u8 index; +struct usb_phy *phy; +struct list_head list; +};/* for board-specific init logic */ extern int usb_add_phy (struct usb_phy *,enum usb_phy_type type);
@@ -151,6 +166,8 @@ extern struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type);extern void usb_put_phy (struct usb_phy *);extern void devm_usb_put_phy (struct device *dev,struct usb_phy *x); +extern int usb_bind_phy (const char *dev_name,u8 index, +const char *phy_dev_name);#else static inline struct usb_phy *usb_get_phy (enum usb_phy_type type) {
@@ -171,6 +188,11 @@ static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x) { } +static inline int usb_bind_phy (const char *dev_name,u8 index, +const char *phy_dev_name) +{ +return NULL ; +}#endif static inline int
Signature · 1 line
1.7.9.5
Re: [PATCH v2 1/6] usb: otg: Add an API to bind the USB controller and PHY
Quoted 39 lines · Kishon Vijay Abraham I
In order to support platforms which has multiple PHY's (of same type) and which has multiple USB controllers, a new design is adopted wherin the binding information (between the PHY and the USB controller) should be passed to the PHY library from platform specific file (board file).
So added a new API to pass the binding information.Signed-off-by Kishon Vijay Abraham I <[email protected]>--- drivers/usb/otg/otg.c | 37 +++++++++++++++++++++++++++++++++++++ include/linux/usb/phy.h | 22 ++++++++++++++++++++++ 2 files changed, 59 insertions(+)drivers/usb/otg/otg.c +12
-0@@ -18,6 +18,7 @@#include <linux/usb/otg.h> static LIST_HEAD (phy_list); +static LIST_HEAD (phy_bind_list);static DEFINE_SPINLOCK (phy_lock); static struct usb_phy *__usb_find_phy(struct list_head *list,@@ -201,6 +202,42 @@ void usb_remove_phy(struct usb_phy *x) }EXPORT_SYMBOL (usb_remove_phy); +/** +* usb_bind_phy - bind the phy and the controller that uses the phy +* @dev_name: the device name of the device that will bind to the phy +* @index: index to specify the port number +* @phy_dev_name: the device name of the phy +* +* Fills the phy_bind structure with the dev_name and phy_dev_name. This will +* be used when the phy driver registers the phy and when the controller +* requests this phy. +* +* To be used by platform specific initialization code.
drivers/usb/otg/otg.c void usb_remove_phy(struct usb_phy *x) · line 225
Quoted 10 lines
drivers/usb/otg/otg.c +10
-0+*/ +int __init usb_bind_phy (const char *dev_name,u8 index, +const char *phy_dev_name) +{ +struct usb_phy_bind *phy_bind; +unsigned long flags; + + phy_bind =kzalloc (sizeof (*phy_bind),GFP_KERNEL ); +if (!phy_bind) { +pr_err ("phy_bind(): No memory for phy_bind" );
nitpick. Function name is usb_bind_phy() and you don't need to mention it twice ;).
Is it even needed to print here as the user would most likely print it anyways. At least the user can decide if it needs to be printed or not.
Quoted 23 lines
drivers/usb/otg/otg.c +15
-0+return -ENOMEM ; + } + + phy_bind->dev_name = dev_name; + phy_bind->phy_dev_name = phy_dev_name; + phy_bind->index = index; + +spin_lock_irqsave (&phy_lock, flags); +list_add_tail (&phy_bind->list, &phy_bind_list); +spin_unlock_irqrestore (&phy_lock, flags); + +return 0 ; +} +EXPORT_SYMBOL_GPL (usb_bind_phy); +const char *otg_state_string (enum usb_otg_state state) {switch (state) {include/linux/usb/phy.h +0
-0
include/linux/usb/phy.h struct usb_phy { · line 107
Quoted 2 lines
include/linux/usb/phy.h +0
-0@@ -106,6 +106,21 @@ struct usb_phy { enum usb_device_speed speed); };
cheers,
-roger
Re: [PATCH v2 1/6] usb: otg: Add an API to bind the USB controller and PHY
In reply to Kishon Vijay Abraham IQuoted 103 lines · Kishon Vijay Abraham I
In order to support platforms which has multiple PHY's (of same type) and which has multiple USB controllers, a new design is adopted wherin the binding information (between the PHY and the USB controller) should be passed to the PHY library from platform specific file (board file).
So added a new API to pass the binding information.Signed-off-by Kishon Vijay Abraham I <[email protected]>--- drivers/usb/otg/otg.c | 37 +++++++++++++++++++++++++++++++++++++ include/linux/usb/phy.h | 22 ++++++++++++++++++++++ 2 files changed, 59 insertions(+)drivers/usb/otg/otg.c +37
-0@@ -18,6 +18,7 @@#include <linux/usb/otg.h> static LIST_HEAD (phy_list); +static LIST_HEAD (phy_bind_list);static DEFINE_SPINLOCK (phy_lock); static struct usb_phy *__usb_find_phy(struct list_head *list,@@ -201,6 +202,42 @@ void usb_remove_phy(struct usb_phy *x) }EXPORT_SYMBOL (usb_remove_phy); +/** +* usb_bind_phy - bind the phy and the controller that uses the phy +* @dev_name: the device name of the device that will bind to the phy +* @index: index to specify the port number +* @phy_dev_name: the device name of the phy +* +* Fills the phy_bind structure with the dev_name and phy_dev_name. This will +* be used when the phy driver registers the phy and when the controller +* requests this phy. +* +* To be used by platform specific initialization code. +*/ +int __init usb_bind_phy (const char *dev_name,u8 index, +const char *phy_dev_name) +{ +struct usb_phy_bind *phy_bind; +unsigned long flags; + + phy_bind =kzalloc (sizeof (*phy_bind),GFP_KERNEL ); +if (!phy_bind) { +pr_err ("phy_bind(): No memory for phy_bind" ); +return -ENOMEM ; + } + + phy_bind->dev_name = dev_name; + phy_bind->phy_dev_name = phy_dev_name; + phy_bind->index = index; + +spin_lock_irqsave (&phy_lock, flags); +list_add_tail (&phy_bind->list, &phy_bind_list); +spin_unlock_irqrestore (&phy_lock, flags); + +return 0 ; +} +EXPORT_SYMBOL_GPL (usb_bind_phy); +const char *otg_state_string (enum usb_otg_state state) {switch (state) {include/linux/usb/phy.h +17
-0@@ -106,6 +106,21 @@ struct usb_phy { enum usb_device_speed speed); }; +/** +* struct usb_phy_bind - represent the binding for the phy +* @dev_name: the device name of the device that will bind to the phy +* @phy_dev_name: the device name of the phy +* @index: used if a single controller uses multiple phys +* @phy: reference to the phy +* @list: to maintain a linked list of the binding information +*/ +struct usb_phy_bind { +const char *dev_name; +const char *phy_dev_name; +u8 index; +struct usb_phy *phy; +struct list_head list; +};/* for board-specific init logic */ extern int usb_add_phy (struct usb_phy *,enum usb_phy_type type);@@ -151,6 +166,8 @@ extern struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type);extern void usb_put_phy (struct usb_phy *);extern void devm_usb_put_phy (struct device *dev,struct usb_phy *x); +extern int usb_bind_phy (const char *dev_name,u8 index, +const char *phy_dev_name);#else static inline struct usb_phy *usb_get_phy (enum usb_phy_type type) {
include/linux/usb/phy.h static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x) · line 194
Quoted 7 lines
include/linux/usb/phy.h +4
-0@@ -171,6 +188,11 @@ static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x) { } +static inline int usb_bind_phy (const char *dev_name,u8 index, +const char *phy_dev_name) +{ +return NULL ;
The return value looks bogus.
Marc
Quoted 5 lines
include/linux/usb/phy.h +1
-0+}#endif static inline int
Signature · 12 lines
Pengutronix e.K. | Marc Kleine-Budde | Industrial Linux Solutions | Phone: +49-231-2826-924 | Vertretung West/Dortmund | Fax: +49-5121-206917-5555 | Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 263 bytes Desc: OpenPGP digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130201/7ccbeae2/attachment.sig>
Re: [PATCH v2 1/6] usb: otg: Add an API to bind the USB controller and PHY
Hi,
Quoted 107 lines · Marc Kleine-Budde
Quoted 106 lines · Kishon Vijay Abraham I
In order to support platforms which has multiple PHY's (of same type) and which has multiple USB controllers, a new design is adopted wherin the binding information (between the PHY and the USB controller) should be passed to the PHY library from platform specific file (board file).
So added a new API to pass the binding information.Signed-off-by Kishon Vijay Abraham I <[email protected]>--- drivers/usb/otg/otg.c | 37 +++++++++++++++++++++++++++++++++++++ include/linux/usb/phy.h | 22 ++++++++++++++++++++++ 2 files changed, 59 insertions(+)drivers/usb/otg/otg.c +37
-0@@ -18,6 +18,7 @@#include <linux/usb/otg.h> static LIST_HEAD (phy_list); +static LIST_HEAD (phy_bind_list);static DEFINE_SPINLOCK (phy_lock); static struct usb_phy *__usb_find_phy(struct list_head *list,@@ -201,6 +202,42 @@ void usb_remove_phy(struct usb_phy *x) }EXPORT_SYMBOL (usb_remove_phy); +/** +* usb_bind_phy - bind the phy and the controller that uses the phy +* @dev_name: the device name of the device that will bind to the phy +* @index: index to specify the port number +* @phy_dev_name: the device name of the phy +* +* Fills the phy_bind structure with the dev_name and phy_dev_name. This will +* be used when the phy driver registers the phy and when the controller +* requests this phy. +* +* To be used by platform specific initialization code. +*/ +int __init usb_bind_phy (const char *dev_name,u8 index, +const char *phy_dev_name) +{ +struct usb_phy_bind *phy_bind; +unsigned long flags; + + phy_bind =kzalloc (sizeof (*phy_bind),GFP_KERNEL ); +if (!phy_bind) { +pr_err ("phy_bind(): No memory for phy_bind" ); +return -ENOMEM ; + } + + phy_bind->dev_name = dev_name; + phy_bind->phy_dev_name = phy_dev_name; + phy_bind->index = index; + +spin_lock_irqsave (&phy_lock, flags); +list_add_tail (&phy_bind->list, &phy_bind_list); +spin_unlock_irqrestore (&phy_lock, flags); + +return 0 ; +} +EXPORT_SYMBOL_GPL (usb_bind_phy); +const char *otg_state_string (enum usb_otg_state state) {switch (state) {include/linux/usb/phy.h +17
-0@@ -106,6 +106,21 @@ struct usb_phy { enum usb_device_speed speed); }; +/** +* struct usb_phy_bind - represent the binding for the phy +* @dev_name: the device name of the device that will bind to the phy +* @phy_dev_name: the device name of the phy +* @index: used if a single controller uses multiple phys +* @phy: reference to the phy +* @list: to maintain a linked list of the binding information +*/ +struct usb_phy_bind { +const char *dev_name; +const char *phy_dev_name; +u8 index; +struct usb_phy *phy; +struct list_head list; +};/* for board-specific init logic */ extern int usb_add_phy (struct usb_phy *,enum usb_phy_type type);@@ -151,6 +166,8 @@ extern struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type);extern void usb_put_phy (struct usb_phy *);extern void devm_usb_put_phy (struct device *dev,struct usb_phy *x); +extern int usb_bind_phy (const char *dev_name,u8 index, +const char *phy_dev_name);#else static inline struct usb_phy *usb_get_phy (enum usb_phy_type type) {@@ -171,6 +188,11 @@ static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x) { }
Quoted 6 lines
include/linux/usb/phy.h static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x) · line 194
Quoted 4 lines
include/linux/usb/phy.h +4
-0+static inline int usb_bind_phy (const char *dev_name,u8 index, +const char *phy_dev_name) +{ +return NULL ;The return value looks bogus.
Yes. Felipe has fixed this and has merged the patch already.
Thanks
Kishon
PATCH v2 2/6 usb: otg: utils: add facilities in phy lib to support multiple PHYs of same type
In reply to Kishon Vijay Abraham IIn order to add support for multipe PHY's of the same type, new API's for adding PHY and getting PHY has been added. Now the binding information for the PHY and controller should be done in platform file using usb_bind_phy API. And for getting a PHY, the device pointer of the USB controller and an index should be passed. Based on the binding information that is added in the platform file, usb_get_phy_dev will return the appropriate PHY.
Already existing API's to add and get phy by type is not removed. These API's are deprecated and will be removed once all the platforms start to use the new API.
--- drivers/usb/otg/otg.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++- include/linux/usb/phy.h | 13 ++++++ 2 files changed, 130 insertions(+), 1 deletion(-)
drivers/usb/otg/otg.c +117 -1
@@ -36,6 +36,24 @@ static struct usb_phy *__usb_find_phy(struct list_head *list,return ERR_PTR (-ENODEV ); } +static struct usb_phy *__usb_find_phy_dev (struct device *dev, +struct list_head *list,u8 index) +{ +struct usb_phy_bind *phy_bind =NULL ; + +list_for_each_entry (phy_bind, list, list) { +if (!(strcmp (phy_bind->dev_name,dev_name (dev))) && + phy_bind->index == index) { +if (phy_bind->phy) +return phy_bind->phy; +else +return ERR_PTR (-EPROBE_DEFER ); + } + } + +return ERR_PTR (-ENODEV ); +} +static void devm_usb_phy_release (struct device *dev,void *res) {struct usb_phy *phy = *(struct usb_phy **)res;
@@ -112,6 +130,69 @@ err0:EXPORT_SYMBOL (usb_get_phy);/** +* usb_get_phy_dev - find the USB PHY +* @dev - device that requests this phy +* @index - the index of the phy +* +* Returns the phy driver, after getting a refcount to it; or +* -ENODEV if there is no such phy. The caller is responsible for +* calling usb_put_phy() to release that count. +* +* For use by USB host and peripheral drivers. +*/ +struct usb_phy *usb_get_phy_dev (struct device *dev,u8 index) +{ +struct usb_phy *phy =NULL ; +unsigned long flags; + +spin_lock_irqsave (&phy_lock, flags); + + phy =__usb_find_phy_dev (dev, &phy_bind_list, index); +if (IS_ERR (phy)) { +pr_err ("unable to find transceiver\n" ); + goto err0; + } + +get_device (phy->dev); + +err0: +spin_unlock_irqrestore (&phy_lock, flags); + +return phy; +} +EXPORT_SYMBOL (usb_get_phy_dev); + +/** +* devm_usb_get_phy_dev - find the USB PHY using device ptr and index +* @dev - device that requests this phy +* @index - the index of the phy +* +* Gets the phy using usb_get_phy_dev(), and associates a device with it using +* devres. On driver detach, release function is invoked on the devres data, +* then, devres data is freed. +* +* For use by USB host and peripheral drivers. +*/ +struct usb_phy *devm_usb_get_phy_dev (struct device *dev,u8 index) +{ +struct usb_phy **ptr, *phy; + + ptr =devres_alloc (devm_usb_phy_release,sizeof (*ptr),GFP_KERNEL ); +if (!ptr) +return NULL ; + + phy =usb_get_phy_dev (dev, index); +if (!IS_ERR (phy)) { + *ptr = phy; +devres_add (dev, ptr); + }else +devres_free (ptr); + +return phy; +} +EXPORT_SYMBOL (devm_usb_get_phy_dev); + +/** * devm_usb_put_phy - release the USB PHY * @dev - device that wants to release this phy * @phy - the phy returned by devm_usb_get_phy()
@@ -186,6 +267,36 @@ out:EXPORT_SYMBOL (usb_add_phy);/** +* usb_add_phy_dev - declare the USB PHY +* @x: the USB phy to be used; or NULL +* +* This call is exclusively for use by phy drivers, which +* coordinate the activities of drivers for host and peripheral +* controllers, and in some cases for VBUS current regulation. +*/ +int usb_add_phy_dev (struct usb_phy *x) +{ +struct usb_phy_bind *phy_bind; +unsigned long flags; + +if (!x->dev) { +dev_err (x->dev,"no device provided for PHY\n" ); +return -EINVAL ; + } + +spin_lock_irqsave (&phy_lock, flags); +list_for_each_entry (phy_bind, &phy_bind_list, list) +if (!(strcmp (phy_bind->phy_dev_name,dev_name (x->dev)))) + phy_bind->phy = x; + +list_add_tail (&x->head, &phy_list); + +spin_unlock_irqrestore (&phy_lock, flags); +return 0 ; +} +EXPORT_SYMBOL (usb_add_phy_dev); + +/** * usb_remove_phy - remove the OTG PHY * @x: the USB OTG PHY to be removed; *
@@ -194,10 +305,15 @@ EXPORT_SYMBOL(usb_add_phy);void usb_remove_phy (struct usb_phy *x) {unsigned long flags; +struct usb_phy_bind *phy_bind;spin_lock_irqsave (&phy_lock, flags); -if (x) +if (x) { +list_for_each_entry (phy_bind, &phy_bind_list, list) +if (phy_bind->phy == x) + phy_bind->phy =NULL ;list_del (&x->head); + }spin_unlock_irqrestore (&phy_lock, flags); }EXPORT_SYMBOL (usb_remove_phy);
include/linux/usb/phy.h +13 -0
@@ -124,6 +124,7 @@ struct usb_phy_bind {/* for board-specific init logic */ extern int usb_add_phy (struct usb_phy *,enum usb_phy_type type); +extern int usb_add_phy_dev (struct usb_phy *);extern void usb_remove_phy (struct usb_phy *);/* helpers for direct access thru low-level io interface */
@@ -164,6 +165,8 @@ usb_phy_shutdown(struct usb_phy *x)extern struct usb_phy *usb_get_phy (enum usb_phy_type type);extern struct usb_phy *devm_usb_get_phy (struct device *dev,enum usb_phy_type type); +extern struct usb_phy *usb_get_phy_dev (struct device *dev,u8 index); +extern struct usb_phy *devm_usb_get_phy_dev (struct device *dev,u8 index);extern void usb_put_phy (struct usb_phy *);extern void devm_usb_put_phy (struct device *dev,struct usb_phy *x); extern int usb_bind_phy(const char *dev_name, u8 index,
@@ -180,6 +183,16 @@ static inline struct usb_phy *devm_usb_get_phy(struct device *dev,return NULL ; } +static inline struct usb_phy *usb_get_phy_dev (struct device *dev,u8 index) +{ +return NULL ; +} + +static inline struct usb_phy *devm_usb_get_phy_dev (struct device *dev,u8 index) +{ +return NULL ; +} +static inline void usb_put_phy (struct usb_phy *x) { }
Signature · 1 line
1.7.9.5
Re: [PATCH v2 2/6] usb: otg: utils: add facilities in phy lib to support multiple PHYs of same type
Quoted 47 lines · Kishon Vijay Abraham I
In order to add support for multipe PHY's of the same type, new API's for adding PHY and getting PHY has been added. Now the binding information for the PHY and controller should be done in platform file using
usb_bind_phyAPI. And for getting a PHY, the device pointer of the USB controller and an index should be passed. Based on the binding information that is added in the platform file,usb_get_phy_devwill return the appropriate PHY.
Already existing API's to add and get phy by type is not removed. These API's are deprecated and will be removed once all the platforms start to use the new API.Signed-off-by Kishon Vijay Abraham I <[email protected]>--- drivers/usb/otg/otg.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++- include/linux/usb/phy.h | 13 ++++++ 2 files changed, 130 insertions(+), 1 deletion(-)drivers/usb/otg/otg.c +18
-0@@ -36,6 +36,24 @@ static struct usb_phy *__usb_find_phy(struct list_head *list,return ERR_PTR (-ENODEV ); } +static struct usb_phy *__usb_find_phy_dev (struct device *dev, +struct list_head *list,u8 index) +{ +struct usb_phy_bind *phy_bind =NULL ; + +list_for_each_entry (phy_bind, list, list) { +if (!(strcmp (phy_bind->dev_name,dev_name (dev))) && + phy_bind->index == index) { +if (phy_bind->phy) +return phy_bind->phy; +else +return ERR_PTR (-EPROBE_DEFER ); + } + } + +return ERR_PTR (-ENODEV ); +} +static void devm_usb_phy_release (struct device *dev,void *res) {struct usb_phy *phy = *(struct usb_phy **)res;
drivers/usb/otg/otg.c err0: · line 137
Quoted 8 lines
drivers/usb/otg/otg.c +5
-0@@ -112,6 +130,69 @@ err0:EXPORT_SYMBOL (usb_get_phy);/** +* usb_get_phy_dev - find the USB PHY +* @dev - device that requests this phy +* @index - the index of the phy +* +* Returns the phy driver, after getting a refcount to it; or
PHY driver or PHY device?
Quoted 5 lines
drivers/usb/otg/otg.c +5
-0+* -ENODEV if there is no such phy. The caller is responsible for +* calling usb_put_phy() to release that count. +* +* For use by USB host and peripheral drivers. +*/
drivers/usb/otg/otg.c err0: · line 152
Quoted 10 lines
drivers/usb/otg/otg.c +10
-0+struct usb_phy *usb_get_phy_dev (struct device *dev,u8 index) +{ +struct usb_phy *phy =NULL ; +unsigned long flags; + +spin_lock_irqsave (&phy_lock, flags); + + phy =__usb_find_phy_dev (dev, &phy_bind_list, index); +if (IS_ERR (phy)) { +pr_err ("unable to find transceiver\n" );
I would suggest not to print and leave it to the user. This print "unable to find transceiver" gives no valuable information/context.
Also -EPROBE_DEFER is a valid case where this message must not be printed.
Quoted 47 lines
drivers/usb/otg/otg.c +43
-0+ goto err0; + } + +get_device (phy->dev); + +err0: +spin_unlock_irqrestore (&phy_lock, flags); + +return phy; +} +EXPORT_SYMBOL (usb_get_phy_dev); + +/** +* devm_usb_get_phy_dev - find the USB PHY using device ptr and index +* @dev - device that requests this phy +* @index - the index of the phy +* +* Gets the phy using usb_get_phy_dev(), and associates a device with it using +* devres. On driver detach, release function is invoked on the devres data, +* then, devres data is freed. +* +* For use by USB host and peripheral drivers. +*/ +struct usb_phy *devm_usb_get_phy_dev (struct device *dev,u8 index) +{ +struct usb_phy **ptr, *phy; + + ptr =devres_alloc (devm_usb_phy_release,sizeof (*ptr),GFP_KERNEL ); +if (!ptr) +return NULL ; + + phy =usb_get_phy_dev (dev, index); +if (!IS_ERR (phy)) { + *ptr = phy; +devres_add (dev, ptr); + }else +devres_free (ptr); + +return phy; +} +EXPORT_SYMBOL (devm_usb_get_phy_dev); + +/** * devm_usb_put_phy - release the USB PHY * @dev - device that wants to release this phy * @phy - the phy returned by devm_usb_get_phy()
drivers/usb/otg/otg.c out: · line 271
Quoted 5 lines
drivers/usb/otg/otg.c +2
-0@@ -186,6 +267,36 @@ out:EXPORT_SYMBOL (usb_add_phy);/** +* usb_add_phy_dev - declare the USB PHY +* @x: the USB phy to be used; or NULL
@phy is better than @x?
Quoted 20 lines
drivers/usb/otg/otg.c +20
-0+* +* This call is exclusively for use by phy drivers, which +* coordinate the activities of drivers for host and peripheral +* controllers, and in some cases for VBUS current regulation. +*/ +int usb_add_phy_dev (struct usb_phy *x) +{ +struct usb_phy_bind *phy_bind; +unsigned long flags; + +if (!x->dev) { +dev_err (x->dev,"no device provided for PHY\n" ); +return -EINVAL ; + } + +spin_lock_irqsave (&phy_lock, flags); +list_for_each_entry (phy_bind, &phy_bind_list, list) +if (!(strcmp (phy_bind->phy_dev_name,dev_name (x->dev)))) + phy_bind->phy = x; +
drivers/usb/otg/otg.c out: · line 301
Quoted 10 lines
drivers/usb/otg/otg.c +8
-0+list_add_tail (&x->head, &phy_list); + +spin_unlock_irqrestore (&phy_lock, flags); +return 0 ; +} +EXPORT_SYMBOL (usb_add_phy_dev); + +/** * usb_remove_phy - remove the OTG PHY * @x: the USB OTG PHY to be removed;
@phy
Also the PHY may not always be an OTG PHY, so remove OTG from description.
Quoted 47 lines
drivers/usb/otg/otg.c +6
-1* @@ -194,10 +305,15 @@ EXPORT_SYMBOL(usb_add_phy);void usb_remove_phy (struct usb_phy *x) {unsigned long flags; +struct usb_phy_bind *phy_bind;spin_lock_irqsave (&phy_lock, flags); -if (x) +if (x) { +list_for_each_entry (phy_bind, &phy_bind_list, list) +if (phy_bind->phy == x) + phy_bind->phy =NULL ;list_del (&x->head); + }spin_unlock_irqrestore (&phy_lock, flags); }EXPORT_SYMBOL (usb_remove_phy);include/linux/usb/phy.h +6
-0@@ -124,6 +124,7 @@ struct usb_phy_bind {/* for board-specific init logic */ extern int usb_add_phy (struct usb_phy *,enum usb_phy_type type); +extern int usb_add_phy_dev (struct usb_phy *);extern void usb_remove_phy (struct usb_phy *);/* helpers for direct access thru low-level io interface */ @@ -164,6 +165,8 @@ usb_phy_shutdown(struct usb_phy *x)extern struct usb_phy *usb_get_phy (enum usb_phy_type type);extern struct usb_phy *devm_usb_get_phy (struct device *dev,enum usb_phy_type type); +extern struct usb_phy *usb_get_phy_dev (struct device *dev,u8 index); +extern struct usb_phy *devm_usb_get_phy_dev (struct device *dev,u8 index);extern void usb_put_phy (struct usb_phy *);extern void devm_usb_put_phy (struct device *dev,struct usb_phy *x); extern int usb_bind_phy(const char *dev_name, u8 index,@@ -180,6 +183,16 @@ static inline struct usb_phy *devm_usb_get_phy(struct device *dev,return NULL ; } +static inline struct usb_phy *usb_get_phy_dev (struct device *dev,u8 index) +{ +return NULL ;
include/linux/usb/phy.h static inline struct usb_phy *devm_usb_get_phy(struct device *dev, · line 198
Quoted 10 lines
include/linux/usb/phy.h +7
-0+} + +static inline struct usb_phy *devm_usb_get_phy_dev (struct device *dev,u8 index) +{ +return NULL ; +} +static inline void usb_put_phy (struct usb_phy *x) { }
cheers,
-roger
Re: [PATCH v2 2/6] usb: otg: utils: add facilities in phy lib to support multiple PHYs of same type
In reply to Kishon Vijay Abraham IQuoted 59 lines · Kishon Vijay Abraham I
In order to add support for multipe PHY's of the same type, new API's for adding PHY and getting PHY has been added. Now the binding information for the PHY and controller should be done in platform file using
usb_bind_phyAPI. And for getting a PHY, the device pointer of the USB controller and an index should be passed. Based on the binding information that is added in the platform file,usb_get_phy_devwill return the appropriate PHY.
Already existing API's to add and get phy by type is not removed. These API's are deprecated and will be removed once all the platforms start to use the new API.Signed-off-by Kishon Vijay Abraham I <[email protected]>--- drivers/usb/otg/otg.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++- include/linux/usb/phy.h | 13 ++++++ 2 files changed, 130 insertions(+), 1 deletion(-)drivers/usb/otg/otg.c +27
-0@@ -36,6 +36,24 @@ static struct usb_phy *__usb_find_phy(struct list_head *list,return ERR_PTR (-ENODEV ); } +static struct usb_phy *__usb_find_phy_dev (struct device *dev, +struct list_head *list,u8 index) +{ +struct usb_phy_bind *phy_bind =NULL ; + +list_for_each_entry (phy_bind, list, list) { +if (!(strcmp (phy_bind->dev_name,dev_name (dev))) && + phy_bind->index == index) { +if (phy_bind->phy) +return phy_bind->phy; +else +return ERR_PTR (-EPROBE_DEFER ); + } + } + +return ERR_PTR (-ENODEV ); +} +static void devm_usb_phy_release (struct device *dev,void *res) {struct usb_phy *phy = *(struct usb_phy **)res;@@ -112,6 +130,69 @@ err0:EXPORT_SYMBOL (usb_get_phy);/** +* usb_get_phy_dev - find the USB PHY +* @dev - device that requests this phy +* @index - the index of the phy +* +* Returns the phy driver, after getting a refcount to it; or +* -ENODEV if there is no such phy. The caller is responsible for +* calling usb_put_phy() to release that count. +* +* For use by USB host and peripheral drivers.
drivers/usb/otg/otg.c err0: · line 151
Quoted 10 lines
drivers/usb/otg/otg.c +10
-0+*/ +struct usb_phy *usb_get_phy_dev (struct device *dev,u8 index) +{ +struct usb_phy *phy =NULL ; +unsigned long flags; + +spin_lock_irqsave (&phy_lock, flags); + + phy =__usb_find_phy_dev (dev, &phy_bind_list, index); +if (IS_ERR (phy)) {
You should probably lock the phy module in memory. See my patch "usb:
otg: use try_module_get in all usb_get_phy functions and add missing module_put".
Marc
Signature · 12 lines
Pengutronix e.K. | Marc Kleine-Budde | Industrial Linux Solutions | Phone: +49-231-2826-924 | Vertretung West/Dortmund | Fax: +49-5121-206917-5555 | Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 263 bytes Desc: OpenPGP digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130201/c716d5f4/attachment-0001.sig>
PATCH v2 3/6 ARM: OMAP: USB: Add phy binding information
In reply to Kishon Vijay Abraham IThis is w.r.t the changes in PHY library to support adding and getting multiple PHYs of the same type. In the new design, the binding information between the PHY and the USB controller should be specified in the platform specific initialization code. So it's been done here for OMAP platforms.
--- arch/arm/mach-omap2/board-2430sdp.c | 2 ++ arch/arm/mach-omap2/board-3430sdp.c | 2 ++ arch/arm/mach-omap2/board-4430sdp.c | 2 ++ arch/arm/mach-omap2/board-cm-t35.c | 2 ++ arch/arm/mach-omap2/board-devkit8000.c | 2 ++ arch/arm/mach-omap2/board-igep0020.c | 2 ++ arch/arm/mach-omap2/board-ldp.c | 2 ++ arch/arm/mach-omap2/board-omap3beagle.c | 2 ++ arch/arm/mach-omap2/board-omap3evm.c | 2 ++ arch/arm/mach-omap2/board-omap3logic.c | 2 ++ arch/arm/mach-omap2/board-omap3pandora.c | 2 ++ arch/arm/mach-omap2/board-omap3stalker.c | 2 ++ arch/arm/mach-omap2/board-omap3touchbook.c | 2 ++ arch/arm/mach-omap2/board-omap4panda.c | 2 ++ arch/arm/mach-omap2/board-overo.c | 2 ++ arch/arm/mach-omap2/board-rm680.c | 2 ++ arch/arm/mach-omap2/board-zoom-peripherals.c | 2 ++ 17 files changed, 34 insertions(+)
arch/arm/mach-omap2/board-2430sdp.c +2 -0
@@ -27,6 +27,7 @@#include <linux/clk.h> #include <linux/io.h> #include <linux/gpio.h> +#include <linux/usb/phy.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -263,6 +264,7 @@ static void __init omap_2430sdp_init(void)omap_hsmmc_init (mmc);omap_mux_init_signal ("usb0hs_stp" ,OMAP_PULL_ENA |OMAP_PULL_UP ); +usb_bind_phy ("musb-hdrc.0.auto" ,0 ,"twl4030_usb" );usb_musb_init (NULL );board_smc91x_init ();
arch/arm/mach-omap2/board-3430sdp.c +2 -0
@@ -25,6 +25,7 @@#include <linux/gpio.h> #include <linux/mmc/host.h> #include <linux/platform_data/spi-omap2-mcspi.h> +#include <linux/usb/phy.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -579,6 +580,7 @@ static void __init omap_3430sdp_init(void)omap_ads7846_init (1 , gpio_pendown,310 ,NULL );omap_serial_init ();omap_sdrc_init (hyb18m512160af6_sdrc_params,NULL ); +usb_bind_phy ("musb-hdrc.0.auto" ,0 ,"twl4030_usb" );usb_musb_init (NULL );board_smc91x_init ();board_flash_init (sdp_flash_partitions, chip_sel_3430,0 );
arch/arm/mach-omap2/board-4430sdp.c +2 -0
@@ -28,6 +28,7 @@#include <linux/leds_pwm.h> #include <linux/platform_data/omap4-keypad.h> #include <linux/usb/musb.h> +#include <linux/usb/phy.h> #include <asm/hardware/gic.h> #include <asm/mach-types.h>
@@ -696,6 +697,7 @@ static void __init omap_4430sdp_init(void)omap4_sdp4430_wifi_init ();omap4_twl6030_hsmmc_init (mmc); +usb_bind_phy ("musb-hdrc.0.auto" ,0 ,"omap-usb2.1.auto" );usb_musb_init (&musb_board_data); status =omap_ethernet_init ();
arch/arm/mach-omap2/board-cm-t35.c +2 -0
@@ -30,6 +30,7 @@#include <linux/regulator/fixed.h> #include <linux/regulator/machine.h> #include <linux/mmc/host.h> +#include <linux/usb/phy.h> #include <linux/spi/spi.h> #include <linux/spi/tdo24m.h>
@@ -724,6 +725,7 @@ static void __init cm_t3x_common_init(void)cm_t35_init_display ();omap_twl4030_audio_init ("cm-t3x" ); +usb_bind_phy ("musb-hdrc.0.auto" ,0 ,"twl4030_usb" );usb_musb_init (NULL );cm_t35_init_usbh ();cm_t35_init_camera ();
arch/arm/mach-omap2/board-devkit8000.c +2 -0
@@ -29,6 +29,7 @@#include <linux/mtd/partitions.h> #include <linux/mtd/nand.h> #include <linux/mmc/host.h> +#include <linux/usb/phy.h> #include <linux/regulator/machine.h> #include <linux/i2c/twl.h>
@@ -622,6 +623,7 @@ static void __init devkit8000_init(void)omap_ads7846_init (2 ,OMAP3_DEVKIT_TS_GPIO ,0 ,NULL ); +usb_bind_phy ("musb-hdrc.0.auto" ,0 ,"twl4030_usb" );usb_musb_init (NULL );usbhs_init (&usbhs_bdata); board_nand_init(devkit8000_nand_partitions,
arch/arm/mach-omap2/board-igep0020.c +2 -0
@@ -18,6 +18,7 @@#include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/input.h> +#include <linux/usb/phy.h> #include <linux/regulator/machine.h> #include <linux/regulator/fixed.h>
@@ -625,6 +626,7 @@ static void __init igep_init(void)omap_serial_init ();omap_sdrc_init (m65kxxxxam_sdrc_params, m65kxxxxam_sdrc_params); +usb_bind_phy ("musb-hdrc.0.auto" ,0 ,"twl4030_usb" );usb_musb_init (NULL );igep_flash_init ();
arch/arm/mach-omap2/board-ldp.c +2 -0
@@ -28,6 +28,7 @@#include <linux/io.h> #include <linux/smsc911x.h> #include <linux/mmc/host.h> +#include <linux/usb/phy.h> #include <linux/platform_data/spi-omap2-mcspi.h> #include <asm/mach-types.h>
@@ -418,6 +419,7 @@ static void __init omap_ldp_init(void)omap_ads7846_init (1 ,54 ,310 ,NULL );omap_serial_init ();omap_sdrc_init (NULL ,NULL ); +usb_bind_phy ("musb-hdrc.0.auto" ,0 ,"twl4030_usb" );usb_musb_init (NULL );board_nand_init (ldp_nand_partitions,ARRAY_SIZE (ldp_nand_partitions),ZOOM_NAND_CS ,0 , nand_default_timings);
arch/arm/mach-omap2/board-omap3beagle.c +2 -0
@@ -30,6 +30,7 @@#include <linux/mtd/partitions.h> #include <linux/mtd/nand.h> #include <linux/mmc/host.h> +#include <linux/usb/phy.h> #include <linux/regulator/machine.h> #include <linux/i2c/twl.h>
@@ -519,6 +520,7 @@ static void __init omap3_beagle_init(void)omap_sdrc_init (mt46h32m32lf6_sdrc_params, mt46h32m32lf6_sdrc_params); +usb_bind_phy ("musb-hdrc.0.auto" ,0 ,"twl4030_usb" );usb_musb_init (NULL );usbhs_init (&usbhs_bdata); board_nand_init(omap3beagle_nand_partitions,
arch/arm/mach-omap2/board-omap3evm.c +2 -0
@@ -41,6 +41,7 @@#include <linux/regulator/machine.h> #include <linux/mmc/host.h> #include <linux/export.h> +#include <linux/usb/phy.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -734,6 +735,7 @@ static void __init omap3_evm_init(void)omap_mux_init_gpio (135 ,OMAP_PIN_OUTPUT ); usbhs_bdata.reset_gpio_port[1 ] =135 ; } +usb_bind_phy ("musb-hdrc.0.auto" ,0 ,"twl4030_usb" );usb_musb_init (&musb_board_data);usbhs_init (&usbhs_bdata); board_nand_init(omap3evm_nand_partitions,
arch/arm/mach-omap2/board-omap3logic.c +2 -0
@@ -29,6 +29,7 @@#include <linux/i2c/twl.h> #include <linux/mmc/host.h> +#include <linux/usb/phy.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -215,6 +216,7 @@ static void __init omap3logic_init(void)board_mmc_init ();board_smsc911x_init (); +usb_bind_phy ("musb-hdrc.0.auto" ,0 ,"twl4030_usb" );usb_musb_init (NULL );/* Ensure SDRC pins are mux'd for self-refresh */
arch/arm/mach-omap2/board-omap3pandora.c +2 -0
@@ -35,6 +35,7 @@#include <linux/mmc/host.h> #include <linux/mmc/card.h> #include <linux/regulator/fixed.h> +#include <linux/usb/phy.h> #include <linux/platform_data/spi-omap2-mcspi.h> #include <asm/mach-types.h>
@@ -601,6 +602,7 @@ static void __init omap3pandora_init(void) ARRAY_SIZE(omap3pandora_spi_board_info));omap_ads7846_init (1 ,OMAP3_PANDORA_TS_GPIO ,0 ,NULL );usbhs_init (&usbhs_bdata); +usb_bind_phy ("musb-hdrc.0.auto" ,0 ,"twl4030_usb" );usb_musb_init (NULL );gpmc_nand_init (&pandora_nand_data,NULL );
arch/arm/mach-omap2/board-omap3stalker.c +2 -0
@@ -33,6 +33,7 @@#include <linux/interrupt.h> #include <linux/smsc911x.h> #include <linux/i2c/at24.h> +#include <linux/usb/phy.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -404,6 +405,7 @@ static void __init omap3_stalker_init(void)omap_serial_init ();omap_sdrc_init (mt46h32m32lf6_sdrc_params,NULL ); +usb_bind_phy ("musb-hdrc.0.auto" ,0 ,"twl4030_usb" );usb_musb_init (NULL );usbhs_init (&usbhs_bdata);omap_ads7846_init (1 ,OMAP3_STALKER_TS_GPIO ,310 ,NULL );
arch/arm/mach-omap2/board-omap3touchbook.c +2 -0
@@ -28,6 +28,7 @@#include <linux/mtd/partitions.h> #include <linux/mtd/nand.h> #include <linux/mmc/host.h> +#include <linux/usb/phy.h> #include <linux/platform_data/spi-omap2-mcspi.h> #include <linux/spi/spi.h>
@@ -365,6 +366,7 @@ static void __init omap3_touchbook_init(void)/* Touchscreen and accelerometer */ omap_ads7846_init (4 ,OMAP3_TS_GPIO ,310 , &ads7846_pdata); +usb_bind_phy ("musb-hdrc.0.auto" ,0 ,"twl4030_usb" );usb_musb_init (NULL );usbhs_init (&usbhs_bdata); board_nand_init(omap3touchbook_nand_partitions,
arch/arm/mach-omap2/board-omap4panda.c +2 -0
@@ -30,6 +30,7 @@#include <linux/regulator/fixed.h> #include <linux/ti_wilink_st.h> #include <linux/usb/musb.h> +#include <linux/usb/phy.h> #include <linux/wl12xx.h> #include <linux/platform_data/omap-abe-twl6040.h>
@@ -441,6 +442,7 @@ static void __init omap4_panda_init(void)omap_sdrc_init (NULL ,NULL );omap4_twl6030_hsmmc_init (mmc);omap4_ehci_init (); +usb_bind_phy ("musb-hdrc.0.auto" ,0 ,"omap-usb2.1.auto" );usb_musb_init (&musb_board_data);omap4_panda_display_init (); }
arch/arm/mach-omap2/board-overo.c +2 -0
@@ -36,6 +36,7 @@#include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> #include <linux/mmc/host.h> +#include <linux/usb/phy.h> #include <linux/platform_data/mtd-nand-omap2.h> #include <linux/platform_data/spi-omap2-mcspi.h>
@@ -499,6 +500,7 @@ static void __init overo_init(void) mt46h32m32lf6_sdrc_params);board_nand_init (overo_nand_partitions,ARRAY_SIZE (overo_nand_partitions),NAND_CS ,0 ,NULL ); +usb_bind_phy ("musb-hdrc.0.auto" ,0 ,"twl4030_usb" );usb_musb_init (NULL );usbhs_init (&usbhs_bdata);overo_spi_init ();
arch/arm/mach-omap2/board-rm680.c +2 -0
@@ -18,6 +18,7 @@#include <linux/regulator/machine.h> #include <linux/regulator/consumer.h> #include <linux/platform_data/mtd-onenand-omap2.h> +#include <linux/usb/phy.h> #include <asm/mach/arch.h> #include <asm/mach-types.h>
@@ -134,6 +135,7 @@ static void __init rm680_init(void) sdrc_params =nokia_get_sdram_timings ();omap_sdrc_init (sdrc_params, sdrc_params); +usb_bind_phy ("musb-hdrc.0.auto" ,0 ,"twl4030_usb" );usb_musb_init (NULL );rm680_peripherals_init (); }
arch/arm/mach-omap2/board-zoom-peripherals.c +2 -0
@@ -20,6 +20,7 @@#include <linux/wl12xx.h> #include <linux/mmc/host.h> #include <linux/platform_data/gpio-omap.h> +#include <linux/usb/phy.h> #include <asm/mach-types.h> #include <asm/mach/arch.h>
@@ -298,6 +299,7 @@ void __init zoom_peripherals_init(void)omap_hsmmc_init (mmc);omap_i2c_init ();platform_device_register (&omap_vwlan_device); +usb_bind_phy ("musb-hdrc.0.auto" ,0 ,"twl4030_usb" );usb_musb_init (NULL );enable_board_wakeup_source ();omap_serial_init ();
Signature · 1 line
1.7.9.5
Tony Lindgren
maintainerRe: [PATCH v2 3/6] ARM: OMAP: USB: Add phy binding information
Quoted 5 lines · Kishon Vijay Abraham I
This is w.r.t the changes in PHY library to support adding and getting multiple PHYs of the same type. In the new design, the binding information between the PHY and the USB controller should be specified in the platform specific initialization code. So it's been done here for OMAP platforms.
This looks OK to me, but should be queued by Felipe in his minimal USB platform_data changes branch that I can pull in too to avoid pointless merge conflicts.
Regards,
Tony
PATCH v2 4/6 drivers: usb: musb: omap: make use of the new PHY lib APIs
In reply to Kishon Vijay Abraham INew PHY lib APIs like usb_add_phy_dev() and devm_usb_get_phy_dev() are used in MUSB (OMAP), in order to make use of the binding information provided in the board file (of OMAP platforms).
All the platforms should be modified similar to this to add and get the PHY.
--- drivers/usb/musb/omap2430.c | 2 +- drivers/usb/otg/twl4030-usb.c | 3 ++- drivers/usb/phy/omap-usb2.c | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-)
drivers/usb/musb/omap2430.c +1 -1
@@ -345,7 +345,7 @@ static int omap2430_musb_init(struct musb *musb)* up through ULPI. TWL4030-family PMICs include one, * which needs a driver, drivers aren't always needed. */ - musb->xceiv =devm_usb_get_phy (dev,USB_PHY_TYPE_USB2 ); + musb->xceiv =devm_usb_get_phy_dev (dev,0 );if (IS_ERR_OR_NULL (musb->xceiv)) {pr_err ("HS USB OTG: no transceiver configured\n" );return -ENODEV ;
drivers/usb/otg/twl4030-usb.c +2 -1
@@ -610,6 +610,7 @@ static int twl4030_usb_probe(struct platform_device *pdev) twl->phy.dev = twl->dev; twl->phy.label ="twl4030" ; twl->phy.otg = otg; + twl->phy.type =USB_PHY_TYPE_USB2 ; twl->phy.set_suspend = twl4030_set_suspend; otg->phy = &twl->phy;
@@ -624,7 +625,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)dev_err (&pdev->dev,"ldo init failed\n" );return err; } -usb_add_phy (&twl->phy,USB_PHY_TYPE_USB2 ); +usb_add_phy_dev (&twl->phy);platform_set_drvdata (pdev, twl);if (device_create_file (&pdev->dev, &dev_attr_vbus))
drivers/usb/phy/omap-usb2.c +2 -1
@@ -142,6 +142,7 @@ static int omap_usb2_probe(struct platform_device *pdev) phy->phy.label ="omap-usb2" ; phy->phy.set_suspend = omap_usb2_suspend; phy->phy.otg = otg; + phy->phy.type =USB_PHY_TYPE_USB2 ; phy->control_dev =omap_get_control_dev ();if (IS_ERR (phy->control_dev)) {
@@ -165,7 +166,7 @@ static int omap_usb2_probe(struct platform_device *pdev) }clk_prepare (phy->wkupclk); -usb_add_phy (&phy->phy,USB_PHY_TYPE_USB2 ); +usb_add_phy_dev (&phy->phy);platform_set_drvdata (pdev, phy);
Signature · 1 line
1.7.9.5
PATCH v2 5/6 usb: otg: add device tree support to otg library
In reply to Kishon Vijay Abraham IAdded an API devm_usb_get_phy_by_phandle(), to get usb phy by passing a device node phandle value. This function will return a pointer to the phy on success, -EPROBE_DEFER if there is a device_node for the phandle, but the phy has not been added, or a ERR_PTR() otherwise.
--- drivers/usb/otg/otg.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/usb/phy.h | 8 +++++ 2 files changed, 88 insertions(+)
drivers/usb/otg/otg.c +80 -0
@@ -13,7 +13,9 @@#include <linux/export.h> #include <linux/err.h> #include <linux/device.h> +#include <linux/module.h> #include <linux/slab.h> +#include <linux/of.h> #include <linux/usb/otg.h>
@@ -54,6 +56,20 @@ static struct usb_phy *__usb_find_phy_dev(struct device *dev,return ERR_PTR (-ENODEV ); } +static struct usb_phy *__of_usb_find_phy (struct device_node *node) +{ +struct usb_phy *phy; + +list_for_each_entry (phy, &phy_list, head) { +if (node != phy->dev->of_node) +continue ; + +return phy; + } + +return ERR_PTR (-ENODEV ); +} +static void devm_usb_phy_release (struct device *dev,void *res) {struct usb_phy *phy = *(struct usb_phy **)res;
@@ -129,6 +145,70 @@ err0: }EXPORT_SYMBOL (usb_get_phy); +/** +* devm_usb_get_phy_by_phandle - find the USB PHY by phandle +* @dev - device that requests this phy +* @phandle - name of the property holding the phy phandle value +* @index - the index of the phy +* +* Returns the phy driver associated with the given phandle value, +* after getting a refcount to it, -ENODEV if there is no such phy or +* -EPROBE_DEFER if there is a phandle to the phy, but the device is +* not yet loaded. While at that, it also associates the device with +* the phy using devres. On driver detach, release function is invoked +* on the devres data, then, devres data is freed. +* +* For use by USB host and peripheral drivers. +*/ +struct usb_phy *devm_usb_get_phy_by_phandle (struct device *dev, +const char *phandle,u8 index) +{ +struct usb_phy *phy =ERR_PTR (-ENOMEM ), **ptr; +unsigned long flags; +struct device_node *node; + +if (!dev->of_node) { +dev_dbg (dev,"device does not have a device node entry\n" ); +return ERR_PTR (-EINVAL ); + } + + node =of_parse_phandle (dev->of_node, phandle, index); +if (!node) { +dev_dbg (dev,"failed to get %s phandle in %s node\n" , phandle, + dev->of_node->full_name); +return ERR_PTR (-ENODEV ); + } + + ptr =devres_alloc (devm_usb_phy_release,sizeof (*ptr),GFP_KERNEL ); +if (!ptr) { +dev_dbg (dev,"failed to allocate memory for devres\n" ); + goto err0; + } + +spin_lock_irqsave (&phy_lock, flags); + + phy =__of_usb_find_phy (node); +if (IS_ERR (phy) || !try_module_get (phy->dev->driver->owner)) { + phy =ERR_PTR (-EPROBE_DEFER ); +devres_free (ptr); + goto err1; + } + + *ptr = phy; +devres_add (dev, ptr); + +get_device (phy->dev); + +err1: +spin_unlock_irqrestore (&phy_lock, flags); + +err0: +of_node_put (node); + +return phy; +} +EXPORT_SYMBOL (devm_usb_get_phy_by_phandle); +/** * usb_get_phy_dev - find the USB PHY * @dev - device that requests this phy
include/linux/usb/phy.h +8 -0
@@ -167,6 +167,8 @@ extern struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type);extern struct usb_phy *usb_get_phy_dev (struct device *dev,u8 index);extern struct usb_phy *devm_usb_get_phy_dev (struct device *dev,u8 index); +extern struct usb_phy *devm_usb_get_phy_by_phandle (struct device *dev, +const char *phandle,u8 index);extern void usb_put_phy (struct usb_phy *);extern void devm_usb_put_phy (struct device *dev,struct usb_phy *x); extern int usb_bind_phy(const char *dev_name, u8 index,
@@ -193,6 +195,12 @@ static inline struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index)return NULL ; } +static inline struct usb_phy *devm_usb_get_phy_by_phandle (struct device *dev, +const char *phandle,u8 index) +{ +return NULL ; +} +static inline void usb_put_phy (struct usb_phy *x) { }
Signature · 1 line
1.7.9.5
PATCH v2 6/6 USB: MUSB: OMAP: get PHY by phandle for dt boot
In reply to Kishon Vijay Abraham IThe OMAP glue has been modified to get PHY by phandle for dt boot.
---
There were some comments w.r.t this patch for returning EPROBE_DEFER if not able to get the phy, in my previous version.
Currently we can't have that because the gadget driver doesn't do a EPROBE_DEFER. We have a separate activity planned for making gadget driver also do EPROBE_DEFER for 3.10.
drivers/usb/musb/omap2430.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/usb/musb/omap2430.c +6 -1
@@ -345,7 +345,12 @@ static int omap2430_musb_init(struct musb *musb)* up through ULPI. TWL4030-family PMICs include one, * which needs a driver, drivers aren't always needed. */ - musb->xceiv =devm_usb_get_phy_dev (dev,0 ); +if (dev->parent->of_node) + musb->xceiv =devm_usb_get_phy_by_phandle (dev->parent, +"usb_phy" ,0 ); +else + musb->xceiv =devm_usb_get_phy_dev (dev,0 ); +if (IS_ERR_OR_NULL (musb->xceiv)) {pr_err ("HS USB OTG: no transceiver configured\n" );return -ENODEV ;
Signature · 1 line
1.7.9.5
PATCH v3 6/6 USB: MUSB: OMAP: get PHY by phandle for dt boot
The OMAP glue has been modified to get PHY by phandle for dt boot.
---
There were some comments w.r.t this patch for returning EPROBE_DEFER if not able to get the phy, in my previous version.
Currently we can't have that because the gadget driver doesn't do a EPROBE_DEFER. We have a separate activity planned for making gadget driver also do EPROBE_DEFER for 3.10.
drivers/usb/musb/omap2430.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/usb/musb/omap2430.c +6 -1
@@ -345,7 +345,12 @@ static int omap2430_musb_init(struct musb *musb)* up through ULPI. TWL4030-family PMICs include one, * which needs a driver, drivers aren't always needed. */ - musb->xceiv =devm_usb_get_phy_dev (dev,0 ); +if (dev->parent->of_node) + musb->xceiv =devm_usb_get_phy_by_phandle (dev->parent, +"usb-phy" ,0 ); +else + musb->xceiv =devm_usb_get_phy_dev (dev,0 ); +if (IS_ERR_OR_NULL (musb->xceiv)) {pr_err ("HS USB OTG: no transceiver configured\n" );return -ENODEV ;
Signature · 1 line
1.7.9.5