Message ID | 1477324559-24752-4-git-send-email-akdwived@codeaurora.org (mailing list archive) |
---|---|
State | Changes Requested |
Headers | show |
On Mon 24 Oct 08:55 PDT 2016, Avaneesh Kumar Dwivedi wrote: > q6v55 reset sequence is handled separately and removing idle check > before asserting reset as it has been observed it return idle some > time even without being in idle. > > Signed-off-by: Avaneesh Kumar Dwivedi <akdwived@codeaurora.org> > --- > drivers/remoteproc/qcom_q6v5_pil.c | 103 +++++++++++++++++++++++++++++++++++-- > 1 file changed, 98 insertions(+), 5 deletions(-) > > diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c > index c7dca40..0fac8d8 100644 > --- a/drivers/remoteproc/qcom_q6v5_pil.c > +++ b/drivers/remoteproc/qcom_q6v5_pil.c > @@ -536,6 +536,104 @@ static int q6v5proc_reset(struct q6v5 *qproc) > return ret; > } > > +static int q6v6proc_reset(struct q6v5 *qproc) Which version is this? 5.5, 55 or 6? It's perfectly fine to introduce q6v55-functions and use those, but if the version is 6 then the compatible should reflect that at least. > +{ > + int ret, i, count; > + u64 val; > + > + /* Override the ACC value if required */ > + writel_relaxed(QDSP6SS_ACC_OVERRIDE_VAL, > + qproc->reg_base + QDSP6SS_STRAP_ACC); > + > + /* Assert resets, stop core */ > + val = readl_relaxed(qproc->reg_base + QDSP6SS_RESET_REG); > + val |= (Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE); > + writel_relaxed(val, qproc->reg_base + QDSP6SS_RESET_REG); > + > + /* BHS require xo cbcr to be enabled */ > + val = readl_relaxed(qproc->reg_base + QDSP6SS_XO_CBCR); > + val |= 0x1; > + writel_relaxed(val, qproc->reg_base + QDSP6SS_XO_CBCR); > + for (count = HALT_CHECK_MAX_LOOPS; count > 0; count--) { > + val = readl_relaxed(qproc->reg_base + QDSP6SS_XO_CBCR); > + if (!(val & BIT(31))) > + break; > + udelay(1); > + } > + > + val = readl_relaxed(qproc->reg_base + QDSP6SS_XO_CBCR); > + if ((val & BIT(31))) > + dev_err(qproc->dev, "Failed to enable xo branch clock.\n"); > + > + /* Enable power block headswitch, and wait for it to stabilize */ > + val = readl_relaxed(qproc->reg_base + QDSP6SS_PWR_CTL_REG); > + val |= QDSP6v55_BHS_ON; > + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); > + udelay(1); > + > + /* Put LDO in bypass mode */ > + val |= QDSP6v55_LDO_BYP; > + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); > + /* > + * Turn on memories. L2 banks should be done individually > + * to minimize inrush current. > + */ > + val = readl_relaxed(qproc->reg_base + QDSP6SS_PWR_CTL_REG); > + val &= ~QDSP6v55_CLAMP_QMC_MEM; > + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); > + > + /* Deassert memory peripheral sleep and L2 memory standby */ > + val |= (Q6SS_L2DATA_STBY_N | Q6SS_SLP_RET_N); > + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); > + > + /* Turn on L1, L2, ETB and JU memories 1 at a time */ > + val = readl_relaxed(qproc->reg_base + QDSP6SS_MEM_PWR_CTL); > + for (i = 19; i >= 0; i--) { > + val |= BIT(i); > + writel_relaxed(val, qproc->reg_base + > + QDSP6SS_MEM_PWR_CTL); > + /* > + * Wait for 1us for both memory peripheral and > + * data array to turn on. > + */ > + mb(); > + udelay(1); > + } > + > + /* Remove word line clamp */ > + val = readl_relaxed(qproc->reg_base + QDSP6SS_PWR_CTL_REG); > + val &= ~QDSP6v55_CLAMP_WL; > + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); > + > + /* Remove IO clamp */ > + val &= ~Q6SS_CLAMP_IO; > + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); > + > + /* Bring core out of reset */ > + val = readl_relaxed(qproc->reg_base + QDSP6SS_RESET_REG); > + val &= ~(Q6SS_CORE_ARES | Q6SS_STOP_CORE); > + writel_relaxed(val, qproc->reg_base + QDSP6SS_RESET_REG); > + > + /* Turn on core clock */ > + val = readl_relaxed(qproc->reg_base + QDSP6SS_GFMUX_CTL_REG); > + val |= Q6SS_CLK_ENABLE; > + writel_relaxed(val, qproc->reg_base + QDSP6SS_GFMUX_CTL_REG); > + > + > + /* Wait for PBL status */ > + ret = q6v5_rmb_pbl_wait(qproc, 1000); > + if (ret == -ETIMEDOUT) { > + dev_err(qproc->dev, "PBL boot timed out\n"); > + } else if (ret != RMB_PBL_SUCCESS) { > + dev_err(qproc->dev, "PBL returned unexpected status %d\n", ret); > + ret = -EINVAL; > + } else { > + ret = 0; > + } > + > + return ret; > +} Most of this function is exactly the same as q6v5proc_reset(), do we need two copies or can we make the differences conditional based on compatible? > + > static void q6v5proc_halt_axi_port(struct q6v5 *qproc, > struct regmap *halt_map, > u32 offset) > @@ -544,11 +642,6 @@ static void q6v5proc_halt_axi_port(struct q6v5 *qproc, > unsigned int val; > int ret; > > - /* Check if we're already idle */ > - ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val); > - if (!ret && val) > - return; > - I presume this check isn't needed on the other versions either? > /* Assert halt request */ > regmap_write(halt_map, offset + AXI_HALTREQ_REG, 1); > Regards, Bjorn -- To unsubscribe from this list: send the line "unsubscribe linux-remoteproc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 10/26/2016 12:45 AM, Bjorn Andersson wrote: > On Mon 24 Oct 08:55 PDT 2016, Avaneesh Kumar Dwivedi wrote: > >> q6v55 reset sequence is handled separately and removing idle check >> before asserting reset as it has been observed it return idle some >> time even without being in idle. >> >> Signed-off-by: Avaneesh Kumar Dwivedi <akdwived@codeaurora.org> >> --- >> drivers/remoteproc/qcom_q6v5_pil.c | 103 +++++++++++++++++++++++++++++++++++-- >> 1 file changed, 98 insertions(+), 5 deletions(-) >> >> diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c >> index c7dca40..0fac8d8 100644 >> --- a/drivers/remoteproc/qcom_q6v5_pil.c >> +++ b/drivers/remoteproc/qcom_q6v5_pil.c >> @@ -536,6 +536,104 @@ static int q6v5proc_reset(struct q6v5 *qproc) >> return ret; >> } >> >> +static int q6v6proc_reset(struct q6v5 *qproc) > Which version is this? 5.5, 55 or 6? > > It's perfectly fine to introduce q6v55-functions and use those, but if > the version is 6 then the compatible should reflect that at least. OK. > >> +{ >> + int ret, i, count; >> + u64 val; >> + >> + /* Override the ACC value if required */ >> + writel_relaxed(QDSP6SS_ACC_OVERRIDE_VAL, >> + qproc->reg_base + QDSP6SS_STRAP_ACC); >> + >> + /* Assert resets, stop core */ >> + val = readl_relaxed(qproc->reg_base + QDSP6SS_RESET_REG); >> + val |= (Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE); >> + writel_relaxed(val, qproc->reg_base + QDSP6SS_RESET_REG); >> + >> + /* BHS require xo cbcr to be enabled */ >> + val = readl_relaxed(qproc->reg_base + QDSP6SS_XO_CBCR); >> + val |= 0x1; >> + writel_relaxed(val, qproc->reg_base + QDSP6SS_XO_CBCR); >> + for (count = HALT_CHECK_MAX_LOOPS; count > 0; count--) { >> + val = readl_relaxed(qproc->reg_base + QDSP6SS_XO_CBCR); >> + if (!(val & BIT(31))) >> + break; >> + udelay(1); >> + } >> + >> + val = readl_relaxed(qproc->reg_base + QDSP6SS_XO_CBCR); >> + if ((val & BIT(31))) >> + dev_err(qproc->dev, "Failed to enable xo branch clock.\n"); >> + >> + /* Enable power block headswitch, and wait for it to stabilize */ >> + val = readl_relaxed(qproc->reg_base + QDSP6SS_PWR_CTL_REG); >> + val |= QDSP6v55_BHS_ON; >> + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); >> + udelay(1); >> + >> + /* Put LDO in bypass mode */ >> + val |= QDSP6v55_LDO_BYP; >> + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); >> + /* >> + * Turn on memories. L2 banks should be done individually >> + * to minimize inrush current. >> + */ >> + val = readl_relaxed(qproc->reg_base + QDSP6SS_PWR_CTL_REG); >> + val &= ~QDSP6v55_CLAMP_QMC_MEM; >> + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); >> + >> + /* Deassert memory peripheral sleep and L2 memory standby */ >> + val |= (Q6SS_L2DATA_STBY_N | Q6SS_SLP_RET_N); >> + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); >> + >> + /* Turn on L1, L2, ETB and JU memories 1 at a time */ >> + val = readl_relaxed(qproc->reg_base + QDSP6SS_MEM_PWR_CTL); >> + for (i = 19; i >= 0; i--) { >> + val |= BIT(i); >> + writel_relaxed(val, qproc->reg_base + >> + QDSP6SS_MEM_PWR_CTL); >> + /* >> + * Wait for 1us for both memory peripheral and >> + * data array to turn on. >> + */ >> + mb(); >> + udelay(1); >> + } >> + >> + /* Remove word line clamp */ >> + val = readl_relaxed(qproc->reg_base + QDSP6SS_PWR_CTL_REG); >> + val &= ~QDSP6v55_CLAMP_WL; >> + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); >> + >> + /* Remove IO clamp */ >> + val &= ~Q6SS_CLAMP_IO; >> + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); >> + >> + /* Bring core out of reset */ >> + val = readl_relaxed(qproc->reg_base + QDSP6SS_RESET_REG); >> + val &= ~(Q6SS_CORE_ARES | Q6SS_STOP_CORE); >> + writel_relaxed(val, qproc->reg_base + QDSP6SS_RESET_REG); >> + >> + /* Turn on core clock */ >> + val = readl_relaxed(qproc->reg_base + QDSP6SS_GFMUX_CTL_REG); >> + val |= Q6SS_CLK_ENABLE; >> + writel_relaxed(val, qproc->reg_base + QDSP6SS_GFMUX_CTL_REG); >> + >> + >> + /* Wait for PBL status */ >> + ret = q6v5_rmb_pbl_wait(qproc, 1000); >> + if (ret == -ETIMEDOUT) { >> + dev_err(qproc->dev, "PBL boot timed out\n"); >> + } else if (ret != RMB_PBL_SUCCESS) { >> + dev_err(qproc->dev, "PBL returned unexpected status %d\n", ret); >> + ret = -EINVAL; >> + } else { >> + ret = 0; >> + } >> + >> + return ret; >> +} > Most of this function is exactly the same as q6v5proc_reset(), do we > need two copies or can we make the differences conditional based on > compatible? OK. in reorganized code have merged them in one > >> + >> static void q6v5proc_halt_axi_port(struct q6v5 *qproc, >> struct regmap *halt_map, >> u32 offset) >> @@ -544,11 +642,6 @@ static void q6v5proc_halt_axi_port(struct q6v5 *qproc, >> unsigned int val; >> int ret; >> >> - /* Check if we're already idle */ >> - ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val); >> - if (!ret && val) >> - return; >> - > I presume this check isn't needed on the other versions either? YES, i believe so. have removed that > >> /* Assert halt request */ >> regmap_write(halt_map, offset + AXI_HALTREQ_REG, 1); >> > Regards, > Bjorn -- To unsubscribe from this list: send the line "unsubscribe linux-remoteproc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c index c7dca40..0fac8d8 100644 --- a/drivers/remoteproc/qcom_q6v5_pil.c +++ b/drivers/remoteproc/qcom_q6v5_pil.c @@ -536,6 +536,104 @@ static int q6v5proc_reset(struct q6v5 *qproc) return ret; } +static int q6v6proc_reset(struct q6v5 *qproc) +{ + int ret, i, count; + u64 val; + + /* Override the ACC value if required */ + writel_relaxed(QDSP6SS_ACC_OVERRIDE_VAL, + qproc->reg_base + QDSP6SS_STRAP_ACC); + + /* Assert resets, stop core */ + val = readl_relaxed(qproc->reg_base + QDSP6SS_RESET_REG); + val |= (Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENABLE | Q6SS_STOP_CORE); + writel_relaxed(val, qproc->reg_base + QDSP6SS_RESET_REG); + + /* BHS require xo cbcr to be enabled */ + val = readl_relaxed(qproc->reg_base + QDSP6SS_XO_CBCR); + val |= 0x1; + writel_relaxed(val, qproc->reg_base + QDSP6SS_XO_CBCR); + for (count = HALT_CHECK_MAX_LOOPS; count > 0; count--) { + val = readl_relaxed(qproc->reg_base + QDSP6SS_XO_CBCR); + if (!(val & BIT(31))) + break; + udelay(1); + } + + val = readl_relaxed(qproc->reg_base + QDSP6SS_XO_CBCR); + if ((val & BIT(31))) + dev_err(qproc->dev, "Failed to enable xo branch clock.\n"); + + /* Enable power block headswitch, and wait for it to stabilize */ + val = readl_relaxed(qproc->reg_base + QDSP6SS_PWR_CTL_REG); + val |= QDSP6v55_BHS_ON; + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + udelay(1); + + /* Put LDO in bypass mode */ + val |= QDSP6v55_LDO_BYP; + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + /* + * Turn on memories. L2 banks should be done individually + * to minimize inrush current. + */ + val = readl_relaxed(qproc->reg_base + QDSP6SS_PWR_CTL_REG); + val &= ~QDSP6v55_CLAMP_QMC_MEM; + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + + /* Deassert memory peripheral sleep and L2 memory standby */ + val |= (Q6SS_L2DATA_STBY_N | Q6SS_SLP_RET_N); + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + + /* Turn on L1, L2, ETB and JU memories 1 at a time */ + val = readl_relaxed(qproc->reg_base + QDSP6SS_MEM_PWR_CTL); + for (i = 19; i >= 0; i--) { + val |= BIT(i); + writel_relaxed(val, qproc->reg_base + + QDSP6SS_MEM_PWR_CTL); + /* + * Wait for 1us for both memory peripheral and + * data array to turn on. + */ + mb(); + udelay(1); + } + + /* Remove word line clamp */ + val = readl_relaxed(qproc->reg_base + QDSP6SS_PWR_CTL_REG); + val &= ~QDSP6v55_CLAMP_WL; + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + + /* Remove IO clamp */ + val &= ~Q6SS_CLAMP_IO; + writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG); + + /* Bring core out of reset */ + val = readl_relaxed(qproc->reg_base + QDSP6SS_RESET_REG); + val &= ~(Q6SS_CORE_ARES | Q6SS_STOP_CORE); + writel_relaxed(val, qproc->reg_base + QDSP6SS_RESET_REG); + + /* Turn on core clock */ + val = readl_relaxed(qproc->reg_base + QDSP6SS_GFMUX_CTL_REG); + val |= Q6SS_CLK_ENABLE; + writel_relaxed(val, qproc->reg_base + QDSP6SS_GFMUX_CTL_REG); + + + /* Wait for PBL status */ + ret = q6v5_rmb_pbl_wait(qproc, 1000); + if (ret == -ETIMEDOUT) { + dev_err(qproc->dev, "PBL boot timed out\n"); + } else if (ret != RMB_PBL_SUCCESS) { + dev_err(qproc->dev, "PBL returned unexpected status %d\n", ret); + ret = -EINVAL; + } else { + ret = 0; + } + + return ret; +} + static void q6v5proc_halt_axi_port(struct q6v5 *qproc, struct regmap *halt_map, u32 offset) @@ -544,11 +642,6 @@ static void q6v5proc_halt_axi_port(struct q6v5 *qproc, unsigned int val; int ret; - /* Check if we're already idle */ - ret = regmap_read(halt_map, offset + AXI_IDLE_REG, &val); - if (!ret && val) - return; - /* Assert halt request */ regmap_write(halt_map, offset + AXI_HALTREQ_REG, 1);
q6v55 reset sequence is handled separately and removing idle check before asserting reset as it has been observed it return idle some time even without being in idle. Signed-off-by: Avaneesh Kumar Dwivedi <akdwived@codeaurora.org> --- drivers/remoteproc/qcom_q6v5_pil.c | 103 +++++++++++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 5 deletions(-)