Linux Audio

Check our new training course

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