#define QDSS_BHS_ON BIT(21)
#define QDSS_LDO_BYP BIT(22)
+struct reg_info {
+ struct regulator *reg;
+ int uV;
+ int uA;
+};
+
+struct qcom_mss_reg_res {
+ const char *supply;
+ int uV;
+ int uA;
+};
+
struct rproc_hexagon_res {
const char *hexagon_mba_image;
+ struct qcom_mss_reg_res proxy_supply[4];
+ struct qcom_mss_reg_res active_supply[2];
char **proxy_clk_names;
char **active_clk_names;
};
int active_clk_count;
int proxy_clk_count;
- struct regulator_bulk_data supply[4];
-
+ struct reg_info active_regs[1];
+ struct reg_info proxy_regs[3];
+ int active_reg_count;
+ int proxy_reg_count;
struct completion start_done;
struct completion stop_done;
size_t mpss_size;
};
-enum {
- Q6V5_SUPPLY_CX,
- Q6V5_SUPPLY_MX,
- Q6V5_SUPPLY_MSS,
- Q6V5_SUPPLY_PLL,
-};
-
-static int q6v5_regulator_init(struct q6v5 *qproc)
+static int q6v5_regulator_init(struct device *dev, struct reg_info *regs,
+ const struct qcom_mss_reg_res *reg_res)
{
- int ret;
+ int rc;
+ int i;
- qproc->supply[Q6V5_SUPPLY_CX].supply = "cx";
- qproc->supply[Q6V5_SUPPLY_MX].supply = "mx";
- qproc->supply[Q6V5_SUPPLY_MSS].supply = "mss";
- qproc->supply[Q6V5_SUPPLY_PLL].supply = "pll";
+ for (i = 0; reg_res[i].supply; i++) {
+ regs[i].reg = devm_regulator_get(dev, reg_res[i].supply);
+ if (IS_ERR(regs[i].reg)) {
+ rc = PTR_ERR(regs[i].reg);
+ if (rc != -EPROBE_DEFER)
+ dev_err(dev, "Failed to get %s\n regulator",
+ reg_res[i].supply);
+ return rc;
+ }
- ret = devm_regulator_bulk_get(qproc->dev,
- ARRAY_SIZE(qproc->supply), qproc->supply);
- if (ret < 0) {
- dev_err(qproc->dev, "failed to get supplies\n");
- return ret;
+ regs[i].uV = reg_res[i].uV;
+ regs[i].uA = reg_res[i].uA;
}
- regulator_set_load(qproc->supply[Q6V5_SUPPLY_CX].consumer, 100000);
- regulator_set_load(qproc->supply[Q6V5_SUPPLY_MSS].consumer, 100000);
- regulator_set_load(qproc->supply[Q6V5_SUPPLY_PLL].consumer, 10000);
-
- return 0;
+ return i;
}
-static int q6v5_regulator_enable(struct q6v5 *qproc)
+static int q6v5_regulator_enable(struct q6v5 *qproc,
+ struct reg_info *regs, int count)
{
- struct regulator *mss = qproc->supply[Q6V5_SUPPLY_MSS].consumer;
- struct regulator *mx = qproc->supply[Q6V5_SUPPLY_MX].consumer;
int ret;
+ int i;
- /* TODO: Q6V5_SUPPLY_CX is supposed to be set to super-turbo here */
+ for (i = 0; i < count; i++) {
+ if (regs[i].uV > 0) {
+ ret = regulator_set_voltage(regs[i].reg,
+ regs[i].uV, INT_MAX);
+ if (ret) {
+ dev_err(qproc->dev,
+ "Failed to request voltage for %d.\n",
+ i);
+ goto err;
+ }
+ }
- ret = regulator_set_voltage(mx, 1050000, INT_MAX);
- if (ret)
- return ret;
+ if (regs[i].uA > 0) {
+ ret = regulator_set_load(regs[i].reg,
+ regs[i].uA);
+ if (ret < 0) {
+ dev_err(qproc->dev,
+ "Failed to set regulator mode\n");
+ goto err;
+ }
+ }
+
+ ret = regulator_enable(regs[i].reg);
+ if (ret) {
+ dev_err(qproc->dev, "Regulator enable failed\n");
+ goto err;
+ }
+ }
+
+ return 0;
+err:
+ for (; i >= 0; i--) {
+ if (regs[i].uV > 0)
+ regulator_set_voltage(regs[i].reg, 0, INT_MAX);
+
+ if (regs[i].uA > 0)
+ regulator_set_load(regs[i].reg, 0);
- regulator_set_voltage(mss, 1000000, 1150000);
+ regulator_disable(regs[i].reg);
+ }
- return regulator_bulk_enable(ARRAY_SIZE(qproc->supply), qproc->supply);
+ return ret;
}
-static void q6v5_regulator_disable(struct q6v5 *qproc)
+static void q6v5_regulator_disable(struct q6v5 *qproc,
+ struct reg_info *regs, int count)
{
- struct regulator *mss = qproc->supply[Q6V5_SUPPLY_MSS].consumer;
- struct regulator *mx = qproc->supply[Q6V5_SUPPLY_MX].consumer;
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if (regs[i].uV > 0)
+ regulator_set_voltage(regs[i].reg, 0, INT_MAX);
- /* TODO: Q6V5_SUPPLY_CX corner votes should be released */
+ if (regs[i].uA > 0)
+ regulator_set_load(regs[i].reg, 0);
- regulator_bulk_disable(ARRAY_SIZE(qproc->supply), qproc->supply);
- regulator_set_voltage(mx, 0, INT_MAX);
- regulator_set_voltage(mss, 0, 1150000);
+ regulator_disable(regs[i].reg);
+ }
}
static int q6v5_clk_enable(struct device *dev,
struct q6v5 *qproc = (struct q6v5 *)rproc->priv;
int ret;
- ret = q6v5_regulator_enable(qproc);
+ ret = q6v5_regulator_enable(qproc, qproc->proxy_regs,
+ qproc->proxy_reg_count);
if (ret) {
- dev_err(qproc->dev, "failed to enable supplies\n");
+ dev_err(qproc->dev, "failed to enable proxy supplies\n");
return ret;
}
qproc->proxy_clk_count);
if (ret) {
dev_err(qproc->dev, "failed to enable proxy clocks\n");
- goto disable_vdd;
+ goto disable_proxy_reg;
+ }
+
+ ret = q6v5_regulator_enable(qproc, qproc->active_regs,
+ qproc->active_reg_count);
+ if (ret) {
+ dev_err(qproc->dev, "failed to enable supplies\n");
+ goto disable_proxy_clk;
}
ret = reset_control_deassert(qproc->mss_restart);
if (ret) {
dev_err(qproc->dev, "failed to deassert mss restart\n");
- goto disable_proxy_clk;
+ goto disable_vdd;
}
ret = q6v5_clk_enable(qproc->dev, qproc->active_clks,
q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
qproc->proxy_clk_count);
+ q6v5_regulator_disable(qproc, qproc->proxy_regs,
+ qproc->proxy_reg_count);
return 0;
qproc->active_clk_count);
assert_reset:
reset_control_assert(qproc->mss_restart);
+disable_vdd:
+ q6v5_regulator_disable(qproc, qproc->active_regs,
+ qproc->active_reg_count);
disable_proxy_clk:
q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
qproc->proxy_clk_count);
-disable_vdd:
- q6v5_regulator_disable(qproc);
+disable_proxy_reg:
+ q6v5_regulator_disable(qproc, qproc->proxy_regs,
+ qproc->proxy_reg_count);
return ret;
}
reset_control_assert(qproc->mss_restart);
q6v5_clk_disable(qproc->dev, qproc->active_clks,
qproc->active_clk_count);
- q6v5_regulator_disable(qproc);
+ q6v5_regulator_disable(qproc, qproc->active_regs,
+ qproc->active_reg_count);
return 0;
}
}
qproc->active_clk_count = ret;
- ret = q6v5_regulator_init(qproc);
- if (ret)
+ ret = q6v5_regulator_init(&pdev->dev, qproc->proxy_regs,
+ desc->proxy_supply);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to get proxy regulators.\n");
goto free_rproc;
+ }
+ qproc->proxy_reg_count = ret;
+
+ ret = q6v5_regulator_init(&pdev->dev, qproc->active_regs,
+ desc->active_supply);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to get active regulators.\n");
+ goto free_rproc;
+ }
+ qproc->active_reg_count = ret;
ret = q6v5_init_reset(qproc);
if (ret)
static const struct rproc_hexagon_res msm8916_mss = {
.hexagon_mba_image = "mba.mbn",
+ .proxy_supply = (struct qcom_mss_reg_res[]) {
+ {
+ .supply = "mx",
+ .uV = 1050000,
+ },
+ {
+ .supply = "cx",
+ .uA = 100000,
+ },
+ {
+ .supply = "pll",
+ .uA = 100000,
+ },
+ {}
+ },
+ .active_supply = (struct qcom_mss_reg_res[]) {
+ {
+ .supply = "mss",
+ .uV = 1050000,
+ .uA = 100000,
+ },
+ {}
+ },
.proxy_clk_names = (char*[]){
"xo",
NULL
static const struct rproc_hexagon_res msm8974_mss = {
.hexagon_mba_image = "mba.b00",
+ .proxy_supply = (struct qcom_mss_reg_res[]) {
+ {
+ .supply = "mx",
+ .uV = 1050000,
+ },
+ {
+ .supply = "cx",
+ .uA = 100000,
+ },
+ {
+ .supply = "pll",
+ .uA = 100000,
+ },
+ {}
+ },
+ .active_supply = (struct qcom_mss_reg_res[]) {
+ {
+ .supply = "mss",
+ .uV = 1050000,
+ .uA = 100000,
+ },
+ {}
+ },
.proxy_clk_names = (char*[]){
"xo",
NULL