[08/28] venus: hfi_venus: add suspend function for 4xx version

Message ID 20180424124436.26955-9-stanimir.varbanov@linaro.org
State New
Headers show
Series
  • Venus updates
Related show

Commit Message

Stanimir Varbanov April 24, 2018, 12:44 p.m.
This adds suspend (power collapse) function with slightly
different order of calls comparing with Venus 3xx.

Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>

---
 drivers/media/platform/qcom/venus/hfi_venus.c | 52 +++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

-- 
2.14.1

Comments

Vikash Garodia May 2, 2018, 6:07 a.m. | #1
Hello Stanimir,

On 2018-04-24 18:14, Stanimir Varbanov wrote:
> This adds suspend (power collapse) function with slightly

> different order of calls comparing with Venus 3xx.

> 

> Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>

> ---

>  drivers/media/platform/qcom/venus/hfi_venus.c | 52 

> +++++++++++++++++++++++++++

>  1 file changed, 52 insertions(+)

> 

> diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c

> b/drivers/media/platform/qcom/venus/hfi_venus.c

> index 53546174aab8..f61d34bf61b4 100644

> --- a/drivers/media/platform/qcom/venus/hfi_venus.c

> +++ b/drivers/media/platform/qcom/venus/hfi_venus.c

> @@ -1443,6 +1443,55 @@ static int venus_suspend_1xx(struct venus_core 

> *core)

>  	return 0;

>  }

> 

> +static int venus_suspend_4xx(struct venus_core *core)

> +{

> +	struct venus_hfi_device *hdev = to_hfi_priv(core);

> +	struct device *dev = core->dev;

> +	u32 val;

> +	int ret;

> +

> +	if (!hdev->power_enabled || hdev->suspended)

> +		return 0;

> +

> +	mutex_lock(&hdev->lock);

> +	ret = venus_is_valid_state(hdev);

> +	mutex_unlock(&hdev->lock);

> +

> +	if (!ret) {

> +		dev_err(dev, "bad state, cannot suspend\n");

> +		return -EINVAL;

> +	}

> +

> +	ret = venus_prepare_power_collapse(hdev, false);

> +	if (ret) {

> +		dev_err(dev, "prepare for power collapse fail (%d)\n", ret);

> +		return ret;

> +	}

> +

> +	ret = readl_poll_timeout(core->base + CPU_CS_SCIACMDARG0, val,

> +				 val & CPU_CS_SCIACMDARG0_PC_READY,

> +				 POLL_INTERVAL_US, 100000);

> +	if (ret) {

> +		dev_err(dev, "Polling power collapse ready timed out\n");

> +		return ret;

> +	}

> +

> +	mutex_lock(&hdev->lock);

> +

> +	ret = venus_power_off(hdev);

> +	if (ret) {

> +		dev_err(dev, "venus_power_off (%d)\n", ret);

> +		mutex_unlock(&hdev->lock);

> +		return ret;

> +	}

> +

> +	hdev->suspended = true;

> +

> +	mutex_unlock(&hdev->lock);

> +

> +	return 0;

> +}

> +

>  static int venus_suspend_3xx(struct venus_core *core)

>  {

>  	struct venus_hfi_device *hdev = to_hfi_priv(core);

> @@ -1507,6 +1556,9 @@ static int venus_suspend(struct venus_core *core)

>  	if (core->res->hfi_version == HFI_VERSION_3XX)

>  		return venus_suspend_3xx(core);

> 

> +	if (core->res->hfi_version == HFI_VERSION_4XX)

> +		return venus_suspend_4xx(core);

> +

>  	return venus_suspend_1xx(core);

>  }


Let me brief on the power collapse sequence for Venus_4xx
1. Host checks for ARM9 and Video core to be idle.
    This can be done by checking for WFI bit (bit 0) in CPU status 
register for ARM9 and by checking bit 30 in Control status reg for video 
core/s.
2. Host then sends command to ARM9 to prepare for power collapse.
3. Host then checks for WFI bit and PC_READY bit before withdrawing 
going for power off.

As per this patch, host is preparing for power collapse without checking 
for #1.
Update the code to handle #3.

Thanks
Vikash
Stanimir Varbanov May 9, 2018, 11:15 a.m. | #2
Hi Vikash,

On 05/02/2018 09:07 AM, vgarodia@codeaurora.org wrote:
> Hello Stanimir,

> 

> On 2018-04-24 18:14, Stanimir Varbanov wrote:

>> This adds suspend (power collapse) function with slightly

>> different order of calls comparing with Venus 3xx.

>>

>> Signed-off-by: Stanimir Varbanov <stanimir.varbanov@linaro.org>

>> ---

>>  drivers/media/platform/qcom/venus/hfi_venus.c | 52

>> +++++++++++++++++++++++++++

>>  1 file changed, 52 insertions(+)

>>

>> diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c

>> b/drivers/media/platform/qcom/venus/hfi_venus.c

>> index 53546174aab8..f61d34bf61b4 100644

>> --- a/drivers/media/platform/qcom/venus/hfi_venus.c

>> +++ b/drivers/media/platform/qcom/venus/hfi_venus.c

>> @@ -1443,6 +1443,55 @@ static int venus_suspend_1xx(struct venus_core

>> *core)

>>      return 0;

>>  }

>>

>> +static int venus_suspend_4xx(struct venus_core *core)

