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/common.c | |
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/common.c')
-rw-r--r-- | arch/arm/mach-kirkwood/common.c | 59 |
1 files changed, 59 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); | ||