diff options
author | Rabeeh Khoury <rabeeh@marvell.com> | 2009-03-22 11:30:32 -0400 |
---|---|---|
committer | Nicolas Pitre <nico@cam.org> | 2009-06-08 13:04:58 -0400 |
commit | e8b2b7ba1200de8e50788e358e2d945a0c0fcfad (patch) | |
tree | db48240d16d267bca6b740fe401406f9838410e3 /arch/arm/mach-kirkwood | |
parent | fb7b2d3f0dda3fbd711c191fd3b9496653e81ac7 (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>
Diffstat (limited to 'arch/arm/mach-kirkwood')
-rw-r--r-- | arch/arm/mach-kirkwood/common.c | 59 | ||||
-rw-r--r-- | arch/arm/mach-kirkwood/include/mach/bridge-regs.h | 18 | ||||
-rw-r--r-- | arch/arm/mach-kirkwood/include/mach/kirkwood.h | 7 | ||||
-rw-r--r-- | arch/arm/mach-kirkwood/pcie.c | 4 |
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 | */ | ||
63 | unsigned 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 | ||
97 | void __init kirkwood_ehci_init(void) | 104 | void __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 | ||
153 | void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data) | 161 | void __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 | ||
214 | void __init kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data) | 223 | void __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 = { | |||
287 | void __init kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, | 297 | void __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 | ||
339 | void __init kirkwood_sata_init(struct mv_sata_platform_data *sata_data) | 350 | void __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 | ||
415 | void __init kirkwood_spi_init() | 430 | void __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 | ||
635 | static void __init kirkwood_xor0_init(void) | 651 | static 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 | ||
733 | static void __init kirkwood_xor1_init(void) | 750 | static 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 | |||
866 | static 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 | } | ||
905 | late_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 = { | |||
95 | static int kirkwood_pcie_setup(int nr, struct pci_sys_data *sys) | 96 | static 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 | ||