>> +{

>> +    struct venus_hfi_device *hdev = to_hfi_priv(core);

>> +    struct device *dev = core->dev;

>> +    u32 val;

>> +    int ret;

>> +

>> +    if (!hdev->power_enabled || hdev->suspended)

>> +        return 0;

>> +

>> +    mutex_lock(&hdev->lock);

>> +    ret = venus_is_valid_state(hdev);

>> +    mutex_unlock(&hdev->lock);

>> +

>> +    if (!ret) {

>> +        dev_err(dev, "bad state, cannot suspend\n");

>> +        return -EINVAL;

>> +    }

>> +

>> +    ret = venus_prepare_power_collapse(hdev, false);

>> +    if (ret) {

>> +        dev_err(dev, "prepare for power collapse fail (%d)\n", ret);

>> +        return ret;

>> +    }

>> +

>> +    ret = readl_poll_timeout(core->base + CPU_CS_SCIACMDARG0, val,

>> +                 val & CPU_CS_SCIACMDARG0_PC_READY,

>> +                 POLL_INTERVAL_US, 100000);

>> +    if (ret) {

>> +        dev_err(dev, "Polling power collapse ready timed out\n");

>> +        return ret;

>> +    }

>> +

>> +    mutex_lock(&hdev->lock);

>> +

>> +    ret = venus_power_off(hdev);

>> +    if (ret) {

>> +        dev_err(dev, "venus_power_off (%d)\n", ret);

>> +        mutex_unlock(&hdev->lock);

>> +        return ret;

>> +    }

>> +

>> +    hdev->suspended = true;

>> +

>> +    mutex_unlock(&hdev->lock);

>> +

>> +    return 0;

>> +}

>> +

>>  static int venus_suspend_3xx(struct venus_core *core)

>>  {

>>      struct venus_hfi_device *hdev = to_hfi_priv(core);

>> @@ -1507,6 +1556,9 @@ static int venus_suspend(struct venus_core *core)

>>      if (core->res->hfi_version == HFI_VERSION_3XX)

>>          return venus_suspend_3xx(core);

>>

>> +    if (core->res->hfi_version == HFI_VERSION_4XX)

>> +        return venus_suspend_4xx(core);

>> +

>>      return venus_suspend_1xx(core);

>>  }

> 

> Let me brief on the power collapse sequence for Venus_4xx

> 1. Host checks for ARM9 and Video core to be idle.

>    This can be done by checking for WFI bit (bit 0) in CPU status

> register for ARM9 and by checking bit 30 in Control status reg for video

> core/s.

> 2. Host then sends command to ARM9 to prepare for power collapse.

> 3. Host then checks for WFI bit and PC_READY bit before withdrawing

> going for power off.

> 

> As per this patch, host is preparing for power collapse without checking

> for #1.

> Update the code to handle #3.


This looks similar to suspend for Venus 3xx. Can you confirm that the
sequence of checks for 4xx is the same as 3xx?

-- 
regards,
Stan

Patch

diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c b/drivers/media/platform/qcom/venus/hfi_venus.c
index 53546174aab8..f61d34bf61b4 100644
--- a/drivers/media/platform/qcom/venus/hfi_venus.c
+++ b/drivers/media/platform/qcom/venus/hfi_venus.c
@@ -1443,6 +1443,55 @@  static int venus_suspend_1xx(struct venus_core *core)
 	return 0;
 }
 
+static int venus_suspend_4xx(struct venus_core *core)
+{
+	struct venus_hfi_device *hdev = to_hfi_priv(core);
+	struct device *dev = core->dev;
+	u32 val;
+	int ret;
+
+	if (!hdev->power_enabled || hdev->suspended)
+		return 0;
+
+	mutex_lock(&hdev->lock);
+	ret = venus_is_valid_state(hdev);
+	mutex_unlock(&hdev->lock);
+
+	if (!ret) {
+		dev_err(dev, "bad state, cannot suspend\n");
+		return -EINVAL;
+	}
+
+	ret = venus_prepare_power_collapse(hdev, false);
+	if (ret) {
+		dev_err(dev, "prepare for power collapse fail (%d)\n", ret);
+		return ret;
+	}
+
+	ret = readl_poll_timeout(core->base + CPU_CS_SCIACMDARG0, val,
+				 val & CPU_CS_SCIACMDARG0_PC_READY,
+				 POLL_INTERVAL_US, 100000);
+	if (ret) {
+		dev_err(dev, "Polling power collapse ready timed out\n");
+		return ret;
+	}
+
+	mutex_lock(&hdev->lock);
+
+	ret = venus_power_off(hdev);
+	if (ret) {
+		dev_err(dev, "venus_power_off (%d)\n", ret);
+		mutex_unlock(&hdev->lock);
+		return ret;
+	}
+
+	hdev->suspended = true;
+
+	mutex_unlock(&hdev->lock);
+
+	return 0;
+}
+
 static int venus_suspend_3xx(struct venus_core *core)
 {
 	struct venus_hfi_device *hdev = to_hfi_priv(core);
@@ -1507,6 +1556,9 @@  static int venus_suspend(struct venus_core *core)
 	if (core->res->hfi_version == HFI_VERSION_3XX)
 		return venus_suspend_3xx(core);
 
+	if (core->res->hfi_version == HFI_VERSION_4XX)
+		return venus_suspend_4xx(core);
+
 	return venus_suspend_1xx(core);
 }