1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
From 17589962c1787310e6373478a9fcb7641184cd91 Mon Sep 17 00:00:00 2001
From: Rabeeh Khoury <rabeeh@marvell.com>
Date: Sun, 22 Mar 2009 17:30:32 +0200
Subject: [PATCH] [ARM] Kirkwood: peripherals clock gating for power management
1. Enabling clock gating of unused peripherals
2. PLL and PHY of the units are also disabled (when possible.
Signed-off-by: Rabeeh Khoury <rabeeh@marvell.com>
[ This needs to be revisited to make power handling dynamic and
per device. -- Nico ]
---
arch/arm/mach-kirkwood/common.c | 32 ++++++++++++++++++++++++
arch/arm/mach-kirkwood/common.h | 1 +
arch/arm/mach-kirkwood/include/mach/kirkwood.h | 23 +++++++++++++++++
arch/arm/mach-kirkwood/sheevaplug-setup.c | 2 +
4 files changed, 58 insertions(+), 0 deletions(-)
Index: git/arch/arm/mach-kirkwood/common.c
===================================================================
--- git.orig/arch/arm/mach-kirkwood/common.c
+++ git/arch/arm/mach-kirkwood/common.c
@@ -779,6 +779,38 @@ static void __init kirkwood_l2_init(void
#endif
}
+void __init kirkwood_clock_gate(u32 reg)
+{
+ printk(KERN_INFO "Kirkwood: Gating clock using mask 0x%x\n", reg);
+ /* First make sure that the units are accessible */
+ writel(readl(CLOCK_GATING_CTRL) | reg, CLOCK_GATING_CTRL);
+ /* For SATA first shutdown the phy */
+ if (reg & CGC_SATA0) {
+ /* Disable PLL and IVREF */
+ writel(readl(SATA0_PHY_MODE_2) & ~0xf, SATA0_PHY_MODE_2);
+ /* Disable PHY */
+ writel(readl(SATA0_IF_CTRL) | 0x200, SATA0_IF_CTRL);
+ }
+ if (reg & CGC_SATA1) {
+ /* Disable PLL and IVREF */
+ writel(readl(SATA1_PHY_MODE_2) & ~0xf, SATA1_PHY_MODE_2);
+ /* Disable PHY */
+ writel(readl(SATA1_IF_CTRL) | 0x200, SATA1_IF_CTRL);
+ }
+ /* For PCI-E first shutdown the phy */
+ if (reg & CGC_PEX0) {
+ writel(readl(PCIE_LINK_CTRL) | 0x10, PCIE_LINK_CTRL);
+ while (1) {
+ if (readl(PCIE_STATUS) & 0x1)
+ break;
+ }
+ writel(readl(PCIE_LINK_CTRL) & ~0x10, PCIE_LINK_CTRL);
+ }
+ /* Now gate clock the required units */
+ writel(readl(CLOCK_GATING_CTRL) & ~reg, CLOCK_GATING_CTRL);
+ return;
+}
+
void __init kirkwood_init(void)
{
printk(KERN_INFO "Kirkwood: %s, TCLK=%d.\n",
Index: git/arch/arm/mach-kirkwood/common.h
===================================================================
--- git.orig/arch/arm/mach-kirkwood/common.h
+++ git/arch/arm/mach-kirkwood/common.h
@@ -22,6 +22,7 @@ struct mvsdio_platform_data;
void kirkwood_map_io(void);
void kirkwood_init(void);
void kirkwood_init_irq(void);
+void __init kirkwood_clock_gate(u32 reg);
extern struct mbus_dram_target_info kirkwood_mbus_dram_info;
void kirkwood_setup_cpu_mbus(void);
Index: git/arch/arm/mach-kirkwood/include/mach/kirkwood.h
===================================================================
--- git.orig/arch/arm/mach-kirkwood/include/mach/kirkwood.h
+++ git/arch/arm/mach-kirkwood/include/mach/kirkwood.h
@@ -65,6 +65,8 @@
#define BRIDGE_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x20000)
#define PCIE_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x40000)
+#define PCIE_LINK_CTRL (PCIE_VIRT_BASE | 0x70)
+#define PCIE_STATUS (PCIE_VIRT_BASE | 0x1a04)
#define USB_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x50000)
@@ -81,9 +83,30 @@
#define GE01_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x74000)
#define SATA_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x80000)
+#define SATA_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x80000)
+#define SATA0_IF_CTRL (SATA_VIRT_BASE | 0x2050)
+#define SATA0_PHY_MODE_2 (SATA_VIRT_BASE | 0x2330)
+#define SATA1_IF_CTRL (SATA_VIRT_BASE | 0x4050)
+#define SATA1_PHY_MODE_2 (SATA_VIRT_BASE | 0x4330)
#define SDIO_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x90000)
+#define CLOCK_GATING_CTRL (BRIDGE_VIRT_BASE | 0x11c)
+#define CGC_GE0 0x1
+#define CGC_PEX0 0x4
+#define CGC_USB0 0x8
+#define CGC_SDIO 0x10
+#define CGC_TSU 0x20
+#define CGC_NAND_SPI 0x80
+#define CGC_XOR0 0x100
+#define CGC_AUDIO 0x200
+#define CGC_SATA0 0x4000
+#define CGC_SATA1 0x8000
+#define CGC_XOR1 0x10000
+#define CGC_CRYPTO 0x20000
+#define CGC_GE1 0x80000
+#define CGC_TDM 0x100000
+
/*
* Supported devices and revisions.
*/
Index: git/arch/arm/mach-kirkwood/sheevaplug-setup.c
===================================================================
--- git.orig/arch/arm/mach-kirkwood/sheevaplug-setup.c
+++ git/arch/arm/mach-kirkwood/sheevaplug-setup.c
@@ -122,6 +122,8 @@ static void __init sheevaplug_init(void)
platform_device_register(&sheevaplug_nand_flash);
platform_device_register(&sheevaplug_leds);
+ kirkwood_clock_gate(CGC_PEX0 | CGC_TSU | CGC_AUDIO | CGC_SATA0 |\
+ CGC_SATA1 | CGC_CRYPTO | CGC_GE1 | CGC_TDM);
}
MACHINE_START(SHEEVAPLUG, "Marvell SheevaPlug Reference Board")
|