Re: [PATCH 3/3] CPU-idle trial fix + PM debug expansion

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



"ext Tero Kristo" <tero.kristo@xxxxxxxxx> writes:

> CPU-idle has a possibility of working now, also added full PRCM register dump
> into pm-debug.
>
> Signed-off-by: Tero Kristo <tero.kristo@xxxxxxxxx>
> ---
>  arch/arm/mach-omap2/cpuidle34xx.c |   30 -------------------------
>  arch/arm/mach-omap2/pm-debug.c    |   17 ++++++++++----
>  arch/arm/mach-omap2/pm34xx.c      |   43 +++++++++++++++++++++++++++---------
>  3 files changed, 44 insertions(+), 46 deletions(-)
>  mode change 100644 => 100755 arch/arm/mach-omap2/pm-debug.c
>
> diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
> index 7af8653..9e65631 100755
> --- a/arch/arm/mach-omap2/cpuidle34xx.c
> +++ b/arch/arm/mach-omap2/cpuidle34xx.c
> @@ -461,10 +461,6 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
>  	per_pwrst = pwrdm_read_pwrst(per_pd);
>  	neon_pwrst = pwrdm_read_pwrst(neon_pd);
>  
> -	/* Do this before any changes to PRCM registers */
> -	if (cx->core_state == PWRDM_POWER_OFF)
> -		omap3_save_prcm_ctx();
> -
>  	/* Program MPU to target state */
>  	if (cx->mpu_state < PWRDM_POWER_ON) {
>  		if (neon_pwrst == PWRDM_POWER_ON) {
> @@ -478,17 +474,6 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
>  
>  	/* Program CORE and PER to target state */
>  	if (cx->core_state < PWRDM_POWER_ON) {
> -		if (per_pwrst == PWRDM_POWER_ON) {
> -			omap2_gpio_prepare_for_retention();
> -			if (clocks_off_while_idle) {
> -				omap3_save_per_ctx();
> -				per_gpio_clk_disable();
> -				omap_save_uart_ctx(2);
> -				omap_serial_enable_clocks(0, 2);
> -			}
> -		}
> -		if (cx->core_state == PWRDM_POWER_OFF)
> -			omap3_save_core_ctx();
>  		pwrdm_set_next_pwrst(core_pd, cx->core_state);
>  	}

This will leave cx->core_state to its previous value in case of ON
state. So just pwrdm_set_next_pwrst(core_pd, cx->core_state) without
if is better.

>  
> @@ -510,22 +495,7 @@ static int omap3_enter_idle(struct cpuidle_device *dev,
>  	}
>  
>  	if (cx->core_state < PWRDM_POWER_ON) {
> -		if ((cx->core_state == PWRDM_POWER_OFF)
> -		&& (pwrdm_read_prev_pwrst(core_pd) == PWRDM_POWER_OFF)) {
> -			omap3_restore_core_ctx();
> -			omap3_restore_prcm_ctx();
> -			omap3_restore_sram_ctx();
> -		}
>  		pwrdm_set_next_pwrst(core_pd, PWRDM_POWER_ON);
> -		if (per_pwrst == PWRDM_POWER_ON) {
> -			if (clocks_off_while_idle) {
> -				omap_serial_enable_clocks(1, 2);
> -				omap_restore_uart_ctx(2);
> -				per_gpio_clk_enable();
> -				omap3_restore_per_ctx();
> -			}
> -			omap2_gpio_resume_after_retention();
> -		}
>  	}
>  
>  	pr_debug("MPU prev st:%x,NEON prev st:%x\n",
> diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
> old mode 100644
> new mode 100755
> index b6f8621..f35b082
> --- a/arch/arm/mach-omap2/pm-debug.c
> +++ b/arch/arm/mach-omap2/pm-debug.c
> @@ -182,26 +182,33 @@ struct pm_module_def {
>  #define MOD_PRM 1
>  
>  static const struct pm_module_def pm_dbg_reg_modules[] = {
> +	{ "IVA2", MOD_CM, OMAP3430_IVA2_MOD, 0, 0x4c },
>  	{ "OCP", MOD_CM, OCP_MOD, 0, 0x10 },
>  	{ "MPU", MOD_CM, MPU_MOD, 4, 0x4c },
>  	{ "CORE", MOD_CM, CORE_MOD, 0, 0x4c },
> -	{ "NEON", MOD_CM, OMAP3430_NEON_MOD, 0x20, 0x48 },
> +	{ "SGX", MOD_CM, OMAP3430ES2_SGX_MOD, 0, 0x4c },
>  	{ "WKUP", MOD_CM, WKUP_MOD, 0, 0x40 },
> -	{ "EMU", MOD_CM, OMAP3430_EMU_MOD, 0x40, 0x54 },
>  	{ "CCR", MOD_CM, PLL_MOD, 0, 0x70 },
>  	{ "DSS", MOD_CM, OMAP3430_DSS_MOD, 0, 0x4c },
> +	{ "CAM", MOD_CM, OMAP3430_CAM_MOD, 0, 0x4c },
>  	{ "PER", MOD_CM, OMAP3430_PER_MOD, 0, 0x4c },
> +	{ "EMU", MOD_CM, OMAP3430_EMU_MOD, 0x40, 0x54 },
> +	{ "NEON", MOD_CM, OMAP3430_NEON_MOD, 0x20, 0x48 },
>  	{ "USB", MOD_CM, OMAP3430ES2_USBHOST_MOD, 0, 0x4c },
>  
> -	{ "OCP", MOD_PRM, OCP_MOD, 0x1c },
> +	{ "IVA2", MOD_PRM, OMAP3430_IVA2_MOD, 0x50, 0xfc },
> +	{ "OCP", MOD_PRM, OCP_MOD, 4, 0x1c },
>  	{ "MPU", MOD_PRM, MPU_MOD, 0x58, 0xe8 },
>  	{ "CORE", MOD_PRM, CORE_MOD, 0x58, 0xf8 },
> -	{ "NEON", MOD_PRM, OMAP3430_NEON_MOD, 0x58, 0xe8 },
> +	{ "SGX", MOD_PRM, OMAP3430ES2_SGX_MOD, 0x58, 0xe8 },
>  	{ "WKUP", MOD_PRM, WKUP_MOD, 0xa0, 0xb0 },
> -	{ "EMU", MOD_PRM, OMAP3430_EMU_MOD, 0x58, 0xe4 },
>  	{ "CCR", MOD_PRM, PLL_MOD, 0x40, 0x70 },
>  	{ "DSS", MOD_PRM, OMAP3430_DSS_MOD, 0x58, 0xe8 },
> +	{ "CAM", MOD_PRM, OMAP3430_CAM_MOD, 0x58, 0xe8 },
>  	{ "PER", MOD_PRM, OMAP3430_PER_MOD, 0x58, 0xe8 },
> +	{ "EMU", MOD_PRM, OMAP3430_EMU_MOD, 0x58, 0xe4 },
> +	{ "GLBL", MOD_PRM, OMAP3430_GR_MOD, 0x20, 0xe4 },
> +	{ "NEON", MOD_PRM, OMAP3430_NEON_MOD, 0x58, 0xe8 },
>  	{ "USB", MOD_PRM, OMAP3430ES2_USBHOST_MOD, 0x58, 0xe8 },
>  	{ "", 0, 0, 0, 0 },
>  };
> diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
> index c4afa7d..3c62b68 100755
> --- a/arch/arm/mach-omap2/pm34xx.c
> +++ b/arch/arm/mach-omap2/pm34xx.c
> @@ -75,6 +75,8 @@ void (*_omap_sram_idle)(u32 *addr, int save_state);
>  static void (*saved_idle)(void);
>  
>  static struct powerdomain *mpu_pwrdm;
> +static struct powerdomain *core_pwrdm;
> +static struct powerdomain *per_pwrdm;
>  
>  /* XXX This is for gpio fclk hack. Will be removed as gpio driver
>   * handles fcks correctly */
> @@ -235,6 +237,8 @@ void omap_sram_idle(void)
>  	/* save_state = 2 => Only L2 lost */
>  	/* save_state = 3 => L1, L2 and logic lost */
>  	int save_state = 0, mpu_next_state;
> +	int save_core;
> +	int save_per;
>  
>  	if (!_omap_sram_idle)
>  		return;
> @@ -255,17 +259,26 @@ void omap_sram_idle(void)
>  		return;
>  	}
>  
> -	omap3_save_core_ctx();
> -	omap3_save_prcm_ctx();
> +	save_core = (pwrdm_read_next_pwrst(core_pwrdm) == PWRDM_POWER_OFF);
> +	save_per = (pwrdm_read_next_pwrst(per_pwrdm) ==
> PWRDM_POWER_OFF);

Just read next states here.

> +
> +	if (save_core) {
> +		omap3_save_core_ctx();
> +		omap3_save_prcm_ctx();
> +	}

And do this if core next_st < PWRDM_POWER_ON

> +
> +	if (save_per)
> +		omap3_save_per_ctx();

And same here. Additionally, do this only if core next_st <
PWRDM_POWER_ON.

>  
> -	omap3_save_per_ctx();
>  	omap2_gpio_prepare_for_retention();
>  
>  	/* XXX This is for gpio fclk hack. Will be removed as gpio driver
>  	 * handqles fcks correctly */
>  	per_gpio_clk_disable();
>  
> -	omap_save_uart_ctx();
> +	if (save_per)
> +		omap_save_uart_ctx();

Again, do this only if core next_st < PWRDM_POWER_ON and per next_st ==
PWRDM_POWER_OFF.

> +
>  	omap_serial_enable_clocks(0);

Consider Rajendras idea to do this only if needed.

>  
>  	*(scratchpad_restore_addr) = restore_pointer_address;
> @@ -277,19 +290,24 @@ void omap_sram_idle(void)
>  	if (pwrdm_read_prev_pwrst(mpu_pwrdm) == 0x0)
>  		restore_table_entry();
>  
> -	omap3_restore_prcm_ctx();
> -	omap3_restore_sram_ctx();
> -	omap3_restore_core_ctx();
> +	if (save_core) {
> +		omap3_restore_prcm_ctx();
> +		omap3_restore_sram_ctx();
> +		omap3_restore_core_ctx();
> +	}
>  
>  	omap_serial_enable_clocks(1); /* Causes crash with CORE off */
>  
> -	omap_restore_uart_ctx();
> +	if (save_per)
> +		omap_restore_uart_ctx();
>  
>  	/* XXX This is for gpio fclk hack. Will be removed as gpio driver
>  	 * handles fcks correctly */
>  
>  	per_gpio_clk_enable();
> -	omap3_restore_per_ctx();
> +
> +	if (save_per)
> +		omap3_restore_per_ctx();
>  
>  	omap2_gpio_resume_after_retention();

Same comments to restore part as before wfi. I think you should look
at what Rajendra has done (logic in omap3_enter_idle). You might also
want to look at previous discussion related to this. Something like this:

void omap_sram_idle(void)
{
	/* Variable to tell what needs to be saved and restored
	 * in omap_sram_idle*/
	/* save_state = 0 => Nothing to save and restored */
	/* save_state = 1 => Only L1 and logic lost */
	/* save_state = 2 => Only L2 lost */
	/* save_state = 3 => L1, L2 and logic lost */
	int save_state = 0;
	int mpu_next_state = PWRDM_POWER_ON, core_next_state = PWRDM_POWER_ON,
		per_next_state = PWRDM_POWER_ON;
	int neon_state;

	if (!_omap_sram_idle)
		return;

	mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm);
	switch (mpu_next_state) {
	case PWRDM_POWER_ON:
	case PWRDM_POWER_RET:
		/* No need to save context */
		save_state = 0;
		break;
	case PWRDM_POWER_OFF:
		save_state = 3;
		break;
	default:
		/* Invalid state */
		printk(KERN_ERR "Invalid mpu state in sram_idle\n");
		return;
	}

	pm_dbg_pre_suspend();

	/* NEON control */
	if (mpu_next_state < PWRDM_POWER_ON) {
		neon_state = pwrdm_read_pwrst(neon_pwrdm);
		if (neon_state == PWRDM_POWER_ON)
			pwrdm_set_next_pwrst(neon_pwrdm, mpu_next_state);
	}

	/* CORE & PER */
	core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
	if (core_next_state < PWRDM_POWER_ON) {
		/* PER changes only with core */
		per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
		if (per_next_state < PWRDM_POWER_ON) {
			if (per_next_state == PWRDM_POWER_OFF) {
				omap3_save_per_ctx();
				/* This would be actually more effective */
				/* omap_save_uart_ctx(2); */
			}
			if (clocks_off_while_idle)
				per_gpio_clk_disable();
			/* This would be actually more effective */
			/* omap_serial_enable_clocks(0, 2); */
		}
		if (core_next_state == PWRDM_POWER_OFF) {
			omap3_save_core_ctx();
			omap3_save_prcm_ctx();
			/* omap_save_uart_ctx(2); */
			/* omap_save_uart_ctx(2); */
		}
		if (core_next_state == PWRDM_POWER_OFF || per_next_state == PWRDM_POWER_OFF)
			omap_save_uart_ctx();
		if (clocks_off_while_idle)
			omap_serial_enable_clocks(0);
		/* omap_serial_enable_clocks(0, 2); */
		/* omap_serial_enable_clocks(0, 2); */
		
	}

	/* Is this related to per transition or transition in general? */
	omap2_gpio_prepare_for_retention();

	*(scratchpad_restore_addr) = restore_pointer_address;

	_omap_sram_idle(context_mem, save_state);

	*(scratchpad_restore_addr) = 0x0;

	if (pwrdm_read_prev_pwrst(mpu_pwrdm) == 0x0)
		restore_table_entry();
	
	if (core_next_state < PWRDM_POWER_ON) {
		if (core_next_state == PWRDM_POWER_OFF) {
			omap3_restore_core_ctx();
			omap3_restore_sram_ctx();
			omap3_restore_prcm_ctx();
			/* omap_restore_uart_ctx(0); */
			/* omap_restore_uart_ctx(1); */
		}
		if (per_next_state < PWRDM_POWER_ON) {
			if (per_next_state == PWRDM_POWER_OFF) {
				omap3_restore_per_ctx();
				/* This would be actually more effective */
				/* omap_restore_uart_ctx(2); */
			}
			if (clocks_off_while_idle) {
				per_gpio_clk_enable();
				/* This would be actually more effective */
				/* omap_serial_enable_clocks(0, 2); */
			}
		}
		if (core_next_state == PWRDM_POWER_OFF || per_next_state == PWRDM_POWER_OFF)
			omap_restore_uart_ctx();
		if (clocks_off_while_idle)
			omap_serial_enable_clocks(1);
		/* omap_serial_enable_clocks(1, 0); */
		/* omap_serial_enable_clocks(1, 1); */
	}

	omap2_gpio_resume_after_retention();

	pm_dbg_post_suspend();
}


>  }
> @@ -718,10 +736,13 @@ int __init omap3_pm_init(void)
>  	}
>  
>  	mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
> +	core_pwrdm = pwrdm_lookup("core_pwrdm");
> +	per_pwrdm = pwrdm_lookup("per_pwrdm");
>  	neon_pwrdm = pwrdm_lookup("neon_pwrdm");
>  
> -	if (mpu_pwrdm == NULL || neon_pwrdm == NULL) {
> -		printk(KERN_ERR "Failed to get mpu_pwrdm or neon_pwrdm\n");
> +	if (mpu_pwrdm == NULL || neon_pwrdm == NULL || per_pwrdm == NULL ||
> +			core_pwrdm == NULL) {
> +		printk(KERN_ERR "Failed to get pwrdm pointers\n");

Neon handling is missing.

>  		goto err2;
>  	}
>  
> -- 
> 1.5.4.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-omap" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>

-- 
Jouni Högander

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux