aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-kirkwood/common.c
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 /arch/arm/mach-kirkwood/common.c
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>
Diffstat (limited to 'arch/arm/mach-kirkwood/common.c')
-rw-r--r--arch/arm/mach-kirkwood/common.c59
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 */
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);