usb: phy: msm: Add support for secondary PHY control

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>
This commit is contained in:
Ivan T. Ivanov 2014-04-28 16:34:17 +03:00 committed by Felipe Balbi
parent a273454341
commit cfa3ff5dfe
4 changed files with 30 additions and 2 deletions

View File

@ -59,6 +59,12 @@ Optional properties:
For example: qcom,phy-init-sequence = < -1 0x63 >; For example: qcom,phy-init-sequence = < -1 0x63 >;
Will update only value at address ULPI_EXT_VENDOR_SPECIFIC + 1. 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: Example HSUSB OTG controller device node:
usb@f9a55000 { usb@f9a55000 {

View File

@ -314,6 +314,9 @@ static int msm_otg_phy_reset(struct msm_otg *motg)
if (!retries) if (!retries)
return -ETIMEDOUT; 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"); dev_info(motg->phy.dev, "phy_reset: success\n");
return 0; 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); 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; return 0;
} }
@ -404,6 +410,7 @@ static int msm_otg_suspend(struct msm_otg *motg)
struct usb_phy *phy = &motg->phy; struct usb_phy *phy = &motg->phy;
struct usb_bus *bus = phy->otg->host; struct usb_bus *bus = phy->otg->host;
struct msm_otg_platform_data *pdata = motg->pdata; struct msm_otg_platform_data *pdata = motg->pdata;
void __iomem *addr;
int cnt = 0; int cnt = 0;
if (atomic_read(&motg->in_lpm)) 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); 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 && if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
motg->pdata->otg_control == OTG_PMIC_CONTROL) 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->pclk);
clk_disable_unprepare(motg->clk); 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_phy *phy = &motg->phy;
struct usb_bus *bus = phy->otg->host; struct usb_bus *bus = phy->otg->host;
void __iomem *addr;
int cnt = 0; int cnt = 0;
unsigned temp; unsigned temp;
@ -508,9 +520,14 @@ static int msm_otg_resume(struct msm_otg *motg)
if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY && if (motg->pdata->phy_type == SNPS_28NM_INTEGRATED_PHY &&
motg->pdata->otg_control == OTG_PMIC_CONTROL) { 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_ldo_set_mode(motg, 1);
msm_hsusb_config_vddcx(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); 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) if (val == OTG_PMIC_CONTROL)
pdata->otg_control = val; 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); prop = of_find_property(node, "qcom,phy-init-sequence", &len);
if (!prop || !len) if (!prop || !len)
return 0; return 0;

View File

@ -158,6 +158,7 @@ struct msm_otg {
atomic_t in_lpm; atomic_t in_lpm;
int async_int; int async_int;
unsigned cur_power; unsigned cur_power;
int phy_number;
struct delayed_work chg_work; struct delayed_work chg_work;
enum usb_chg_state chg_state; enum usb_chg_state chg_state;
enum usb_chg_type chg_type; enum usb_chg_type chg_type;

View File

@ -25,6 +25,7 @@
#define USB_OTGSC (MSM_USB_BASE + 0x01A4) #define USB_OTGSC (MSM_USB_BASE + 0x01A4)
#define USB_USBMODE (MSM_USB_BASE + 0x01A8) #define USB_USBMODE (MSM_USB_BASE + 0x01A8)
#define USB_PHY_CTRL (MSM_USB_BASE + 0x0240) #define USB_PHY_CTRL (MSM_USB_BASE + 0x0240)
#define USB_PHY_CTRL2 (MSM_USB_BASE + 0x0278)
#define USBCMD_RESET 2 #define USBCMD_RESET 2
#define USB_USBINTR (MSM_USB_BASE + 0x0148) #define USB_USBINTR (MSM_USB_BASE + 0x0148)