Updates for Tegra support in 2.6.39
Subsystems (3)
v2 cover Updates for Tegra support in 2.6.39
This patch set adds support for suspend, idle, and cpufreq for the Tegra subsystem.
Patch 2 adds functions to save and restore the GIC state during suspend and resume, and patch 3 exports the GIC irq chip functions to support custom IRQ chips that need to update the GIC as well as another block during IRQ operations. Patches 2 and 3 depend on patch 1, which fixes a naming conflict in mach-tegra, so the whole stack will need to go in through one tree.
arch/arm/common/gic.c | 138 ++++- arch/arm/configs/tegra_defconfig | 123 ++++ arch/arm/include/asm/hardware/cache-l2x0.h | 3 +- arch/arm/include/asm/hardware/gic.h | 13 + arch/arm/mach-tegra/Makefile | 12 +- arch/arm/mach-tegra/board.h | 6 + arch/arm/mach-tegra/common.c | 49 ++- arch/arm/mach-tegra/cortex-a9.S | 504 +++++++++++++++ arch/arm/mach-tegra/cpu-tegra.c | 75 ++- arch/arm/mach-tegra/cpuidle.c | 714 ++++++++++++++++++++++ arch/arm/mach-tegra/dma.c | 198 ++++--- arch/arm/mach-tegra/gpio.c | 15 +- arch/arm/mach-tegra/headsmp-t2.S | 216 +++++++ arch/arm/mach-tegra/headsmp.S | 61 -- arch/arm/mach-tegra/hotplug.c | 126 ---- arch/arm/mach-tegra/include/mach/clk.h | 2 + arch/arm/mach-tegra/include/mach/clkdev.h | 2 + arch/arm/mach-tegra/include/mach/debug-macro.S | 25 +- arch/arm/mach-tegra/include/mach/iomap.h | 69 ++- arch/arm/mach-tegra/include/mach/irqs.h | 14 +- arch/arm/mach-tegra/include/mach/legacy_irq.h | 7 +- arch/arm/mach-tegra/include/mach/pinmux-t2.h | 10 + arch/arm/mach-tegra/include/mach/powergate.h | 40 ++ arch/arm/mach-tegra/include/mach/suspend.h | 80 +++ arch/arm/mach-tegra/include/mach/system.h | 10 +- arch/arm/mach-tegra/include/mach/uncompress.h | 18 +- arch/arm/mach-tegra/irq.c | 334 ++++++++--- arch/arm/mach-tegra/legacy_irq.c | 109 ++++- arch/arm/mach-tegra/pinmux-t2-tables.c | 26 +- arch/arm/mach-tegra/platsmp.c | 89 +++- arch/arm/mach-tegra/power-macros.S | 57 ++ arch/arm/mach-tegra/power.h | 64 ++ arch/arm/mach-tegra/powergate.c | 212 +++++++ arch/arm/mach-tegra/suspend-t2.c | 414 +++++++++++++ arch/arm/mach-tegra/suspend.c | 776 ++++++++++++++++++++++++ arch/arm/mach-tegra/tegra2_clocks.c | 264 ++++++++- arch/arm/mach-tegra/tegra2_save.S | 413 +++++++++++++ arch/arm/mach-tegra/timer.c | 96 +++- arch/arm/mm/cache-l2x0.c | 14 +- 39 files changed, 4898 insertions(+), 500 deletions(-)
PATCH v2 1/28 ARM: tegra: irq: Rename gic pointers to avoid conflicts
A future patch will export gic_mask_irq and gic_unmask_irq. Rename the pointers in arch/arm/mach-tegra/irq.c to avoid a compile error.
--- arch/arm/mach-tegra/irq.c | 18 +++++++++--------- 1 files changed, 9 insertions(+), 9 deletions(-)
arch/arm/mach-tegra/irq.c +9 -9
@@ -46,24 +46,24 @@#define ICTLR_COP_IER_CLR 0x38#define ICTLR_COP_IEP_CLASS 0x3c -static void (*gic_mask_irq)(struct irq_data *d); -static void (*gic_unmask_irq)(struct irq_data *d); +static void (*tegra_gic_mask_irq)(struct irq_data *d); +static void (*tegra_gic_unmask_irq)(struct irq_data *d); -#define irq_to_ictlr (irq) (((irq)-32) >> 5) +#define irq_to_ictlr (irq) (((irq) - 32) >> 5)static void __iomem *tegra_ictlr_base =IO_ADDRESS (TEGRA_PRIMARY_ICTLR_BASE ); -#define ictlr_to_virt (ictlr) (tegra_ictlr_base + (ictlr)*0x100) +#define ictlr_to_virt (ictlr) (tegra_ictlr_base + (ictlr) * 0x100)static void tegra_mask (struct irq_data *d) {void __iomem *addr =ictlr_to_virt (irq_to_ictlr (d->irq)); -gic_mask_irq (d); -writel (1 <<(d->irq&31 ), addr+ICTLR_CPU_IER_CLR ); +tegra_gic_mask_irq (d); +writel (1 << (d->irq &31 ), addr+ICTLR_CPU_IER_CLR ); }static void tegra_unmask (struct irq_data *d) {void __iomem *addr =ictlr_to_virt (irq_to_ictlr (d->irq)); -gic_unmask_irq (d); +tegra_gic_unmask_irq (d);writel (1 <<(d->irq&31 ), addr+ICTLR_CPU_IER_SET ); }
@@ -98,8 +98,8 @@ void __init tegra_init_irq(void) IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100)); gic =get_irq_chip (29 ); - gic_unmask_irq = gic->irq_unmask; - gic_mask_irq = gic->irq_mask; + tegra_gic_unmask_irq = gic->irq_unmask; + tegra_gic_mask_irq = gic->irq_mask; tegra_irq.irq_ack = gic->irq_ack;#ifdef CONFIG_SMP tegra_irq.irq_set_affinity = gic->irq_set_affinity;
Signature · 1 line
1.7.3.1
Re: [PATCH v2 01/28] ARM: tegra: irq: Rename gic pointers to avoid conflicts
Quoted 54 lines · Colin Cross
A future patch will export
gic_mask_irqandgic_unmask_irq. Rename the pointers inarch/arm/mach-tegra/irq.cto avoid a compile error.Signed-off-by Colin Cross <[email protected]>---
?arch/arm/mach-tegra/irq.c | ? 18 +++++++++--------- ?1 files changed, 9 insertions(+), 9 deletions(-)arch/arm/mach-tegra/irq.c +0
-0@@ -46,24 +46,24 @@?#define
ICTLR_COP_IER_CLR? ? ?0x38
?#defineICTLR_COP_IEP_CLASS? ?0x3carch/arm/mach-tegra/irq.c +3
-3-static void (*gic_mask_irq)(struct irq_data *d); -static void (*gic_unmask_irq)(struct irq_data *d); +static void (*tegra_gic_mask_irq)(struct irq_data *d); +static void (*tegra_gic_unmask_irq)(struct irq_data *d); -#define irq_to_ictlr (irq) (((irq)-32) >> 5) +#define irq_to_ictlr (irq) (((irq) - 32) >> 5)?static void
__iomem*tegra_ictlr_base=IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE);arch/arm/mach-tegra/irq.c +1
-1-#define ictlr_to_virt (ictlr) (tegra_ictlr_base + (ictlr)*0x100) +#define ictlr_to_virt (ictlr) (tegra_ictlr_base + (ictlr) * 0x100)?static void
tegra_mask(struct irq_data *d)
?{
? ? ? ?void__iomem*addr = ictlr_to_virt(irq_to_ictlr(d->irq));
- ? ? ?gic_mask_irq(d);
- ? ? ?writel(1<<(d->irq&31), addr+ICTLR_CPU_IER_CLR);
+ ? ? ?tegra_gic_mask_irq(d);
+ ? ? ?writel(1 << (d->irq & 31), addr+ICTLR_CPU_IER_CLR); ?}?static void
tegra_unmask(struct irq_data *d)
?{
? ? ? ?void__iomem*addr = ictlr_to_virt(irq_to_ictlr(d->irq));
- ? ? ?gic_unmask_irq(d);
+ ? ? ?tegra_gic_unmask_irq(d);
? ? ? ?writel(1<<(d->irq&31), addr+ICTLR_CPU_IER_SET); ?}arch/arm/mach-tegra/irq.c +2
-2@@ -98,8 +98,8 @@ void __init tegra_init_irq(void) ? ? ? ? ? ? ? ? IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100)); ? ? ? ?gic = get_irq_chip(29); - ? ? ? gic_unmask_irq = gic->irq_unmask; - ? ? ? gic_mask_irq = gic->irq_mask; + ? ? ? tegra_gic_unmask_irq = gic->irq_unmask; + ? ? ? tegra_gic_mask_irq = gic->irq_mask; ? ? ? ?tegra_irq.irq_ack = gic->irq_ack;
Quoted 4 lines
?#ifdef
CONFIG_SMP
? ? ? ?tegra_irq.irq_set_affinity =gic->irq_set_affinity; --
1.7.3.1
If there are no objections, I'm going to put this patch into tegra/for-linus for a pull request for 2.6.38-rc3.
PATCH v2 2/28 ARM: gic: Add functions to save and restore gic state
In reply to Colin Crosson systems with idle states which power-gate the logic including the gic, such as tegra, the gic distributor needs to be shut down and restored on entry and exit from the architecture idle code
Original-author: Gary King <[email protected]>
---
v2: Updated on top of changes to gic initialization
This patch depends on patch 1:
ARM: tegra: irq: Rename gic pointers to avoid conflicts
arch/arm/common/gic.c | 127 +++++++++++++++++++++++++++++++++-- arch/arm/include/asm/hardware/gic.h | 3 + 2 files changed, 125 insertions(+), 5 deletions(-)
arch/arm/common/gic.c +122 -5
@@ -42,6 +42,13 @@ struct gic_chip_data {unsigned int irq_offset;void __iomem *dist_base;void __iomem *cpu_base; +#ifdef CONFIG_PM +u32 saved_enable[DIV_ROUND_UP (1020 ,32 )]; +u32 saved_conf[DIV_ROUND_UP (1020 ,16 )]; +u32 saved_pri[DIV_ROUND_UP (1020 ,4 )]; +u32 saved_target[DIV_ROUND_UP (1020 ,4 )]; +#endif +unsigned int gic_irqs; };#ifndef MAX_GIC_NR
@@ -216,10 +223,9 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)set_irq_chained_handler (irq, gic_handle_cascade_irq); } -static void __init gic_dist_init (struct gic_chip_data *gic, -unsigned int irq_start) +static unsigned int _gic_dist_init (struct gic_chip_data *gic) { -unsigned int gic_irqs, irq_limit, i; +unsigned int gic_irqs, i;void __iomem *base = gic->dist_base;u32 cpumask =1 <<smp_processor_id ();
@@ -262,10 +268,25 @@ static void __init gic_dist_init(struct gic_chip_data *gic,for (i =32 ; i < gic_irqs; i +=32 )writel (0xffffffff , base +GIC_DIST_ENABLE_CLEAR + i *4 /32 ); +return gic_irqs; +} + +static void _gic_dist_exit (unsigned int gic_nr) +{ +writel (0 , gic_data[gic_nr].dist_base +GIC_DIST_CTRL ); +} + +void __init gic_dist_init (struct gic_chip_data *gic,unsigned int irq_start) +{ +unsigned int irq_limit; +unsigned int i; + + gic->gic_irqs =_gic_dist_init (gic); +/* * Limit number of interrupts registered to the platform maximum */ - irq_limit = gic->irq_offset + gic_irqs; + irq_limit = gic->irq_offset + gic->gic_irqs;if (WARN_ON (irq_limit >NR_IRQS )) irq_limit =NR_IRQS ;
@@ -279,7 +300,15 @@ static void __init gic_dist_init(struct gic_chip_data *gic,set_irq_flags (i,IRQF_VALID |IRQF_PROBE ); } -writel (1 , base +GIC_DIST_CTRL ); +writel (1 , gic->dist_base +GIC_DIST_CTRL ); +} + +void gic_dist_exit (unsigned int gic_nr) +{ +if (gic_nr >=MAX_GIC_NR ) +BUG (); + +_gic_dist_exit (gic_nr); }static void __cpuinit gic_cpu_init (struct gic_chip_data *gic)
@@ -305,6 +334,14 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)writel (1 , base +GIC_CPU_CTRL ); } +void gic_cpu_exit (unsigned int gic_nr) +{ +if (gic_nr >=MAX_GIC_NR ) +BUG (); + +writel (0 , gic_data[gic_nr].cpu_base +GIC_CPU_CTRL ); +} +void __init gic_init (unsigned int gic_nr,unsigned int irq_start,void __iomem *dist_base,void __iomem *cpu_base) {
@@ -350,3 +387,83 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)writel (map <<16 | irq, gic_data[0 ].dist_base +GIC_DIST_SOFTINT ); }#endif + +#ifdef CONFIG_PM +/* +* Saves the GIC distributor registers during suspend or idle. Must be called +* with interrupts disabled but before powering down the GIC. After calling +* this function, no interrupts will be delivered by the GIC, and another +* platform-specific wakeup source must be enabled. +*/ +void gic_dist_save (unsigned int gic_nr) +{ +unsigned int gic_irqs = gic_data[gic_nr].gic_irqs; +void __iomem *dist_base = gic_data[gic_nr].dist_base; +int i; + +if (gic_nr >=MAX_GIC_NR ) +BUG (); + +_gic_dist_exit (gic_nr); + +for (i =0 ; i <DIV_ROUND_UP (gic_irqs,16 ); i++) + gic_data[gic_nr].saved_conf[i] = +readl (dist_base +GIC_DIST_CONFIG + i *4 ); + +for (i =0 ; i <DIV_ROUND_UP (gic_irqs,4 ); i++) + gic_data[gic_nr].saved_pri[i] = +readl (dist_base +GIC_DIST_PRI + i *4 ); + +for (i =0 ; i <DIV_ROUND_UP (gic_irqs,4 ); i++) + gic_data[gic_nr].saved_target[i] = +readl (dist_base +GIC_DIST_TARGET + i *4 ); + +for (i =0 ; i <DIV_ROUND_UP (gic_irqs,32 ); i++) + gic_data[gic_nr].saved_enable[i] = +readl (dist_base +GIC_DIST_ENABLE_SET + i *4 ); +} + +/* +* Restores the GIC distributor registers during resume or when coming out of +* idle. Must be called before enabling interrupts. If a level interrupt +* that occured while the GIC was suspended is still present, it will be +* handled normally, but any edge interrupts that occured will not be seen by +* the GIC and need to be handled by the platform-specific wakeup source. +*/ +void gic_dist_restore (unsigned int gic_nr) +{ +unsigned int gic_irqs; +unsigned int i; +void __iomem *dist_base; +void __iomem *cpu_base; + +if (gic_nr >=MAX_GIC_NR ) +BUG (); + +_gic_dist_init (&gic_data[gic_nr]); + + gic_irqs = gic_data[gic_nr].gic_irqs; + dist_base = gic_data[gic_nr].dist_base; + cpu_base = gic_data[gic_nr].cpu_base; + +for (i =0 ; i <DIV_ROUND_UP (gic_irqs,16 ); i++) +writel (gic_data[gic_nr].saved_conf[i], + dist_base +GIC_DIST_CONFIG + i *4 ); + +for (i =0 ; i <DIV_ROUND_UP (gic_irqs,4 ); i++) +writel (gic_data[gic_nr].saved_pri[i], + dist_base +GIC_DIST_PRI + i *4 ); + +for (i =0 ; i <DIV_ROUND_UP (gic_irqs,4 ); i++) +writel (gic_data[gic_nr].saved_target[i], + dist_base +GIC_DIST_TARGET + i *4 ); + +for (i =0 ; i <DIV_ROUND_UP (gic_irqs,32 ); i++) +writel (gic_data[gic_nr].saved_enable[i], + dist_base +GIC_DIST_ENABLE_SET + i *4 ); + +writel (1 , dist_base +GIC_DIST_CTRL ); +writel (0xf0 , cpu_base +GIC_CPU_PRIMASK ); +writel (1 , cpu_base +GIC_CPU_CTRL ); +} +#endif
arch/arm/include/asm/hardware/gic.h +3 -0
@@ -37,6 +37,9 @@ extern void __iomem *gic_cpu_base_addr;void gic_init (unsigned int ,unsigned int ,void __iomem *,void __iomem *);void gic_secondary_init (unsigned int ); +void gic_dist_save (unsigned int gic_nr); +void gic_dist_restore (unsigned int gic_nr); +void gic_cpu_exit (unsigned int gic_nr);void gic_cascade_irq (unsigned int gic_nr,unsigned int irq);void gic_raise_softirq (const struct cpumask *mask,unsigned int irq);void gic_enable_ppi (unsigned int );
Signature · 1 line
1.7.3.1
Re: [PATCH v2 02/28] ARM: gic: Add functions to save and restore gic state
Quoted 3 lines · Colin Cross
on systems with idle states which power-gate the logic including the gic, such as tegra, the gic distributor needs to be shut down and restored on entry and exit from the architecture idle code
I'd rather not add this and then have to weed it back out when we have a proper interface for dealign with idle shutdown stuff.
Can some effort please be put into coming up with a proper interface such as an idle notifier list rather than calling directly into random parts of the kernel on idle.
PATCH v2 3/28 ARM: gic: Export irq chip functions
In reply to Colin CrossSome systems combine the GIC with an external interrupt controller. On these systems it may be necessary to update both the GIC registers and the external controller's registers to control IRQ behavior. Export the irq chip functions so that these systems can define a custom irq chip that calls into the GIC handlers.
---
v2: Updated on top of irq_data changes
arch/arm/common/gic.c | 11 +++++------ arch/arm/include/asm/hardware/gic.h | 10 ++++++++++ 2 files changed, 15 insertions(+), 6 deletions(-)
arch/arm/common/gic.c +5 -6
@@ -78,14 +78,14 @@ static inline unsigned int gic_irq(struct irq_data *d)/* * Routines to acknowledge, disable and enable interrupts */ -static void gic_ack_irq (struct irq_data *d) +void gic_ack_irq (struct irq_data *d) {spin_lock (&irq_controller_lock);writel (gic_irq (d),gic_cpu_base (d) +GIC_CPU_EOI );spin_unlock (&irq_controller_lock); } -static void gic_mask_irq (struct irq_data *d) +void gic_mask_irq (struct irq_data *d) {u32 mask =1 << (d->irq %32 );
@@ -94,7 +94,7 @@ static void gic_mask_irq(struct irq_data *d)spin_unlock (&irq_controller_lock); } -static void gic_unmask_irq (struct irq_data *d) +void gic_unmask_irq (struct irq_data *d) {u32 mask =1 << (d->irq %32 );
@@ -103,7 +103,7 @@ static void gic_unmask_irq(struct irq_data *d)spin_unlock (&irq_controller_lock); } -static int gic_set_type (struct irq_data *d,unsigned int type) +int gic_set_type (struct irq_data *d,unsigned int type) {void __iomem *base =gic_dist_base (d);unsigned int gicirq =gic_irq (d);
@@ -149,8 +149,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type) }#ifdef CONFIG_SMP -static int -gic_set_cpu (struct irq_data *d,const struct cpumask *mask_val,bool force) +int gic_set_cpu (struct irq_data *d,const struct cpumask *mask_val,bool force) {void __iomem *reg =gic_dist_base (d) +GIC_DIST_TARGET + (gic_irq (d) & ~3 );unsigned int shift = (d->irq %4 ) *8 ;
arch/arm/include/asm/hardware/gic.h +10 -0
@@ -33,6 +33,8 @@#define GIC_DIST_SOFTINT 0xf00#ifndef __ASSEMBLY__ +struct irq_data ; +extern void __iomem *gic_cpu_base_addr;void gic_init (unsigned int ,unsigned int ,void __iomem *,void __iomem *);
@@ -43,6 +45,14 @@ void gic_cpu_exit(unsigned int gic_nr);void gic_cascade_irq (unsigned int gic_nr,unsigned int irq);void gic_raise_softirq (const struct cpumask *mask,unsigned int irq);void gic_enable_ppi (unsigned int ); + +void gic_ack_irq (struct irq_data *d); +void gic_mask_irq (struct irq_data *d); +void gic_unmask_irq (struct irq_data *d); +int gic_set_type (struct irq_data *d,unsigned int type); +#ifdef CONFIG_SMP +int gic_set_cpu (struct irq_data *d,const struct cpumask *mask_val,bool force); +#endif #endif #endif
Signature · 1 line
1.7.3.1
RE: [PATCH v2 03/28] ARM: gic: Export irq chip functions
Colin,
Quoted 18 lines
-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux- arm-kernel-bounces at lists.infradead.org] On Behalf Of Colin Cross
Sent: Monday, January 24, 2011 7:31 AM
To: linux-tegra at vger.kernel.org
Cc: Russell King; Linus Walleij; konkers at android.com; Gary King; Catalin Marinas; Abhijeet Dharmapurikar; linux-
kernel at vger.kernel.org; Colin Cross; olof at lixom.net; linux-arm- kernel at lists.infradead.org
Subject: [PATCH v2 03/28] ARM: gic: Export irq chip functionsSome systems combine the GIC with an external interrupt controller. On these systems it may be necessary to update both the GIC registers
and the external controller's registers to control IRQ behavior. Export the irq chip functions so that these systems can define a custom irq chip that calls into the GIC handlers.
Quoted 8 lines
Signed-off-by Colin Cross <[email protected]>---
v2: Updated on top ofirq_datachangesarch/arm/common/gic.c | 11 +++++------ arch/arm/include/asm/hardware/gic.h | 10 ++++++++++ 2 files changed, 15 insertions(+), 6 deletions(-)
Instead of exporting the GIC library, I think we could add the flexibility with slightly different approach.
Have few common arm patches mainly for PM.
Will post them shortly. Have a look at them.
Regards,
Santosh
PATCH v2 4/28 ARM: mm: cache-l2x0: Add support for re-enabling l2x0
In reply to Colin CrossRemove __init annotation from l2x0_init so it can be used to reinitialize the l2x0 after it has been reset during suspend.
Add l2x0_enable to re-enable the l2x0 after l2x0_disable if the l2x0 was not reset.
l2x0_disable cannot use writel, as writel calls wmb(), and wmb() may call outer_cache_sync, which takes the same spinlock as l2x0_disable.
--- arch/arm/include/asm/hardware/cache-l2x0.h | 3 ++- arch/arm/mm/cache-l2x0.c | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-)
arch/arm/include/asm/hardware/cache-l2x0.h +2 -1
@@ -72,7 +72,8 @@#define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT 30#ifndef __ASSEMBLY__ -extern void __init l2x0_init (void __iomem *base,__u32 aux_val,__u32 aux_mask); +extern void l2x0_init (void __iomem *base,__u32 aux_val,__u32 aux_mask); +extern void l2x0_enable (void );#endif #endif
arch/arm/mm/cache-l2x0.c +12 -2
@@ -252,16 +252,26 @@ static void l2x0_flush_range(unsigned long start, unsigned long end)spin_unlock_irqrestore (&l2x0_lock, flags); } +/* enables l2x0 after l2x0_disable, does not invalidate */ +void l2x0_enable (void ) +{ +unsigned long flags; + +spin_lock_irqsave (&l2x0_lock, flags); +writel_relaxed (1 , l2x0_base +L2X0_CTRL ); +spin_unlock_irqrestore (&l2x0_lock, flags); +} +static void l2x0_disable (void ) {unsigned long flags;spin_lock_irqsave (&l2x0_lock, flags); -writel (0 , l2x0_base +L2X0_CTRL ); +writel_relaxed (0 , l2x0_base +L2X0_CTRL );spin_unlock_irqrestore (&l2x0_lock, flags); } -void __init l2x0_init (void __iomem *base,__u32 aux_val,__u32 aux_mask) +void l2x0_init (void __iomem *base,__u32 aux_val,__u32 aux_mask) {__u32 aux;__u32 cache_id;
Signature · 1 line
1.7.3.1
Re: [PATCH v2 04/28] ARM: mm: cache-l2x0: Add support for re-enabling l2x0
Quoted 21 lines · Colin Cross
arch/arm/mm/cache-l2x0.c +10
-0@@ -252,16 +252,26 @@ static void l2x0_flush_range(unsigned long start, unsigned long end)spin_unlock_irqrestore (&l2x0_lock, flags); } +/* enables l2x0 after l2x0_disable, does not invalidate */ +void l2x0_enable (void ) +{ +unsigned long flags; + +spin_lock_irqsave (&l2x0_lock, flags); +writel_relaxed (1 , l2x0_base +L2X0_CTRL ); +spin_unlock_irqrestore (&l2x0_lock, flags); +} +static void l2x0_disable (void ) {unsigned long flags;spin_lock_irqsave (&l2x0_lock, flags);
arch/arm/mm/cache-l2x0.c static void l2x0_flush_range(unsigned long start, unsigned long end) · line 277
Quoted 10 lines
arch/arm/mm/cache-l2x0.c +2
-2-writel (0 , l2x0_base +L2X0_CTRL ); +writel_relaxed (0 , l2x0_base +L2X0_CTRL );spin_unlock_irqrestore (&l2x0_lock, flags); } -void __init l2x0_init (void __iomem *base,__u32 aux_val,__u32 aux_mask) +void l2x0_init (void __iomem *base,__u32 aux_val,__u32 aux_mask) {__u32 aux;__u32 cache_id;
So this assumes that the L2 registers are accessible. I suspect the platform code calling it should know this.
The patch looks fine.
Re: [PATCH v2 04/28] ARM: mm: cache-l2x0: Add support for re-enabling l2x0
Quoted 36 lines · Catalin Marinas
Quoted 21 lines · Colin Cross
arch/arm/mm/cache-l2x0.c +10
-0@@ -252,16 +252,26 @@ static void l2x0_flush_range(unsigned long start, unsigned long end)spin_unlock_irqrestore (&l2x0_lock, flags); } +/* enables l2x0 after l2x0_disable, does not invalidate */ +void l2x0_enable (void ) +{ +unsigned long flags; + +spin_lock_irqsave (&l2x0_lock, flags); +writel_relaxed (1 , l2x0_base +L2X0_CTRL ); +spin_unlock_irqrestore (&l2x0_lock, flags); +} +static void l2x0_disable (void ) {unsigned long flags;spin_lock_irqsave (&l2x0_lock, flags);arch/arm/mm/cache-l2x0.c static void l2x0_flush_range(unsigned long start, unsigned long end) · line 277
Quoted 10 lines
arch/arm/mm/cache-l2x0.c +2
-2-writel (0 , l2x0_base +L2X0_CTRL ); +writel_relaxed (0 , l2x0_base +L2X0_CTRL );spin_unlock_irqrestore (&l2x0_lock, flags); } -void __init l2x0_init (void __iomem *base,__u32 aux_val,__u32 aux_mask) +void l2x0_init (void __iomem *base,__u32 aux_val,__u32 aux_mask) {__u32 aux;__u32 cache_id;So this assumes that the L2 registers are accessible. I suspect the platform code calling it should know this.
Quoted 3 lines
The patch looks fine.
Acked-by Catalin Marinas <[email protected]>
I think we need to come up with some proper way to deal with cpuidle which doesn't involve adding lots of globally visible functions to all sorts of bits of code and having platforms call them individually, otherwise this is going to get _really_ messy in the future.
Maybe we need a notifier list which can be told when cpuidle events happen, so that parts of the system such as VFP and L2 cache support can do the right thing without having platforms add lots of stuff like
gic_secondary_init(); gic_restore_interrupt_types(); vfp_enable(); l2x0_enable(); twd_enable(); ... etc ...
in their SoC specific code.
Re: [PATCH v2 04/28] ARM: mm: cache-l2x0: Add support for re-enabling l2x0
Quoted 9 lines · Russell King - ARM Linux
I think we need to come up with some proper way to deal with cpuidle which doesn't involve adding lots of globally visible functions to all sorts of bits of code and having platforms call them individually, otherwise this is going to get _really_ messy in the future.
Maybe we need a notifier list which can be told when cpuidle events happen, so that parts of the system such as VFP and L2 cache support can do the right thing without having platforms add lots of stuff like
Quoted 8 lines
gic_secondary_init(); gic_restore_interrupt_types(); vfp_enable(); l2x0_enable(); twd_enable(); ... etc ...in their SoC specific code.
But do we need a strict order between such operations? The notifier call chain isn't too flexible.
Signature · 1 line
Catalin
RE: [PATCH v2 04/28] ARM: mm: cache-l2x0: Add support for re-enabling l2x0
Quoted 33 lines
-----Original Message-----
From: Catalin Marinas [mailto:catalin.marinas at arm.com]
Sent: Tuesday, January 25, 2011 11:44 PM
To: Russell King - ARM Linux
Cc: Colin Cross; linux-tegra at vger.kernel.org; linux-arm- kernel at lists.infradead.org; olof at lixom.net; konkers at android.com; Santosh Shilimkar; Linus Walleij; Tony Lindgren; linux- kernel at vger.kernel.org
Subject: Re: [PATCH v2 04/28] ARM: mm: cache-l2x0: Add support for re-enabling l2x0Quoted 1 line · Russell King - ARM Linux
I think we need to come up with some proper way to deal with
cpuidle
Quoted 1 line
which doesn't involve adding lots of globally visible functions to
all
Quoted 4 lines
sorts of bits of code and having platforms call them individually, otherwise this is going to get _really_ messy in the future.
Maybe we need a notifier list which can be told when cpuidle
events
Quoted 1 line
happen, so that parts of the system such as VFP and L2 cache
support
Quoted 1 line
can do the right thing without having platforms add lots of stuff
like
Quoted 8 lines
gic_secondary_init(); gic_restore_interrupt_types(); vfp_enable(); l2x0_enable(); twd_enable(); ... etc ...
Quoted 6 lines
Quoted 1 line
in their SoC specific code.
But do we need a strict order between such operations? The notifier call
chain isn't too flexible.
I guess it does depends on how the archs have integrated a9. Example on OMAP there are different power modes possible.
1. CPU context ,TWD lost
2. CPU context ,TWD + L1 is lost
3. CPU context + L1 is lost + GIC lost
4. CPU context + L1 is lost + GIC lost + L2 lost
So there is need to have flexibility of calling these function based on power modes. I don't know how notifiers can give this flexibility
Regards,
Santosh
PATCH v2 4/28 ARM: mm: cache-l2x0: Add support for re-enabling l2x0
Santosh,
Quoted 20 lines
Quoted 14 lines
Quoted 1 line
Maybe we need a notifier list which can be told when cpuidle
events
Quoted 1 line
happen, so that parts of the system such as VFP and L2 cache
support
Quoted 1 line
can do the right thing without having platforms add lots of stuff
like
Quoted 8 lines
gic_secondary_init(); gic_restore_interrupt_types(); vfp_enable(); l2x0_enable(); twd_enable(); ... etc ...Quoted 6 lines
Quoted 1 line
in their SoC specific code.
But do we need a strict order between such operations? The notifier call
chain isn't too flexible.
Quoted 9 lines
I guess it does depends on how the archs have integrated a9. Example on OMAP there are different power modes possible.
1. CPU context ,TWD lost
2. CPU context ,TWD + L1 is lost
3. CPU context + L1 is lost + GIC lost
4. CPU context + L1 is lost + GIC lost + L2 lost
So there is need to have flexibility of calling these function based on power modes. I don't know how notifiers can give this flexibility
Well if you set the priority fields in the notifier blocks correctly then you can just return NOTIFY_STOP when you've saved/restored as much as you want. This assumes of course that you can identify which power mode you're entering/leaving and that each one is `deeper' than the previous.
Will
A message that is not in the archive (sent off-list or not yet received): -8932138696981683633@unknownmsgid
Re: [PATCH v2 04/28] ARM: mm: cache-l2x0: Add support for re-enabling l2x0
Quoted 32 lines · Will Deacon
Santosh,
Quoted 20 lines
Quoted 14 lines
Quoted 1 line
Maybe we need a notifier list which can be told when cpuidle
events
Quoted 1 line
happen, so that parts of the system such as VFP and L2 cache
support
Quoted 1 line
can do the right thing without having platforms add lots of stuff
like
Quoted 8 lines
? ? ? ?
gic_secondary_init();
? ? ? ?gic_restore_interrupt_types();
? ? ? ?vfp_enable();
? ? ? ?l2x0_enable();
? ? ? ?twd_enable();
? ? ? ? ... etc ...Quoted 6 lines
Quoted 1 line
in their SoC specific code.
But do we need a strict order between such operations? The notifier call
chain isn't too flexible.Quoted 9 lines
I guess it does depends on how the archs have integrated a9. Example on OMAP there are different power modes possible.
? ? ? 1. CPU context ,TWD lost
? ? ? 2. CPU context ,TWD + L1 is lost
? ? ? 3. CPU context + L1 is lost + GIC lost
? ? ? 4. CPU context + L1 is lost + GIC lost + L2 lost
So there is need to have flexibility of calling these function based on power modes. I don't know how notifiers can give this flexibility
Quoted 4 lines
Well if you set the priority fields in the notifier blocks correctly then you can just return
NOTIFY_STOPwhen you've saved/restored as much as you want. This assumes of course that you can identify which power mode you're entering/leaving and that each one is `deeper' than the previous.
I doubt its possible to create an order that will work for all architectures, and returning NOTIFY_STOP would require the decision on when to finish to be made by the notifier block instead of the platform code.
Tegra has three possible idle modes:
1. WFI - nothing reset 2. CPU, TWD, L1, GIC lost, L2 needs to be disabled but not reset 3. CPU, TWD, L1, GIC, and L2 lost
CPU and L1 are already handled by the platform-specific suspend code. TWD is handled by the clockevents broadcast notifiers. That leaves L2 and GIC.
The L2 can be idled in two ways: just disable it, but keep the contents, which prevents having to refill the cache, or a full reset. Disabling can already be handled by outer_cache_disable().
The GIC needs to be idled differently depending on which cpus are idle. On Tegra, if both cpus are idle, the secondary cpu needs to disable its GIC and go to WFI, while the first cpu saves the GIC distributor state and powers off both cpus.
While it seems possible to handle all of these cases with a notifier chain, the amount of platform-specific knowledge and ordering seems too much to make it worthwhile.
If the ordering requirements are close enough between platforms, or non-existent (I don't think there are any requirements on Tegra), a notifier chain with a mask of the hardware that is being reset could work. On Tegra, in case 2 above, CPU1 would call:
idle_notify(IDLE_ENTER | GIC_DISABLE)
and CPU0 would call:
idle_notify(IDLE_ENTER | GIC_DISABLE | GIC_SAVE | L2_DISABLE)
Re: [PATCH v2 04/28] ARM: mm: cache-l2x0: Add support for re-enabling l2x0
Quoted 11 lines · Colin Cross
Quoted 4 lines · Will Deacon
Well if you set the priority fields in the notifier blocks correctly then you can just return
NOTIFY_STOPwhen you've saved/restored as much as you want. This assumes of course that you can identify which power mode you're entering/leaving and that each one is `deeper' than the previous.I doubt its possible to create an order that will work for all architectures, and returning
NOTIFY_STOPwould require the decision on when to finish to be made by the notifier block instead of the platform code.
Quoted 5 lines
Tegra has three possible idle modes:
1. WFI - nothing reset 2. CPU, TWD, L1, GIC lost, L2 needs to be disabled but not reset 3. CPU, TWD, L1, GIC, and L2 lost
(2) and (3) don't sound like per-cpu modes but system modes. If you're having to disable L2, then your other CPU can't be active.
Quoted 3 lines
CPU and L1 are already handled by the platform-specific suspend code. TWD is handled by the clockevents broadcast notifiers. That leaves L2 and GIC.
GIC can be handled in just the same way - upon a CPU idling and it being decided that the CPU should enter low power mode, the idle states are entered which does what's required with TWD, L1, VFP, Neon, etc. We just need the GIC CPU interface included in there.
When both CPUs are idled, then the L2 comes into play, and then modes
(2) and (3) become possible and this is where you start doing the extra stuff.
Note that you have to do it that way anyway, because you can't save the state of the other CPU's GIC without doing an IPI call, which could kick it out of its idle mode.
Re: [PATCH v2 04/28] ARM: mm: cache-l2x0: Add support for re-enabling l2x0
Quoted 12 lines · Russell King - ARM Linux
Quoted 11 lines · Colin Cross
Quoted 4 lines · Will Deacon
Well if you set the priority fields in the notifier blocks correctly then you can just return
NOTIFY_STOPwhen you've saved/restored as much as you want. This assumes of course that you can identify which power mode you're entering/leaving and that each one is `deeper' than the previous.I doubt its possible to create an order that will work for all architectures, and returning
NOTIFY_STOPwould require the decision on when to finish to be made by the notifier block instead of the platform code.
Quoted 8 lines
Quoted 5 lines
Tegra has three possible idle modes:
1. ?WFI - nothing reset
2. ?CPU, TWD, L1, GIC lost, L2 needs to be disabled but not reset
3. ?CPU, TWD, L1, GIC, and L2 lost(2) and (3) don't sound like per-cpu modes but system modes. ?If you're having to disable L2, then your other CPU can't be active.
Yes, 2 and 3 require both CPUs to be idle. Unfortunately, on Tegra, it is important to use at least 2 as much as possible, because the two CPUs are not individually power gated.
Quoted 4 lines
Quoted 3 lines
CPU and L1 are already handled by the platform-specific suspend code. TWD is handled by the clockevents broadcast notifiers. ?That leaves L2 and GIC.
Quoted 8 lines
GIC can be handled in just the same way - upon a CPU idling and it being decided that the CPU should enter low power mode, the idle states are entered which does what's required with TWD, L1, VFP, Neon, etc. We just need the GIC CPU interface included in there.
When both CPUs are idled, then the L2 comes into play, and then modes
(2) and (3) become possible and this is where you start doing the extra stuff.
Are you suggesting that the idle notifiers only handle TWD, L1, VFP, Neon, and GIC? That would simplify things, as there are probably no ordering requirements, and they should be the same for any platform that uses them.
Quoted 3 lines
Note that you have to do it that way anyway, because you can't save the state of the other CPU's GIC without doing an IPI call, which could kick it out of its idle mode.
There is currently no state that needs to be saved in the GIC CPU registers, they can all be reinitialized.
RE: [PATCH v2 04/28] ARM: mm: cache-l2x0: Add support for re-enabling l2x0
Quoted 71 lines
-----Original Message-----
From: ccross at google.com [mailto:ccross at google.com] On Behalf Of Colin Cross
Sent: Saturday, February 05, 2011 7:15 AM
To: Russell King - ARM Linux
Cc: Will Deacon; Santosh Shilimkar; Catalin Marinas; Linus Walleij; konkers at android.com; Tony Lindgren; linux-kernel at vger.kernel.org; linux-tegra at vger.kernel.org; olof at lixom.net; linux-arm- kernel at lists.infradead.org
Subject: Re: [PATCH v2 04/28] ARM: mm: cache-l2x0: Add support for re-enabling l2x0Quoted 2 lines · Russell King - ARM Linux
Quoted 1 line · Colin Cross
On Tue, Jan 25, 2011 at 12:39 PM, Will Deacon
Quoted 1 line · <[email protected]> wrote:
Quoted 1 line
Quoted 1 line
Well if you set the priority fields in the notifier blocks
correctly
Quoted 1 line
Quoted 1 line
Quoted 1 line
then you can just return
NOTIFY_STOPwhen you've saved/restoredas much
Quoted 1 line
Quoted 1 line
Quoted 1 line
as you want. This assumes of course that you can identify which
power
Quoted 1 line
Quoted 1 line
Quoted 1 line
mode you're entering/leaving and that each one is `deeper' than
the previous.
Quoted 3 lines
Quoted 3 lines
I doubt its possible to create an order that will work for all architectures, and returning
NOTIFY_STOPwould require thedecision on
Quoted 10 lines
Quoted 8 lines
when to finish to be made by the notifier block instead of the platform code.
Tegra has three possible idle modes:
1. ?WFI - nothing reset
2. ?CPU, TWD, L1, GIC lost, L2 needs to be disabled but not reset
3. ?CPU, TWD, L1, GIC, and L2 lost(2) and (3) don't sound like per-cpu modes but system modes. ?If
you're
Quoted 1 line
having to disable L2, then your other CPU can't be active.
Yes, 2 and 3 require both CPUs to be idle. Unfortunately, on Tegra, it is important to use at least 2 as much as possible, because the two
CPUs are not individually power gated.Quoted 1 line
Quoted 1 line
CPU and L1 are already handled by the platform-specific suspend
code.
Quoted 1 line
Quoted 1 line
TWD is handled by the clockevents broadcast notifiers. ?That
leaves L2
Quoted 4 lines
Quoted 1 line
and GIC.
GIC can be handled in just the same way - upon a CPU idling and it being decided that the CPU should enter low power mode, the idle
states
Quoted 1 line
are entered which does what's required with TWD, L1, VFP, Neon,
etc.
Quoted 3 lines
We just need the GIC CPU interface included in there.
When both CPUs are idled, then the L2 comes into play, and then
modes
Quoted 1 line
(2) and (3) become possible and this is where you start doing the
extra
Quoted 1 line
stuff.
Are you suggesting that the idle notifiers only handle TWD, L1, VFP, Neon, and GIC? That would simplify things, as there are probably no ordering requirements, and they should be the same for any platform that uses them.
Quoted 7 lines
Quoted 1 line
Note that you have to do it that way anyway, because you can't
save
Quoted 2 lines
the state of the other CPU's GIC without doing an IPI call, which could kick it out of its idle mode.
There is currently no state that needs to be saved in the GIC CPU registers, they can all be reinitialized.
GIC save/restore on OMAP follows different strategy. There is a Predefined layout to save content and restore is done atomically by boot ROM code.
L2 cache also same case. Only AUXCTRL needs to be programmed on wakeup from low power mode and that too with secure call. Rest of the registers are managed by boot ROM code.
TWD is already managed through framework. Othe CPU low power sequence is very small and OMAP has restrictions on the last core to go down and first to wakeup.
So at least I don't see any use of common notifiers for GIC and L2 will help OMAP lower power code.
Regards,
Santosh
Re: [PATCH v2 04/28] ARM: mm: cache-l2x0: Add support for re-enabling l2x0
Quoted 7 lines · Santosh Shilimkar
GIC save/restore on OMAP follows different strategy. There is a Predefined layout to save content and restore is done atomically by boot ROM code.
L2 cache also same case. Only AUXCTRL needs to be programmed on wakeup from low power mode and that too with secure call. Rest of the registers are managed by boot ROM code.
Quoted 6 lines
TWD is already managed through framework. Othe CPU low power sequence is very small and OMAP has restrictions on the last core to go down and first to wakeup.
So at least I don't see any use of common notifiers for GIC and L2 will help OMAP lower power code.
What this means is that we're going to end up littering things like GIC and other stuff with lots of individual SoC specific code to save state into individual SoC specific structures. This is not sane, and we're not going to corrupt generic code with SoC specific code.
RE: [PATCH v2 04/28] ARM: mm: cache-l2x0: Add support forre-enabling l2x0
Quoted 26 lines
-----Original Message-----
From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
Sent: Saturday, February 05, 2011 3:18 PM
To: Santosh Shilimkar
Cc: Colin Cross; Will Deacon; Catalin Marinas; Linus Walleij; konkers at android.com; Tony Lindgren; linux-kernel at vger.kernel.org; linux-tegra at vger.kernel.org; olof at lixom.net; linux-arm- kernel at lists.infradead.org
Subject: Re: [PATCH v2 04/28] ARM: mm: cache-l2x0: Add support forre-enabling l2x0Quoted 7 lines · Santosh Shilimkar
GIC save/restore on OMAP follows different strategy. There is a Predefined layout to save content and restore is done atomically by boot ROM code.
L2 cache also same case. Only AUXCTRL needs to be programmed on wakeup from low power mode and that too with secure call. Rest of the registers are managed by boot ROM code.Quoted 6 lines
TWD is already managed through framework. Othe CPU low power sequence is very small and OMAP has restrictions on the last core to go down and first to wakeup.
So at least I don't see any use of common notifiers for GIC and L2 will help OMAP lower power code.
Quoted 7 lines
What this means is that we're going to end up littering things like GIC
and other stuff with lots of individual SoC specific code to save state
into individual SoC specific structures. This is not sane, and we're
not going to corrupt generic code with SoC specific code.
Fully agree and hence flagged it early.
Regards,
Santosh
Re: [PATCH v2 04/28] ARM: mm: cache-l2x0: Add support forre-enabling l2x0
Quoted 34 lines · Santosh Shilimkar
Quoted 26 lines
-----Original Message-----
From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
Sent: Saturday, February 05, 2011 3:18 PM
To: Santosh Shilimkar
Cc: Colin Cross; Will Deacon; Catalin Marinas; Linus Walleij; konkers at android.com; Tony Lindgren; linux-kernel at vger.kernel.org; linux-tegra at vger.kernel.org; olof at lixom.net; linux-arm- kernel at lists.infradead.org
Subject: Re: [PATCH v2 04/28] ARM: mm: cache-l2x0: Add support forre-enabling l2x0Quoted 7 lines · Santosh Shilimkar
GIC save/restore on OMAP follows different strategy. There is a Predefined layout to save content and restore is done atomically by boot ROM code.
L2 cache also same case. Only AUXCTRL needs to be programmed on wakeup from low power mode and that too with secure call. Rest of the registers are managed by boot ROM code.Quoted 6 lines
TWD is already managed through framework. Othe CPU low power sequence is very small and OMAP has restrictions on the last core to go down and first to wakeup.
So at least I don't see any use of common notifiers for GIC and L2 will help OMAP lower power code.
Quoted 7 lines
What this means is that we're going to end up littering things like GIC
and other stuff with lots of individual SoC specific code to save state
into individual SoC specific structures. ?This is not sane, and we're
not going to corrupt generic code with SoC specific code.
Quoted 5 lines
Fully agree and hence flagged it early.
Regards,
Santosh
Would putting dummy values in the areas the boot ROM uses and then letting the common GIC code restore over them cause any problems?
RE: [PATCH v2 04/28] ARM: mm: cache-l2x0: Add support forre-enabling l2x0
Quoted 14 lines
-----Original Message-----
From: ccross at google.com [mailto:ccross at google.com] On Behalf Of Colin Cross
Sent: Saturday, February 05, 2011 10:06 PM
To: Santosh Shilimkar
Cc: Russell King - ARM Linux; Will Deacon; Catalin Marinas; Linus Walleij; konkers at android.com; Tony Lindgren; linux-
kernel at vger.kernel.org; linux-tegra at vger.kernel.org; olof at lixom.net; linux-arm-kernel at lists.infradead.org
Subject: Re: [PATCH v2 04/28] ARM: mm: cache-l2x0: Add support forre-enabling l2x0On Sat, Feb 5, 2011 at 4:41 AM, Santosh Shilimkar
<[email protected]> wrote:
[....]
Quoted 28 lines
Quoted 1 line
Quoted 1 line
On Sat, Feb 05, 2011 at 01:21:24PM +0530, Santosh Shilimkar
Quoted 2 lines · wrote:
Quoted 2 lines
Quoted 2 lines
GIC save/restore on OMAP follows different strategy. There is a Predefined layout to save content and restore is done
atomically
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
by boot ROM code.
L2 cache also same case. Only AUXCTRL needs to be programmed on wakeup from low power mode and that too with secure call. Rest of the registers are managed by boot ROM code.Quoted 8 lines
Quoted 8 lines
Quoted 6 lines
TWD is already managed through framework. Othe CPU low power sequence is very small and OMAP has restrictions on the last core to go down and first to wakeup.
So at least I don't see any use of common notifiers for GIC and L2 will help OMAP lower power code.
What this means is that we're going to end up littering things
like
Quoted 9 lines
Quoted 6 lines
GIC
and other stuff with lots of individual SoC specific code to save state
into individual SoC specific structures. ?This is not sane, and we're
not going to corrupt generic code with SoC specific code.Fully agree and hence flagged it early.
[....]
Quoted 3 lines
Would putting dummy values in the areas the boot ROM uses and then letting the common GIC code restore over them cause any problems?
Ya there are few issue. GIC and GIC OMAP extension are managed together by BOOT ROM code. It's far optimal save and restore. Only needed registers from OMAP point of view are saved/restored. And for such reasons I would not like to use dummy stuff.
Regards
Santosh
PATCH v2 5/28 ARM: tegra: Centralize macros to define debug uart base
In reply to Colin Cross--- arch/arm/mach-tegra/include/mach/debug-macro.S | 25 ++++------------------- arch/arm/mach-tegra/include/mach/iomap.h | 14 +++++++++++++ arch/arm/mach-tegra/include/mach/uncompress.h | 18 +--------------- 3 files changed, 21 insertions(+), 36 deletions(-)
arch/arm/mach-tegra/include/mach/debug-macro.S +5 -20
@@ -19,30 +19,15 @@ */ #include <mach/io.h> +#include <mach/iomap.h> .macro addruart, rp, rv ldr \rp, =IO_APB_PHYS @ physical ldr \rv, =IO_APB_VIRT @ virtual -#if defined(CONFIG_TEGRA_DEBUG_UART_NONE) -#error "A debug UART must be selected in the kernel config to use DEBUG_LL" -#elif defined(CONFIG_TEGRA_DEBUG_UARTA) - orr \rp, \rp, #0x6000 - orr \rv, \rv, #0x6000 -#elif defined(CONFIG_TEGRA_DEBUG_UARTB) - orr \rp, \rp, #0x6000 - orr \rp, \rp, #0x40 - orr \rv, \rv, #0x6000 - orr \rv, \rv, #0x40 -#elif defined(CONFIG_TEGRA_DEBUG_UARTC) - orr \rp, \rp, #0x6200 - orr \rv, \rv, #0x6200 -#elif defined(CONFIG_TEGRA_DEBUG_UARTD) - orr \rp, \rp, #0x6300 - orr \rv, \rv, #0x6300 -#elif defined(CONFIG_TEGRA_DEBUG_UARTE) - orr \rp, \rp, #0x6400 - orr \rv, \rv, #0x6400 -#endif + orr \rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF) + orr \rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF00) + orr \rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF) + orr \rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF00) .endm #define UART_SHIFT 2
arch/arm/mach-tegra/include/mach/iomap.h +14 -0
@@ -221,4 +221,18 @@#define TEGRA_SDMMC4_BASE 0xC8000600#define TEGRA_SDMMC4_SIZE SZ_512 +#if defined(CONFIG_TEGRA_DEBUG_UART_NONE ) +# define TEGRA_DEBUG_UART_BASE 0 +#elif defined(CONFIG_TEGRA_DEBUG_UARTA ) +# define TEGRA_DEBUG_UART_BASE TEGRA_UARTA_BASE +#elif defined(CONFIG_TEGRA_DEBUG_UARTB ) +# define TEGRA_DEBUG_UART_BASE TEGRA_UARTB_BASE +#elif defined(CONFIG_TEGRA_DEBUG_UARTC ) +# define TEGRA_DEBUG_UART_BASE TEGRA_UARTC_BASE +#elif defined(CONFIG_TEGRA_DEBUG_UARTD ) +# define TEGRA_DEBUG_UART_BASE TEGRA_UARTD_BASE +#elif defined(CONFIG_TEGRA_DEBUG_UARTE ) +# define TEGRA_DEBUG_UART_BASE TEGRA_UARTE_BASE +#endif +#endif
arch/arm/mach-tegra/include/mach/uncompress.h +2 -16
@@ -26,23 +26,9 @@#include <mach/iomap.h> -#if defined(CONFIG_TEGRA_DEBUG_UARTA ) -#define DEBUG_UART_BASE TEGRA_UARTA_BASE -#elif defined(CONFIG_TEGRA_DEBUG_UARTB ) -#define DEBUG_UART_BASE TEGRA_UARTB_BASE -#elif defined(CONFIG_TEGRA_DEBUG_UARTC ) -#define DEBUG_UART_BASE TEGRA_UARTC_BASE -#elif defined(CONFIG_TEGRA_DEBUG_UARTD ) -#define DEBUG_UART_BASE TEGRA_UARTD_BASE -#elif defined(CONFIG_TEGRA_DEBUG_UARTE ) -#define DEBUG_UART_BASE TEGRA_UARTE_BASE -#else -#define DEBUG_UART_BASE NULL -#endif -static void putc (int c) { -volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE ; +volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE ;int shift =2 ;if (uart ==NULL )
@@ -59,7 +45,7 @@ static inline void flush(void)static inline void arch_decomp_setup (void ) { -volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE ; +volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE ;int shift =2 ;if (uart ==NULL )
Signature · 1 line
1.7.3.1
PATCH v2 6/28 ARM: tegra: Add api to control internal powergating
In reply to Colin Cross--- arch/arm/mach-tegra/Makefile | 1 + arch/arm/mach-tegra/include/mach/powergate.h | 40 +++++ arch/arm/mach-tegra/powergate.c | 212 ++++++++++++++++++++++++++ 3 files changed, 253 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-tegra/include/mach/powergate.h create mode 100644 arch/arm/mach-tegra/powergate.c
arch/arm/mach-tegra/Makefile +1 -0
@@ -5,6 +5,7 @@ obj-y += clock.o obj-y += timer.o obj-y += gpio.o obj-y += pinmux.o +obj-y += powergate.o obj-y += fuse.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clock.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o
arch/arm/mach-tegra/include/mach/powergate.h new file +40 -0
@@ -0,0 +1,40 @@ +/* +* drivers/regulator/tegra-regulator.c +* +* Copyright (c) 2010 Google, Inc +* +* Author: +* Colin Cross <[email protected]> +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + +#ifndef _MACH_TEGRA_POWERGATE_H_ +#define _MACH_TEGRA_POWERGATE_H_ + +#define TEGRA_POWERGATE_CPU 0 +#define TEGRA_POWERGATE_3D 1 +#define TEGRA_POWERGATE_VENC 2 +#define TEGRA_POWERGATE_PCIE 3 +#define TEGRA_POWERGATE_VDEC 4 +#define TEGRA_POWERGATE_L2 5 +#define TEGRA_POWERGATE_MPE 6 +#define TEGRA_NUM_POWERGATE 7 + +int tegra_powergate_power_on (int id); +int tegra_powergate_power_off (int id); +bool tegra_powergate_is_powered (int id); +int tegra_powergate_remove_clamping (int id); + +/* Must be called with clk disabled, and returns with clk enabled */ +int tegra_powergate_sequence_power_up (int id,struct clk *clk); + +#endif /* _MACH_TEGRA_POWERGATE_H_ */
arch/arm/mach-tegra/powergate.c new file +212 -0
212 lines not on this page · raw message
Signature · 1 line
1.7.3.1
PATCH v2 7/28 ARM: tegra: irqs: Update irq list
In reply to Colin CrossFixes typo in INT_CPU1_PMU_INTR (original fix from Will Deacon) Adds board irqs
--- arch/arm/mach-tegra/include/mach/irqs.h | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-)
arch/arm/mach-tegra/include/mach/irqs.h +11 -3
@@ -88,7 +88,7 @@#define INT_SYS_STATS_MON (INT_SEC_BASE + 22)#define INT_GPIO5 (INT_SEC_BASE + 23)#define INT_CPU0_PMU_INTR (INT_SEC_BASE + 24) -#define INT_CPU2_PMU_INTR (INT_SEC_BASE + 25) +#define INT_CPU1_PMU_INTR (INT_SEC_BASE + 25)#define INT_SEC_RES_26 (INT_SEC_BASE + 26)#define INT_S_LINK1 (INT_SEC_BASE + 27)#define INT_APB_DMA_COP (INT_SEC_BASE + 28)
@@ -166,10 +166,18 @@#define INT_QUAD_RES_30 (INT_QUAD_BASE + 30)#define INT_QUAD_RES_31 (INT_QUAD_BASE + 31) -#define INT_GPIO_BASE (INT_QUAD_BASE + 32) +#define INT_MAIN_NR (INT_QUAD_BASE + 32 - INT_PRI_BASE) + +#define INT_GPIO_BASE (INT_PRI_BASE + INT_MAIN_NR) +#define INT_GPIO_NR (28 * 8) -#define NR_IRQS (INT_GPIO_BASE + INT_GPIO_NR) +#define TEGRA_NR_IRQS (INT_GPIO_BASE + INT_GPIO_NR) + +#define INT_BOARD_BASE TEGRA_NR_IRQS +#define NR_BOARD_IRQS 32 + +#define NR_IRQS (INT_BOARD_BASE + NR_BOARD_IRQS)#endif #endif
Signature · 1 line
1.7.3.1
PATCH v2 8/28 ARM: tegra: Add prototypes for subsystem suspend functions
In reply to Colin Cross--- arch/arm/mach-tegra/dma.c | 1 + arch/arm/mach-tegra/gpio.c | 1 + arch/arm/mach-tegra/include/mach/suspend.h | 38 ++++++++++++++++++++++++++++ arch/arm/mach-tegra/irq.c | 1 + arch/arm/mach-tegra/pinmux-t2-tables.c | 1 + arch/arm/mach-tegra/tegra2_clocks.c | 1 + arch/arm/mach-tegra/timer.c | 1 + 7 files changed, 44 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-tegra/include/mach/suspend.h
arch/arm/mach-tegra/dma.c +1 -0
@@ -30,6 +30,7 @@#include <mach/dma.h> #include <mach/irqs.h> #include <mach/iomap.h> +#include <mach/suspend.h> #define APB_DMA_GEN 0x000#define GEN_ENABLE (1<<31)
arch/arm/mach-tegra/gpio.c +1 -0
@@ -25,6 +25,7 @@#include <linux/gpio.h> #include <mach/iomap.h> +#include <mach/suspend.h> #define GPIO_BANK (x) ((x) >> 5)#define GPIO_PORT (x) (((x) >> 3) & 0x3)
arch/arm/mach-tegra/include/mach/suspend.h new file +38 -0
@@ -0,0 +1,38 @@ +/* +* arch/arm/mach-tegra/include/mach/suspend.h +* +* Copyright (C) 2010 Google, Inc. +* +* Author: +* Colin Cross <[email protected]> +* +* This software is licensed under the terms of the GNU General Public +* License version 2, as published by the Free Software Foundation, and +* may be copied, distributed, and modified under those terms. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +*/ + + +#ifndef _MACH_TEGRA_SUSPEND_H_ +#define _MACH_TEGRA_SUSPEND_H_ + +void tegra_pinmux_suspend (void ); +void tegra_irq_suspend (void ); +void tegra_gpio_suspend (void ); +void tegra_clk_suspend (void ); +void tegra_dma_suspend (void ); +void tegra_timer_suspend (void ); + +void tegra_pinmux_resume (void ); +void tegra_irq_resume (void ); +void tegra_gpio_resume (void ); +void tegra_clk_resume (void ); +void tegra_dma_resume (void ); +void tegra_timer_resume (void ); + +#endif /* _MACH_TEGRA_SUSPEND_H_ */
arch/arm/mach-tegra/irq.c +1 -0
@@ -26,6 +26,7 @@#include <asm/hardware/gic.h> #include <mach/iomap.h> +#include <mach/suspend.h> #include "board.h"
arch/arm/mach-tegra/pinmux-t2-tables.c +1 -0
@@ -29,6 +29,7 @@#include <mach/iomap.h> #include <mach/pinmux.h> +#include <mach/suspend.h> #define DRIVE_PINGROUP (pg_name, r) \ [TEGRA_DRIVE_PINGROUP_ ## pg_name] = { \
arch/arm/mach-tegra/tegra2_clocks.c +1 -0
@@ -27,6 +27,7 @@#include <linux/clkdev.h> #include <mach/iomap.h> +#include <mach/suspend.h> #include "clock.h" #include "fuse.h"
arch/arm/mach-tegra/timer.c +1 -0
@@ -33,6 +33,7 @@#include <mach/iomap.h> #include <mach/irqs.h> +#include <mach/suspend.h> #include "board.h" #include "clock.h"
Signature · 1 line
1.7.3.1
PATCH v2 9/28 ARM: tegra: clock: Suspend fixes, and add new clocks
In reply to Colin CrossSave and restore pll and osc state during suspend
Add digital audio clocks
Update clk dev associations
Correct max clock frequencies
Add pll_p as additional cpu clock state
Add values to plld table
Fix register offset for sdmmc4 clock
Add blink timer to tegra2_clocks
--- arch/arm/mach-tegra/tegra2_clocks.c | 263 ++++++++++++++++++++++++++++++++--- 1 files changed, 244 insertions(+), 19 deletions(-)
arch/arm/mach-tegra/tegra2_clocks.c +244 -19
@@ -52,7 +52,7 @@#define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30)#define OSC_CTRL_OSC_FREQ_12MHZ (2<<30)#define OSC_CTRL_OSC_FREQ_26MHZ (3<<30) -#define OSC_CTRL_MASK 0x3f2 +#define OSC_CTRL_MASK (0x3f2 | OSC_CTRL_OSC_FREQ_MASK)#define OSC_FREQ_DET 0x58#define OSC_FREQ_DET_TRIG (1<<31)
@@ -135,12 +135,29 @@#define BUS_CLK_DISABLE (1<<3)#define BUS_CLK_DIV_MASK 0x3 +#define PMC_CTRL 0x0 +#define PMC_CTRL_BLINK_ENB (1 << 7) + +#define PMC_DPD_PADS_ORIDE 0x1c +#define PMC_DPD_PADS_ORIDE_BLINK_ENB (1 << 20) + +#define PMC_BLINK_TIMER_DATA_ON_SHIFT 0 +#define PMC_BLINK_TIMER_DATA_ON_MASK 0x7fff +#define PMC_BLINK_TIMER_ENB (1 << 15) +#define PMC_BLINK_TIMER_DATA_OFF_SHIFT 16 +#define PMC_BLINK_TIMER_DATA_OFF_MASK 0xffff +static void __iomem *reg_clk_base =IO_ADDRESS (TEGRA_CLK_RESET_BASE ); +static void __iomem *reg_pmc_base =IO_ADDRESS (TEGRA_PMC_BASE );#define clk_writel (value, reg) \ __raw_writel(value, (u32)reg_clk_base + (reg))#define clk_readl (reg) \ __raw_readl((u32)reg_clk_base + (reg)) +#define pmc_writel (value, reg) \ + __raw_writel(value, (u32)reg_pmc_base + (reg)) +#define pmc_readl (reg) \ + __raw_readl((u32)reg_pmc_base + (reg))unsigned long clk_measure_input_freq (void ) {
@@ -358,6 +375,9 @@ static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate)return ret; } +if (rate == c->backup->rate) + goto out; + ret =clk_set_rate_locked (c->main, rate);if (ret) {pr_err ("Failed to change cpu pll to %lu\n" , rate);
@@ -370,6 +390,7 @@ static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate)return ret; } +out:return 0 ; }
@@ -429,6 +450,87 @@ static struct clk_ops tegra_bus_ops = { .set_rate = tegra2_bus_clk_set_rate, }; +/* Blink output functions */ + +static void tegra2_blink_clk_init (struct clk *c) +{ +u32 val; + + val =pmc_readl (PMC_CTRL ); + c->state = (val &PMC_CTRL_BLINK_ENB ) ?ON :OFF ; + c->mul =1 ; + val =pmc_readl (c->reg); + +if (val &PMC_BLINK_TIMER_ENB ) { +unsigned int on_off; + + on_off = (val >>PMC_BLINK_TIMER_DATA_ON_SHIFT ) & +PMC_BLINK_TIMER_DATA_ON_MASK ; + val >>=PMC_BLINK_TIMER_DATA_OFF_SHIFT ; + val &=PMC_BLINK_TIMER_DATA_OFF_MASK ; + on_off += val; +/* each tick in the blink timer is 4 32KHz clocks */ + c->div = on_off *4 ; + }else { + c->div =1 ; + } +} + +static int tegra2_blink_clk_enable (struct clk *c) +{ +u32 val; + + val =pmc_readl (PMC_DPD_PADS_ORIDE ); +pmc_writel (val |PMC_DPD_PADS_ORIDE_BLINK_ENB ,PMC_DPD_PADS_ORIDE ); + + val =pmc_readl (PMC_CTRL ); +pmc_writel (val |PMC_CTRL_BLINK_ENB ,PMC_CTRL ); + +return 0 ; +} + +static void tegra2_blink_clk_disable (struct clk *c) +{ +u32 val; + + val =pmc_readl (PMC_CTRL ); +pmc_writel (val & ~PMC_CTRL_BLINK_ENB ,PMC_CTRL ); + + val =pmc_readl (PMC_DPD_PADS_ORIDE ); +pmc_writel (val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB ,PMC_DPD_PADS_ORIDE ); +} + +static int tegra2_blink_clk_set_rate (struct clk *c,unsigned long rate) +{ +if (rate >= c->parent->rate) { + c->div =1 ; +pmc_writel (0 , c->reg); + }else { +unsigned int on_off; +u32 val; + + on_off =DIV_ROUND_UP (c->parent->rate /8 , rate); + c->div = on_off *8 ; + + val = (on_off &PMC_BLINK_TIMER_DATA_ON_MASK ) << +PMC_BLINK_TIMER_DATA_ON_SHIFT ; + on_off &=PMC_BLINK_TIMER_DATA_OFF_MASK ; + on_off <<=PMC_BLINK_TIMER_DATA_OFF_SHIFT ; + val |= on_off; + val |=PMC_BLINK_TIMER_ENB ; +pmc_writel (val, c->reg); + } + +return 0 ; +} + +static struct clk_ops tegra_blink_clk_ops = { + .init = &tegra2_blink_clk_init, + .enable = &tegra2_blink_clk_enable, + .disable = &tegra2_blink_clk_disable, + .set_rate = &tegra2_blink_clk_set_rate, +}; +/* PLL Functions */ static int tegra2_pll_clk_wait_for_lock (struct clk *c) {
@@ -929,6 +1031,7 @@ static struct clk_ops tegra_clk_double_ops = { .set_rate = &tegra2_clk_double_set_rate, }; +/* Audio sync clock ops */ static void tegra2_audio_sync_clk_init (struct clk *c) {int source;
@@ -1007,6 +1110,37 @@ static struct clk_ops tegra_audio_sync_clk_ops = { .set_parent = tegra2_audio_sync_clk_set_parent, }; +/* cdev1 and cdev2 (dap_mclk1 and dap_mclk2) ops */ + +static void tegra2_cdev_clk_init (struct clk *c) +{ +/* We could un-tristate the cdev1 or cdev2 pingroup here; this is +* currently done in the pinmux code. */ + c->state =ON ; +if (!(clk_readl (CLK_OUT_ENB +PERIPH_CLK_TO_ENB_REG (c)) & +PERIPH_CLK_TO_ENB_BIT (c))) + c->state =OFF ; +} + +static int tegra2_cdev_clk_enable (struct clk *c) +{ +clk_writel (PERIPH_CLK_TO_ENB_BIT (c), +CLK_OUT_ENB_SET +PERIPH_CLK_TO_ENB_SET_REG (c)); +return 0 ; +} + +static void tegra2_cdev_clk_disable (struct clk *c) +{ +clk_writel (PERIPH_CLK_TO_ENB_BIT (c), +CLK_OUT_ENB_CLR +PERIPH_CLK_TO_ENB_SET_REG (c)); +} + +static struct clk_ops tegra_cdev_clk_ops = { + .init = &tegra2_cdev_clk_init, + .enable = &tegra2_cdev_clk_enable, + .disable = &tegra2_cdev_clk_disable, +}; +/* Clock definitions */ static struct clk tegra_clk_32k = { .name ="clk_32k" ,
@@ -1227,10 +1361,21 @@ static struct clk tegra_pll_a_out0 = { };static struct clk_pll_table tegra_pll_d_table[] = { + {12000000 ,216000000 ,216 ,12 ,1 ,4 }, + {13000000 ,216000000 ,216 ,13 ,1 ,4 }, + {19200000 ,216000000 ,135 ,12 ,1 ,3 }, + {26000000 ,216000000 ,216 ,26 ,1 ,4 }, + + {12000000 ,594000000 ,594 ,12 ,1 ,8 }, + {13000000 ,594000000 ,594 ,13 ,1 ,8 }, + {19200000 ,594000000 ,495 ,16 ,1 ,8 }, + {26000000 ,594000000 ,594 ,26 ,1 ,8 }, + {12000000 ,1000000000 ,1000 ,12 ,1 ,12 }, {13000000 ,1000000000 ,1000 ,13 ,1 ,12 }, {19200000 ,1000000000 ,625 ,12 ,1 ,8 }, {26000000 ,1000000000 ,1000 ,26 ,1 ,12 }, + {0 ,0 ,0 ,0 ,0 ,0 }, };
@@ -1372,6 +1517,24 @@ static struct clk tegra_clk_d = { .max_rate = 52000000, }; +/* dap_mclk1, belongs to the cdev1 pingroup. */ +static struct clk tegra_dev1_clk = { + .name ="clk_dev1" , + .ops = &tegra_cdev_clk_ops, + .clk_num =94 , + .rate =26000000 , + .max_rate =26000000 , +}; + +/* dap_mclk2, belongs to the cdev2 pingroup. */ +static struct clk tegra_dev2_clk = { + .name ="clk_dev2" , + .ops = &tegra_cdev_clk_ops, + .clk_num =93 , + .rate =26000000 , + .max_rate =26000000 , +}; +/* initialized before peripheral clocks */ static struct clk_mux_sel mux_audio_sync_clk[8 +1 ]; static const struct audio_sources {
@@ -1486,7 +1649,7 @@ static struct clk tegra_clk_virtual_cpu = { .name = "cpu", .parent = &tegra_clk_cclk, .main = &tegra_pll_x, - .backup = &tegra_clk_m, + .backup = &tegra_pll_p, .ops = &tegra_cpu_ops, .max_rate = 1000000000, .dvfs = &tegra_dvfs_virtual_cpu_dvfs,
@@ -1512,6 +1675,14 @@ static struct clk tegra_clk_pclk = { .max_rate = 108000000, }; +static struct clk tegra_clk_blink = { + .name ="blink" , + .parent = &tegra_clk_32k, + .reg =0x40 , + .ops = &tegra_blink_clk_ops, + .max_rate =32768 , +}; +static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = { { .input = &tegra_pll_m, .value =0 }, { .input = &tegra_pll_c, .value =1 },
@@ -1626,7 +1797,7 @@ struct clk tegra_periph_clks[] = {PERIPH_CLK ("sdmmc1" ,"sdhci-tegra.0" ,NULL ,14 ,0x150 ,52000000 , mux_pllp_pllc_pllm_clkm,MUX |DIV_U71 ),/* scales with voltage */ PERIPH_CLK ("sdmmc2" ,"sdhci-tegra.1" ,NULL ,9 ,0x154 ,52000000 , mux_pllp_pllc_pllm_clkm,MUX |DIV_U71 ),/* scales with voltage */ PERIPH_CLK ("sdmmc3" ,"sdhci-tegra.2" ,NULL ,69 ,0x1bc ,52000000 , mux_pllp_pllc_pllm_clkm,MUX |DIV_U71 ),/* scales with voltage */ -PERIPH_CLK ("sdmmc4" ,"sdhci-tegra.3" ,NULL ,15 ,0x160 ,52000000 , mux_pllp_pllc_pllm_clkm,MUX |DIV_U71 ),/* scales with voltage */ +PERIPH_CLK ("sdmmc4" ,"sdhci-tegra.3" ,NULL ,15 ,0x164 ,52000000 , mux_pllp_pllc_pllm_clkm,MUX |DIV_U71 ),/* scales with voltage */ PERIPH_CLK ("vde" ,"vde" ,NULL ,61 ,0x1c8 ,250000000 , mux_pllp_pllc_pllm_clkm,MUX |DIV_U71 ),/* scales with voltage and process_id */ PERIPH_CLK("csite", "csite", NULL, 73, 0x1d4, 144000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* max rate ??? *//* FIXME: what is la? */
@@ -1642,34 +1813,34 @@ struct clk tegra_periph_clks[] = {PERIPH_CLK ("i2c2_i2c" ,"tegra-i2c.1" ,"i2c" ,0 ,0 ,72000000 , mux_pllp_out3,0 ),PERIPH_CLK ("i2c3_i2c" ,"tegra-i2c.2" ,"i2c" ,0 ,0 ,72000000 , mux_pllp_out3,0 ),PERIPH_CLK ("dvc_i2c" ,"tegra-i2c.3" ,"i2c" ,0 ,0 ,72000000 , mux_pllp_out3,0 ), -PERIPH_CLK ("uarta" ,"uart.0" ,NULL ,6 ,0x178 ,216000000 , mux_pllp_pllc_pllm_clkm,MUX ), -PERIPH_CLK ("uartb" ,"uart.1" ,NULL ,7 ,0x17c ,216000000 , mux_pllp_pllc_pllm_clkm,MUX ), -PERIPH_CLK ("uartc" ,"uart.2" ,NULL ,55 ,0x1a0 ,216000000 , mux_pllp_pllc_pllm_clkm,MUX ), -PERIPH_CLK ("uartd" ,"uart.3" ,NULL ,65 ,0x1c0 ,216000000 , mux_pllp_pllc_pllm_clkm,MUX ), -PERIPH_CLK ("uarte" ,"uart.4" ,NULL ,66 ,0x1c4 ,216000000 , mux_pllp_pllc_pllm_clkm,MUX ), +PERIPH_CLK ("uarta" ,"uart.0" ,NULL ,6 ,0x178 ,600000000 , mux_pllp_pllc_pllm_clkm,MUX ), +PERIPH_CLK ("uartb" ,"uart.1" ,NULL ,7 ,0x17c ,600000000 , mux_pllp_pllc_pllm_clkm,MUX ), +PERIPH_CLK ("uartc" ,"uart.2" ,NULL ,55 ,0x1a0 ,600000000 , mux_pllp_pllc_pllm_clkm,MUX ), +PERIPH_CLK ("uartd" ,"uart.3" ,NULL ,65 ,0x1c0 ,600000000 , mux_pllp_pllc_pllm_clkm,MUX ), +PERIPH_CLK ("uarte" ,"uart.4" ,NULL ,66 ,0x1c4 ,600000000 , mux_pllp_pllc_pllm_clkm,MUX ),PERIPH_CLK ("3d" ,"3d" ,NULL ,24 ,0x158 ,300000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 |PERIPH_MANUAL_RESET ),/* scales with voltage and process_id */ PERIPH_CLK ("2d" ,"2d" ,NULL ,21 ,0x15c ,300000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 ),/* scales with voltage and process_id */ /* FIXME: vi and vi_sensor share an enable */ -PERIPH_CLK ("vi" ,"vi" ,NULL ,20 ,0x148 ,150000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 ),/* scales with voltage and process_id */ -PERIPH_CLK ("vi_sensor" ,"vi_sensor" ,NULL ,20 ,0x1a8 ,150000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 |PERIPH_NO_RESET ),/* scales with voltage and process_id */ +PERIPH_CLK ("vi" ,"tegra_camera" ,"vi" ,20 ,0x148 ,150000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 ),/* scales with voltage and process_id */ +PERIPH_CLK ("vi_sensor" ,"tegra_camera" ,"vi_sensor" ,20 ,0x1a8 ,150000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 |PERIPH_NO_RESET ),/* scales with voltage and process_id */ PERIPH_CLK ("epp" ,"epp" ,NULL ,19 ,0x16c ,300000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 ),/* scales with voltage and process_id */ PERIPH_CLK ("mpe" ,"mpe" ,NULL ,60 ,0x170 ,250000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 ),/* scales with voltage and process_id */ PERIPH_CLK ("host1x" ,"host1x" ,NULL ,28 ,0x180 ,166000000 , mux_pllm_pllc_pllp_plla,MUX |DIV_U71 ),/* scales with voltage and process_id */ /* FIXME: cve and tvo share an enable */ PERIPH_CLK ("cve" ,"cve" ,NULL ,49 ,0x140 ,250000000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* requires min voltage */ PERIPH_CLK ("tvo" ,"tvo" ,NULL ,49 ,0x188 ,250000000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* requires min voltage */ -PERIPH_CLK ("hdmi" ,"hdmi" ,NULL ,51 ,0x18c ,148500000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* requires min voltage */ +PERIPH_CLK ("hdmi" ,"hdmi" ,NULL ,51 ,0x18c ,600000000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* requires min voltage */ PERIPH_CLK ("tvdac" ,"tvdac" ,NULL ,53 ,0x194 ,250000000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* requires min voltage */ -PERIPH_CLK ("disp1" ,"tegrafb.0" ,NULL ,27 ,0x138 ,190000000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* scales with voltage and process_id */ -PERIPH_CLK ("disp2" ,"tegrafb.1" ,NULL ,26 ,0x13c ,190000000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* scales with voltage and process_id */ +PERIPH_CLK ("disp1" ,"tegradc.0" ,NULL ,27 ,0x138 ,600000000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* scales with voltage and process_id */ +PERIPH_CLK ("disp2" ,"tegradc.1" ,NULL ,26 ,0x13c ,600000000 , mux_pllp_plld_pllc_clkm,MUX |DIV_U71 ),/* scales with voltage and process_id */ PERIPH_CLK ("usbd" ,"fsl-tegra-udc" ,NULL ,22 ,0 ,480000000 , mux_clk_m,0 ),/* requires min voltage */ PERIPH_CLK ("usb2" ,"tegra-ehci.1" ,NULL ,58 ,0 ,480000000 , mux_clk_m,0 ),/* requires min voltage */ PERIPH_CLK ("usb3" ,"tegra-ehci.2" ,NULL ,59 ,0 ,480000000 , mux_clk_m,0 ),/* requires min voltage */ PERIPH_CLK ("emc" ,"emc" ,NULL ,57 ,0x19c ,800000000 , mux_pllm_pllc_pllp_clkm,MUX |DIV_U71 |PERIPH_EMC_ENB ),PERIPH_CLK ("dsi" ,"dsi" ,NULL ,48 ,0 ,500000000 , mux_plld,0 ),/* scales with voltage */ -PERIPH_CLK ("csi" ,"csi" ,NULL ,52 ,0 ,72000000 , mux_pllp_out3,0 ), -PERIPH_CLK ("isp" ,"isp" ,NULL ,23 ,0 ,150000000 , mux_clk_m,0 ),/* same frequency as VI */ -PERIPH_CLK ("csus" ,"csus" ,NULL ,92 ,0 ,150000000 , mux_clk_m,PERIPH_NO_RESET ), +PERIPH_CLK ("csi" ,"tegra_camera" ,"csi" ,52 ,0 ,72000000 , mux_pllp_out3,0 ), +PERIPH_CLK ("isp" ,"tegra_camera" ,"isp" ,23 ,0 ,150000000 , mux_clk_m,0 ),/* same frequency as VI */ +PERIPH_CLK ("csus" ,"tegra_camera" ,"csus" ,92 ,0 ,150000000 , mux_clk_m,PERIPH_NO_RESET ),PERIPH_CLK ("pex" ,NULL ,"pex" ,70 ,0 ,26000000 , mux_clk_m,PERIPH_MANUAL_RESET ),PERIPH_CLK ("afi" ,NULL ,"afi" ,72 ,0 ,26000000 , mux_clk_m,PERIPH_MANUAL_RESET ), PERIPH_CLK("pcie_xclk", NULL, "pcie_xclk", 74, 0, 26000000, mux_clk_m, PERIPH_MANUAL_RESET),
@@ -1694,9 +1865,15 @@ struct clk_duplicate tegra_clk_duplicates[] = {CLK_DUPLICATE ("uartc" ,"tegra_uart.2" ,NULL ),CLK_DUPLICATE ("uartd" ,"tegra_uart.3" ,NULL ),CLK_DUPLICATE ("uarte" ,"tegra_uart.4" ,NULL ), -CLK_DUPLICATE ("host1x" ,"tegrafb.0" ,"host1x" ), -CLK_DUPLICATE ("host1x" ,"tegrafb.1" ,"host1x" ), +CLK_DUPLICATE ("usbd" ,"utmip-pad" ,NULL ),CLK_DUPLICATE ("usbd" ,"tegra-ehci.0" ,NULL ), +CLK_DUPLICATE ("usbd" ,"tegra-otg" ,NULL ), +CLK_DUPLICATE ("hdmi" ,"tegradc.0" ,"hdmi" ), +CLK_DUPLICATE ("hdmi" ,"tegradc.1" ,"hdmi" ), +CLK_DUPLICATE ("pwm" ,"tegra_pwm.0" ,NULL ), +CLK_DUPLICATE ("pwm" ,"tegra_pwm.1" ,NULL ), +CLK_DUPLICATE ("pwm" ,"tegra_pwm.2" ,NULL ), + CLK_DUPLICATE("pwm", "tegra_pwm.3", NULL), };#define CLK (dev, con, ck) \
@@ -1732,7 +1909,10 @@ struct clk_lookup tegra_clk_lookups[] = {CLK (NULL ,"hclk" , &tegra_clk_hclk),CLK (NULL ,"pclk" , &tegra_clk_pclk),CLK (NULL ,"clk_d" , &tegra_clk_d), +CLK (NULL ,"clk_dev1" , &tegra_dev1_clk), +CLK (NULL ,"clk_dev2" , &tegra_dev2_clk),CLK (NULL ,"cpu" , &tegra_clk_virtual_cpu), + CLK(NULL, "blink", &tegra_clk_blink), };void __init tegra2_init_clocks (void )
@@ -1775,14 +1955,34 @@ void __init tegra2_init_clocks(void)#ifdef CONFIG_PM static u32 clk_rst_suspend[RST_DEVICES_NUM +CLK_OUT_ENB_NUM + -PERIPH_CLK_SOURCE_NUM +3 ]; +PERIPH_CLK_SOURCE_NUM +19 ];void tegra_clk_suspend (void ) {unsigned long off, i; +u32 pllx_misc;u32 *ctx = clk_rst_suspend; *ctx++ =clk_readl (OSC_CTRL ) &OSC_CTRL_MASK ; + *ctx++ =clk_readl (tegra_pll_p.reg +PLL_BASE ); + *ctx++ =clk_readl (tegra_pll_p.reg +PLL_MISC (&tegra_pll_p)); + *ctx++ =clk_readl (tegra_pll_c.reg +PLL_BASE ); + *ctx++ =clk_readl (tegra_pll_c.reg +PLL_MISC (&tegra_pll_c)); + *ctx++ =clk_readl (tegra_pll_a.reg +PLL_BASE ); + *ctx++ =clk_readl (tegra_pll_a.reg +PLL_MISC (&tegra_pll_a)); + + *ctx++ =clk_readl (tegra_pll_m_out1.reg); + *ctx++ =clk_readl (tegra_pll_p_out1.reg); + *ctx++ =clk_readl (tegra_pll_p_out3.reg); + *ctx++ =clk_readl (tegra_pll_a_out0.reg); + *ctx++ =clk_readl (tegra_pll_c_out1.reg); + + *ctx++ =clk_readl (tegra_clk_cclk.reg); + *ctx++ =clk_readl (tegra_clk_cclk.reg +SUPER_CLK_DIVIDER ); + + *ctx++ =clk_readl (tegra_clk_sclk.reg); + *ctx++ =clk_readl (tegra_clk_sclk.reg +SUPER_CLK_DIVIDER ); + *ctx++ =clk_readl (tegra_clk_pclk.reg);for (off =PERIPH_CLK_SOURCE_I2S1 ; off <=PERIPH_CLK_SOURCE_OSC ; off +=4 ) {
@@ -1801,6 +2001,10 @@ void tegra_clk_suspend(void) *ctx++ =clk_readl (MISC_CLK_ENB ); *ctx++ =clk_readl (CLK_MASK_ARM ); + + pllx_misc =clk_readl (tegra_pll_x.reg +PLL_MISC (&tegra_pll_x)); + pllx_misc &= ~PLL_MISC_LOCK_ENABLE (&tegra_pll_x); +clk_writel (pllx_misc, tegra_pll_x.reg +PLL_MISC (&tegra_pll_x)); }void tegra_clk_resume (void )
@@ -1813,6 +2017,27 @@ void tegra_clk_resume(void) val |= *ctx++;clk_writel (val,OSC_CTRL ); +clk_writel (*ctx++, tegra_pll_p.reg +PLL_BASE ); +clk_writel (*ctx++, tegra_pll_p.reg +PLL_MISC (&tegra_pll_p)); +clk_writel (*ctx++, tegra_pll_c.reg +PLL_BASE ); +clk_writel (*ctx++, tegra_pll_c.reg +PLL_MISC (&tegra_pll_c)); +clk_writel (*ctx++, tegra_pll_a.reg +PLL_BASE ); +clk_writel (*ctx++, tegra_pll_a.reg +PLL_MISC (&tegra_pll_a)); +udelay (300 ); + +clk_writel (*ctx++, tegra_pll_m_out1.reg); +clk_writel (*ctx++, tegra_pll_p_out1.reg); +clk_writel (*ctx++, tegra_pll_p_out3.reg); +clk_writel (*ctx++, tegra_pll_a_out0.reg); +clk_writel (*ctx++, tegra_pll_c_out1.reg); + +clk_writel (*ctx++, tegra_clk_cclk.reg); +clk_writel (*ctx++, tegra_clk_cclk.reg +SUPER_CLK_DIVIDER ); + +clk_writel (*ctx++, tegra_clk_sclk.reg); +clk_writel (*ctx++, tegra_clk_sclk.reg +SUPER_CLK_DIVIDER ); +clk_writel (*ctx++, tegra_clk_pclk.reg); +/* enable all clocks before configuring clock sources */ clk_writel (0xbffffff9ul ,CLK_OUT_ENB );clk_writel (0xfefffff7ul ,CLK_OUT_ENB +4 );
Signature · 1 line
1.7.3.1
PATCH v2 10/28 ARM: tegra: pinmux: Add missing drive pingroups and fix suspend
In reply to Colin CrossFrom: Gary King <[email protected]>
Adds missing drive pingroups, saves all drive pingroups in suspend, and restores the pinmux registers in the proper order.
--- arch/arm/mach-tegra/include/mach/pinmux-t2.h | 10 ++++++++++ arch/arm/mach-tegra/pinmux-t2-tables.c | 25 +++++++++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-)
arch/arm/mach-tegra/include/mach/pinmux-t2.h +10 -0
@@ -167,6 +167,16 @@ enum tegra_drive_pingroup {TEGRA_DRIVE_PINGROUP_XM2D ,TEGRA_DRIVE_PINGROUP_XM2CLK ,TEGRA_DRIVE_PINGROUP_MEMCOMP , +TEGRA_DRIVE_PINGROUP_SDIO1 , +TEGRA_DRIVE_PINGROUP_CRT , +TEGRA_DRIVE_PINGROUP_DDC , +TEGRA_DRIVE_PINGROUP_GMA , +TEGRA_DRIVE_PINGROUP_GMB , +TEGRA_DRIVE_PINGROUP_GMC , +TEGRA_DRIVE_PINGROUP_GMD , +TEGRA_DRIVE_PINGROUP_GME , +TEGRA_DRIVE_PINGROUP_OWR , +TEGRA_DRIVE_PINGROUP_UAD , TEGRA_MAX_DRIVE_PINGROUP, };
arch/arm/mach-tegra/pinmux-t2-tables.c +21 -4
@@ -66,6 +66,16 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVEDRIVE_PINGROUP (XM2D ,0x8cc ),DRIVE_PINGROUP (XM2CLK ,0x8d0 ),DRIVE_PINGROUP (MEMCOMP ,0x8d4 ), +DRIVE_PINGROUP (SDIO1 ,0x8e0 ), +DRIVE_PINGROUP (CRT ,0x8ec ), +DRIVE_PINGROUP (DDC ,0x8f0 ), +DRIVE_PINGROUP (GMA ,0x8f4 ), +DRIVE_PINGROUP (GMB ,0x8f8 ), +DRIVE_PINGROUP (GMC ,0x8fc ), +DRIVE_PINGROUP (GMD ,0x900 ), +DRIVE_PINGROUP (GME ,0x904 ), +DRIVE_PINGROUP (OWR ,0x908 ), + DRIVE_PINGROUP(UAD, 0x90c), }; #define PINGROUP(pg_name, vdd, f0, f1, f2, f3, f_safe, \
@@ -217,7 +227,8 @@ const struct tegra_pingroup_desc tegra_soc_pingroups[TEGRA_MAX_PINGROUP] = {#define PULLUPDOWN_REG_NUM 5static u32 pinmux_reg[TRISTATE_REG_NUM +PIN_MUX_CTL_REG_NUM + -PULLUPDOWN_REG_NUM ]; +PULLUPDOWN_REG_NUM + +ARRAY_SIZE (tegra_soc_drive_pingroups)];static inline unsigned long pg_readl (unsigned long offset) {
@@ -234,14 +245,17 @@ void tegra_pinmux_suspend(void)unsigned int i;u32 *ctx = pinmux_reg; -for (i =0 ; i <TRISTATE_REG_NUM ; i++) - *ctx++ =pg_readl (TRISTATE_REG_A + i*4 ); -for (i =0 ; i <PIN_MUX_CTL_REG_NUM ; i++) *ctx++ =pg_readl (PIN_MUX_CTL_REG_A + i*4 );for (i =0 ; i <PULLUPDOWN_REG_NUM ; i++) *ctx++ =pg_readl (PULLUPDOWN_REG_A + i*4 ); + +for (i =0 ; i <TRISTATE_REG_NUM ; i++) + *ctx++ =pg_readl (TRISTATE_REG_A + i*4 ); + +for (i =0 ; i <ARRAY_SIZE (tegra_soc_drive_pingroups); i++) + *ctx++ =pg_readl (tegra_soc_drive_pingroups[i].reg); }void tegra_pinmux_resume (void )
@@ -257,5 +271,8 @@ void tegra_pinmux_resume(void)for (i =0 ; i <TRISTATE_REG_NUM ; i++)pg_writel (*ctx++,TRISTATE_REG_A + i*4 ); + +for (i =0 ; i <ARRAY_SIZE (tegra_soc_drive_pingroups); i++) + pg_writel(*ctx++, tegra_soc_drive_pingroups[i].reg); }#endif
Signature · 1 line
1.7.3.1
PATCH v2 11/28 ARM: tegra: timer: Add idle and suspend support to timers
In reply to Colin CrossThe Tegra processor cannot be woken from idle by the internal ARM timers. Reserve timer 4 to be used as a wake source during idle.
Implement read_persistent_clock by reading the Tegra RTC registers that stay running during suspend.
Save and restore the timer configuration register and the sched_clock value in LP0.
--- arch/arm/mach-tegra/timer.c | 95 ++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 93 insertions(+), 2 deletions(-)
arch/arm/mach-tegra/timer.c +93 -2
@@ -38,6 +38,10 @@#include "board.h" #include "clock.h" +#define RTC_SECONDS 0x08 +#define RTC_SHADOW_SECONDS 0x0c +#define RTC_MILLISECONDS 0x10 +#define TIMERUS_CNTR_1US 0x10#define TIMERUS_USEC_CFG 0x14#define TIMERUS_CNTR_FREEZE 0x4c
@@ -50,9 +54,11 @@#define TIMER_PTV 0x0#define TIMER_PCR 0x4 -struct tegra_timer ; -static void __iomem *timer_reg_base =IO_ADDRESS (TEGRA_TMR1_BASE ); +static void __iomem *rtc_base =IO_ADDRESS (TEGRA_RTC_BASE ); + +static struct timespec persistent_ts; +static u64 persistent_ms, last_persistent_ms;#define timer_writel (value, reg) \ __raw_writel(value, (u32)timer_reg_base + (reg))
@@ -133,6 +139,42 @@ static void notrace tegra_update_sched_clock(void)update_sched_clock (&cd, cyc, (u32 )~0 ); } +/* +* tegra_rtc_read - Reads the Tegra RTC registers +* Care must be taken that this funciton is not called while the +* tegra_rtc driver could be executing to avoid race conditions +* on the RTC shadow register +*/ +u64 tegra_rtc_read_ms (void ) +{ +u32 ms =readl (rtc_base +RTC_MILLISECONDS ); +u32 s =readl (rtc_base +RTC_SHADOW_SECONDS ); +return (u64 )s *MSEC_PER_SEC + ms; +} + +/* +* read_persistent_clock - Return time from a persistent clock. +* +* Reads the time from a source which isn't disabled during PM, the +* 32k sync timer. Convert the cycles elapsed since last read into +* nsecs and adds to a monotonically increasing timespec. +* Care must be taken that this funciton is not called while the +* tegra_rtc driver could be executing to avoid race conditions +* on the RTC shadow register +*/ +void read_persistent_clock (struct timespec *ts) +{ +u64 delta; +struct timespec *tsp = &persistent_ts; + + last_persistent_ms = persistent_ms; + persistent_ms =tegra_rtc_read_ms (); + delta = persistent_ms - last_persistent_ms; + +timespec_add_ns (tsp, delta *NSEC_PER_MSEC ); + *ts = *tsp; +} +static irqreturn_t tegra_timer_interrupt (int irq,void *dev_id) {struct clock_event_device *evt = (struct clock_event_device *)dev_id;
@@ -149,6 +191,20 @@ static struct irqaction tegra_timer_irq = { .irq = INT_TMR3, }; +static irqreturn_t tegra_lp2wake_interrupt (int irq,void *dev_id) +{ +timer_writel (1 <<30 ,TIMER4_BASE +TIMER_PCR ); +return IRQ_HANDLED ; +} + +static struct irqaction tegra_lp2wake_irq = { + .name ="timer_lp2wake" , + .flags =IRQF_DISABLED , + .handler = tegra_lp2wake_interrupt, + .dev_id =NULL , + .irq =INT_TMR4 , +}; +static void __init tegra_init_timer (void ) {unsigned long rate =clk_measure_input_freq ();
@@ -189,6 +245,12 @@ static void __init tegra_init_timer(void)BUG (); } + ret =setup_irq (tegra_lp2wake_irq.irq, &tegra_lp2wake_irq); +if (ret) { +printk (KERN_ERR "Failed to register LP2 timer IRQ: %d\n" , ret); +BUG (); + } +clockevents_calc_mult_shift (&tegra_clockevent,1000000 ,5 ); tegra_clockevent.max_delta_ns =clockevent_delta2ns (0x1fffffff , &tegra_clockevent);
@@ -204,3 +266,32 @@ static void __init tegra_init_timer(void)struct sys_timer tegra_timer = { .init = tegra_init_timer, }; + +void tegra_lp2_set_trigger (unsigned long cycles) +{ +timer_writel (0 ,TIMER4_BASE +TIMER_PTV ); +if (cycles) { +u32 reg =0x80000000ul |min (0x1ffffffful , cycles); +timer_writel (reg,TIMER4_BASE +TIMER_PTV ); + } +} +EXPORT_SYMBOL (tegra_lp2_set_trigger); + +unsigned long tegra_lp2_timer_remain (void ) +{ +return timer_readl (TIMER4_BASE +TIMER_PCR ) &0x1ffffffful ; +} + +#ifdef CONFIG_PM +static u32 usec_config; + +void tegra_timer_suspend (void ) +{ + usec_config =timer_readl (TIMERUS_USEC_CFG ); +} + +void tegra_timer_resume (void ) +{ +timer_writel (usec_config,TIMERUS_USEC_CFG ); +} +#endif
Signature · 1 line
1.7.3.1
PATCH v2 12/28 ARM: tegra: irq: Add support for suspend wake sources
In reply to Colin Cross--- arch/arm/mach-tegra/include/mach/legacy_irq.h | 4 + arch/arm/mach-tegra/irq.c | 190 ++++++++++--------------- arch/arm/mach-tegra/legacy_irq.c | 109 ++++++++++++++- 3 files changed, 187 insertions(+), 116 deletions(-)
arch/arm/mach-tegra/include/mach/legacy_irq.h +4 -0
@@ -27,5 +27,9 @@ int tegra_legacy_force_irq_status(unsigned int irq);void tegra_legacy_select_fiq (unsigned int irq,bool fiq);unsigned long tegra_legacy_vfiq (int nr);unsigned long tegra_legacy_class (int nr); +int tegra_legacy_irq_set_wake (int irq,int enable); +void tegra_legacy_irq_set_lp1_wake_mask (void ); +void tegra_legacy_irq_restore_mask (void ); +void tegra_init_legacy_irq (void );#endif
arch/arm/mach-tegra/irq.c +78 -112
231 lines not on this page · raw message
arch/arm/mach-tegra/legacy_irq.c +105 -4
131 lines not on this page · raw message
Signature · 1 line
1.7.3.1
PATCH v2 13/28 ARM: tegra: Add suspend and hotplug support
In reply to Colin CrossTegra supports three low power modes that involve powering down the CPU.
LP2 powers down both CPU cores and the GICs, but leaves the core peripherals, including the memory controller and the legacy interrupt controller, enabled. The legacy interrupt controller is used as the wakeup source, and any interrupt can wake the device. LP2 can be used in idle.
LP1 is the same as LP2, but in addition turns off the memory controller and puts the DDR memory in self-refresh. Any interrupt can wake the device. LP1 could be used in idle if no peripherals are doing DMA.
LP0 turns off everything in the SoC except the RTC and a power management controller, both of which run off a 32 kHz clock. The power management controller has 32 wake sources, all other interrupts can not be used to wake from LP0.
LP2 idle mode power-gates the main CPU complex, requiring a full processor state save and restore from a reset vector.
Processor context area is allocated during platform initialization from the kernel, and mapped into the hotplug page tables (which also serve as the initial page tables for the LP2 main processor reset).
Platform-specific data (power good times, PMU capabilities, etc.) must be specified when registering the suspend operations to ensure that platform power sequencing restrictions are maintained.
Since all device interrupts (except timers) are disabled in the suspend path, the wakeup interrupts need to be manually unmasked before entering into a suspend state or the processor will never wake up; these forced-unmask interrupts are re-masked immediately in the resume path to prevent the kernel from live-locking prior to driver resume.
In both LP0 and LP1, SDRAM is placed into self-refresh. in order to safely perform this transition, the final shutdown procedure responsible for
* turning off the MMU and L1 data cache
* putting memory into self-refresh
* setting the DDR pads to the lowest power state
* and turning off PLLs
is copied into IRAM (at the address TEGRA_IRAM_BASE + SZ_4K) at the start of the suspend process.
In LP1 mode (like LP2), the CPU is reset and executes the code specified at the EVP reset vector. Since SDRAM is in self-refresh, this code must also be located in IRAM, and it must re-enable DRAM before restoring the full context. In this implementation, it enables the CPU on PLLP, enables PLLC and PLLM, restores the SCLK burst policy, and jumps to the LP2 reset vector to restore the rest of the system (MMU, PLLX, coresite, etc.). The LP2 reset vector is expected to be found in PMC_SCRATCH1, and is initialized during system-bootup.
In LP0 mode, the core voltage domain is also shutoff. As a result, all of the volatile state in the core voltage domain (e.g., pinmux registers, clock registers, etc.) must be saved to memory so that it can be restored after the system resumes. A limited set of wakeups are available from LP0, and the correct levels for the wakeups must be programmed into the PMC wakepad configuration register prior to system shutdown. On resume, the system resets into the boot ROM, and the boot ROM restores SDRAM and other system state using values saved during kernel initialization in the PMC scratch registers.
Resuming from LP0 requires the boot ROM to supply a signed recovery codeblob to the kernel; the kernel expects that the length and address of this blob is supplied with the lp0_vec= command line argument; if not present, suspend- to-LP0 will be disabled
For simplicity, the outer cache is shutdown for both LP0 and LP1; it is possible to optimize the LP1 routine to bypass outer cache shutdown and restart.
To save power, SMP tegra SoCs place non-boot CPUs in reset when they are removed from the scheduling cluster using CPU hotplug.
Slave CPUs save their contexts (incl. CP15 and VFP state) out to a reserved memory region, cancel SMP operation, and write to the SoC reset controller to disable themselves. This is done with caches and MMU enabled, so care is taken to ensure that all the dirty context cache lines are cleaned out to the PoC before shutting down.
When re-enabled, slave CPUs execute a hotplug boot routine which mirrors the initial configuration performed by secondary_startup, but after enabling the MMU "return" to __cortex_a9_restore which restores the saved state from the context area, and returns to platform_cpu_die.
Includes fixes from:
Scott Williams <[email protected]>
Aleksandr Frid <[email protected]>
Vik Kasivajhula <[email protected]>
Bharat Nihalani <[email protected]>
Original-author: Gary King <[email protected]>
---
v2: Updated for comments to v1
Use memblock_reserve to reserve LP0 boot vector Don't save VFP registers, they are already saved Don't save context switch registers, reinitialize them
with cpu_init
Don't save breakpoint and watchpoint registers Don't save L2X0 registers, reinitialize them with
l2x0_init
Update for changes to ARM smp hotplug De-obfuscate macros in suspend-t2.c
Use identity_mapping_add to create suspend page tables Fix checkpatch issues
arch/arm/mach-tegra/Makefile | 10 +- arch/arm/mach-tegra/board.h | 4 + arch/arm/mach-tegra/common.c | 32 ++- arch/arm/mach-tegra/cortex-a9.S | 504 ++++++++++++++++++ arch/arm/mach-tegra/headsmp-t2.S | 216 ++++++++ arch/arm/mach-tegra/headsmp.S | 61 --- arch/arm/mach-tegra/hotplug.c | 126 ----- arch/arm/mach-tegra/include/mach/suspend.h | 42 ++ arch/arm/mach-tegra/platsmp.c | 89 +++- arch/arm/mach-tegra/power-macros.S | 57 ++ arch/arm/mach-tegra/power.h | 64 +++ arch/arm/mach-tegra/suspend-t2.c | 414 +++++++++++++++ arch/arm/mach-tegra/suspend.c | 764 ++++++++++++++++++++++++++++ arch/arm/mach-tegra/tegra2_save.S | 413 +++++++++++++++ 14 files changed, 2596 insertions(+), 200 deletions(-) create mode 100644 arch/arm/mach-tegra/cortex-a9.S create mode 100644 arch/arm/mach-tegra/headsmp-t2.S delete mode 100644 arch/arm/mach-tegra/headsmp.S delete mode 100644 arch/arm/mach-tegra/hotplug.c create mode 100644 arch/arm/mach-tegra/power-macros.S create mode 100644 arch/arm/mach-tegra/power.h create mode 100644 arch/arm/mach-tegra/suspend-t2.c create mode 100644 arch/arm/mach-tegra/suspend.c create mode 100644 arch/arm/mach-tegra/tegra2_save.S
arch/arm/mach-tegra/Makefile +8 -2
@@ -6,13 +6,19 @@ obj-y += timer.o obj-y += gpio.o obj-y += pinmux.o obj-y += powergate.o +obj-y += suspend.o obj-y += fuse.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clock.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_dvfs.o +obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += suspend-t2.o +obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_save.o +obj-$(CONFIG_CPU_V7) += cortex-a9.o + obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pinmux-t2-tables.o -obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o -obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o +obj-$(CONFIG_LOCAL_TIMER) += localtimer.o +obj-$(CONFIG_SMP) += platsmp.o +obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += headsmp-t2.o obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o obj-$(CONFIG_TEGRA_PCI) += pcie.o
arch/arm/mach-tegra/board.h +4 -0
@@ -27,7 +27,11 @@ void __init tegra_common_init(void);void __init tegra_map_common_io (void );void __init tegra_init_irq (void );void __init tegra_init_clock (void ); +void __init tegra_reserve (void );int __init tegra_pcie_init (bool init_port0,bool init_port1); +extern unsigned long tegra_lp0_vec_start; +extern unsigned long tegra_lp0_vec_size; +extern struct sys_timer tegra_timer;#endif
arch/arm/mach-tegra/common.c +31 -1
@@ -21,6 +21,7 @@#include <linux/io.h> #include <linux/clk.h> #include <linux/delay.h> +#include <linux/memblock.h> #include <asm/hardware/cache-l2x0.h>
@@ -30,6 +31,10 @@#include "board.h" #include "clock.h" #include "fuse.h" +#include "power.h" + +unsigned long tegra_lp0_vec_start; +unsigned long tegra_lp0_vec_size;static __initdata struct tegra_clk_init_table common_clk_init_table[] = {/* name parent rate enabled */
@@ -45,7 +50,7 @@ static __initdata struct tegra_clk_init_table common_clk_init_table[] = { { NULL, NULL, 0, 0}, }; -void __init tegra_init_cache (void ) +void tegra_init_cache (void ) {#ifdef CONFIG_CACHE_L2X0 void __iomem *p =IO_ADDRESS (TEGRA_ARM_PERIF_BASE ) +0x3000 ;
@@ -68,3 +73,28 @@ void __init tegra_common_init(void)tegra_dma_init ();#endif } + +static int __init tegra_lp0_vec_arg (char *options) +{ +char *p = options; + + tegra_lp0_vec_size =memparse (p, &p); +if (*p =='@' ) + tegra_lp0_vec_start =memparse (p+1 , &p); + +return 0 ; +} +early_param ("lp0_vec" , tegra_lp0_vec_arg); + +void __init tegra_reserve (void ) +{ +if (tegra_lp0_vec_size) +if (memblock_reserve (tegra_lp0_vec_start, tegra_lp0_vec_size)) +pr_err ("Failed to reserve lp0_vec %08lx@%08lx\n" , + tegra_lp0_vec_size, tegra_lp0_vec_start); + +pr_info ("Tegra reserved memory:\n" +"LP0: %08lx - %08lx\n" , + tegra_lp0_vec_start, + tegra_lp0_vec_start + tegra_lp0_vec_size -1 ); +}
arch/arm/mach-tegra/cortex-a9.S new file +504 -0
504 lines not on this page · raw message
arch/arm/mach-tegra/headsmp-t2.S new file +216 -0
216 lines not on this page · raw message
arch/arm/mach-tegra/headsmp.S deleted +0 -61
61 lines not on this page · raw message
arch/arm/mach-tegra/hotplug.c deleted +0 -126
126 lines not on this page · raw message
arch/arm/mach-tegra/include/mach/suspend.h +42 -0
52 lines not on this page · raw message
arch/arm/mach-tegra/platsmp.c +79 -10
135 lines not on this page · raw message
arch/arm/mach-tegra/power-macros.S new file +57 -0
57 lines not on this page · raw message
arch/arm/mach-tegra/power.h new file +64 -0
64 lines not on this page · raw message
arch/arm/mach-tegra/suspend-t2.c new file +414 -0
414 lines not on this page · raw message
arch/arm/mach-tegra/suspend.c new file +764 -0
764 lines not on this page · raw message
arch/arm/mach-tegra/tegra2_save.S new file +413 -0
413 lines not on this page · raw message
Signature · 1 line
1.7.3.1
Re: [PATCH v2 13/28] ARM: tegra: Add suspend and hotplug support
On Sun, Jan 23, 2011 at 6:01 PM, Colin Cross <[email protected]> wrote:
<snip>
Quoted 3 lines
arch/arm/mach-tegra/Makefile +0
-1--- a/arch/arm/mach-tegra/Makefile
<snip>
Quoted 1 line
+obj-$(CONFIG_LOCAL_TIMER) ? ? ? ? ? ? ? += localtimer.o
This needs to be CONFIG_LOCAL_TIMERS
Re: [PATCH v2 13/28] ARM: tegra: Add suspend and hotplug support
In reply to Colin CrossQuoted 1 line · Colin Cross
Tegra supports three low power modes that involve powering down the CPU.
It is a common misconception that on CPU hot-unplug you need to save the entire universe of the CPU going down.
When CPUs are hot-plugged, they reinitialize, which includes resetting most of the CPU state.
There is no point saving the user register state, svc register state, abort register state, interrupt register state, undefined mode register state, TTB base registers, TTB control register, memory type remapping registers nor the context register. These are all reinitialized when the CPU is brought up again.
VFP state should already be saved - when a CPU is hot-unplugged, we can't leave a threads VFP register set stored in that hardware as it would become inaccessible, so there's no point saving VFP state. Recently code was added to invalidate the software VFP state for a CPU being hot-unplugged and reinitialize the VFP hardware on CPU hotplug.
We also have the necessary hooks into the PM code to deal with VFP state saving/restore on PM suspend/resume.
The breakpoint/watchdog stuff _should_ be handled by the breakpoint/ watchdog code, not by each individual platform. Please can you work with Will Deacon if this is not the case to ensure that the breakpoint/ watchdog code can handle CPU hotplug.
Lastly, L2 cache controller should have suspend/resume support added.
We _really_ need to stop having platforms manually saving lots of CPU state for suspend/hot unplug.
That should reduce the amount of state you're saving down to something more manageable.
Quoted 47 lines
arch/arm/mach-tegra/platsmp.c +47
-0+ +#ifdef CONFIG_HOTPLUG_CPU + +int platform_cpu_kill (unsigned int cpu) +{ +unsigned int reg; + +do { + reg =readl (CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET ); +cpu_relax (); + }while (!(reg & (1 <<cpu))); + +spin_lock (&boot_lock); + reg =readl (CLK_RST_CONTROLLER_CLK_CPU_CMPLX ); +writel (reg | (1 <<(8 +cpu)),CLK_RST_CONTROLLER_CLK_CPU_CMPLX ); +spin_unlock (&boot_lock); + +return 1 ; +} + +void platform_cpu_die (unsigned int cpu) +{ +#ifdef DEBUG +unsigned int this_cpu =hard_smp_processor_id (); + +if (cpu != this_cpu) { +printk (KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n" , + this_cpu, cpu); +BUG (); + } +#endif + +gic_cpu_exit (0 ); +barrier (); +flush_cache_all (); +barrier (); +__cortex_a9_save (0 ); + +/* +* __cortex_a9_save can return through __cortex_a9_restore, but that +* should never happen for a hotplugged cpu +*/ +BUG (); +} + +int platform_cpu_disable (unsigned int cpu) +{
arch/arm/mach-tegra/platsmp.c void __init platform_smp_prepare_cpus(unsigned int max_cpus) · line 208
Quoted 10 lines
arch/arm/mach-tegra/platsmp.c +10
-0+/* +* we don't allow CPU 0 to be shutdown (it is still too special +* e.g. clock tick interrupts) +*/ +if (unlikely (!tegra_context_area)) +return -ENXIO ; + + return cpu == 0 ? -EPERM : 0; +} +#endif
Please leave this in hotplug.c so that it matches what other platforms do. Otherwise it's likely to be missed by any updates that happen architecture-wide.
Re: [PATCH v2 13/28] ARM: tegra: Add suspend and hotplug support
Quoted 8 lines · Russell King - ARM Linux
Quoted 1 line · Colin Cross
Tegra supports three low power modes that involve powering down the CPU.
It is a common misconception that on CPU hot-unplug you need to save the entire universe of the CPU going down.
When CPUs are hot-plugged, they reinitialize, which includes resetting most of the CPU state.
The hotplug code path on Tegra currently shares the same path as cpu idle, because the CPU ends up in the same state for both. This version of the patch ensures that when the cpu is brought back online, it goes through the normal reset vector. In hotplug, the state ends up getting saved on the way down, but not used on the way back up.
Quoted 5 lines
There is no point saving the user register state, svc register state, abort register state, interrupt register state, undefined mode register state, TTB base registers, TTB control register, memory type remapping registers nor the context register. ?These are all reinitialized when the CPU is brought up again.
The register state is fixed in this version of the patch by calling cpu_init() in the resume and idle code. I'll look again if there is a better way of handling the rest of the registers, but this code is mostly needed for the suspend and idle cases where the normal boot process is not used.
Quoted 5 lines
VFP state should already be saved - when a CPU is hot-unplugged, we can't leave a threads VFP register set stored in that hardware as it would become inaccessible, so there's no point saving VFP state. ?Recently code was added to invalidate the software VFP state for a CPU being hot-unplugged and reinitialize the VFP hardware on CPU hotplug.
Despite what the patch description says, this version of the patch does not save VFP state any more. I will update the description. It looks like if CONFIG_SMP=y, the VFP code saves the VFP context on every task switch, so nothing is needed during cpu idle. However, if CONFIG_SMP=n, I think some way to save the VFP context is needed.
Quoted 7 lines
We also have the necessary hooks into the PM code to deal with VFP state saving/restore on PM suspend/resume.
The breakpoint/watchdog stuff _should_ be handled by the breakpoint/ watchdog code, not by each individual platform. ?Please can you work with Will Deacon if this is not the case to ensure that the breakpoint/ watchdog code can handle CPU hotplug.
This version of the patch does not save breakpoint/watchdogs, but something will need to save them during idle when the cpu is powered down.
Quoted 1 line
Lastly, L2 cache controller should have suspend/resume support added.
Patch 4 in this series improves the L2 controller's PM support, and this patch uses l2x0_disable, l2x0_enable, and l2x0_init.
Quoted 59 lines
We _really_ need to stop having platforms manually saving lots of CPU state for suspend/hot unplug.
That should reduce the amount of state you're saving down to something more manageable.
Quoted 53 lines
(quoted diff) +53
-0+ +#ifdef CONFIG_HOTPLUG_CPU + +int platform_cpu_kill(unsigned int cpu) +{ + ? ? unsigned int reg; + + ? ? do { + ? ? ? ? ? ? reg = readl(CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET); + ? ? ? ? ? ? cpu_relax(); + ? ? } while (!(reg & (1<<cpu))); + + ? ? spin_lock(&boot_lock); + ? ? reg = readl(CLK_RST_CONTROLLER_CLK_CPU_CMPLX); + ? ? writel(reg | (1<<(8+cpu)), CLK_RST_CONTROLLER_CLK_CPU_CMPLX); + ? ? spin_unlock(&boot_lock); + + ? ? return 1; +} + +void platform_cpu_die(unsigned int cpu) +{ +#ifdef DEBUG + ? ? unsigned int this_cpu = hard_smp_processor_id(); + + ? ? if (cpu != this_cpu) { + ? ? ? ? ? ? printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n", + ? ? ? ? ? ? ? ? ? ? ? ?this_cpu, cpu); + ? ? ? ? ? ? BUG(); + ? ? } +#endif + + ? ? gic_cpu_exit(0); + ? ? barrier(); + ? ? flush_cache_all(); + ? ? barrier(); + ? ? __cortex_a9_save(0); + + ? ? /* + ? ? ?* __cortex_a9_save can return through __cortex_a9_restore, but that + ? ? ?* should never happen for a hotplugged cpu + ? ? ?*/ + ? ? BUG(); +} + +int platform_cpu_disable(unsigned int cpu) +{ + ? ? /* + ? ? ?* we don't allow CPU 0 to be shutdown (it is still too special + ? ? ?* e.g. clock tick interrupts) + ? ? ?*/ + ? ? if (unlikely(!tegra_context_area)) + ? ? ? ? ? ? return -ENXIO;
Quoted 8 lines
arch/arm/mach-tegra/platsmp.c void __init platform_smp_prepare_cpus(unsigned int max_cpus) · line 182
Quoted 4 lines
arch/arm/mach-tegra/platsmp.c +4
-0+ + ? ? return cpu == 0 ? -EPERM : 0; +} +#endif Please leave this in
hotplug.cso that it matches what other platforms do. ?Otherwise it's likely to be missed by any updates that happen architecture-wide.
Will do
Re: [PATCH v2 13/28] ARM: tegra: Add suspend and hotplug support
Quoted 2 lines · Colin Cross
Despite what the patch description says, this version of the patch does not save VFP state any more. I will update the description.
I was going by the definitions of the context save area.
Quoted 3 lines
It looks like if
CONFIG_SMP=y, the VFP code saves the VFP context on every task switch, so nothing is needed during cpu idle. However, ifCONFIG_SMP=n, I think some way to save the VFP context is needed.
I think we need proper idle PM support as I think this will become commonplace.
Quoted 3 lines
This version of the patch does not save breakpoint/watchdogs, but something will need to save them during idle when the cpu is powered down.
Ditto.
Quoted 4 lines
Quoted 1 line
Lastly, L2 cache controller should have suspend/resume support added.
Patch 4 in this series improves the L2 controller's PM support, and this patch uses
l2x0_disable,l2x0_enable, andl2x0_init.
I was going by the definitions of the context save state - maybe the ones which aren't used anymore should be removed?
PATCH v2 14/28 ARM: tegra: irq: Add set_wake and set_type support for suspend
In reply to Colin Cross--- arch/arm/mach-tegra/include/mach/legacy_irq.h | 3 +- arch/arm/mach-tegra/irq.c | 106 +++++++++++++++++++++++++ arch/arm/mach-tegra/legacy_irq.c | 4 +- 3 files changed, 110 insertions(+), 3 deletions(-)
arch/arm/mach-tegra/include/mach/legacy_irq.h +2 -1
@@ -31,5 +31,6 @@ int tegra_legacy_irq_set_wake(int irq, int enable);void tegra_legacy_irq_set_lp1_wake_mask (void );void tegra_legacy_irq_restore_mask (void );void tegra_init_legacy_irq (void ); - +void tegra_legacy_irq_suspend (void ); +void tegra_legacy_irq_resume (void );#endif
arch/arm/mach-tegra/irq.c +106 -0
132 lines not on this page · raw message
arch/arm/mach-tegra/legacy_irq.c +2 -2
@@ -179,7 +179,7 @@ static u32 cop_ier[NUM_ICTLRS];static u32 cpu_ier[NUM_ICTLRS ];static u32 cpu_iep[NUM_ICTLRS ]; -void tegra_irq_suspend (void ) +void tegra_legacy_irq_suspend (void ) {unsigned long flags;int i;
@@ -195,7 +195,7 @@ void tegra_irq_suspend(void)local_irq_restore (flags); } -void tegra_irq_resume (void ) +void tegra_legacy_irq_resume (void ) {unsigned long flags;int i;
Signature · 1 line
1.7.3.1
PATCH v2 15/28 ARM: tegra: irq: Add debugfs file to show wake irqs
In reply to Colin Cross---
v2: Fix permissions on debufs file
arch/arm/mach-tegra/irq.c | 66 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 66 insertions(+), 0 deletions(-)
arch/arm/mach-tegra/irq.c +66 -0
@@ -19,10 +19,12 @@#include <linux/kernel.h> #include <linux/delay.h> +#include <linux/debugfs.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/io.h> +#include <linux/seq_file.h> #include <asm/hardware/gic.h>
@@ -46,6 +48,8 @@ static u32 tegra_lp0_wake_enb;static u32 tegra_lp0_wake_level;static u32 tegra_lp0_wake_level_any; +static unsigned int tegra_wake_irq_count[32 ]; +/* ensures that sufficient time is passed for a register write to * serialize into the 32KHz domain */ static void pmc_32kwritel (u32 val,unsigned long offs)
@@ -165,6 +169,8 @@ static void tegra_irq_handle_wake(void)pr_info ("Resume caused by WAKE%d, %s\n" , wake, desc->action->name); + tegra_wake_irq_count[wake]++; +generic_handle_irq (irq); } }
@@ -242,3 +248,63 @@ void tegra_irq_resume(void)tegra_legacy_irq_resume ();tegra_irq_handle_wake (); } + +#ifdef CONFIG_DEBUG_FS +static int tegra_wake_irq_debug_show (struct seq_file *s,void *data) +{ +int wake; +int irq; +struct irq_desc *desc; +const char *irq_name; + +seq_printf (s,"wake irq count name\n" ); +seq_printf (s,"----------------------\n" ); +for (wake =0 ; wake <32 ; wake++) { + irq =tegra_wake_to_irq (wake); +if (irq <0 ) +continue ; + + desc =irq_to_desc (irq); +if (tegra_wake_irq_count[wake] ==0 && desc->action ==NULL ) +continue ; + +if (!(desc->status &IRQ_WAKEUP )) +continue ; + + irq_name = (desc->action && desc->action->name) ? + desc->action->name :"???" ; + +seq_printf (s,"%4d %3d %5d %s\n" , + wake, irq, tegra_wake_irq_count[wake], irq_name); + } +return 0 ; +} + +static int tegra_wake_irq_debug_open (struct inode *inode,struct file *file) +{ +return single_open (file, tegra_wake_irq_debug_show,NULL ); +} + +static const struct file_operations tegra_wake_irq_debug_fops = { + .open = tegra_wake_irq_debug_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init tegra_irq_debug_init (void ) +{ +struct dentry *d; + + d =debugfs_create_file ("wake_irq" ,S_IRUGO ,NULL ,NULL , + &tegra_wake_irq_debug_fops); +if (!d) { +pr_info ("Failed to create suspend_mode debug file\n" ); +return -ENOMEM ; + } + +return 0 ; +} + +late_initcall (tegra_irq_debug_init); +#endif
Signature · 1 line
1.7.3.1
Re: [PATCH v2 15/28] ARM: tegra: irq: Add debugfs file to show wake irqs
arch/arm/mach-tegra/irq.c void tegra_irq_resume(void) · line 302
Quoted 9 lines · Colin Cross
arch/arm/mach-tegra/irq.c +8
-0+static int __init tegra_irq_debug_init (void ) +{ +struct dentry *d; + + d =debugfs_create_file ("wake_irq" ,S_IRUGO ,NULL ,NULL , + &tegra_wake_irq_debug_fops); +if (!d) { +pr_info ("Failed to create suspend_mode debug file\n" );
Does this want to be a pr_err()?
Signature · 2 lines
Sent by an employee of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
PATCH v2 16/28 ARM: tegra: irq: Implement retrigger
In reply to Colin Cross--- arch/arm/mach-tegra/irq.c | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletions(-)
arch/arm/mach-tegra/irq.c +14 -1
@@ -208,9 +208,21 @@ static int tegra_set_type(struct irq_data *d, unsigned int flow_type)return 0 ; } +static void tegra_ack (struct irq_data *d) +{ +tegra_legacy_force_irq_clr (d->irq); +gic_ack_irq (d); +} + +static int tegra_retrigger (struct irq_data *d) +{ +tegra_legacy_force_irq_set (d->irq); +return 1 ; +} +static struct irq_chip tegra_irq = { .name ="PPI" , - .irq_ack = gic_ack_irq, + .irq_ack = tegra_ack, .irq_mask = tegra_mask, .irq_unmask = tegra_unmask, .irq_set_wake = tegra_set_wake,
@@ -218,6 +230,7 @@ static struct irq_chip tegra_irq = {#ifdef CONFIG_SMP .irq_set_affinity = gic_set_cpu, #endif + .irq_retrigger = tegra_retrigger, };void __init tegra_init_irq (void )
Signature · 1 line
1.7.3.1
PATCH v2 17/28 ARM: tegra: gpio: Add support for waking from suspend
In reply to Colin Cross--- arch/arm/mach-tegra/gpio.c | 14 +++++++++++++- 1 files changed, 13 insertions(+), 1 deletions(-)
arch/arm/mach-tegra/gpio.c +13 -1
@@ -212,6 +212,9 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type)else if (type & (IRQ_TYPE_EDGE_FALLING |IRQ_TYPE_EDGE_RISING ))__set_irq_handler_unlocked (d->irq, handle_edge_irq); +if (tegra_get_suspend_mode () ==TEGRA_SUSPEND_LP0 ) +tegra_set_lp0_wake_type (d->irq, type); +return 0 ; }
@@ -319,8 +322,17 @@ void tegra_gpio_suspend(void)static int tegra_gpio_wake_enable (struct irq_data *d,unsigned int enable) { +int ret;struct tegra_gpio_bank *bank =irq_data_get_irq_chip_data (d); -return set_irq_wake (bank->irq, enable); + + ret =tegra_set_lp1_wake (bank->irq, enable); +if (ret) +return ret; + +if (tegra_get_suspend_mode () ==TEGRA_SUSPEND_LP0 ) +return tegra_set_lp0_wake (d->irq, enable); + +return 0 ; }#endif
Signature · 1 line
1.7.3.1
PATCH v2 18/28 ARM: tegra: add CPU_IDLE driver
In reply to Colin CrossSupports clock-gated (LP3) SMP idle mode, and power-gated (LP2) idle.
Latency for LP2 idle state is calculated as a 2-sample weighted moving average, to allow for future variations due to (e.g.) CPU frequency scaling.
LP3 idle gates a single CPU core, but LP2 requires power gating both CPU cores. An interrupt is used to handshake between the two cores to ensure both are ready to enter LP2, and another interrupt is used to manage the process of entering LP2.
--- arch/arm/mach-tegra/Makefile | 1 + arch/arm/mach-tegra/cpuidle.c | 714 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 715 insertions(+), 0 deletions(-) create mode 100644 arch/arm/mach-tegra/cpuidle.c
arch/arm/mach-tegra/Makefile +1 -0
@@ -22,6 +22,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += headsmp-t2.o obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o obj-$(CONFIG_TEGRA_PCI) += pcie.o +obj-$(CONFIG_CPU_IDLE) += cpuidle.o obj-${CONFIG_MACH_HARMONY} += board-harmony.o obj-${CONFIG_MACH_HARMONY} += board-harmony-pinmux.o
arch/arm/mach-tegra/cpuidle.c new file +714 -0
714 lines not on this page · raw message
Signature · 1 line
1.7.3.1
Re: [PATCH v2 18/28] ARM: tegra: add CPU_IDLE driver
Quoted 10 lines · Colin Cross
arch/arm/mach-tegra/cpuidle.c new file +9
-0+static int __init tegra_cpuidle_debug_init (void ) +{ +struct dentry *dir; +struct dentry *d; + + dir =debugfs_create_dir ("cpuidle" ,NULL ); +if (!dir) +return -ENOMEM ; +
arch/arm/mach-tegra/cpuidle.c line 714
Quoted 10 lines
arch/arm/mach-tegra/cpuidle.c new file +10
-0+ d =debugfs_create_file ("lp2" ,S_IRUGO , dir,NULL , + &tegra_lp2_debug_ops); +if (!d) +return -ENOMEM ; + + return 0; +} +#endif + +late_initcall (tegra_cpuidle_debug_init);
Will this compile with CONFIG_DEBUG_FS=n?
Signature · 2 lines
Sent by an employee of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
Re: [PATCH v2 18/28] ARM: tegra: add CPU_IDLE driver
Quoted 15 lines · Stephen Boyd
Quoted 14 lines · Colin Cross
(quoted diff) +13
-0+static int __init tegra_cpuidle_debug_init(void) +{ + ? ? struct dentry *dir; + ? ? struct dentry *d; + + ? ? dir = debugfs_create_dir("cpuidle", NULL); + ? ? if (!dir) + ? ? ? ? ? ? return -ENOMEM; + + ? ? d = debugfs_create_file("lp2", S_IRUGO, dir, NULL, + ? ? ? ? ? ? &tegra_lp2_debug_ops); + ? ? if (!d) + ? ? ? ? ? ? return -ENOMEM;
Quoted 8 lines
arch/arm/mach-tegra/cpuidle.c line 714
Quoted 6 lines
arch/arm/mach-tegra/cpuidle.c new file +6
-0+ + ? ? return 0; +} +#endif + +late_initcall (tegra_cpuidle_debug_init);Will this compile with
CONFIG_DEBUG_FS=n?
Yes. All debugfs ops return ERR_PTR(-ENODEV) if CONFIG_DEBUG_FS=n, so tegra_cpuidle_debug_init will do nothing and return 0.
Re: [PATCH v2 18/28] ARM: tegra: add CPU_IDLE driver
Quoted 25 lines · Colin Cross
Quoted 15 lines · Stephen Boyd
Quoted 14 lines · Colin Cross
(quoted diff) +13
-0+static int __init tegra_cpuidle_debug_init(void) +{ + ? ? struct dentry *dir; + ? ? struct dentry *d; + + ? ? dir = debugfs_create_dir("cpuidle", NULL); + ? ? if (!dir) + ? ? ? ? ? ? return -ENOMEM; + + ? ? d = debugfs_create_file("lp2", S_IRUGO, dir, NULL, + ? ? ? ? ? ? &tegra_lp2_debug_ops); + ? ? if (!d) + ? ? ? ? ? ? return -ENOMEM;Quoted 8 lines
arch/arm/mach-tegra/cpuidle.c line 714
Quoted 6 lines
arch/arm/mach-tegra/cpuidle.c new file +6
-0+ + ? ? return 0; +} +#endif + +late_initcall (tegra_cpuidle_debug_init);Will this compile with
CONFIG_DEBUG_FS=n?
Quoted 3 lines
Yes. ?All debugfs ops return
ERR_PTR(-ENODEV)ifCONFIG_DEBUG_FS=n, sotegra_cpuidle_debug_initwill do nothing and return 0.
Oops no, it will not compile. Will fix.
PATCH v2 19/28 ARM: tegra: iomap: Add missing devices, fix use of SZ_8, SZ_64
In reply to Colin CrossFrom: Gary King <[email protected]>
Adds gart, hdmi, avp, host1x, and pwm controllers to mach/iomap.h There is no SZ_8 or SZ_64, replace them with constants
--- arch/arm/mach-tegra/include/mach/iomap.h | 55 ++++++++++++++++++++++++------ 1 files changed, 44 insertions(+), 11 deletions(-)
arch/arm/mach-tegra/include/mach/iomap.h +44 -11
@@ -26,6 +26,9 @@#define TEGRA_IRAM_BASE 0x40000000#define TEGRA_IRAM_SIZE SZ_256K +#define TEGRA_HOST1X_BASE 0x50000000 +#define TEGRA_HOST1X_SIZE 0x24000 +#define TEGRA_ARM_PERIF_BASE 0x50040000#define TEGRA_ARM_PERIF_SIZE SZ_8K
@@ -35,38 +38,56 @@#define TEGRA_ARM_INT_DIST_BASE 0x50041000#define TEGRA_ARM_INT_DIST_SIZE SZ_4K +#define TEGRA_MPE_BASE 0x54040000 +#define TEGRA_MPE_SIZE SZ_256K + +#define TEGRA_VI_BASE 0x54080000 +#define TEGRA_VI_SIZE SZ_256K + +#define TEGRA_ISP_BASE 0x54100000 +#define TEGRA_ISP_SIZE SZ_256K +#define TEGRA_DISPLAY_BASE 0x54200000#define TEGRA_DISPLAY_SIZE SZ_256K#define TEGRA_DISPLAY2_BASE 0x54240000#define TEGRA_DISPLAY2_SIZE SZ_256K +#define TEGRA_HDMI_BASE 0x54280000 +#define TEGRA_HDMI_SIZE SZ_256K + +#define TEGRA_GART_BASE 0x58000000 +#define TEGRA_GART_SIZE SZ_32M + +#define TEGRA_RES_SEMA_BASE 0x60001000 +#define TEGRA_RES_SEMA_SIZE SZ_4K +#define TEGRA_PRIMARY_ICTLR_BASE 0x60004000 -#define TEGRA_PRIMARY_ICTLR_SIZE SZ_64 +#define TEGRA_PRIMARY_ICTLR_SIZE 64#define TEGRA_SECONDARY_ICTLR_BASE 0x60004100 -#define TEGRA_SECONDARY_ICTLR_SIZE SZ_64 +#define TEGRA_SECONDARY_ICTLR_SIZE 64#define TEGRA_TERTIARY_ICTLR_BASE 0x60004200 -#define TEGRA_TERTIARY_ICTLR_SIZE SZ_64 +#define TEGRA_TERTIARY_ICTLR_SIZE 64#define TEGRA_QUATERNARY_ICTLR_BASE 0x60004300 -#define TEGRA_QUATERNARY_ICTLR_SIZE SZ_64 +#define TEGRA_QUATERNARY_ICTLR_SIZE 64#define TEGRA_TMR1_BASE 0x60005000 -#define TEGRA_TMR1_SIZE SZ_8 +#define TEGRA_TMR1_SIZE 8#define TEGRA_TMR2_BASE 0x60005008 -#define TEGRA_TMR2_SIZE SZ_8 +#define TEGRA_TMR2_SIZE 8#define TEGRA_TMRUS_BASE 0x60005010 -#define TEGRA_TMRUS_SIZE SZ_64 +#define TEGRA_TMRUS_SIZE 64#define TEGRA_TMR3_BASE 0x60005050 -#define TEGRA_TMR3_SIZE SZ_8 +#define TEGRA_TMR3_SIZE 8#define TEGRA_TMR4_BASE 0x60005058 -#define TEGRA_TMR4_SIZE SZ_8 +#define TEGRA_TMR4_SIZE 8#define TEGRA_CLK_RESET_BASE 0x60006000#define TEGRA_CLK_RESET_SIZE SZ_4K
@@ -114,10 +135,10 @@#define TEGRA_I2S2_SIZE SZ_256#define TEGRA_UARTA_BASE 0x70006000 -#define TEGRA_UARTA_SIZE SZ_64 +#define TEGRA_UARTA_SIZE 64#define TEGRA_UARTB_BASE 0x70006040 -#define TEGRA_UARTB_SIZE SZ_64 +#define TEGRA_UARTB_SIZE 64#define TEGRA_UARTC_BASE 0x70006200#define TEGRA_UARTC_SIZE SZ_256
@@ -140,6 +161,18 @@#define TEGRA_PWFM_BASE 0x7000A000#define TEGRA_PWFM_SIZE SZ_256 +#define TEGRA_PWFM0_BASE 0x7000A000 +#define TEGRA_PWFM0_SIZE 4 + +#define TEGRA_PWFM1_BASE 0x7000A010 +#define TEGRA_PWFM1_SIZE 4 + +#define TEGRA_PWFM2_BASE 0x7000A020 +#define TEGRA_PWFM2_SIZE 4 + +#define TEGRA_PWFM3_BASE 0x7000A030 +#define TEGRA_PWFM3_SIZE 4 +#define TEGRA_MIPI_BASE 0x7000B000#define TEGRA_MIPI_SIZE SZ_256
Signature · 1 line
1.7.3.1
PATCH v2 20/28 ARM: tegra: cpufreq: Disable cpufreq during suspend
In reply to Colin CrossAdds a SUSPEND_PREPARE notification hook to drop the frequency to the lowest possible during suspend. This prevents the cpufreq driver from attempting regulator calls after suspend has started - the regulator api can call into drivers that have already been suspended. Also adds 216MHz (off of PLLP) as the lowest CPU frequency, which allows PLLX to be turned off.
--- arch/arm/mach-tegra/cpu-tegra.c | 75 +++++++++++++++++++++++++++++++-------- 1 files changed, 60 insertions(+), 15 deletions(-)
arch/arm/mach-tegra/cpu-tegra.c +60 -15
@@ -28,6 +28,7 @@#include <linux/err.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/suspend.h> #include <asm/system.h>
@@ -36,14 +37,15 @@/* Frequency table index must be sequential starting at 0 */ static struct cpufreq_frequency_table freq_table[] = { - {0 ,312000 }, - {1 ,456000 }, - {2 ,608000 }, - {3 ,760000 }, - {4 ,816000 }, - {5 ,912000 }, - {6 ,1000000 }, - {7 ,CPUFREQ_TABLE_END }, + {0 ,216000 }, + {1 ,312000 }, + {2 ,456000 }, + {3 ,608000 }, + {4 ,760000 }, + {5 ,816000 }, + {6 ,912000 }, + {7 ,1000000 }, + {8 ,CPUFREQ_TABLE_END }, };#define NUM_CPUS 2
@@ -51,6 +53,8 @@ static struct cpufreq_frequency_table freq_table[] = {static struct clk *cpu_clk;static unsigned long target_cpu_speed[NUM_CPUS ]; +static DEFINE_MUTEX (tegra_cpu_lock); +static bool is_suspended;int tegra_verify_speed (struct cpufreq_policy *policy) {
@@ -68,16 +72,11 @@ unsigned int tegra_getspeed(unsigned int cpu)return rate; } -static int tegra_update_cpu_speed (void ) +static int tegra_update_cpu_speed (unsigned long rate) { -int i; -unsigned long rate =0 ;int ret =0 ;struct cpufreq_freqs freqs; -for_each_online_cpu (i) - rate =max (rate, target_cpu_speed[i]); - freqs.old =tegra_getspeed (0 ); freqs.new = rate;
@@ -105,12 +104,30 @@ static int tegra_update_cpu_speed(void)return 0 ; } +static unsigned long tegra_cpu_highest_speed (void ) +{ +unsigned long rate =0 ; +int i; + +for_each_online_cpu (i) + rate =max (rate, target_cpu_speed[i]); +return rate; +} +static int tegra_target (struct cpufreq_policy *policy,unsigned int target_freq,unsigned int relation) {int idx;unsigned int freq; +int ret =0 ; + +mutex_lock (&tegra_cpu_lock); + +if (is_suspended) { + ret = -EBUSY ; + goto out; + }cpufreq_frequency_table_target (policy, freq_table, target_freq, relation, &idx);
@@ -119,9 +136,34 @@ static int tegra_target(struct cpufreq_policy *policy, target_cpu_speed[policy->cpu] = freq; -return tegra_update_cpu_speed (); + ret =tegra_update_cpu_speed (tegra_cpu_highest_speed ()); + +out: +mutex_unlock (&tegra_cpu_lock); +return ret; } +static int tegra_pm_notify (struct notifier_block *nb,unsigned long event, +void *dummy) +{ +mutex_lock (&tegra_cpu_lock); +if (event ==PM_SUSPEND_PREPARE ) { + is_suspended = true; +pr_info ("Tegra cpufreq suspend: setting frequency to %d kHz\n" , + freq_table[0 ].frequency); +tegra_update_cpu_speed (freq_table[0 ].frequency); + }else if (event ==PM_POST_SUSPEND ) { + is_suspended = false; + } +mutex_unlock (&tegra_cpu_lock); + +return NOTIFY_OK ; +} + +static struct notifier_block tegra_cpu_pm_notifier = { + .notifier_call = tegra_pm_notify, +}; +static int tegra_cpu_init (struct cpufreq_policy *policy) {if (policy->cpu >=NUM_CPUS )
@@ -142,6 +184,9 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) policy->shared_type =CPUFREQ_SHARED_TYPE_ALL ;cpumask_copy (policy->related_cpus, cpu_possible_mask); +if (policy->cpu ==0 ) +register_pm_notifier (&tegra_cpu_pm_notifier); +return 0 ; }
Signature · 1 line
1.7.3.1
Re: [PATCH v2 20/28] ARM: tegra: cpufreq: Disable cpufreq during suspend
Quoted 4 lines · Colin Cross
Adds a
SUSPEND_PREPAREnotification hook to drop the frequency to the lowest possible during suspend. This prevents the cpufreq driver from attempting regulator calls after suspend has started - the regulator api can call into drivers that have already been suspended.
Hrm, what's the situation where that happens and why does it cause problems? The regulator API doesn't care if suspend is going on, and nor do any of the current drivers for regulators. There is an issue with keeping things like I2C alive until the bitter end of suspend so you've got a control bus to the regulators but that's a generic issue which crops up with other subsystems too so a regulator-specific workaround seems dodgy.
The patch itself seems fine, it's just that it feels like there's something else going on.
Re: [PATCH v2 20/28] ARM: tegra: cpufreq: Disable cpufreq during suspend
Quoted 6 lines · Mark Brown
Quoted 4 lines · Colin Cross
Adds a
SUSPEND_PREPAREnotification hook to drop the frequency to the lowest possible during suspend. ?This prevents the cpufreq driver from attempting regulator calls after suspend has started - the regulator api can call into drivers that have already been suspended.
Quoted 7 lines
Hrm, what's the situation where that happens and why does it cause problems? ?The regulator API doesn't care if suspend is going on, and nor do any of the current drivers for regulators. ?There is an issue with keeping things like I2C alive until the bitter end of suspend so you've got a control bus to the regulators but that's a generic issue which crops up with other subsystems too so a regulator-specific workaround seems dodgy.
The end result is that the regulator driver calls the i2c driver after the i2c driver has been suspended. On Tegra, this happens because of voltage scaling on the CPU regulator, which can be on the i2c bus. A sleep in a suspend handler after the i2c bus has been suspended can cause the cpufreq governor to lower the frequency, and try to lower the voltage as well.
The problem isn't limited to i2c busses, there are some regulators on spi busses. You would need to ensure that any driver that has a regulator consumer suspends before the regulator driver it communicates with, and that still wouldn't fix cpufreq, which has a sysdev suspend handler.
Quoted 3 lines
The patch itself seems fine, it's just that it feels like there's something else going on.
Re: [PATCH v2 20/28] ARM: tegra: cpufreq: Disable cpufreq during suspend
Quoted 10 lines · Colin Cross
On Mon, Jan 24, 2011 at 6:41 AM, Mark Brown
Quoted 7 lines
Hrm, what's the situation where that happens and why does it cause problems? ?The regulator API doesn't care if suspend is going on, and nor do any of the current drivers for regulators. ?There is an issue with keeping things like I2C alive until the bitter end of suspend so you've got a control bus to the regulators but that's a generic issue which crops up with other subsystems too so a regulator-specific workaround seems dodgy.
Quoted 6 lines
The end result is that the regulator driver calls the i2c driver after the i2c driver has been suspended. On Tegra, this happens because of voltage scaling on the CPU regulator, which can be on the i2c bus. A sleep in a suspend handler after the i2c bus has been suspended can cause the cpufreq governor to lower the frequency, and try to lower the voltage as well.
OK, that's a general problem - you need to ensure that the I2C and SPI controllers are suspended really late. The OMAP guys also have this problem for some RTCs, though in their case things are slightly different due to their use of runtime PM. Looking at your I2C driver (BTW, I'd suggest reminding Ben on a more regular basis about that) I suspect that moving your suspend and resume callbacks to the _noirq varaints will cover a lot of this.
Quoted 2 lines
The problem isn't limited to i2c busses, there are some regulators on spi busses. You would need to ensure that any driver that has a
For all practical purposes in this sort of discussion you can typically do a s/I2C/I2C and SPI/ - in terms of system integration issues they're very similar.
Quoted 3 lines
regulator consumer suspends before the regulator driver it communicates with, and that still wouldn't fix cpufreq, which has a sysdev suspend handler.
So you actively need to push the processor into low power mode during suspend? I'm still not 100% clear what's triggering the issues you're seeing and why this seems to be Tegra-only. If there were a general cpufreq/regulator interaction here I'd expect to see all ARM cpufreq drivers needing to do the same thing (and probably some handling of this in cpufreq core as a result). If it's not such an issue I'd expect there's also entertaining suspend ordering issues elsewhere.
Typically this stuff isn't a problem for regulators themselves since if they're active by the time I2C is off they normally get suspended by hardware handshakes from the CPU as that enters low power mode - right now we have no regulators at all in mainline that do anything in software on suspend. We can get a long way by just ignoring what happens to regulators over suspend (there is some work to do here but it's orthogonal to this sort of issue).
Re: [PATCH v2 20/28] ARM: tegra: cpufreq: Disable cpufreq during suspend
Quoted 18 lines · Mark Brown
Quoted 10 lines · Colin Cross
On Mon, Jan 24, 2011 at 6:41 AM, Mark Brown
Quoted 7 lines
Hrm, what's the situation where that happens and why does it cause problems? ?The regulator API doesn't care if suspend is going on, and nor do any of the current drivers for regulators. ?There is an issue with keeping things like I2C alive until the bitter end of suspend so you've got a control bus to the regulators but that's a generic issue which crops up with other subsystems too so a regulator-specific workaround seems dodgy.
Quoted 6 lines
The end result is that the regulator driver calls the i2c driver after the i2c driver has been suspended. ?On Tegra, this happens because of voltage scaling on the CPU regulator, which can be on the i2c bus. ?A sleep in a suspend handler after the i2c bus has been suspended can cause the cpufreq governor to lower the frequency, and try to lower the voltage as well.
Quoted 7 lines
OK, that's a general problem - you need to ensure that the I2C and SPI controllers are suspended really late. ?The OMAP guys also have this problem for some RTCs, though in their case things are slightly different due to their use of runtime PM. ?Looking at your I2C driver (BTW, I'd suggest reminding Ben on a more regular basis about that) I suspect that moving your suspend and resume callbacks to the
_noirqvaraints will cover a lot of this.
Even _noirq isn't late enough, if cpufreq keeps trying to change the frequency (and thus voltage) until sysdev suspend.
Quoted 6 lines
Quoted 2 lines
The problem isn't limited to i2c busses, there are some regulators on spi busses. ?You would need to ensure that any driver that has a
For all practical purposes in this sort of discussion you can typically do a s/I2C/I2C and SPI/ - in terms of system integration issues they're very similar.
True
Quoted 11 lines
Quoted 3 lines
regulator consumer suspends before the regulator driver it communicates with, and that still wouldn't fix cpufreq, which has a sysdev suspend handler.
So you actively need to push the processor into low power mode during suspend? ?I'm still not 100% clear what's triggering the issues you're seeing and why this seems to be Tegra-only. ?If there were a general cpufreq/regulator interaction here I'd expect to see all ARM cpufreq drivers needing to do the same thing (and probably some handling of this in cpufreq core as a result). ?If it's not such an issue I'd expect there's also entertaining suspend ordering issues elsewhere.
It's more of a voltage scaling issue than a cpufreq issue directly. Tegra requires the voltage be set to nominal during resume, and the only time it can be set for resume is before I2C suspends. I handle the problem with a suspend notifier in the latest version of the clock voltage scaling patches, but I kept this patch to avoid cpufreq trying to go to frequencies that are not supported by the suspend voltage.
Quoted 7 lines
Typically this stuff isn't a problem for regulators themselves since if they're active by the time I2C is off they normally get suspended by hardware handshakes from the CPU as that enters low power mode - right now we have no regulators at all in mainline that do anything in software on suspend. ?We can get a long way by just ignoring what happens to regulators over suspend (there is some work to do here but it's orthogonal to this sort of issue).
The regulator driver itself has nothing to do, and when the CPU enters its lowest power mode it signals the regulator to turn off, but something needs to tell the regulator to go to the correct voltage.
Re: [PATCH v2 20/28] ARM: tegra: cpufreq: Disable cpufreq during suspend
Quoted 2 lines · Colin Cross
Even
_noirqisn't late enough, if cpufreq keeps trying to change the frequency (and thus voltage) until sysdev suspend.
If it were just cpufreq in isolation I'm not sure it'd be a big deal - nothing will go hideously wrong if it's ticking away by itself providing it's just governors working away providing the error handling is OK. However...
Quoted 11 lines
On Mon, Jan 24, 2011 at 11:35 AM, Mark Brown
Quoted 2 lines
So you actively need to push the processor into low power mode during suspend? ?I'm still not 100% clear what's triggering the issues you're
It's more of a voltage scaling issue than a cpufreq issue directly. Tegra requires the voltage be set to nominal during resume, and the only time it can be set for resume is before I2C suspends. I handle the problem with a suspend notifier in the latest version of the clock voltage scaling patches, but I kept this patch to avoid cpufreq trying to go to frequencies that are not supported by the suspend voltage.
...it sounds like you do actually have something of the above issue - but I think it's a generic-ish problem. See below.
Quoted 11 lines
Quoted 7 lines
Typically this stuff isn't a problem for regulators themselves since if they're active by the time I2C is off they normally get suspended by hardware handshakes from the CPU as that enters low power mode - right now we have no regulators at all in mainline that do anything in software on suspend. ?We can get a long way by just ignoring what happens to regulators over suspend (there is some work to do here but it's orthogonal to this sort of issue).
The regulator driver itself has nothing to do, and when the CPU enters its lowest power mode it signals the regulator to turn off, but something needs to tell the regulator to go to the correct voltage.
Normally that's handled by the same transition logic - the core PMIC will usually sequence a bunch of voltage and power status changes when entering its own low power mode and have a similar transition on resume which will ensure that the regulators power back up with a sane setup regardless of the state they were in beforehand.
It sounds like for your systems what's happening is that the resume is restoring the previously configured voltages for the core rails rather than going to a known good state. Is my understanding correct here? While your fix is good and I don't see any reason not to do it this does sound like something we should have a solution for in common code as I'd not be surprised if there were other hardware out there which did a similar thing.
Assuming I'm not completely off base with the above it'd be good if you could clarify this in the commit message - there's enough dragons with this stuff and it's common to refer to other implementations so it'd be nice if we had a clear record of the issue in the log.
Re: [PATCH v2 20/28] ARM: tegra: cpufreq: Disable cpufreq during suspend
Quoted 37 lines · Mark Brown
Quoted 2 lines · Colin Cross
Even
_noirqisn't late enough, if cpufreq keeps trying to change the frequency (and thus voltage) until sysdev suspend.If it were just cpufreq in isolation I'm not sure it'd be a big deal - nothing will go hideously wrong if it's ticking away by itself providing it's just governors working away providing the error handling is OK. However...
Quoted 11 lines
On Mon, Jan 24, 2011 at 11:35 AM, Mark Brown
Quoted 2 lines
So you actively need to push the processor into low power mode during suspend? ?I'm still not 100% clear what's triggering the issues you're
It's more of a voltage scaling issue than a cpufreq issue directly. Tegra requires the voltage be set to nominal during resume, and the only time it can be set for resume is before I2C suspends. ?I handle the problem with a suspend notifier in the latest version of the clock voltage scaling patches, but I kept this patch to avoid cpufreq trying to go to frequencies that are not supported by the suspend voltage.
...it sounds like you do actually have something of the above issue - but I think it's a generic-ish problem. ?See below.
Quoted 11 lines
Quoted 7 lines
Typically this stuff isn't a problem for regulators themselves since if they're active by the time I2C is off they normally get suspended by hardware handshakes from the CPU as that enters low power mode - right now we have no regulators at all in mainline that do anything in software on suspend. ?We can get a long way by just ignoring what happens to regulators over suspend (there is some work to do here but it's orthogonal to this sort of issue).
The regulator driver itself has nothing to do, and when the CPU enters its lowest power mode it signals the regulator to turn off, but something needs to tell the regulator to go to the correct voltage.
Quoted 5 lines
Normally that's handled by the same transition logic - the core PMIC will usually sequence a bunch of voltage and power status changes when entering its own low power mode and have a similar transition on resume which will ensure that the regulators power back up with a sane setup regardless of the state they were in beforehand.
I believe Tegra supports this mode, where the Tegra PMC can master the I2C bus to control an external PMIC during resume, but I've never seen it used.
Quoted 7 lines
It sounds like for your systems what's happening is that the resume is restoring the previously configured voltages for the core rails rather than going to a known good state. ?Is my understanding correct here? While your fix is good and I don't see any reason not to do it this does sound like something we should have a solution for in common code as I'd not be surprised if there were other hardware out there which did a similar thing.
Yes - the core can be connected to a dumb I2C regulator, which the core can turn on and off with a request line, but can't control the voltage without a regulator driver controlling the I2C bus.
Quoted 4 lines
Assuming I'm not completely off base with the above it'd be good if you could clarify this in the commit message - there's enough dragons with this stuff and it's common to refer to other implementations so it'd be nice if we had a clear record of the issue in the log.
Will do
Re: [PATCH v2 20/28] ARM: tegra: cpufreq: Disable cpufreq during suspend
Quoted 11 lines · Colin Cross
On Mon, Jan 24, 2011 at 12:26 PM, Mark Brown
Quoted 5 lines
Normally that's handled by the same transition logic - the core PMIC will usually sequence a bunch of voltage and power status changes when entering its own low power mode and have a similar transition on resume which will ensure that the regulators power back up with a sane setup regardless of the state they were in beforehand.
I believe Tegra supports this mode, where the Tegra PMC can master the I2C bus to control an external PMIC during resume, but I've never seen it used.
In almost all cases it's implemented in the PMIC rather than the CPU - it's essentially the same logic as implements the initial power on of the system and the PMIC needs to be capable of starting the system boot without external assistance anyway, including sequencing the power up of the CPU.
With most PMICs the settings will be hard coded into the silicon so you really need to get a PMIC specifically designed for whatever CPU you're using (this is one of the reasons you always see the same CPU/PMIC combinations, people are terrified of changing a known good pairing in case they build something that won't power on). Some more modern PMICs make this configurable which gives system designers a lot more flexibility.
The PMC stuff is newer and in the designs I've seen is more focused on runtime management than this stuff.
Quoted 11 lines
Quoted 7 lines
It sounds like for your systems what's happening is that the resume is restoring the previously configured voltages for the core rails rather than going to a known good state. ?Is my understanding correct here? While your fix is good and I don't see any reason not to do it this does sound like something we should have a solution for in common code as I'd not be surprised if there were other hardware out there which did a similar thing.
Yes - the core can be connected to a dumb I2C regulator, which the core can turn on and off with a request line, but can't control the voltage without a regulator driver controlling the I2C bus.
AIUI generally they end up working because whatever puts them into suspend actually resets them so when you release reset during resume they just recover whatever the default voltage they have is and normally the boot and resume conditions for the CPU are identical. I could be off base there, most of the regulator API stuff has been done with integrated PMICs.
Re: [PATCH v2 20/28] ARM: tegra: cpufreq: Disable cpufreq during suspend
Quoted 19 lines · Mark Brown
Quoted 11 lines · Colin Cross
On Mon, Jan 24, 2011 at 12:26 PM, Mark Brown
Quoted 5 lines
Normally that's handled by the same transition logic - the core PMIC will usually sequence a bunch of voltage and power status changes when entering its own low power mode and have a similar transition on resume which will ensure that the regulators power back up with a sane setup regardless of the state they were in beforehand.
I believe Tegra supports this mode, where the Tegra PMC can master the I2C bus to control an external PMIC during resume, but I've never seen it used.
In almost all cases it's implemented in the PMIC rather than the CPU - it's essentially the same logic as implements the initial power on of the system and the PMIC needs to be capable of starting the system boot without external assistance anyway, including sequencing the power up of the CPU.
Quoted 7 lines
With most PMICs the settings will be hard coded into the silicon so you really need to get a PMIC specifically designed for whatever CPU you're using (this is one of the reasons you always see the same CPU/PMIC combinations, people are terrified of changing a known good pairing in case they build something that won't power on). ?Some more modern PMICs make this configurable which gives system designers a lot more flexibility.
I'm seeing the opposite problem - changing CPUs, and keeping the PMIC.
Quoted 15 lines
The PMC stuff is newer and in the designs I've seen is more focused on runtime management than this stuff.
Quoted 11 lines
Quoted 7 lines
It sounds like for your systems what's happening is that the resume is restoring the previously configured voltages for the core rails rather than going to a known good state. ?Is my understanding correct here? While your fix is good and I don't see any reason not to do it this does sound like something we should have a solution for in common code as I'd not be surprised if there were other hardware out there which did a similar thing.
Yes - the core can be connected to a dumb I2C regulator, which the core can turn on and off with a request line, but can't control the voltage without a regulator driver controlling the I2C bus.
Quoted 6 lines
AIUI generally they end up working because whatever puts them into suspend actually resets them so when you release reset during resume they just recover whatever the default voltage they have is and normally the boot and resume conditions for the CPU are identical. ?I could be off base there, most of the regulator API stuff has been done with integrated PMICs.
Resetting during suspend would be the sane thing to do, but that's not what the hardware does. The regulator also gets turned off during idle, so it can't just be reset every time it turns off.
Re: [PATCH v2 20/28] ARM: tegra: cpufreq: Disable cpufreq during suspend
In reply to Mark BrownQuoted 18 lines · Mark Brown
Quoted 10 lines · Colin Cross
On Mon, Jan 24, 2011 at 6:41 AM, Mark Brown
Quoted 7 lines
Hrm, what's the situation where that happens and why does it cause problems? ?The regulator API doesn't care if suspend is going on, and nor do any of the current drivers for regulators. ?There is an issue with keeping things like I2C alive until the bitter end of suspend so you've got a control bus to the regulators but that's a generic issue which crops up with other subsystems too so a regulator-specific workaround seems dodgy.
Quoted 6 lines
The end result is that the regulator driver calls the i2c driver after the i2c driver has been suspended. ?On Tegra, this happens because of voltage scaling on the CPU regulator, which can be on the i2c bus. ?A sleep in a suspend handler after the i2c bus has been suspended can cause the cpufreq governor to lower the frequency, and try to lower the voltage as well.
Quoted 7 lines
OK, that's a general problem - you need to ensure that the I2C and SPI controllers are suspended really late. ?The OMAP guys also have this problem for some RTCs, though in their case things are slightly different due to their use of runtime PM. ?Looking at your I2C driver (BTW, I'd suggest reminding Ben on a more regular basis about that) I suspect that moving your suspend and resume callbacks to the
_noirqvaraints will cover a lot of this.
Right, it's same as Samsung SoCs. we also disable to access the cpufreq when suspending.
the PMIC is connected with I2C and I2C is suspended before PMIC.
Thank you,
Kyungmin Park
Quoted 33 lines
Quoted 3 lines
The problem isn't limited to i2c busses, there are some regulators on spi busses. ?You would need to ensure that any driver that has a
For all practical purposes in this sort of discussion you can typically do a s/I2C/I2C and SPI/ - in terms of system integration issues they're very similar.
Quoted 3 lines
regulator consumer suspends before the regulator driver it communicates with, and that still wouldn't fix cpufreq, which has a sysdev suspend handler.
So you actively need to push the processor into low power mode during suspend? ?I'm still not 100% clear what's triggering the issues you're seeing and why this seems to be Tegra-only. ?If there were a general cpufreq/regulator interaction here I'd expect to see all ARM cpufreq drivers needing to do the same thing (and probably some handling of this in cpufreq core as a result). ?If it's not such an issue I'd expect there's also entertaining suspend ordering issues elsewhere.
Typically this stuff isn't a problem for regulators themselves since if they're active by the time I2C is off they normally get suspended by hardware handshakes from the CPU as that enters low power mode - right now we have no regulators at all in mainline that do anything in software on suspend. ?We can get a long way by just ignoring what happens to regulators over suspend (there is some work to do here but it's orthogonal to this sort of issue).
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
PATCH v2 21/28 ARM: tegra: Allow overriding arch_reset
In reply to Colin Cross---
v2: Move definition of tegra_assert_system_reset out of static
inline
arch/arm/mach-tegra/board.h | 2 ++ arch/arm/mach-tegra/common.c | 13 +++++++++++++ arch/arm/mach-tegra/include/mach/system.h | 10 ++-------- 3 files changed, 17 insertions(+), 8 deletions(-)
arch/arm/mach-tegra/board.h +2 -0
@@ -23,6 +23,8 @@#include <linux/types.h> +void tegra_assert_system_reset (char mode,const char *cmd); +void __init tegra_common_init (void );void __init tegra_map_common_io (void );void __init tegra_init_irq (void );
arch/arm/mach-tegra/common.c +13 -0
@@ -27,6 +27,7 @@#include <mach/iomap.h> #include <mach/dma.h> +#include <mach/system.h> #include "board.h" #include "clock.h"
@@ -36,6 +37,18 @@unsigned long tegra_lp0_vec_start;unsigned long tegra_lp0_vec_size; +void (*arch_reset)(char mode,const char *cmd) = tegra_assert_system_reset; + +void tegra_assert_system_reset (char mode,const char *cmd) +{ +void __iomem *reset =IO_ADDRESS (TEGRA_CLK_RESET_BASE +0x04 ); +u32 reg; + + reg =readl (reset); + reg |=0x04 ; +writel (reg, reset); +} +static __initdata struct tegra_clk_init_table common_clk_init_table[] = {/* name parent rate enabled */ {"clk_m" ,NULL ,0 , true },
arch/arm/mach-tegra/include/mach/system.h +2 -8
@@ -24,16 +24,10 @@#include <mach/hardware.h> #include <mach/iomap.h> -static inline void arch_idle (void ) -{ -} +extern void (*arch_reset)(char mode,const char *cmd); -static inline void arch_reset (char mode,const char *cmd) +static inline void arch_idle (void ) { -void __iomem *reset =IO_ADDRESS (TEGRA_CLK_RESET_BASE +0x04 ); -u32 reg =readl (reset); - reg |=0x04 ; -writel (reg, reset); }#endif
Signature · 1 line
1.7.3.1
PATCH v2 22/28 ARM: tegra: dma: Fix critical data corruption bugs
In reply to Colin CrossSometimes, due to high interrupt latency in the continuous mode of DMA transfer, the half buffer complete interrupt is handled after DMA has transferred the full buffer. When this is detected, stop DMA immediately and restart with the next buffer if the next buffer is ready.
originally fixed by Victor(Weiguo) Pan <[email protected]>
In place of using the simple spin_lock()/spi_unlock() in the interrupt thread, using the spin_lock_irqsave() and spin_unlock_irqrestore(). The lock is shared between the normal process context and interrupt context.
originally fixed by Laxman Dewangan (ldewangan at nvidia.com)
The use of shadow registers caused memory corruption at physical address 0 because the enable bit was not shadowed, and assuming it needed to be set would enable an unconfigured dma block. Most of the register accesses don't need to know the previous state of the registers, and the few places that do need to modify only a few bits in the registers are the same ones that were sometimes incorrectly setting the enable bit. This patch convert tegra_dma_update_hardware to set the entire register, and the other users to read-modify-write, and drops the shadow registers completely.
Also fixes missing locking in tegra_dma_allocate_channel
--- arch/arm/mach-tegra/dma.c | 197 +++++++++++++++++++++++++-------------------- 1 files changed, 108 insertions(+), 89 deletions(-)
arch/arm/mach-tegra/dma.c +108 -89
@@ -121,17 +121,13 @@ struct tegra_dma_channel {void __iomem *addr;int mode;int irq; - -/* Register shadow */ -u32 csr; -u32 ahb_seq; -u32 ahb_ptr; -u32 apb_seq; -u32 apb_ptr; +int req_transfer_count; };#define NV_DMA_MAX_CHANNELS 32 +static DEFINE_MUTEX (tegra_dma_lock); + static DECLARE_BITMAP(channel_usage, NV_DMA_MAX_CHANNELS);static struct tegra_dma_channel dma_channels[NV_DMA_MAX_CHANNELS ];
@@ -139,7 +135,6 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch, struct tegra_dma_req *req);static void tegra_dma_update_hw_partial (struct tegra_dma_channel *ch,struct tegra_dma_req *req); -static void tegra_dma_init_hw (struct tegra_dma_channel *ch);static void tegra_dma_stop (struct tegra_dma_channel *ch);void tegra_dma_flush (struct tegra_dma_channel *ch)
@@ -151,6 +146,9 @@ void tegra_dma_dequeue(struct tegra_dma_channel *ch) {struct tegra_dma_req *req; +if (tegra_dma_is_empty (ch)) +return ; + req =list_entry (ch->list.next,typeof (*req), node);tegra_dma_dequeue_req (ch, req);
@@ -159,10 +157,10 @@ void tegra_dma_dequeue(struct tegra_dma_channel *ch)void tegra_dma_stop (struct tegra_dma_channel *ch) { -unsigned int csr; -unsigned int status; +u32 csr; +u32 status; - csr = ch->csr; + csr =readl (ch->addr +APB_DMA_CHAN_CSR ); csr &= ~CSR_IE_EOC ;writel (csr, ch->addr +APB_DMA_CHAN_CSR );
@@ -176,19 +174,16 @@ void tegra_dma_stop(struct tegra_dma_channel *ch)int tegra_dma_cancel (struct tegra_dma_channel *ch) { -unsigned int csr; +u32 csr;unsigned long irq_flags;spin_lock_irqsave (&ch->lock, irq_flags);while (!list_empty (&ch->list))list_del (ch->list.next); - csr = ch->csr; + csr =readl (ch->addr +APB_DMA_CHAN_CSR ); csr &= ~CSR_REQ_SEL_MASK ; csr |=CSR_REQ_SEL_INVALID ; - -/* Set the enable as that is not shadowed */ - csr |=CSR_ENB ;writel (csr, ch->addr +APB_DMA_CHAN_CSR );tegra_dma_stop (ch);
@@ -230,18 +225,15 @@ int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,* - Finally stop or program the DMA to the next buffer in the * list. */ - csr = ch->csr; + csr =readl (ch->addr +APB_DMA_CHAN_CSR ); csr &= ~CSR_REQ_SEL_MASK ; csr |=CSR_REQ_SEL_INVALID ; - -/* Set the enable as that is not shadowed */ - csr |=CSR_ENB ;writel (csr, ch->addr +APB_DMA_CHAN_CSR );/* Get the transfer count */ status =readl (ch->addr +APB_DMA_CHAN_STA ); to_transfer = (status &STA_COUNT_MASK ) >>STA_COUNT_SHIFT ; - req_transfer_count = (ch->csr &CSR_WCOUNT_MASK ) >>CSR_WCOUNT_SHIFT ; + req_transfer_count = ch->req_transfer_count; req_transfer_count +=1 ; to_transfer +=1 ;
@@ -349,7 +341,9 @@ EXPORT_SYMBOL(tegra_dma_enqueue_req);struct tegra_dma_channel *tegra_dma_allocate_channel (int mode) {int channel; -struct tegra_dma_channel *ch; +struct tegra_dma_channel *ch =NULL ; + +mutex_lock (&tegra_dma_lock);/* first channel is the shared channel */ if (mode &TEGRA_DMA_SHARED ) {
@@ -358,11 +352,14 @@ struct tegra_dma_channel *tegra_dma_allocate_channel(int mode) channel =find_first_zero_bit (channel_usage,ARRAY_SIZE (dma_channels));if (channel >=ARRAY_SIZE (dma_channels)) -return NULL ; + goto out; }__set_bit (channel, channel_usage); ch = &dma_channels[channel]; ch->mode = mode; + +out: +mutex_unlock (&tegra_dma_lock);return ch; }EXPORT_SYMBOL (tegra_dma_allocate_channel);
@@ -372,22 +369,27 @@ void tegra_dma_free_channel(struct tegra_dma_channel *ch)if (ch->mode &TEGRA_DMA_SHARED )return ;tegra_dma_cancel (ch); +mutex_lock (&tegra_dma_lock);__clear_bit (ch->id, channel_usage); +mutex_unlock (&tegra_dma_lock); }EXPORT_SYMBOL (tegra_dma_free_channel);static void tegra_dma_update_hw_partial (struct tegra_dma_channel *ch,struct tegra_dma_req *req) { +u32 apb_ptr; +u32 ahb_ptr; +if (req->to_memory) { - ch->apb_ptr = req->source_addr; - ch->ahb_ptr = req->dest_addr; + apb_ptr = req->source_addr; + ahb_ptr = req->dest_addr; }else { - ch->apb_ptr = req->dest_addr; - ch->ahb_ptr = req->source_addr; + apb_ptr = req->dest_addr; + ahb_ptr = req->source_addr; } -writel (ch->apb_ptr, ch->addr +APB_DMA_CHAN_APB_PTR ); -writel (ch->ahb_ptr, ch->addr +APB_DMA_CHAN_AHB_PTR ); +writel (apb_ptr, ch->addr +APB_DMA_CHAN_APB_PTR ); +writel (ahb_ptr, ch->addr +APB_DMA_CHAN_AHB_PTR ); req->status =TEGRA_DMA_REQ_INFLIGHT ;return ;
@@ -401,38 +403,39 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch,int ahb_bus_width;int apb_bus_width;int index; -unsigned long csr; +u32 ahb_seq; +u32 apb_seq; +u32 ahb_ptr; +u32 apb_ptr; +u32 csr; + + csr =CSR_IE_EOC |CSR_FLOW ; + ahb_seq =AHB_SEQ_INTR_ENB |AHB_SEQ_BURST_1 ; + apb_seq =0 ; - ch->csr |=CSR_FLOW ; - ch->csr &= ~CSR_REQ_SEL_MASK ; - ch->csr |= req->req_sel <<CSR_REQ_SEL_SHIFT ; - ch->ahb_seq &= ~AHB_SEQ_BURST_MASK ; - ch->ahb_seq |=AHB_SEQ_BURST_1 ; + csr |= req->req_sel <<CSR_REQ_SEL_SHIFT ;/* One shot mode is always single buffered, * continuous mode is always double buffered * */ if (ch->mode &TEGRA_DMA_MODE_ONESHOT ) { - ch->csr |=CSR_ONCE ; - ch->ahb_seq &= ~AHB_SEQ_DBL_BUF ; - ch->csr &= ~CSR_WCOUNT_MASK ; - ch->csr |= ((req->size>>2 ) -1 ) <<CSR_WCOUNT_SHIFT ; + csr |=CSR_ONCE ; + ch->req_transfer_count = (req->size >>2 ) -1 ; }else { - ch->csr &= ~CSR_ONCE ; - ch->ahb_seq |=AHB_SEQ_DBL_BUF ; + ahb_seq |=AHB_SEQ_DBL_BUF ;/* In double buffered mode, we set the size to half the * requested size and interrupt when half the buffer * is full */ - ch->csr &= ~CSR_WCOUNT_MASK ; - ch->csr |= ((req->size>>3 ) -1 ) <<CSR_WCOUNT_SHIFT ; + ch->req_transfer_count = (req->size >>3 ) -1 ; } + csr |= ch->req_transfer_count <<CSR_WCOUNT_SHIFT ; +if (req->to_memory) { - ch->csr &= ~CSR_DIR ; - ch->apb_ptr = req->source_addr; - ch->ahb_ptr = req->dest_addr; + apb_ptr = req->source_addr; + ahb_ptr = req->dest_addr; apb_addr_wrap = req->source_wrap; ahb_addr_wrap = req->dest_wrap;
@@ -440,9 +443,9 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch, ahb_bus_width = req->dest_bus_width; }else { - ch->csr |=CSR_DIR ; - ch->apb_ptr = req->dest_addr; - ch->ahb_ptr = req->source_addr; + csr |=CSR_DIR ; + apb_ptr = req->dest_addr; + ahb_ptr = req->source_addr; apb_addr_wrap = req->dest_wrap; ahb_addr_wrap = req->source_wrap;
@@ -461,8 +464,7 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch, index++; }while (index <ARRAY_SIZE (apb_addr_wrap_table));BUG_ON (index ==ARRAY_SIZE (apb_addr_wrap_table)); - ch->apb_seq &= ~APB_SEQ_WRAP_MASK ; - ch->apb_seq |= index <<APB_SEQ_WRAP_SHIFT ; + apb_seq |= index <<APB_SEQ_WRAP_SHIFT ;/* set address wrap for AHB size */ index =0 ;
@@ -472,55 +474,42 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch, index++; }while (index <ARRAY_SIZE (ahb_addr_wrap_table));BUG_ON (index ==ARRAY_SIZE (ahb_addr_wrap_table)); - ch->ahb_seq &= ~AHB_SEQ_WRAP_MASK ; - ch->ahb_seq |= index <<AHB_SEQ_WRAP_SHIFT ; + ahb_seq |= index <<AHB_SEQ_WRAP_SHIFT ;for (index =0 ; index <ARRAY_SIZE (bus_width_table); index++) {if (bus_width_table[index] == ahb_bus_width)break ; }BUG_ON (index ==ARRAY_SIZE (bus_width_table)); - ch->ahb_seq &= ~AHB_SEQ_BUS_WIDTH_MASK ; - ch->ahb_seq |= index <<AHB_SEQ_BUS_WIDTH_SHIFT ; + ahb_seq |= index <<AHB_SEQ_BUS_WIDTH_SHIFT ;for (index =0 ; index <ARRAY_SIZE (bus_width_table); index++) {if (bus_width_table[index] == apb_bus_width)break ; }BUG_ON (index ==ARRAY_SIZE (bus_width_table)); - ch->apb_seq &= ~APB_SEQ_BUS_WIDTH_MASK ; - ch->apb_seq |= index <<APB_SEQ_BUS_WIDTH_SHIFT ; - - ch->csr |=CSR_IE_EOC ; + apb_seq |= index <<APB_SEQ_BUS_WIDTH_SHIFT ; -/* update hw registers with the shadow */ -writel (ch->csr, ch->addr +APB_DMA_CHAN_CSR ); -writel (ch->apb_seq, ch->addr +APB_DMA_CHAN_APB_SEQ ); -writel (ch->apb_ptr, ch->addr +APB_DMA_CHAN_APB_PTR ); -writel (ch->ahb_seq, ch->addr +APB_DMA_CHAN_AHB_SEQ ); -writel (ch->ahb_ptr, ch->addr +APB_DMA_CHAN_AHB_PTR ); +writel (csr, ch->addr +APB_DMA_CHAN_CSR ); +writel (apb_seq, ch->addr +APB_DMA_CHAN_APB_SEQ ); +writel (apb_ptr, ch->addr +APB_DMA_CHAN_APB_PTR ); +writel (ahb_seq, ch->addr +APB_DMA_CHAN_AHB_SEQ ); +writel (ahb_ptr, ch->addr +APB_DMA_CHAN_AHB_PTR ); - csr = ch->csr |CSR_ENB ; + csr |=CSR_ENB ;writel (csr, ch->addr +APB_DMA_CHAN_CSR ); req->status =TEGRA_DMA_REQ_INFLIGHT ; } -static void tegra_dma_init_hw (struct tegra_dma_channel *ch) -{ -/* One shot with an interrupt to CPU after transfer */ - ch->csr =CSR_ONCE |CSR_IE_EOC ; - ch->ahb_seq =AHB_SEQ_BUS_WIDTH_32 |AHB_SEQ_INTR_ENB ; - ch->apb_seq =APB_SEQ_BUS_WIDTH_32 |1 <<APB_SEQ_WRAP_SHIFT ; -} -static void handle_oneshot_dma (struct tegra_dma_channel *ch) {struct tegra_dma_req *req; +unsigned long irq_flags; -spin_lock (&ch->lock); +spin_lock_irqsave (&ch->lock, irq_flags);if (list_empty (&ch->list)) { -spin_unlock (&ch->lock); +spin_unlock_irqrestore (&ch->lock, irq_flags);return ; }
@@ -528,8 +517,7 @@ static void handle_oneshot_dma(struct tegra_dma_channel *ch)if (req) {int bytes_transferred; - bytes_transferred = - (ch->csr &CSR_WCOUNT_MASK ) >>CSR_WCOUNT_SHIFT ; + bytes_transferred = ch->req_transfer_count; bytes_transferred +=1 ; bytes_transferred <<=2 ;
@@ -537,12 +525,12 @@ static void handle_oneshot_dma(struct tegra_dma_channel *ch) req->bytes_transferred = bytes_transferred; req->status =TEGRA_DMA_REQ_SUCCESS ; -spin_unlock (&ch->lock); +spin_unlock_irqrestore (&ch->lock, irq_flags);/* Callback should be called without any lock */ pr_debug ("%s: transferred %d bytes\n" , __func__, req->bytes_transferred); req->complete (req); -spin_lock (&ch->lock); +spin_lock_irqsave (&ch->lock, irq_flags); }if (!list_empty (&ch->list)) {
@@ -552,22 +540,55 @@ static void handle_oneshot_dma(struct tegra_dma_channel *ch)if (req->status !=TEGRA_DMA_REQ_INFLIGHT )tegra_dma_update_hw (ch, req); } -spin_unlock (&ch->lock); +spin_unlock_irqrestore (&ch->lock, irq_flags); }static void handle_continuous_dma (struct tegra_dma_channel *ch) {struct tegra_dma_req *req; +unsigned long irq_flags; -spin_lock (&ch->lock); +spin_lock_irqsave (&ch->lock, irq_flags);if (list_empty (&ch->list)) { -spin_unlock (&ch->lock); +spin_unlock_irqrestore (&ch->lock, irq_flags);return ; } req =list_entry (ch->list.next,typeof (*req), node);if (req) {if (req->buffer_status ==TEGRA_DMA_REQ_BUF_STATUS_EMPTY ) { +bool is_dma_ping_complete; + is_dma_ping_complete = (readl (ch->addr +APB_DMA_CHAN_STA ) + &STA_PING_PONG ) ? true : false; +if (req->to_memory) + is_dma_ping_complete = !is_dma_ping_complete; +/* Out of sync - Release current buffer */ +if (!is_dma_ping_complete) { +int bytes_transferred; + + bytes_transferred = ch->req_transfer_count; + bytes_transferred +=1 ; + bytes_transferred <<=3 ; + req->buffer_status =TEGRA_DMA_REQ_BUF_STATUS_FULL ; + req->bytes_transferred = bytes_transferred; + req->status =TEGRA_DMA_REQ_SUCCESS ; +tegra_dma_stop (ch); + +if (!list_is_last (&req->node, &ch->list)) { +struct tegra_dma_req *next_req; + + next_req =list_entry (req->node.next, +typeof (*next_req), node); +tegra_dma_update_hw (ch, next_req); + } + +list_del (&req->node); + +/* DMA lock is NOT held when callbak is called */ +spin_unlock_irqrestore (&ch->lock, irq_flags); + req->complete (req); +return ; + }/* Load the next request into the hardware, if available * */ if (!list_is_last (&req->node, &ch->list)) {
@@ -580,7 +601,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch) req->buffer_status =TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL ; req->status =TEGRA_DMA_REQ_SUCCESS ;/* DMA lock is NOT held when callback is called */ -spin_unlock (&ch->lock); +spin_unlock_irqrestore (&ch->lock, irq_flags);if (likely (req->threshold)) req->threshold (req);return ;
@@ -591,8 +612,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch)* the second interrupt */ int bytes_transferred; - bytes_transferred = - (ch->csr &CSR_WCOUNT_MASK ) >>CSR_WCOUNT_SHIFT ; + bytes_transferred = ch->req_transfer_count; bytes_transferred +=1 ; bytes_transferred <<=3 ;
@@ -602,7 +622,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch)list_del (&req->node);/* DMA lock is NOT held when callbak is called */ -spin_unlock (&ch->lock); +spin_unlock_irqrestore (&ch->lock, irq_flags); req->complete (req);return ;
@@ -610,7 +630,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch)BUG (); } } -spin_unlock (&ch->lock); +spin_unlock_irqrestore (&ch->lock, irq_flags); }static irqreturn_t dma_isr (int irq,void *data)
@@ -674,7 +694,6 @@ int __init tegra_dma_init(void)spin_lock_init (&ch->lock);INIT_LIST_HEAD (&ch->list); -tegra_dma_init_hw (ch); irq =INT_APB_DMA_CH0 + i; ret = request_threaded_irq(irq, dma_isr, dma_thread_fn, 0,
Signature · 1 line
1.7.3.1
PATCH v2 23/28 ARM: tegra: add tegra_defconfig
In reply to Colin CrossFrom: Olof Johansson <[email protected]>
Adding one single defconfig for the tegra family of boards, to over time cover the superset of supported platform and drivers.
--- arch/arm/configs/tegra_defconfig | 123 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 123 insertions(+), 0 deletions(-) create mode 100644 arch/arm/configs/tegra_defconfig
arch/arm/configs/tegra_defconfig new file +123 -0
@@ -0,0 +1,123 @@ +CONFIG_EXPERIMENTAL=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_EMBEDDED=y +# CONFIG_SYSCTL_SYSCALL is not set +# CONFIG_ELF_CORE is not set +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +CONFIG_ARCH_TEGRA=y +CONFIG_MACH_HARMONY=y +CONFIG_TEGRA_DEBUG_UARTD=y +CONFIG_ARM_ERRATA_742230=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_SMP=y +CONFIG_NR_CPUS=2 +CONFIG_PREEMPT=y +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +CONFIG_HIGHMEM=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_VFP=y +CONFIG_PM=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_INET_ESP=y +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +CONFIG_IPV6=y +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_MULTIPLE_TABLES=y +# CONFIG_WIRELESS is not set +# CONFIG_FIRMWARE_IN_KERNEL is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_MISC_DEVICES=y +CONFIG_AD525X_DPOT=y +CONFIG_AD525X_DPOT_I2C=y +CONFIG_ICS932S401=y +CONFIG_APDS9802ALS=y +CONFIG_ISL29003=y +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set +# CONFIG_WLAN is not set +# CONFIG_INPUT is not set +# CONFIG_SERIO is not set +# CONFIG_VT is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +# CONFIG_HWMON is not set +# CONFIG_MFD_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +# CONFIG_DNOTIFY is not set +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_PRINTK_TIME=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_KERNEL=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y +CONFIG_DEBUG_SLAB=y +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_SPINLOCK_SLEEP=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_VM=y +CONFIG_DEBUG_SG=y +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +CONFIG_DEBUG_LL=y +CONFIG_EARLY_PRINTK=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y
Signature · 1 line
1.7.3.1
PATCH v2 24/28 ARM: tegra: Use writel_relaxed in tegra_init_cache
In reply to Colin Cross--- arch/arm/mach-tegra/common.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
arch/arm/mach-tegra/common.c +2 -2
@@ -68,8 +68,8 @@ void tegra_init_cache(void)#ifdef CONFIG_CACHE_L2X0 void __iomem *p =IO_ADDRESS (TEGRA_ARM_PERIF_BASE ) +0x3000 ; -writel (0x331 , p +L2X0_TAG_LATENCY_CTRL ); -writel (0x441 , p +L2X0_DATA_LATENCY_CTRL ); +writel_relaxed (0x331 , p +L2X0_TAG_LATENCY_CTRL ); +writel_relaxed (0x441 , p +L2X0_DATA_LATENCY_CTRL );l2x0_init (p,0x6C080001 ,0x8200c3fe );#endif
Signature · 1 line
1.7.3.1
PATCH v2 25/28 ARM: tegra: suspend: Save protected aperture across LP0
In reply to Colin Cross--- arch/arm/mach-tegra/suspend.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
arch/arm/mach-tegra/suspend.c +4 -1
@@ -497,12 +497,13 @@ static void tegra_debug_uart_resume(void)#define MC_SECURITY_START 0x6c#define MC_SECURITY_SIZE 0x70 +#define MC_SECURITY_CFG2 0x7cstatic int tegra_suspend_enter (suspend_state_t state) {void __iomem *mc =IO_ADDRESS (TEGRA_MC_BASE );unsigned long flags; -u32 mc_data[2 ]; +u32 mc_data[3 ] = {0 ,0 ,0 };bool do_lp0 = (current_suspend_mode ==TEGRA_SUSPEND_LP0 );bool do_lp2 = (current_suspend_mode ==TEGRA_SUSPEND_LP2 );int lp_state;
@@ -533,6 +534,7 @@ static int tegra_suspend_enter(suspend_state_t state) mc_data[0 ] =readl (mc +MC_SECURITY_START ); mc_data[1 ] =readl (mc +MC_SECURITY_SIZE ); + mc_data[2 ] =readl (mc +MC_SECURITY_CFG2 ); } rtc_before =tegra_rtc_read_ms ();
@@ -550,6 +552,7 @@ static int tegra_suspend_enter(suspend_state_t state)if (do_lp0) {writel (mc_data[0 ], mc +MC_SECURITY_START );writel (mc_data[1 ], mc +MC_SECURITY_SIZE ); +writel (mc_data[2 ], mc +MC_SECURITY_CFG2 );tegra_clk_resume ();tegra_gpio_resume ();
Signature · 1 line
1.7.3.1
PATCH v2 26/28 ARM: tegra: suspend: protect suspend functions with CONFIG_PM
In reply to Colin CrossFrom: Allen Martin <[email protected]>
Protect suspend/resume functions behind #ifdef CONFIG_PM. This prevents a compile error with CONFIG_PM turned off.
--- arch/arm/mach-tegra/suspend.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
arch/arm/mach-tegra/suspend.c +3 -2
@@ -75,10 +75,12 @@ struct suspend_context {struct suspend_context tegra_sctx;static void __iomem *pmc =IO_ADDRESS (TEGRA_PMC_BASE ); +#ifdef CONFIG_PM static void __iomem *clk_rst =IO_ADDRESS (TEGRA_CLK_RESET_BASE );static void __iomem *flow_ctrl =IO_ADDRESS (TEGRA_FLOW_CTRL_BASE );static void __iomem *evp_reset =IO_ADDRESS (TEGRA_EXCEPTION_VECTORS_BASE ) +0x100 ;static void __iomem *tmrus =IO_ADDRESS (TEGRA_TMRUS_BASE ); +#endif #define PMC_CTRL 0x0#define PMC_CTRL_LATCH_WAKEUPS (1 << 5)
@@ -205,6 +207,7 @@ static int create_suspend_pgtable(void)return 0 ; } +#ifdef CONFIG_PM static noinline void restore_cpu_complex(void) {unsigned int reg;
@@ -326,8 +329,6 @@ unsigned int tegra_suspend_lp2(unsigned int us)return remain; } -#ifdef CONFIG_PM -/* ensures that sufficient time is passed for a register write to * serialize into the 32KHz domain */ static void pmc_32kwritel (u32 val,unsigned long offs)
Signature · 1 line
1.7.3.1
PATCH v2 27/28 ARM: tegra: enable emc clock updates after lp0
In reply to Colin CrossFrom: James Wylder <[email protected]>
Write a dummy value to EMC_MRW_0 to allow
clock frequency changes after lp0.
--- arch/arm/mach-tegra/suspend.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-)
arch/arm/mach-tegra/suspend.c +8 -0
@@ -122,6 +122,10 @@ static void __iomem *tmrus = IO_ADDRESS(TEGRA_TMRUS_BASE);#define FLOW_CTRL_CPU_CSR 0x8#define FLOW_CTRL_CPU1_CSR 0x18 +#define EMC_MRW_0 0x0e8 +#define EMC_MRW_DEV_SELECTN 30 +#define EMC_MRW_DEV_NONE (3 << EMC_MRW_DEV_SELECTN) +unsigned long tegra_pgd_phys;/* pgd used by hotplug & LP2 bootup */ static pgd_t *tegra_pgd;void *tegra_context_area;
@@ -503,6 +507,7 @@ static void tegra_debug_uart_resume(void)static int tegra_suspend_enter (suspend_state_t state) {void __iomem *mc =IO_ADDRESS (TEGRA_MC_BASE ); +void __iomem *emc =IO_ADDRESS (TEGRA_EMC_BASE );unsigned long flags;u32 mc_data[3 ] = {0 ,0 ,0 };bool do_lp0 = (current_suspend_mode ==TEGRA_SUSPEND_LP0 );
@@ -555,6 +560,9 @@ static int tegra_suspend_enter(suspend_state_t state)writel (mc_data[1 ], mc +MC_SECURITY_SIZE );writel (mc_data[2 ], mc +MC_SECURITY_CFG2 ); +/* trigger emc mode write */ +writel (EMC_MRW_DEV_NONE , emc +EMC_MRW_0 ); +tegra_clk_resume ();tegra_gpio_resume ();tegra_timer_resume ();
Signature · 1 line
1.7.3.1
PATCH v2 28/28 ARM: tegra: clock: Add forward reference to struct clk
In reply to Colin Cross--- arch/arm/mach-tegra/include/mach/clk.h | 2 ++ arch/arm/mach-tegra/include/mach/clkdev.h | 2 ++ 2 files changed, 4 insertions(+), 0 deletions(-)
arch/arm/mach-tegra/include/mach/clk.h +2 -0
@@ -20,6 +20,8 @@#ifndef __MACH_CLK_H#define __MACH_CLK_H +struct clk ; +void tegra_periph_reset_deassert (struct clk *c);void tegra_periph_reset_assert (struct clk *c);
arch/arm/mach-tegra/include/mach/clkdev.h +2 -0
@@ -20,6 +20,8 @@#ifndef __MACH_CLKDEV_H#define __MACH_CLKDEV_H +struct clk ; +static inline int __clk_get (struct clk *clk) {return 1 ;
Signature · 1 line
1.7.3.1
Re: [PATCH v2 28/28] ARM: tegra: clock: Add forward reference to struct clk
arch/arm/mach-tegra/include/mach/clkdev.h line 27
Quoted 13 lines · Colin Cross
arch/arm/mach-tegra/include/mach/clkdev.h +2
-0@@ -20,6 +20,8 @@#ifndef __MACH_CLKDEV_H#define __MACH_CLKDEV_H +struct clk ; +static inline int __clk_get (struct clk *clk) {return 1 ;
If you're having to add that, I suspect this include is being inappropriately included by files.
Re: [PATCH v2 28/28] ARM: tegra: clock: Add forward reference to struct clk
Quoted 9 lines · Russell King - ARM Linux
Quoted 8 lines · Colin Cross
arch/arm/mach-tegra/include/mach/clkdev.h +0
-0@@ -20,6 +20,8 @@?#ifndef
__MACH_CLKDEV_H
?#define__MACH_CLKDEV_H
Quoted 9 lines
Quoted 5 lines
arch/arm/mach-tegra/include/mach/clkdev.h +2
-0+struct clk ; +?static inline int
__clk_get(struct clk *clk)
?{
? ? ? return 1;If you're having to add that, I suspect this include is being inappropriately included by files.
The Tegra clock definition file, arch/arm/mach-tegra/tegra2_clocks.c, includes the private clock.h that defines struct clk after including linux/clkdev.h, and does not include linux/clk.h, so the forward declaration is necessary.
Re: [PATCH v2 28/28] ARM: tegra: clock: Add forward reference to struct clk
In reply to Colin CrossQuoted 1 line · Colin Cross
Signed-off-by Colin Cross <[email protected]>
Hi Colin,
This build warning exists in current mainline. It should go out to Linus now instead of waiting for 2.6.29.
g.
Quoted 40 lines
---
?arch/arm/mach-tegra/include/mach/clk.h ? ?| ? ?2 ++ ?arch/arm/mach-tegra/include/mach/clkdev.h | ? ?2 ++ ?2 files changed, 4 insertions(+), 0 deletions(-)arch/arm/mach-tegra/include/mach/clk.h +0
-0@@ -20,6 +20,8 @@?#ifndef
__MACH_CLK_H
?#define__MACH_CLK_Harch/arm/mach-tegra/include/mach/clk.h +2
-0+struct clk ; +?void
tegra_periph_reset_deassert(struct clk *c);
?voidtegra_periph_reset_assert(struct clk *c);arch/arm/mach-tegra/include/mach/clkdev.h +0
-0@@ -20,6 +20,8 @@?#ifndef
__MACH_CLKDEV_H
?#define__MACH_CLKDEV_Harch/arm/mach-tegra/include/mach/clkdev.h +2
-0+struct clk ; +?static inline int
__clk_get(struct clk *clk)
?{
? ? ? ?return 1;
--
1.7.3.1--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html Please read the FAQ at ?http://www.tux.org/lkml/
Signature · 2 lines
Grant Likely, B.Sc., P.Eng. Secret Lab Technologies Ltd.
Re: [PATCH v2 28/28] ARM: tegra: clock: Add forward reference to struct clk
Quoted 38 lines · Grant Likely
Quoted 1 line · Colin Cross
Signed-off-by Colin Cross <[email protected]>Hi Colin,
This build warning exists in current mainline. ?It should go out to Linus now instead of waiting for 2.6.29.
Acked-by Grant Likely <[email protected]>g.
Quoted 26 lines
---
?arch/arm/mach-tegra/include/mach/clk.h ? ?| ? ?2 ++ ?arch/arm/mach-tegra/include/mach/clkdev.h | ? ?2 ++ ?2 files changed, 4 insertions(+), 0 deletions(-)arch/arm/mach-tegra/include/mach/clk.h +0
-0@@ -20,6 +20,8 @@?#ifndef
__MACH_CLK_H
?#define__MACH_CLK_Harch/arm/mach-tegra/include/mach/clk.h +2
-0+struct clk ; +?void
tegra_periph_reset_deassert(struct clk *c);
?voidtegra_periph_reset_assert(struct clk *c);arch/arm/mach-tegra/include/mach/clkdev.h +0
-0@@ -20,6 +20,8 @@?#ifndef
__MACH_CLKDEV_H
?#define__MACH_CLKDEV_H
Quoted 7 lines
Quoted 7 lines
arch/arm/mach-tegra/include/mach/clkdev.h +2
-0+struct clk ; +?static inline int
__clk_get(struct clk *clk)
?{
? ? ? ?return 1;
--
1.7.3.1
It will, I just haven't sent it yet. I have one more patch I'd like to send with it to prevent a possible variable name conflict in 2.6.39.
Re: [PATCH v2 28/28] ARM: tegra: clock: Add forward reference to struct clk
Quoted 9 lines · Colin Cross
Quoted 8 lines · Grant Likely
Quoted 1 line · Colin Cross
Signed-off-by Colin Cross <[email protected]>Hi Colin,
This build warning exists in current mainline. ?It should go out to Linus now instead of waiting for 2.6.29.
Quoted 7 lines
Quoted 3 lines
Acked-by Grant Likely <[email protected]>g.
It will, I just haven't sent it yet. ?I have one more patch I'd like to send with it to prevent a possible variable name conflict in 2.6.39.
Cool, thx.
g.