usb: phy: msm: Add support for secondary PHY control
authorIvan T. Ivanov <iivanov@mm-sol.com>
Mon, 28 Apr 2014 13:34:17 +0000 (16:34 +0300)
committerFelipe Balbi <balbi@ti.com>
Wed, 30 Apr 2014 16:28:45 +0000 (11:28 -0500)
Allow support to use 2nd HSPHY with USB2 Core.
Some platforms may have configuration to allow USB controller
work with any of the two HSPHYs present. By default driver
configures USB core to use primary HSPHY. Add support to allow
user select 2nd HSPHY using DT parameter.

Signed-off-by: Ivan T. Ivanov <iivanov@mm-sol.com>
Cc: Manu Gautam <mgautam@codeaurora.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Documentation/devicetree/bindings/usb/msm-hsusb.txt
drivers/usb/phy/phy-msm-usb.c
include/linux/usb/msm_hsusb.h
include/linux/usb/msm_hsusb_hw.h

index ee4123de3de4359aaff8765446bcb86ca9308cd8..066966706ca11e840f4c74d8c1928696016c42dd 100644 (file)
@@ -59,6 +59,12 @@ Optional properties:
                 For example: qcom,phy-init-sequence = < -1 0x63 >;
                 Will update only value at address ULPI_EXT_VENDOR_SPECIFIC + 1.
 
+- qcom,phy-num: Select number of pyco-phy to use, can be one of
+                0 - PHY one, default
+                1 - Second PHY
+                Some platforms may have configuration to allow USB
+                controller work with any of the two HSPHYs present.
+
 Example HSUSB OTG controller device node:
 
     usb@f9a55000 {
index a6abb1b3a7f07be20c01d62c25b652f7c4e2a102..8d57045ac93840b1a1a9f871d13cdd4c174e676b 100644 (file)
@@ -314,6 +314,9 @@ static int msm_otg_phy_reset(struct msm_otg *motg)
        if (!retries)
                return -ETIMEDOUT;
 
+       if (motg->phy_number)
+               writel(readl(USB_PHY_CTRL2) | BIT(16), USB_PHY_CTRL2);
+
        dev_info(motg->phy.dev, "phy_reset: success\n");
        return 0;
 }
@@ -368,6 +371,9 @@ static int msm_otg_reset(struct usb_phy *phy)
                ulpi_write(phy, ulpi_val, ULPI_USB_INT_EN_FALL);
        }
 
+       if (motg->phy_number)
+               writel(readl(USB_PHY_CTRL2) | BIT(16), USB_PHY_CTRL2);
+
        return 0;
 }
 
@@ -404,6 +410,7 @@ static int msm_otg_suspend(struct msm_otg *motg)
        struct usb_phy *phy = &motg->phy;
        struct usb_bus *bus = phy->otg->host;
        struct msm_otg_platform_data *pdata = motg->pdata;
+       void __iomem *addr;
        int cnt = 0;
 
        if (atomic_read(&motg->in_lpm))
@@ -463,9 +470,13 @@ static int msm_otg_suspend(struct msm_otg *motg)
         */
        writel(readl(USB_USBCMD) | ASYNC_INTR_CTRL | ULPI_STP_CTRL, USB_USBCMD);
 
+       addr = USB_PHY_CTRL;
+       if (motg->phy_number)
+               addr = USB_PHY_CTRL2;
+
        if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
                        motg->pdata->otg_control == OTG_PMIC_CONTROL)
-               writel(readl(USB_PHY_CTRL) | PHY_RETEN, USB_PHY_CTRL);
+               writel(readl(addr) | PHY_RETEN, addr);
 
        clk_disable_unprepare(motg->pclk);
        clk_disable_unprepare(motg->clk);
@@ -495,6 +506,7 @@ static int msm_otg_resume(struct msm_otg *motg)
 {
        struct usb_phy *phy = &motg->phy;
        struct usb_bus *bus = phy->otg->host;
+       void __iomem *addr;
        int cnt = 0;
        unsigned temp;
 
@@ -508,9 +520,14 @@ static int msm_otg_resume(struct msm_otg *motg)
 
        if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
                        motg->pdata->otg_control == OTG_PMIC_CONTROL) {
+
+               addr = USB_PHY_CTRL;
+               if (motg->phy_number)
+                       addr = USB_PHY_CTRL2;
+
                msm_hsusb_ldo_set_mode(motg, 1);
                msm_hsusb_config_vddcx(motg, 1);
-               writel(readl(USB_PHY_CTRL) & ~PHY_RETEN, USB_PHY_CTRL);
+               writel(readl(addr) & ~PHY_RETEN, addr);
        }
 
        temp = readl(USB_USBCMD);
@@ -1399,6 +1416,9 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
                if (val == OTG_PMIC_CONTROL)
                        pdata->otg_control = val;
 
+       if (!of_property_read_u32(node, "qcom,phy-num", &val) && val < 2)
+               motg->phy_number = val;
+
        prop = of_find_property(node, "qcom,phy-init-sequence", &len);
        if (!prop || !len)
                return 0;
index 4e5d9168f52e4efc0cf05380da739e4e0eb3bdea..4628f1a4713e7cebffb8877dec479b269ed81971 100644 (file)
@@ -158,6 +158,7 @@ struct msm_otg {
        atomic_t in_lpm;
        int async_int;
        unsigned cur_power;
+       int phy_number;
        struct delayed_work chg_work;
        enum usb_chg_state chg_state;
        enum usb_chg_type chg_type;
index 6e97a2d3d39fbb0d7e2d70be26bcc5e225045c2d..e6d70356715508c5a50e245676c6ae37162200b1 100644 (file)
@@ -25,6 +25,7 @@
 #define USB_OTGSC            (MSM_USB_BASE + 0x01A4)
 #define USB_USBMODE          (MSM_USB_BASE + 0x01A8)
 #define USB_PHY_CTRL         (MSM_USB_BASE + 0x0240)
+#define USB_PHY_CTRL2        (MSM_USB_BASE + 0x0278)
 
 #define USBCMD_RESET   2
 #define USB_USBINTR          (MSM_USB_BASE + 0x0148)