diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-14 13:05:21 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-14 13:05:21 -0800 |
commit | 4964e0664c80680fa6b28ef91381c076a5b25c2c (patch) | |
tree | 62099c5aaeee7274bcc66bcfba35d479affa97cf /arch/mips/alchemy/common/vss.c | |
parent | 0a80939b3e6af4b0dc93bf88ec02fd7e90a16f1b (diff) | |
parent | 7bf6612e8a9d6a0b3b82e8e2611942be1258b307 (diff) |
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (119 commits)
MIPS: Delete unused function add_temporary_entry.
MIPS: Set default pci cache line size.
MIPS: Flush huge TLB
MIPS: Octeon: Remove SYS_SUPPORTS_HIGHMEM.
MIPS: Octeon: Add support for OCTEON II PCIe
MIPS: Octeon: Update PCI Latency timer and enable more error reporting.
MIPS: Alchemy: Update cpu-feature-overrides
MIPS: Alchemy: db1200: Improve PB1200 detection.
MIPS: Alchemy: merge Au1000 and Au1300-style IRQ controller code.
MIPS: Alchemy: chain IRQ controllers to MIPS IRQ controller
MIPS: Alchemy: irq: register pm at irq init time
MIPS: Alchemy: Touchscreen support on DB1100
MIPS: Alchemy: Hook up IrDA on DB1000/DB1100
net/irda: convert au1k_ir to platform driver.
MIPS: Alchemy: remove unused board headers
MTD: nand: make au1550nd.c a platform_driver
MIPS: Netlogic: Mark Netlogic chips as SMT capable
MIPS: Netlogic: Add support for XLP 3XX cores
MIPS: Netlogic: Merge some of XLR/XLP wakup code
MIPS: Netlogic: Add default XLP config.
...
Fix up trivial conflicts in arch/mips/kernel/{perf_event_mipsxx.c,
traps.c} and drivers/tty/serial/Makefile
Diffstat (limited to 'arch/mips/alchemy/common/vss.c')
-rw-r--r-- | arch/mips/alchemy/common/vss.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/arch/mips/alchemy/common/vss.c b/arch/mips/alchemy/common/vss.c new file mode 100644 index 000000000000..d23b1444d365 --- /dev/null +++ b/arch/mips/alchemy/common/vss.c @@ -0,0 +1,84 @@ +/* + * Au1300 media block power gating (VSS) + * + * This is a stop-gap solution until I have the clock framework integration + * ready. This stuff here really must be handled transparently when clocks + * for various media blocks are enabled/disabled. + */ + +#include <linux/module.h> +#include <linux/spinlock.h> +#include <asm/mach-au1x00/au1000.h> + +#define VSS_GATE 0x00 /* gate wait timers */ +#define VSS_CLKRST 0x04 /* clock/block control */ +#define VSS_FTR 0x08 /* footers */ + +#define VSS_ADDR(blk) (KSEG1ADDR(AU1300_VSS_PHYS_ADDR) + (blk * 0x0c)) + +static DEFINE_SPINLOCK(au1300_vss_lock); + +/* enable a block as outlined in the databook */ +static inline void __enable_block(int block) +{ + void __iomem *base = (void __iomem *)VSS_ADDR(block); + + __raw_writel(3, base + VSS_CLKRST); /* enable clock, assert reset */ + wmb(); + + __raw_writel(0x01fffffe, base + VSS_GATE); /* maximum setup time */ + wmb(); + + /* enable footers in sequence */ + __raw_writel(0x01, base + VSS_FTR); + wmb(); + __raw_writel(0x03, base + VSS_FTR); + wmb(); + __raw_writel(0x07, base + VSS_FTR); + wmb(); + __raw_writel(0x0f, base + VSS_FTR); + wmb(); + + __raw_writel(0x01ffffff, base + VSS_GATE); /* start FSM too */ + wmb(); + + __raw_writel(2, base + VSS_CLKRST); /* deassert reset */ + wmb(); + + __raw_writel(0x1f, base + VSS_FTR); /* enable isolation cells */ + wmb(); +} + +/* disable a block as outlined in the databook */ +static inline void __disable_block(int block) +{ + void __iomem *base = (void __iomem *)VSS_ADDR(block); + + __raw_writel(0x0f, base + VSS_FTR); /* disable isolation cells */ + wmb(); + __raw_writel(0, base + VSS_GATE); /* disable FSM */ + wmb(); + __raw_writel(3, base + VSS_CLKRST); /* assert reset */ + wmb(); + __raw_writel(1, base + VSS_CLKRST); /* disable clock */ + wmb(); + __raw_writel(0, base + VSS_FTR); /* disable all footers */ + wmb(); +} + +void au1300_vss_block_control(int block, int enable) +{ + unsigned long flags; + + if (alchemy_get_cputype() != ALCHEMY_CPU_AU1300) + return; + + /* only one block at a time */ + spin_lock_irqsave(&au1300_vss_lock, flags); + if (enable) + __enable_block(block); + else + __disable_block(block); + spin_unlock_irqrestore(&au1300_vss_lock, flags); +} +EXPORT_SYMBOL_GPL(au1300_vss_block_control); |