aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRabeeh Khoury <rabeeh@marvell.com>2009-03-22 11:30:32 -0400
committerNicolas Pitre <nico@cam.org>2009-06-08 13:04:58 -0400
commite8b2b7ba1200de8e50788e358e2d945a0c0fcfad (patch)
treedb48240d16d267bca6b740fe401406f9838410e3
parentfb7b2d3f0dda3fbd711c191fd3b9496653e81ac7 (diff)
[ARM] Kirkwood: clock gating for unused peripherals
To save power: 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> Signed-off-by: Nicolas Pitre <nico@marvell.com>
-rw-r--r--arch/arm/mach-kirkwood/common.c59
-rw-r--r--arch/arm/mach-kirkwood/include/mach/bridge-regs.h18
-rw-r--r--arch/arm/mach-kirkwood/include/mach/kirkwood.h7
-rw-r--r--arch/arm/mach-kirkwood/pcie.c4
4 files changed, 88 insertions, 0 deletions
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index 6e3eb1a6a660..d127731f47dc 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -55,6 +55,13 @@ void __init kirkwood_map_io(void)
55 iotable_init(kirkwood_io_desc, ARRAY_SIZE(kirkwood_io_desc)); 55 iotable_init(kirkwood_io_desc, ARRAY_SIZE(kirkwood_io_desc));
56} 56}
57 57
58/*
59 * Default clock control bits. Any bit _not_ set in this variable
60 * will be cleared from the hardware after platform devices have been
61 * registered. Some reserved bits must be set to 1.
62 */
63unsigned int kirkwood_clk_ctrl = CGC_DUNIT | CGC_RESERVED;
64
58 65
59/***************************************************************************** 66/*****************************************************************************
60 * EHCI 67 * EHCI
@@ -96,6 +103,7 @@ static struct platform_device kirkwood_ehci = {
96 103
97void __init kirkwood_ehci_init(void) 104void __init kirkwood_ehci_init(void)
98{ 105{
106 kirkwood_clk_ctrl |= CGC_USB0;
99 platform_device_register(&kirkwood_ehci); 107 platform_device_register(&kirkwood_ehci);
100} 108}
101 109
@@ -152,6 +160,7 @@ static struct platform_device kirkwood_ge00 = {
152 160
153void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data) 161void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data)
154{ 162{
163 kirkwood_clk_ctrl |= CGC_GE0;
155 eth_data->shared = &kirkwood_ge00_shared; 164 eth_data->shared = &kirkwood_ge00_shared;
156 kirkwood_ge00.dev.platform_data = eth_data; 165 kirkwood_ge00.dev.platform_data = eth_data;
157 166
@@ -213,6 +222,7 @@ static struct platform_device kirkwood_ge01 = {
213 222
214void __init kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data) 223void __init kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data)
215{ 224{
225 kirkwood_clk_ctrl |= CGC_GE1;
216 eth_data->shared = &kirkwood_ge01_shared; 226 eth_data->shared = &kirkwood_ge01_shared;
217 kirkwood_ge01.dev.platform_data = eth_data; 227 kirkwood_ge01.dev.platform_data = eth_data;
218 228
@@ -287,6 +297,7 @@ static struct platform_device kirkwood_nand_flash = {
287void __init kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, 297void __init kirkwood_nand_init(struct mtd_partition *parts, int nr_parts,
288 int chip_delay) 298 int chip_delay)
289{ 299{
300 kirkwood_clk_ctrl |= CGC_RUNIT;
290 kirkwood_nand_data.parts = parts; 301 kirkwood_nand_data.parts = parts;
291 kirkwood_nand_data.nr_parts = nr_parts; 302 kirkwood_nand_data.nr_parts = nr_parts;
292 kirkwood_nand_data.chip_delay = chip_delay; 303 kirkwood_nand_data.chip_delay = chip_delay;
@@ -338,6 +349,9 @@ static struct platform_device kirkwood_sata = {
338 349
339void __init kirkwood_sata_init(struct mv_sata_platform_data *sata_data) 350void __init kirkwood_sata_init(struct mv_sata_platform_data *sata_data)
340{ 351{
352 kirkwood_clk_ctrl |= CGC_SATA0;
353 if (sata_data->n_ports > 1)
354 kirkwood_clk_ctrl |= CGC_SATA1;
341 sata_data->dram = &kirkwood_mbus_dram_info; 355 sata_data->dram = &kirkwood_mbus_dram_info;
342 kirkwood_sata.dev.platform_data = sata_data; 356 kirkwood_sata.dev.platform_data = sata_data;
343 platform_device_register(&kirkwood_sata); 357 platform_device_register(&kirkwood_sata);
@@ -383,6 +397,7 @@ void __init kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data)
383 else 397 else
384 mvsdio_data->clock = 200000000; 398 mvsdio_data->clock = 200000000;
385 mvsdio_data->dram = &kirkwood_mbus_dram_info; 399 mvsdio_data->dram = &kirkwood_mbus_dram_info;
400 kirkwood_clk_ctrl |= CGC_SDIO;
386 kirkwood_sdio.dev.platform_data = mvsdio_data; 401 kirkwood_sdio.dev.platform_data = mvsdio_data;
387 platform_device_register(&kirkwood_sdio); 402 platform_device_register(&kirkwood_sdio);
388} 403}
@@ -414,6 +429,7 @@ static struct platform_device kirkwood_spi = {
414 429
415void __init kirkwood_spi_init() 430void __init kirkwood_spi_init()
416{ 431{
432 kirkwood_clk_ctrl |= CGC_RUNIT;
417 platform_device_register(&kirkwood_spi); 433 platform_device_register(&kirkwood_spi);
418} 434}
419 435
@@ -634,6 +650,7 @@ static struct platform_device kirkwood_xor01_channel = {
634 650
635static void __init kirkwood_xor0_init(void) 651static void __init kirkwood_xor0_init(void)
636{ 652{
653 kirkwood_clk_ctrl |= CGC_XOR0;
637 platform_device_register(&kirkwood_xor0_shared); 654 platform_device_register(&kirkwood_xor0_shared);
638 655
639 /* 656 /*
@@ -732,6 +749,7 @@ static struct platform_device kirkwood_xor11_channel = {
732 749
733static void __init kirkwood_xor1_init(void) 750static void __init kirkwood_xor1_init(void)
734{ 751{
752 kirkwood_clk_ctrl |= CGC_XOR1;
735 platform_device_register(&kirkwood_xor1_shared); 753 platform_device_register(&kirkwood_xor1_shared);
736 754
737 /* 755 /*
@@ -844,3 +862,44 @@ void __init kirkwood_init(void)
844 kirkwood_xor0_init(); 862 kirkwood_xor0_init();
845 kirkwood_xor1_init(); 863 kirkwood_xor1_init();
846} 864}
865
866static int __init kirkwood_clock_gate(void)
867{
868 unsigned int curr = readl(CLOCK_GATING_CTRL);
869
870 printk(KERN_DEBUG "Gating clock of unused units\n");
871 printk(KERN_DEBUG "before: 0x%08x\n", curr);
872
873 /* Make sure those units are accessible */
874 writel(curr | CGC_SATA0 | CGC_SATA1 | CGC_PEX0, CLOCK_GATING_CTRL);
875
876 /* For SATA: first shutdown the phy */
877 if (!(kirkwood_clk_ctrl & CGC_SATA0)) {
878 /* Disable PLL and IVREF */
879 writel(readl(SATA0_PHY_MODE_2) & ~0xf, SATA0_PHY_MODE_2);
880 /* Disable PHY */
881 writel(readl(SATA0_IF_CTRL) | 0x200, SATA0_IF_CTRL);
882 }
883 if (!(kirkwood_clk_ctrl & CGC_SATA1)) {
884 /* Disable PLL and IVREF */
885 writel(readl(SATA1_PHY_MODE_2) & ~0xf, SATA1_PHY_MODE_2);
886 /* Disable PHY */
887 writel(readl(SATA1_IF_CTRL) | 0x200, SATA1_IF_CTRL);
888 }
889
890 /* For PCIe: first shutdown the phy */
891 if (!(kirkwood_clk_ctrl & CGC_PEX0)) {
892 writel(readl(PCIE_LINK_CTRL) | 0x10, PCIE_LINK_CTRL);
893 while (1)
894 if (readl(PCIE_STATUS) & 0x1)
895 break;
896 writel(readl(PCIE_LINK_CTRL) & ~0x10, PCIE_LINK_CTRL);
897 }
898
899 /* Now gate clock the required units */
900 writel(kirkwood_clk_ctrl, CLOCK_GATING_CTRL);
901 printk(KERN_DEBUG " after: 0x%08x\n", readl(CLOCK_GATING_CTRL));
902
903 return 0;
904}
905late_initcall(kirkwood_clock_gate);
diff --git a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
index 4f7029f521cc..00d96abb718c 100644
--- a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
+++ b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
@@ -39,4 +39,22 @@
39#define L2_CONFIG_REG (BRIDGE_VIRT_BASE | 0x0128) 39#define L2_CONFIG_REG (BRIDGE_VIRT_BASE | 0x0128)
40#define L2_WRITETHROUGH 0x00000010 40#define L2_WRITETHROUGH 0x00000010
41 41
42#define CLOCK_GATING_CTRL (BRIDGE_VIRT_BASE | 0x11c)
43#define CGC_GE0 (1 << 0)
44#define CGC_PEX0 (1 << 2)
45#define CGC_USB0 (1 << 3)
46#define CGC_SDIO (1 << 4)
47#define CGC_TSU (1 << 5)
48#define CGC_DUNIT (1 << 6)
49#define CGC_RUNIT (1 << 7)
50#define CGC_XOR0 (1 << 8)
51#define CGC_AUDIO (1 << 9)
52#define CGC_SATA0 (1 << 14)
53#define CGC_SATA1 (1 << 15)
54#define CGC_XOR1 (1 << 16)
55#define CGC_CRYPTO (1 << 17)
56#define CGC_GE1 (1 << 19)
57#define CGC_TDM (1 << 20)
58#define CGC_RESERVED ((1 << 18) | (0x6 << 21))
59
42#endif 60#endif
diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
index f20ff6460485..f49a29bf3369 100644
--- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h
+++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
@@ -65,6 +65,8 @@
65#define BRIDGE_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x20000) 65#define BRIDGE_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x20000)
66 66
67#define PCIE_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x40000) 67#define PCIE_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x40000)
68#define PCIE_LINK_CTRL (PCIE_VIRT_BASE | 0x70)
69#define PCIE_STATUS (PCIE_VIRT_BASE | 0x1a04)
68 70
69#define USB_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x50000) 71#define USB_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x50000)
70 72
@@ -81,6 +83,11 @@
81#define GE01_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x74000) 83#define GE01_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x74000)
82 84
83#define SATA_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x80000) 85#define SATA_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x80000)
86#define SATA_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x80000)
87#define SATA0_IF_CTRL (SATA_VIRT_BASE | 0x2050)
88#define SATA0_PHY_MODE_2 (SATA_VIRT_BASE | 0x2330)
89#define SATA1_IF_CTRL (SATA_VIRT_BASE | 0x4050)
90#define SATA1_PHY_MODE_2 (SATA_VIRT_BASE | 0x4330)
84 91
85#define SDIO_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x90000) 92#define SDIO_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x90000)
86 93
diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c
index 73fccacd1a73..d90b9aae308d 100644
--- a/arch/arm/mach-kirkwood/pcie.c
+++ b/arch/arm/mach-kirkwood/pcie.c
@@ -14,6 +14,7 @@
14#include <asm/irq.h> 14#include <asm/irq.h>
15#include <asm/mach/pci.h> 15#include <asm/mach/pci.h>
16#include <plat/pcie.h> 16#include <plat/pcie.h>
17#include <mach/bridge-regs.h>
17#include "common.h" 18#include "common.h"
18 19
19 20
@@ -95,6 +96,7 @@ static struct pci_ops pcie_ops = {
95static int kirkwood_pcie_setup(int nr, struct pci_sys_data *sys) 96static int kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
96{ 97{
97 struct resource *res; 98 struct resource *res;
99 extern unsigned int kirkwood_clk_ctrl;
98 100
99 /* 101 /*
100 * Generic PCIe unit setup. 102 * Generic PCIe unit setup.
@@ -133,6 +135,8 @@ static int kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
133 sys->resource[2] = NULL; 135 sys->resource[2] = NULL;
134 sys->io_offset = 0; 136 sys->io_offset = 0;
135 137
138 kirkwood_clk_ctrl |= CGC_PEX0;
139
136 return 1; 140 return 1;
137} 141}
138 142