USB: EHCI: Add support for overriding corner voltage levels for VDDCX
Currently ehci-msm2 driver does have support for voting corner voltages
for VDDCX. These corner voltage levels for VDDCX will change from platform
to platform. Hence add support for passing these corner voltage levels for
VDDCX from device tree file.
Change-Id: Id5d8c1d435721d6e2d1640298685b3f701fc3d6e
Signed-off-by: Vijayavardhan Vennapusa <vvreddy@codeaurora.org>
diff --git a/drivers/usb/host/ehci-msm2.c b/drivers/usb/host/ehci-msm2.c
index 0aecaad..dd04f49 100644
--- a/drivers/usb/host/ehci-msm2.c
+++ b/drivers/usb/host/ehci-msm2.c
@@ -40,6 +40,7 @@
#include <mach/msm_xo.h>
#include <mach/msm_iomap.h>
#include <linux/debugfs.h>
+#include <mach/rpm-regulator.h>
#define MSM_USB_BASE (hcd->regs)
@@ -76,6 +77,7 @@
int wakeup_int_cnt;
bool wakeup_irq_enabled;
int wakeup_irq;
+ enum usb_vdd_type vdd_type;
};
static inline struct msm_hcd *hcd_to_mhcd(struct usb_hcd *hcd)
@@ -96,26 +98,87 @@
#define HSUSB_PHY_1P8_VOL_MAX 1800000 /* uV */
#define HSUSB_PHY_1P8_HPM_LOAD 50000 /* uA */
+#define HSUSB_PHY_VDD_DIG_VOL_NONE 0 /* uV */
#define HSUSB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
#define HSUSB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
#define HSUSB_PHY_VDD_DIG_LOAD 49360 /* uA */
+#define HSUSB_PHY_SUSP_DIG_VOL_P50 500000
+#define HSUSB_PHY_SUSP_DIG_VOL_P75 750000
+enum hsusb_vdd_value {
+ VDD_MIN_NONE = 0,
+ VDD_MIN_P50,
+ VDD_MIN_P75,
+ VDD_MIN_OP,
+ VDD_MAX_OP,
+ VDD_VAL_MAX_OP,
+};
+
+static int hsusb_vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX_OP] = {
+ { /* VDD_CX CORNER Voting */
+ [VDD_MIN_NONE] = RPM_VREG_CORNER_NONE,
+ [VDD_MIN_P50] = RPM_VREG_CORNER_NONE,
+ [VDD_MIN_P75] = RPM_VREG_CORNER_NONE,
+ [VDD_MIN_OP] = RPM_VREG_CORNER_NOMINAL,
+ [VDD_MAX_OP] = RPM_VREG_CORNER_HIGH,
+ },
+ { /* VDD_CX Voltage Voting */
+ [VDD_MIN_NONE] = HSUSB_PHY_VDD_DIG_VOL_NONE,
+ [VDD_MIN_P50] = HSUSB_PHY_SUSP_DIG_VOL_P50,
+ [VDD_MIN_P75] = HSUSB_PHY_SUSP_DIG_VOL_P75,
+ [VDD_MIN_OP] = HSUSB_PHY_VDD_DIG_VOL_MIN,
+ [VDD_MAX_OP] = HSUSB_PHY_VDD_DIG_VOL_MAX,
+ },
+};
+
static int msm_ehci_init_vddcx(struct msm_hcd *mhcd, int init)
{
int ret = 0;
+ int none_vol, min_vol, max_vol;
+ u32 tmp[5];
+ int len = 0;
- if (!init)
+ if (!init) {
+ none_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_NONE];
+ max_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MAX_OP];
goto disable_reg;
-
- mhcd->hsusb_vddcx = devm_regulator_get(mhcd->dev, "HSUSB_VDDCX");
- if (IS_ERR(mhcd->hsusb_vddcx)) {
- dev_err(mhcd->dev, "unable to get ehci vddcx\n");
- return PTR_ERR(mhcd->hsusb_vddcx);
}
- ret = regulator_set_voltage(mhcd->hsusb_vddcx,
- HSUSB_PHY_VDD_DIG_VOL_MIN,
- HSUSB_PHY_VDD_DIG_VOL_MAX);
+ mhcd->vdd_type = VDDCX_CORNER;
+ mhcd->hsusb_vddcx = devm_regulator_get(mhcd->dev, "hsusb_vdd_dig");
+ if (IS_ERR(mhcd->hsusb_vddcx)) {
+ mhcd->hsusb_vddcx = devm_regulator_get(mhcd->dev,
+ "HSUSB_VDDCX");
+ if (IS_ERR(mhcd->hsusb_vddcx)) {
+ dev_err(mhcd->dev, "unable to get ehci vddcx\n");
+ return PTR_ERR(mhcd->hsusb_vddcx);
+ }
+ mhcd->vdd_type = VDDCX;
+ }
+
+ if (mhcd->dev->of_node) {
+ of_get_property(mhcd->dev->of_node,
+ "qcom,vdd-voltage-level",
+ &len);
+ if (len == sizeof(tmp)) {
+ of_property_read_u32_array(mhcd->dev->of_node,
+ "qcom,vdd-voltage-level",
+ tmp, len/sizeof(*tmp));
+ hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_NONE] = tmp[0];
+ hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_P50] = tmp[1];
+ hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_P75] = tmp[2];
+ hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_OP] = tmp[3];
+ hsusb_vdd_val[mhcd->vdd_type][VDD_MAX_OP] = tmp[4];
+ } else {
+ dev_dbg(mhcd->dev, "Use default vdd config\n");
+ }
+ }
+
+ none_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_NONE];
+ min_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_OP];
+ max_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MAX_OP];
+
+ ret = regulator_set_voltage(mhcd->hsusb_vddcx, min_vol, max_vol);
if (ret) {
dev_err(mhcd->dev, "unable to set the voltage"
"for ehci vddcx\n");
@@ -143,8 +206,7 @@
reg_enable_err:
regulator_set_optimum_mode(mhcd->hsusb_vddcx, 0);
reg_optimum_mode_err:
- regulator_set_voltage(mhcd->hsusb_vddcx, 0,
- HSUSB_PHY_VDD_DIG_VOL_MIN);
+ regulator_set_voltage(mhcd->hsusb_vddcx, none_vol, max_vol);
return ret;
}
@@ -194,24 +256,22 @@
}
#ifdef CONFIG_PM_SLEEP
-#define HSUSB_PHY_SUSP_DIG_VOL_P50 500000
-#define HSUSB_PHY_SUSP_DIG_VOL_P75 750000
static int msm_ehci_config_vddcx(struct msm_hcd *mhcd, int high)
{
struct msm_usb_host_platform_data *pdata;
- int max_vol = HSUSB_PHY_VDD_DIG_VOL_MAX;
+ int max_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MAX_OP];
int min_vol;
int ret;
pdata = mhcd->dev->platform_data;
if (high)
- min_vol = HSUSB_PHY_VDD_DIG_VOL_MIN;
+ min_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_OP];
else if (pdata && pdata->dock_connect_irq &&
!irq_read_line(pdata->dock_connect_irq))
- min_vol = HSUSB_PHY_SUSP_DIG_VOL_P75;
+ min_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_P75];
else
- min_vol = HSUSB_PHY_SUSP_DIG_VOL_P50;
+ min_vol = hsusb_vdd_val[mhcd->vdd_type][VDD_MIN_P50];
ret = regulator_set_voltage(mhcd->hsusb_vddcx, min_vol, max_vol);
if (ret) {