Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / mips / alchemy / common / vss.c
1 /*
2  * Au1300 media block power gating (VSS)
3  *
4  * This is a stop-gap solution until I have the clock framework integration
5  * ready. This stuff here really must be handled transparently when clocks
6  * for various media blocks are enabled/disabled.
7  */
8
9 #include <linux/module.h>
10 #include <linux/spinlock.h>
11 #include <asm/mach-au1x00/au1000.h>
12
13 #define VSS_GATE        0x00    /* gate wait timers */
14 #define VSS_CLKRST      0x04    /* clock/block control */
15 #define VSS_FTR         0x08    /* footers */
16
17 #define VSS_ADDR(blk)   (KSEG1ADDR(AU1300_VSS_PHYS_ADDR) + (blk * 0x0c))
18
19 static DEFINE_SPINLOCK(au1300_vss_lock);
20
21 /* enable a block as outlined in the databook */
22 static inline void __enable_block(int block)
23 {
24         void __iomem *base = (void __iomem *)VSS_ADDR(block);
25
26         __raw_writel(3, base + VSS_CLKRST);     /* enable clock, assert reset */
27         wmb();
28
29         __raw_writel(0x01fffffe, base + VSS_GATE); /* maximum setup time */
30         wmb();
31
32         /* enable footers in sequence */
33         __raw_writel(0x01, base + VSS_FTR);
34         wmb();
35         __raw_writel(0x03, base + VSS_FTR);
36         wmb();
37         __raw_writel(0x07, base + VSS_FTR);
38         wmb();
39         __raw_writel(0x0f, base + VSS_FTR);
40         wmb();
41
42         __raw_writel(0x01ffffff, base + VSS_GATE); /* start FSM too */
43         wmb();
44
45         __raw_writel(2, base + VSS_CLKRST);     /* deassert reset */
46         wmb();
47
48         __raw_writel(0x1f, base + VSS_FTR);     /* enable isolation cells */
49         wmb();
50 }
51
52 /* disable a block as outlined in the databook */
53 static inline void __disable_block(int block)
54 {
55         void __iomem *base = (void __iomem *)VSS_ADDR(block);
56
57         __raw_writel(0x0f, base + VSS_FTR);     /* disable isolation cells */
58         wmb();
59         __raw_writel(0, base + VSS_GATE);       /* disable FSM */
60         wmb();
61         __raw_writel(3, base + VSS_CLKRST);     /* assert reset */
62         wmb();
63         __raw_writel(1, base + VSS_CLKRST);     /* disable clock */
64         wmb();
65         __raw_writel(0, base + VSS_FTR);        /* disable all footers */
66         wmb();
67 }
68
69 void au1300_vss_block_control(int block, int enable)
70 {
71         unsigned long flags;
72
73         if (alchemy_get_cputype() != ALCHEMY_CPU_AU1300)
74                 return;
75
76         /* only one block at a time */
77         spin_lock_irqsave(&au1300_vss_lock, flags);
78         if (enable)
79                 __enable_block(block);
80         else
81                 __disable_block(block);
82         spin_unlock_irqrestore(&au1300_vss_lock, flags);
83 }
84 EXPORT_SYMBOL_GPL(au1300_vss_block_control);