From: John Youn <John.Youn@synopsys.com>
To: John Stultz <john.stultz@linaro.org>,
Kishon Vijay Abraham I <kishon@ti.com>
Cc: lkml <linux-kernel@vger.kernel.org>,
Wei Xu <xuwei5@hisilicon.com>, Guodong Xu <guodong.xu@linaro.org>,
Amit Pundir <amit.pundir@linaro.org>,
"Rob Herring" <robh+dt@kernel.org>,
John Youn <John.Youn@synopsys.com>,
"Douglas Anderson" <dianders@chromium.org>,
Chen Yu <chenyu56@huawei.com>,
Felipe Balbi <felipe.balbi@linux.intel.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Linux USB List <linux-usb@vger.kernel.org>
Subject: Re: [RFC][PATCH 1/3] phy: phy-hi6220-usb: Wire up extconn support to hikey's phy driver
Date: Fri, 2 Dec 2016 17:07:48 -0800 [thread overview]
Message-ID: <7246f60a-6cb8-b4f0-9c0c-c3f80fc90948@synopsys.com> (raw)
In-Reply-To: <CALAqxLXDqs-Y9Fsx_bcjeT-uB4u8Oi7SKhWRMbmXq-dN8XfUXA@mail.gmail.com>
On 12/1/2016 12:12 PM, John Stultz wrote:
> On Thu, Dec 1, 2016 at 12:23 AM, Kishon Vijay Abraham I <kishon@ti.com> wrote:
>> Hi,
>>
>> On Wednesday 23 November 2016 09:16 AM, John Stultz wrote:
>>> This wires extconn support to hikey's phy driver, and
>>> connects it to the usb UDC layer via a usb_phy structure.
>>>
>>> Not sure if this is the right way to connect phy -> UDC,
>>> but I'm lacking a clear example.
>>>
>>> Cc: Wei Xu <xuwei5@hisilicon.com>
>>> Cc: Guodong Xu <guodong.xu@linaro.org>
>>> Cc: Amit Pundir <amit.pundir@linaro.org>
>>> Cc: Rob Herring <robh+dt@kernel.org>
>>> Cc: John Youn <johnyoun@synopsys.com>
>>> Cc: Douglas Anderson <dianders@chromium.org>
>>> Cc: Chen Yu <chenyu56@huawei.com>
>>> Cc: Kishon Vijay Abraham I <kishon@ti.com>
>>> Cc: Felipe Balbi <felipe.balbi@linux.intel.com>
>>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>>> Cc: linux-usb@vger.kernel.org
>>> Signed-off-by: John Stultz <john.stultz@linaro.org>
>>> ---
>>> arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 11 +++
>>> drivers/phy/Kconfig | 2 +
>>> drivers/phy/phy-hi6220-usb.c | 139 ++++++++++++++++++++++++++++++
>>> 3 files changed, 152 insertions(+)
>>>
>>> diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
>>> index 17839db..171fbb2 100644
>>> --- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
>>> +++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
>>> @@ -732,10 +732,21 @@
>>> regulator-always-on;
>>> };
>>>
>>> + usb_vbus: usb-vbus {
>>> + compatible = "linux,extcon-usb-gpio";
>>> + id-gpio = <&gpio2 6 1>;
>>> + };
>>> +
>>> + usb_id: usb-id {
>>> + compatible = "linux,extcon-usb-gpio";
>>> + id-gpio = <&gpio2 5 1>;
>>> + };
>>> +
>>> usb_phy: usbphy {
>>> compatible = "hisilicon,hi6220-usb-phy";
>>> #phy-cells = <0>;
>>> phy-supply = <&fixed_5v_hub>;
>>> + extcon = <&usb_vbus>, <&usb_id>;
>>> hisilicon,peripheral-syscon = <&sys_ctrl>;
>>> };
>>>
>>> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
>>> index fe00f91..76f4f17 100644
>>> --- a/drivers/phy/Kconfig
>>> +++ b/drivers/phy/Kconfig
>>> @@ -254,8 +254,10 @@ config PHY_MT65XX_USB3
>>> config PHY_HI6220_USB
>>> tristate "hi6220 USB PHY support"
>>> depends on (ARCH_HISI && ARM64) || COMPILE_TEST
>>> + depends on EXTCON
>>> select GENERIC_PHY
>>> select MFD_SYSCON
>>> + select USB_PHY
>>> help
>>> Enable this to support the HISILICON HI6220 USB PHY.
>>>
>>> diff --git a/drivers/phy/phy-hi6220-usb.c b/drivers/phy/phy-hi6220-usb.c
>>> index b2141cb..89d8475 100644
>>> --- a/drivers/phy/phy-hi6220-usb.c
>>> +++ b/drivers/phy/phy-hi6220-usb.c
>>> @@ -12,7 +12,12 @@
>>> #include <linux/module.h>
>>> #include <linux/platform_device.h>
>>> #include <linux/phy/phy.h>
>>> +#include <linux/usb/phy_companion.h>
>>> +#include <linux/usb/otg.h>
>>> +#include <linux/usb/gadget.h>
>>> +#include <linux/usb/phy.h>
>>> #include <linux/regmap.h>
>>> +#include <linux/extcon.h>
>>>
>>> #define SC_PERIPH_CTRL4 0x00c
>>>
>>> @@ -44,9 +49,21 @@
>>>
>>> #define EYE_PATTERN_PARA 0x7053348c
>>>
>>> +
>>> +struct hi6220_usb_cable {
>>> + struct notifier_block nb;
>>> + struct extcon_dev *extcon;
>>> + int state;
>>> +};
>>> +
>>> struct hi6220_priv {
>>> struct regmap *reg;
>>> struct device *dev;
>>> + struct usb_phy phy;
>>> +
>>> + struct delayed_work work;
>>> + struct hi6220_usb_cable vbus;
>>> + struct hi6220_usb_cable id;
>>> };
>>>
>>> static void hi6220_phy_init(struct hi6220_priv *priv)
>>> @@ -112,23 +129,85 @@ static int hi6220_phy_exit(struct phy *phy)
>>> return hi6220_phy_setup(priv, false);
>>> }
>>>
>>> +
>>> static struct phy_ops hi6220_phy_ops = {
>>> .init = hi6220_phy_start,
>>> .exit = hi6220_phy_exit,
>>> .owner = THIS_MODULE,
>>> };
>>>
>>> +static void hi6220_detect_work(struct work_struct *work)
>>> +{
>>> + struct hi6220_priv *priv =
>>> + container_of(to_delayed_work(work), struct hi6220_priv, work);
>>> + struct usb_otg *otg = priv->phy.otg;
>>> +
>>> + if (!IS_ERR(priv->vbus.extcon))
>>> + priv->vbus.state = extcon_get_cable_state_(priv->vbus.extcon,
>>> + EXTCON_USB);
>>> + if (!IS_ERR(priv->id.extcon))
>>> + priv->id.state = extcon_get_cable_state_(priv->id.extcon,
>>> + EXTCON_USB_HOST);
>>> + if (otg->gadget) {
>>> + if (priv->id.state)
>>> + usb_gadget_vbus_connect(otg->gadget);
>>> + else
>>> + usb_gadget_vbus_disconnect(otg->gadget);
>>> + }
>>> +}
>>> +
>>> +static int hi6220_otg_vbus_notifier(struct notifier_block *nb,
>>> + unsigned long event, void *ptr)
>>> +{
>>> + struct hi6220_usb_cable *vbus = container_of(nb,
>>> + struct hi6220_usb_cable, nb);
>>> + struct hi6220_priv *priv = container_of(vbus,
>>> + struct hi6220_priv, vbus);
>>> +
>>> + schedule_delayed_work(&priv->work, msecs_to_jiffies(100));
>>> + return NOTIFY_DONE;
>>> +}
>>> +
>>> +static int hi6220_otg_id_notifier(struct notifier_block *nb,
>>> + unsigned long event, void *ptr)
>>> +{
>>> + struct hi6220_usb_cable *id = container_of(nb,
>>> + struct hi6220_usb_cable, nb);
>>> + struct hi6220_priv *priv = container_of(id, struct hi6220_priv, id);
>>> +
>>> + schedule_delayed_work(&priv->work, msecs_to_jiffies(100));
>>> + return NOTIFY_DONE;
>>> +}
>>> +
>>> +static int hi6220_otg_set_host(struct usb_otg *otg, struct usb_bus *host)
>>> +{
>>> + otg->host = host;
>>> + return 0;
>>> +}
>>> +
>>> +static int hi6220_otg_set_peripheral(struct usb_otg *otg,
>>> + struct usb_gadget *gadget)
>>> +{
>>> + otg->gadget = gadget;
>>> + return 0;
>>> +}
>>> +
>>> static int hi6220_phy_probe(struct platform_device *pdev)
>>> {
>>> struct phy_provider *phy_provider;
>>> struct device *dev = &pdev->dev;
>>> struct phy *phy;
>>> + struct usb_otg *otg;
>>> struct hi6220_priv *priv;
>>> + struct extcon_dev *ext_id, *ext_vbus;
>>> + int ret;
>>>
>>> priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>>> if (!priv)
>>> return -ENOMEM;
>>>
>>> + INIT_DELAYED_WORK(&priv->work, hi6220_detect_work);
>>> +
>>> priv->dev = dev;
>>> priv->reg = syscon_regmap_lookup_by_phandle(dev->of_node,
>>> "hisilicon,peripheral-syscon");
>>> @@ -137,13 +216,73 @@ static int hi6220_phy_probe(struct platform_device *pdev)
>>> return PTR_ERR(priv->reg);
>>> }
>>>
>>> +
>>> + ext_id = ERR_PTR(-ENODEV);
>>> + ext_vbus = ERR_PTR(-ENODEV);
>>> + if (of_property_read_bool(dev->of_node, "extcon")) {
>>> + /* Each one of them is not mandatory */
>>> + ext_vbus = extcon_get_edev_by_phandle(&pdev->dev, 0);
>>> + if (IS_ERR(ext_vbus) && PTR_ERR(ext_vbus) != -ENODEV)
>>> + return PTR_ERR(ext_vbus);
>>> +
>>> + ext_id = extcon_get_edev_by_phandle(&pdev->dev, 1);
>>> + if (IS_ERR(ext_id) && PTR_ERR(ext_id) != -ENODEV)
>>> + return PTR_ERR(ext_id);
>>> + }
>>> +
>>> + priv->vbus.extcon = ext_vbus;
>>> + if (!IS_ERR(ext_vbus)) {
>>> + priv->vbus.nb.notifier_call = hi6220_otg_vbus_notifier;
>>> + ret = extcon_register_notifier(ext_vbus, EXTCON_USB,
>>> + &priv->vbus.nb);
>>> + if (ret < 0) {
>>> + dev_err(&pdev->dev, "register VBUS notifier failed\n");
>>> + return ret;
>>> + }
>>> +
>>> + priv->vbus.state = extcon_get_cable_state_(ext_vbus,
>>> + EXTCON_USB);
>>> + }
>>> +
>>> + priv->id.extcon = ext_id;
>>> + if (!IS_ERR(ext_id)) {
>>> + priv->id.nb.notifier_call = hi6220_otg_id_notifier;
>>> + ret = extcon_register_notifier(ext_id, EXTCON_USB_HOST,
>>> + &priv->id.nb);
>>> + if (ret < 0) {
>>> + dev_err(&pdev->dev, "register ID notifier failed\n");
>>> + return ret;
>>> + }
>>> +
>>> + priv->id.state = extcon_get_cable_state_(ext_id,
>>> + EXTCON_USB_HOST);
>>> + }
>>> +
>>> hi6220_phy_init(priv);
>>>
>>> phy = devm_phy_create(dev, NULL, &hi6220_phy_ops);
>>> if (IS_ERR(phy))
>>> return PTR_ERR(phy);
>>>
>>> + otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
>>> + if (!otg)
>>> + return -ENOMEM;
>>> +
>>> + priv->dev = &pdev->dev;
>>> + priv->phy.dev = priv->dev;
>>> + priv->phy.label = "hi6220_usb_phy";
>>> + priv->phy.otg = otg;
>>> + priv->phy.type = USB_PHY_TYPE_USB2;
>>> + otg->set_host = hi6220_otg_set_host;
>>> + otg->set_peripheral = hi6220_otg_set_peripheral;
>>> + otg->usb_phy = &priv->phy;
>>> +
>>> + platform_set_drvdata(pdev, priv);
>>> +
>>> phy_set_drvdata(phy, priv);
>>> +
>>> + usb_add_phy_dev(&priv->phy);
>>
>> This would be like using two independent phy infrastructure :-( Should we just
>> handle the extcon events in USB driver?
>
> Yes. I was told that the older hikey usb-phy driver got nacked since
> new drivers should use the generic phy infrastructure, so I agree that
> registering a usb-phy device in a generic phy driver felt improper. My
> trouble was that its not obvious what is the way it should be done.
I'm not really sure how this should be solved either. But it seems
wrong to use both PHY frameworks like that.
>
> So as for adding extcon events to the usb driver, do you have a
> pointer to a driver that does it in a way that folks like?
I would be ok with this. Not sure if other folks might have
objections.
Take a look in the probe function in dwc2/platform.c where we handle
things similar to this.
Regards,
John
next prev parent reply other threads:[~2016-12-03 1:07 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-11-23 3:46 [RFC][PATCH 0/3] Try to connect hikey's usb phy to dwc2 driver John Stultz
2016-11-23 3:46 ` [RFC][PATCH 1/3] phy: phy-hi6220-usb: Wire up extconn support to hikey's phy driver John Stultz
2016-12-01 8:23 ` Kishon Vijay Abraham I
2016-12-01 20:12 ` John Stultz
2016-12-03 1:07 ` John Youn [this message]
2016-11-23 3:46 ` [RFC][PATCH 2/3] HACK: dwc2: force dual use of uphy and phy John Stultz
2016-11-23 3:46 ` [RFC][PATCH 3/3] usb: dwc2: Avoid suspending if we're in gadget mode John Stultz
2016-12-01 1:35 ` [RFC][PATCH 0/3] Try to connect hikey's usb phy to dwc2 driver John Stultz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7246f60a-6cb8-b4f0-9c0c-c3f80fc90948@synopsys.com \
--to=john.youn@synopsys.com \
--cc=amit.pundir@linaro.org \
--cc=chenyu56@huawei.com \
--cc=dianders@chromium.org \
--cc=felipe.balbi@linux.intel.com \
--cc=gregkh@linuxfoundation.org \
--cc=guodong.xu@linaro.org \
--cc=john.stultz@linaro.org \
--cc=kishon@ti.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=robh+dt@kernel.org \
--cc=xuwei5@hisilicon.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®