[PATCH 5/8] ARM: tegra30: add LP1 suspend support

Joseph Lo josephl at nvidia.com
Mon Aug 5 02:46:28 EDT 2013


On Tue, 2013-07-30 at 07:45 +0800, Stephen Warren wrote:
> On 07/26/2013 03:15 AM, Joseph Lo wrote:
> > The LP1 suspend mode will power off the CPU, clock gated the PLLs and put
> > SDRAM to self-refresh mode. Any interrupt can wake up device from LP1. The
> > sequence when LP1 suspending:
> 
> > diff --git a/arch/arm/mach-tegra/pm-tegra30.c b/arch/arm/mach-tegra/pm-tegra30.c
> 
> > +void tegra30_lp1_iram_hook(void)
> > +{
> > +	tegra30_lp1_iram.start_addr = &tegra30_iram_start;
> > +	tegra30_lp1_iram.end_addr = &tegra30_iram_end;
> 
> If you need to fill in the values in that struct dynamically anyway, why
> not make tegra_lp1_iram be a struct rather than a pointer, and write
> directly to it?
> 
OK. Will fix.

> > +/*
> > + * tegra30_lp1_reset
> > + *
> > + * reset vector for LP1 restore; copied into IRAM during suspend.
> > + * Brings the system back up to a safe staring point (SDRAM out of
> > + * self-refresh, PLLC, PLLM and PLLP reenabled, CPU running on PLLX,
> > + * system clock running on the same PLL that it suspended at), and
> > + * jumps to tegra_resume to restore virtual addressing.
> > + * The physical address of tegra_resume expected to be stored in
> > + * PMC_SCRATCH41.
> > + *
> > + * NOTE: THIS *MUST* BE RELOCATED TO TEGRA_IRAM_CODE_AREA AND MUST BE FIRST.
> 
> What does "AND MUST BE FIRST" mean?
> 
It means the LP1 reset vector needs to be copied to IRAM_CODE_AREA first
before suspend to LP1. Looks no need this. Will remove it.

> > +ENTRY(tegra30_lp1_reset)
> > +	/*
> > +	 * The CPU and system bus are running at 32KHz and executing from
> > +	 * IRAM when this code is executed; immediately switch to CLKM and
> > +	 * enable PLLP, PLLM, PLLC, PLLA and PLLX.
> > +	 */
> > +	mov32	r0, TEGRA_CLK_RESET_BASE
> > +
> > +	mov	r1, #(1 << 28)
> 
> Some #defines for the various magic values used in this code would be
> useful.
It may still cause some confuse if I add a #defines value for it.
Because it includes a clock policy and the clock source (the value maybe
just 0). I add some comments for these codes about what they are doing.
> 
> > +tegra30_sdram_pad_save:
> > +	.word	0
> > +	.word	0
> > +	.word	0
> > +	.word	0
> > +	.word	0
> > +	.word	0
> > +	.word	0
> > +	.word	0
> 
> This might be simpler, and easier to validate it's the right length:
> 
>         .rept   8
>         .long   0
>         .endr
> 
> > +tegra30_sdram_pad_address:
> > +	.word	TEGRA_EMC_BASE + EMC_CFG				@0x0
> > +	.word	TEGRA_EMC_BASE + EMC_ZCAL_INTERVAL			@0x4
> > +	.word	TEGRA_EMC_BASE + EMC_AUTO_CAL_INTERVAL			@0x8
> > +	.word	TEGRA_EMC_BASE + EMC_XM2VTTGENPADCTRL			@0xc
> > +	.word	TEGRA_EMC_BASE + EMC_XM2VTTGENPADCTRL2			@0x10
> > +	.word	TEGRA_PMC_BASE + PMC_IO_DPD_STATUS			@0x14
> > +	.word	TEGRA_CLK_RESET_BASE + CLK_RESET_CLK_SOURCE_MSELECT	@0x18
> > +	.word	TEGRA_CLK_RESET_BASE + CLK_RESET_SCLK_BURST		@0x1c
> > +
> > +tegra30_sdram_pad_size:
> > +	.word	tegra30_sdram_pad_address - tegra30_sdram_pad_save
> 
> Perhaps if you swapp the order of declaring tegra30_sdram_pad_save and
> tegra30_sdram_pad_address, you can even do something like:
> 
> 	.rept (tegra30_sdram_pad_addr_end - tegra30_sdram_pad_addr) / 4
> 
> ?
OK. Looks better. Will do this.

> 
> > +	/* 2uS delay delay between changing SCLK and CCLK */
> > +	wait_for_us r1, r7, r9
> > +	add	r1, r1, #2
> > +	wait_until r1, r7, r9
> 
> Ah, I see how wait_for_us is used now. Perhaps rename it
> wait_for_us_boundary or wait_for_us_tick? Alternatively, perhaps
> wait_until can just incorporate that logic itself?
Indeed. Will fix.





More information about the linux-arm-kernel mailing list