diff mbox

[3/5] remoteproc: Adding reset sequence and halt seq changes for q6v55

Message ID 1477324559-24752-4-git-send-email-akdwived@codeaurora.org (mailing list archive)
State Changes Requested
Headers show

Commit Message

Dwivedi, Avaneesh Kumar (avani) Oct. 24, 2016, 3:55 p.m. UTC
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(-)

Comments

Bjorn Andersson Oct. 25, 2016, 7:15 p.m. UTC | #1
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
Dwivedi, Avaneesh Kumar (avani) Nov. 4, 2016, 1:42 p.m. UTC | #2
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 mbox

Patch

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);