usb: allow to supply the PHY in the drivers when using HCD
authorAntoine Tenart <antoine.tenart@free-electrons.com>
Thu, 30 Oct 2014 17:41:16 +0000 (18:41 +0100)
committerFelipe Balbi <balbi@ti.com>
Mon, 3 Nov 2014 16:02:50 +0000 (10:02 -0600)
This patch modify the generic code handling PHYs to allow them to be
supplied from the drivers. This adds checks to ensure no PHY was already
there when looking for one in the generic code. This also makes sure we
do not modify its state in the generic HCD functions, it was provided by
the driver.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/chipidea/ci.h
drivers/usb/chipidea/ci_hdrc_imx.c
drivers/usb/chipidea/ci_hdrc_msm.c
drivers/usb/chipidea/core.c
drivers/usb/chipidea/debug.c
drivers/usb/chipidea/host.c
drivers/usb/chipidea/otg_fsm.c
drivers/usb/chipidea/udc.c
drivers/usb/core/hcd.c
include/linux/usb/chipidea.h

index ea40626e0246ab8aa90cbaad045e60f082f91198..9015139a802781cf3521c75da2b449583d7628bf 100644 (file)
@@ -161,7 +161,7 @@ struct hw_bank {
  * @test_mode: the selected test mode
  * @platdata: platform specific information supplied by parent device
  * @vbus_active: is VBUS active
- * @transceiver: pointer to USB PHY, if any
+ * @usb_phy: pointer to USB PHY, if any
  * @hcd: pointer to usb_hcd for ehci host driver
  * @debugfs: root dentry for this controller in debugfs
  * @id_event: indicates there is an id event, and handled at ci_otg_work
@@ -177,6 +177,7 @@ struct ci_hdrc {
        struct ci_role_driver           *roles[CI_ROLE_END];
        enum ci_role                    role;
        bool                            is_otg;
+       struct usb_otg                  otg;
        struct otg_fsm                  fsm;
        struct ci_otg_fsm_timer_list    *fsm_timer;
        struct work_struct              work;
@@ -201,7 +202,7 @@ struct ci_hdrc {
 
        struct ci_hdrc_platform_data    *platdata;
        int                             vbus_active;
-       struct usb_phy                  *transceiver;
+       struct usb_phy                  *usb_phy;
        struct usb_hcd                  *hcd;
        struct dentry                   *debugfs;
        bool                            id_event;
index a7ab0f15926e33253ba46bfada73e7e4362255a1..6f8b1b1045b566a4728253378da3b39ade72b115 100644 (file)
@@ -147,7 +147,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
                goto err_clk;
        }
 
-       pdata.phy = data->phy;
+       pdata.usb_phy = data->phy;
 
        if (imx_platform_flag->flags & CI_HDRC_IMX_IMX28_WRITE_FIX)
                pdata.flags |= CI_HDRC_IMX28_WRITE_FIX;
index 4935ac38fd008d17a51ed866e9fc002cddf021f5..3edf969ed7976a5ae82ff2addaf2428fd89a579d 100644 (file)
@@ -26,15 +26,15 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
                dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
                writel(0, USB_AHBBURST);
                writel(0, USB_AHBMODE);
-               usb_phy_init(ci->transceiver);
+               usb_phy_init(ci->usb_phy);
                break;
        case CI_HDRC_CONTROLLER_STOPPED_EVENT:
                dev_dbg(dev, "CI_HDRC_CONTROLLER_STOPPED_EVENT received\n");
                /*
-                * Put the transceiver in non-driving mode. Otherwise host
+                * Put the phy in non-driving mode. Otherwise host
                 * may not detect soft-disconnection.
                 */
-               usb_phy_notify_disconnect(ci->transceiver, USB_SPEED_UNKNOWN);
+               usb_phy_notify_disconnect(ci->usb_phy, USB_SPEED_UNKNOWN);
                break;
        default:
                dev_dbg(dev, "unknown ci_hdrc event\n");
@@ -68,7 +68,7 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
        if (IS_ERR(phy))
                return PTR_ERR(phy);
 
-       ci_hdrc_msm_platdata.phy = phy;
+       ci_hdrc_msm_platdata.usb_phy = phy;
 
        plat_ci = ci_hdrc_add_device(&pdev->dev,
                                pdev->resource, pdev->num_resources,
index 9bdc6bd73432cd1c39f371f589dd5bbab3a797bc..30f89426bf0528ed49cd5c41428359bc23245207 100644 (file)
@@ -312,7 +312,7 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
        case USBPHY_INTERFACE_MODE_UTMI:
        case USBPHY_INTERFACE_MODE_UTMIW:
        case USBPHY_INTERFACE_MODE_HSIC:
-               ret = usb_phy_init(ci->transceiver);
+               ret = usb_phy_init(ci->usb_phy);
                if (ret)
                        return ret;
                hw_phymode_configure(ci);
@@ -320,12 +320,12 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
        case USBPHY_INTERFACE_MODE_ULPI:
        case USBPHY_INTERFACE_MODE_SERIAL:
                hw_phymode_configure(ci);
-               ret = usb_phy_init(ci->transceiver);
+               ret = usb_phy_init(ci->usb_phy);
                if (ret)
                        return ret;
                break;
        default:
-               ret = usb_phy_init(ci->transceiver);
+               ret = usb_phy_init(ci->usb_phy);
        }
 
        return ret;
@@ -605,13 +605,13 @@ static int ci_hdrc_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       if (ci->platdata->phy)
-               ci->transceiver = ci->platdata->phy;
+       if (ci->platdata->usb_phy)
+               ci->usb_phy = ci->platdata->usb_phy;
        else
-               ci->transceiver = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+               ci->usb_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
 
-       if (IS_ERR(ci->transceiver)) {
-               ret = PTR_ERR(ci->transceiver);
+       if (IS_ERR(ci->usb_phy)) {
+               ret = PTR_ERR(ci->usb_phy);
                /*
                 * if -ENXIO is returned, it means PHY layer wasn't
                 * enabled, so it makes no sense to return -EPROBE_DEFER
@@ -728,7 +728,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
 stop:
        ci_role_destroy(ci);
 deinit_phy:
-       usb_phy_shutdown(ci->transceiver);
+       usb_phy_shutdown(ci->usb_phy);
 
        return ret;
 }
@@ -741,7 +741,7 @@ static int ci_hdrc_remove(struct platform_device *pdev)
        free_irq(ci->irq, ci);
        ci_role_destroy(ci);
        ci_hdrc_enter_lpm(ci, true);
-       usb_phy_shutdown(ci->transceiver);
+       usb_phy_shutdown(ci->usb_phy);
 
        return 0;
 }
index f038804d13ddc6e24624729f990e39e5dd9c5bf2..268e4236e84cfd51ecd9748af71fc772f196666b 100644 (file)
@@ -220,7 +220,7 @@ static int ci_otg_show(struct seq_file *s, void *unused)
 
        /* ------ State ----- */
        seq_printf(s, "OTG state: %s\n\n",
-               usb_otg_state_string(ci->transceiver->otg->state));
+                       usb_otg_state_string(ci->otg.state));
 
        /* ------ State Machine Variables ----- */
        seq_printf(s, "a_bus_drop: %d\n", fsm->a_bus_drop);
index ebde7b6ce687040dda25dbca4802b9daa13e9cfa..789809f680aa1b3229f68c166fbb2ba2dd6066bb 100644 (file)
@@ -59,7 +59,7 @@ static int host_start(struct ci_hdrc *ci)
        hcd->has_tt = 1;
 
        hcd->power_budget = ci->platdata->power_budget;
-       hcd->usb_phy = ci->transceiver;
+       hcd->usb_phy = ci->usb_phy;
        hcd->tpl_support = ci->platdata->tpl_support;
 
        ehci = hcd_to_ehci(hcd);
@@ -86,10 +86,11 @@ static int host_start(struct ci_hdrc *ci)
        if (ret) {
                goto disable_reg;
        } else {
-               struct usb_otg *otg = ci->transceiver->otg;
+               struct usb_otg *otg = &ci->otg;
 
                ci->hcd = hcd;
-               if (otg) {
+
+               if (ci_otg_is_fsm_mode(ci)) {
                        otg->host = &hcd->self;
                        hcd->self.otg_port = 1;
                }
index d8490e758a745df907076d2586b6cf5c52b6bfc6..862d7cb01b9250ab3f46489e7b23ad7cc7f0a817 100644 (file)
@@ -778,20 +778,10 @@ void ci_hdrc_otg_fsm_start(struct ci_hdrc *ci)
 int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci)
 {
        int retval = 0;
-       struct usb_otg *otg;
 
-       otg = devm_kzalloc(ci->dev,
-                       sizeof(struct usb_otg), GFP_KERNEL);
-       if (!otg) {
-               dev_err(ci->dev,
-               "Failed to allocate usb_otg structure for ci hdrc otg!\n");
-               return -ENOMEM;
-       }
-
-       otg->usb_phy = ci->transceiver;
-       otg->gadget = &ci->gadget;
-       ci->fsm.otg = otg;
-       ci->transceiver->otg = ci->fsm.otg;
+       ci->otg.usb_phy = ci->usb_phy;
+       ci->otg.gadget = &ci->gadget;
+       ci->fsm.otg = &ci->otg;
        ci->fsm.power_up = 1;
        ci->fsm.id = hw_read_otgsc(ci, OTGSC_ID) ? 1 : 0;
        ci->fsm.otg->state = OTG_STATE_UNDEFINED;
index f4397b29891fbbf7442401df4c9d06409a332624..a2d80ab3d9c49f6de66c2f4cc4d990b838dc06e4 100644 (file)
@@ -1519,8 +1519,8 @@ static int ci_udc_vbus_draw(struct usb_gadget *_gadget, unsigned ma)
 {
        struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget);
 
-       if (ci->transceiver)
-               return usb_phy_set_power(ci->transceiver, ma);
+       if (ci->usb_phy)
+               return usb_phy_set_power(ci->usb_phy, ma);
        return -ENOTSUPP;
 }
 
index b84fb141e122f7f0d60d9e4ba09642c7c9e15492..6a2a2fd990abe362d2cf809e39bd631f7c0a0c11 100644 (file)
@@ -2648,7 +2648,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
                }
        }
 
-       if (IS_ENABLED(CONFIG_GENERIC_PHY)) {
+       if (IS_ENABLED(CONFIG_GENERIC_PHY) && !hcd->phy) {
                struct phy *phy = phy_get(hcd->self.controller, "usb");
 
                if (IS_ERR(phy)) {
@@ -2668,6 +2668,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
                                goto err_phy;
                        }
                        hcd->phy = phy;
+                       hcd->remove_phy = 1;
                }
        }
 
@@ -2814,7 +2815,7 @@ err_allocate_root_hub:
 err_register_bus:
        hcd_buffer_destroy(hcd);
 err_create_buf:
-       if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->phy) {
+       if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
                phy_power_off(hcd->phy);
                phy_exit(hcd->phy);
                phy_put(hcd->phy);
@@ -2898,7 +2899,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
        usb_deregister_bus(&hcd->self);
        hcd_buffer_destroy(hcd);
 
-       if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->phy) {
+       if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) {
                phy_power_off(hcd->phy);
                phy_exit(hcd->phy);
                phy_put(hcd->phy);
index e14c09a45c5acd342fcf7816600b1aab9ca69e85..4fe161a84c7dc36c76e98a5dc781f819cb2d97d5 100644 (file)
@@ -13,7 +13,7 @@ struct ci_hdrc_platform_data {
        /* offset of the capability registers */
        uintptr_t        capoffset;
        unsigned         power_budget;
-       struct usb_phy  *phy;
+       struct usb_phy  *usb_phy;
        enum usb_phy_interface phy_mode;
        unsigned long    flags;
 #define CI_HDRC_REGS_SHARED            BIT(0)