diff options
author | Yin, Fengwei <fengwei.yin@linaro.org> | 2015-05-15 11:07:38 +0800 |
---|---|---|
committer | Yin, Fengwei <fengwei.yin@linaro.org> | 2015-07-17 10:28:51 +0800 |
commit | 19e3cf2c7caa2cf72c8bdf176a83613b0c9e0688 (patch) | |
tree | 1b1b7426e58aec6c6c9e90f5636c4c6874c112ae /drivers | |
parent | 35c7c2d6b01a09ad23a1f1b3cb66aa7c936cb69c (diff) |
DB410c has different initliazation sequence.
Signed-off-by: Yin, Fengwei <fengwei.yin@linaro.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath/wcn36xx/wcnss_core.c | 147 |
1 files changed, 128 insertions, 19 deletions
diff --git a/drivers/net/wireless/ath/wcn36xx/wcnss_core.c b/drivers/net/wireless/ath/wcn36xx/wcnss_core.c index 707e6288f4fe..3d120d4d2724 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcnss_core.c +++ b/drivers/net/wireless/ath/wcn36xx/wcnss_core.c @@ -12,24 +12,115 @@ #include "wcn36xx.h" #include "wcnss_core.h" +#define VREG_NULL_CONFIG 0x0000 +#define VREG_GET_REGULATOR_MASK 0x0001 +#define VREG_SET_VOLTAGE_MASK 0x0002 +#define VREG_OPTIMUM_MODE_MASK 0x0004 +#define VREG_ENABLE_MASK 0x0008 + +struct vregs_info { + const char * const name; + int state; + const int nominal_min; + const int low_power_min; + const int max_voltage; + const int uA_load; + struct regulator *regulator; +}; + +/* IRIS regulators for Pronto v2 hardware */ +static struct vregs_info iris_vregs_pronto_v2[] = { + {"qcom,iris-vddxo", VREG_NULL_CONFIG, 1800000, 0, + 1800000, 10000, NULL}, + {"qcom,iris-vddrfa", VREG_NULL_CONFIG, 1300000, 0, + 1300000, 100000, NULL}, + {"qcom,iris-vddpa", VREG_NULL_CONFIG, 3300000, 0, + 3300000, 515000, NULL}, + {"qcom,iris-vdddig", VREG_NULL_CONFIG, 1800000, 0, + 1800000, 10000, NULL}, +}; + +/* WCNSS regulators for Pronto v2 hardware */ +static struct vregs_info pronto_vregs_pronto_v2[] = { + {"qcom,pronto-vddmx", VREG_NULL_CONFIG, 1287500, 0, + 1287500, 0, NULL}, + {"qcom,pronto-vddcx", VREG_NULL_CONFIG, RPM_REGULATOR_CORNER_NORMAL, + RPM_REGULATOR_CORNER_NONE, RPM_REGULATOR_CORNER_SUPER_TURBO, + 0, NULL}, + {"qcom,pronto-vddpx", VREG_NULL_CONFIG, 1800000, 0, + 1800000, 0, NULL}, +}; + +/* Common helper routine to turn on all WCNSS & IRIS vregs */ +static int wcnss_vregs_on(struct device *dev, + struct vregs_info regulators[], uint size) +{ + int i, rc = 0, reg_cnt; + + for (i = 0; i < size; i++) { + /* Get regulator source */ + regulators[i].regulator = + regulator_get(dev, regulators[i].name); + if (IS_ERR(regulators[i].regulator)) { + rc = PTR_ERR(regulators[i].regulator); + pr_err("regulator get of %s failed (%d)\n", + regulators[i].name, rc); + goto fail; + } + regulators[i].state |= VREG_GET_REGULATOR_MASK; + reg_cnt = regulator_count_voltages(regulators[i].regulator); + /* Set voltage to nominal. Exclude swtiches e.g. LVS */ + if ((regulators[i].nominal_min || regulators[i].max_voltage) + && (reg_cnt > 0)) { + rc = regulator_set_voltage(regulators[i].regulator, + regulators[i].nominal_min, + regulators[i].max_voltage); + if (rc) { + pr_err("regulator_set_voltage(%s) failed (%d)\n", + regulators[i].name, rc); + goto fail; + } + regulators[i].state |= VREG_SET_VOLTAGE_MASK; + } + + /* Vote for PWM/PFM mode if needed */ + if (regulators[i].uA_load && (reg_cnt > 0)) { + rc = regulator_set_optimum_mode(regulators[i].regulator, + regulators[i].uA_load); + if (rc < 0) { + pr_err("regulator_set_optimum_mode(%s) failed (%d)\n", + regulators[i].name, rc); + goto fail; + } + regulators[i].state |= VREG_OPTIMUM_MODE_MASK; + } + + /* Enable the regulator */ + rc = regulator_enable(regulators[i].regulator); + if (rc) { + pr_err("vreg %s enable failed (%d)\n", + regulators[i].name, rc); + goto fail; + } + regulators[i].state |= VREG_ENABLE_MASK; + } + + return rc; + +fail: + return -1; +} + static int wcnss_core_config(struct platform_device *pdev, void __iomem *base) { int ret = 0; - struct clk *clk = NULL; - u32 value; + u32 value, iris_read_v = 0xbaadbaad, reg; - clk = clk_get(&pdev->dev, "xo"); - if (IS_ERR(clk)) { - dev_err(&pdev->dev, "can't get clock xo\n"); - return PTR_ERR(clk); - } + wcnss_vregs_on(&pdev->dev, pronto_vregs_pronto_v2, + ARRAY_SIZE(pronto_vregs_pronto_v2)); - ret = clk_prepare_enable(clk); - if (ret) { - dev_err(&pdev->dev, "clock xo enabling failed\n"); - clk_put(clk); - return ret; - } + wcnss_vregs_on(&pdev->dev, iris_vregs_pronto_v2, + ARRAY_SIZE(pronto_vregs_pronto_v2)); value = readl_relaxed(base + SPARE_OFFSET); value |= WCNSS_FW_DOWNLOAD_ENABLE; @@ -41,8 +132,29 @@ static int wcnss_core_config(struct platform_device *pdev, void __iomem *base) WCNSS_PMU_CFG_IRIS_XO_EN; writel_relaxed(value, base + PMU_OFFSET); - value &= ~(WCNSS_PMU_CFG_IRIS_XO_MODE); - value |= WCNSS_PMU_CFG_IRIS_XO_MODE_48; + /* + iris_read_v = readl_relaxed(base + 0x1134); + pr_info("iris_read_v: 0x%x\n", iris_read_v); + + iris_read_v &= 0xffff; + iris_read_v |= 0x04; + writel_relaxed(iris_read_v, base + 0x1134); + + value = readl_relaxed(base + PMU_OFFSET); + value |= BIT(9); + writel_relaxed(value, base + PMU_OFFSET); + + while (readl_relaxed(base + PMU_OFFSET) & + BIT(10)) + cpu_relax(); + + iris_read_v = readl_relaxed(base + 0x1134); + pr_info("wcnss: IRIS Reg: 0x%08x\n", iris_read_v); + value &= ~BIT(9); + */ + + // value |= WCNSS_PMU_CFG_IRIS_XO_MODE_48; + value &= ~6; writel_relaxed(value, base + PMU_OFFSET); @@ -71,11 +183,8 @@ static int wcnss_core_config(struct platform_device *pdev, void __iomem *base) value &= ~(WCNSS_PMU_CFG_GC_BUS_MUX_SEL_TOP | WCNSS_PMU_CFG_IRIS_XO_CFG); writel_relaxed(value, base + PMU_OFFSET); - clk_disable_unprepare(clk); - - msleep(200); - clk_put(clk); + msleep(1000); return ret; } |