Linux Audio

Check our new training course

Loading...
v6.2
 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);
v5.14.15
 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);