From 3810735161567141dd49dc93183ca573e461be1d Mon Sep 17 00:00:00 2001 From: Martin Michlmayr Date: Wed, 3 Jun 2009 21:15:30 +0000 Subject: [PATCH] Kirkwood: clock gating for unused peripherals svn path=/dists/trunk/linux-2.6/; revision=13723 --- debian/changelog | 1 + .../patches/features/arm/clock_gating.patch | 236 +++++++++++++ debian/patches/features/arm/nand-setup.patch | 313 ++++++++++++++++++ debian/patches/series/base | 2 + 4 files changed, 552 insertions(+) create mode 100644 debian/patches/features/arm/clock_gating.patch create mode 100644 debian/patches/features/arm/nand-setup.patch diff --git a/debian/changelog b/debian/changelog index 5a7c75725..e9fae0e92 100644 --- a/debian/changelog +++ b/debian/changelog @@ -48,6 +48,7 @@ linux-2.6 (2.6.30~rc8-1~experimental.1) UNRELEASED; urgency=low - alternative copy_to_user: more precise fallback threshold - lower overhead with alternative copy_to_user for small copies - Kirkwood: Add CPU idle driver + - Kirkwood: clock gating for unused peripherals [ Aurelien Jarno ] * [mips(el)/sb1-bcm91250a] Set CONFIG_SCSI_AIC7XXX=y, it is needed diff --git a/debian/patches/features/arm/clock_gating.patch b/debian/patches/features/arm/clock_gating.patch new file mode 100644 index 000000000..a1aea9a56 --- /dev/null +++ b/debian/patches/features/arm/clock_gating.patch @@ -0,0 +1,236 @@ +From: Rabeeh Khoury +Date: Sun, 22 Mar 2009 15:30:32 +0000 (+0200) +Subject: [ARM] Kirkwood: clock gating for unused peripherals +X-Git-Url: +http://git.marvell.com/?p=orion.git;a=commitdiff_plain;h=80d8a1c2acd885a69259640fa6d789b714c9f7b9 + +[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 +Signed-off-by: Nicolas Pitre +--- + +diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c +index 6e3eb1a..d127731 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) + iotable_init(kirkwood_io_desc, ARRAY_SIZE(kirkwood_io_desc)); + } + ++/* ++ * Default clock control bits. Any bit _not_ set in this variable ++ * will be cleared from the hardware after platform devices have been ++ * registered. Some reserved bits must be set to 1. ++ */ ++unsigned int kirkwood_clk_ctrl = CGC_DUNIT | CGC_RESERVED; ++ + + /***************************************************************************** + * EHCI +@@ -96,6 +103,7 @@ static struct platform_device kirkwood_ehci = { + + void __init kirkwood_ehci_init(void) + { ++ kirkwood_clk_ctrl |= CGC_USB0; + platform_device_register(&kirkwood_ehci); + } + +@@ -152,6 +160,7 @@ static struct platform_device kirkwood_ge00 = { + + void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data) + { ++ kirkwood_clk_ctrl |= CGC_GE0; + eth_data->shared = &kirkwood_ge00_shared; + kirkwood_ge00.dev.platform_data = eth_data; + +@@ -213,6 +222,7 @@ static struct platform_device kirkwood_ge01 = { + + void __init kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data) + { ++ kirkwood_clk_ctrl |= CGC_GE1; + eth_data->shared = &kirkwood_ge01_shared; + kirkwood_ge01.dev.platform_data = eth_data; + +@@ -287,6 +297,7 @@ static struct platform_device kirkwood_nand_flash = { + void __init kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, + int chip_delay) + { ++ kirkwood_clk_ctrl |= CGC_RUNIT; + kirkwood_nand_data.parts = parts; + kirkwood_nand_data.nr_parts = nr_parts; + kirkwood_nand_data.chip_delay = chip_delay; +@@ -338,6 +349,9 @@ static struct platform_device kirkwood_sata = { + + void __init kirkwood_sata_init(struct mv_sata_platform_data *sata_data) + { ++ kirkwood_clk_ctrl |= CGC_SATA0; ++ if (sata_data->n_ports > 1) ++ kirkwood_clk_ctrl |= CGC_SATA1; + sata_data->dram = &kirkwood_mbus_dram_info; + kirkwood_sata.dev.platform_data = sata_data; + platform_device_register(&kirkwood_sata); +@@ -383,6 +397,7 @@ void __init kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data) + else + mvsdio_data->clock = 200000000; + mvsdio_data->dram = &kirkwood_mbus_dram_info; ++ kirkwood_clk_ctrl |= CGC_SDIO; + kirkwood_sdio.dev.platform_data = mvsdio_data; + platform_device_register(&kirkwood_sdio); + } +@@ -414,6 +429,7 @@ static struct platform_device kirkwood_spi = { + + void __init kirkwood_spi_init() + { ++ kirkwood_clk_ctrl |= CGC_RUNIT; + platform_device_register(&kirkwood_spi); + } + +@@ -634,6 +650,7 @@ static struct platform_device kirkwood_xor01_channel = { + + static void __init kirkwood_xor0_init(void) + { ++ kirkwood_clk_ctrl |= CGC_XOR0; + platform_device_register(&kirkwood_xor0_shared); + + /* +@@ -732,6 +749,7 @@ static struct platform_device kirkwood_xor11_channel = { + + static void __init kirkwood_xor1_init(void) + { ++ kirkwood_clk_ctrl |= CGC_XOR1; + platform_device_register(&kirkwood_xor1_shared); + + /* +@@ -844,3 +862,44 @@ void __init kirkwood_init(void) + kirkwood_xor0_init(); + kirkwood_xor1_init(); + } ++ ++static int __init kirkwood_clock_gate(void) ++{ ++ unsigned int curr = readl(CLOCK_GATING_CTRL); ++ ++ printk(KERN_DEBUG "Gating clock of unused units\n"); ++ printk(KERN_DEBUG "before: 0x%08x\n", curr); ++ ++ /* Make sure those units are accessible */ ++ writel(curr | CGC_SATA0 | CGC_SATA1 | CGC_PEX0, CLOCK_GATING_CTRL); ++ ++ /* For SATA: first shutdown the phy */ ++ if (!(kirkwood_clk_ctrl & 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 (!(kirkwood_clk_ctrl & 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 PCIe: first shutdown the phy */ ++ if (!(kirkwood_clk_ctrl & 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(kirkwood_clk_ctrl, CLOCK_GATING_CTRL); ++ printk(KERN_DEBUG " after: 0x%08x\n", readl(CLOCK_GATING_CTRL)); ++ ++ return 0; ++} ++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 4f7029f..00d96ab 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 @@ + #define L2_CONFIG_REG (BRIDGE_VIRT_BASE | 0x0128) + #define L2_WRITETHROUGH 0x00000010 + ++#define CLOCK_GATING_CTRL (BRIDGE_VIRT_BASE | 0x11c) ++#define CGC_GE0 (1 << 0) ++#define CGC_PEX0 (1 << 2) ++#define CGC_USB0 (1 << 3) ++#define CGC_SDIO (1 << 4) ++#define CGC_TSU (1 << 5) ++#define CGC_DUNIT (1 << 6) ++#define CGC_RUNIT (1 << 7) ++#define CGC_XOR0 (1 << 8) ++#define CGC_AUDIO (1 << 9) ++#define CGC_SATA0 (1 << 14) ++#define CGC_SATA1 (1 << 15) ++#define CGC_XOR1 (1 << 16) ++#define CGC_CRYPTO (1 << 17) ++#define CGC_GE1 (1 << 19) ++#define CGC_TDM (1 << 20) ++#define CGC_RESERVED ((1 << 18) | (0x6 << 21)) ++ + #endif +diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h +index b3e1395..fa87ce6 100644 +--- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h ++++ b/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,6 +83,11 @@ + #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) + +diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c +index 73fccac..d90b9aa 100644 +--- a/arch/arm/mach-kirkwood/pcie.c ++++ b/arch/arm/mach-kirkwood/pcie.c +@@ -14,6 +14,7 @@ + #include + #include + #include ++#include + #include "common.h" + + +@@ -95,6 +96,7 @@ static struct pci_ops pcie_ops = { + static int kirkwood_pcie_setup(int nr, struct pci_sys_data *sys) + { + struct resource *res; ++ extern unsigned int kirkwood_clk_ctrl; + + /* + * Generic PCIe unit setup. +@@ -133,6 +135,8 @@ static int kirkwood_pcie_setup(int nr, struct pci_sys_data *sys) + sys->resource[2] = NULL; + sys->io_offset = 0; + ++ kirkwood_clk_ctrl |= CGC_PEX0; ++ + return 1; + } + diff --git a/debian/patches/features/arm/nand-setup.patch b/debian/patches/features/arm/nand-setup.patch new file mode 100644 index 000000000..5e832567e --- /dev/null +++ b/debian/patches/features/arm/nand-setup.patch @@ -0,0 +1,313 @@ +From: Nicolas Pitre +Date: Mon, 1 Jun 2009 19:36:36 +0000 (-0400) +Subject: [ARM] Kirkwood: rationalize NAND setup a bit +X-Git-Url: +http://git.marvell.com/?p=orion.git;a=commitdiff_plain;h=3ac7b8d83d92c33647ce21f655931b5cabbcbfd7 + +[ARM] Kirkwood: rationalize NAND setup a bit + +Common resource and platform device structures are moved to common.c +and only the partition table and chip delay remains a per board +parameter. + +Signed-off-by: Nicolas Pitre +--- + +diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c +index be1ca28..6e3eb1a 100644 +--- a/arch/arm/mach-kirkwood/common.c ++++ b/arch/arm/mach-kirkwood/common.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -258,6 +259,42 @@ void __init kirkwood_ge00_switch_init(struct dsa_platform_data *d, int irq) + + + /***************************************************************************** ++ * NAND flash ++ ****************************************************************************/ ++static struct resource kirkwood_nand_resource = { ++ .flags = IORESOURCE_MEM, ++ .start = KIRKWOOD_NAND_MEM_PHYS_BASE, ++ .end = KIRKWOOD_NAND_MEM_PHYS_BASE + ++ KIRKWOOD_NAND_MEM_SIZE - 1, ++}; ++ ++static struct orion_nand_data kirkwood_nand_data = { ++ .cle = 0, ++ .ale = 1, ++ .width = 8, ++}; ++ ++static struct platform_device kirkwood_nand_flash = { ++ .name = "orion_nand", ++ .id = -1, ++ .dev = { ++ .platform_data = &kirkwood_nand_data, ++ }, ++ .resource = &kirkwood_nand_resource, ++ .num_resources = 1, ++}; ++ ++void __init kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, ++ int chip_delay) ++{ ++ kirkwood_nand_data.parts = parts; ++ kirkwood_nand_data.nr_parts = nr_parts; ++ kirkwood_nand_data.chip_delay = chip_delay; ++ platform_device_register(&kirkwood_nand_flash); ++} ++ ++ ++/***************************************************************************** + * SoC RTC + ****************************************************************************/ + static struct resource kirkwood_rtc_resource = { +diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h +index 6ee8840..9de5256 100644 +--- a/arch/arm/mach-kirkwood/common.h ++++ b/arch/arm/mach-kirkwood/common.h +@@ -15,6 +15,7 @@ struct dsa_platform_data; + struct mv643xx_eth_platform_data; + struct mv_sata_platform_data; + struct mvsdio_platform_data; ++struct mtd_partition; + + /* + * Basic Kirkwood init functions used early by machine-setup. +@@ -40,9 +41,11 @@ void kirkwood_spi_init(void); + void kirkwood_i2c_init(void); + void kirkwood_uart0_init(void); + void kirkwood_uart1_init(void); ++void kirkwood_nand_init(struct mtd_partition *parts, int nr_parts, int delay); + + extern int kirkwood_tclk; + extern struct sys_timer kirkwood_timer; + ++#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) + + #endif +diff --git a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c +index 5505d58..39bdf4b 100644 +--- a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c ++++ b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c +@@ -11,14 +11,12 @@ + #include + #include + #include +-#include + #include + #include + #include + #include + #include + #include +-#include + #include + #include "common.h" + #include "mpp.h" +@@ -39,32 +37,6 @@ static struct mtd_partition db88f6281_nand_parts[] = { + }, + }; + +-static struct resource db88f6281_nand_resource = { +- .flags = IORESOURCE_MEM, +- .start = KIRKWOOD_NAND_MEM_PHYS_BASE, +- .end = KIRKWOOD_NAND_MEM_PHYS_BASE + +- KIRKWOOD_NAND_MEM_SIZE - 1, +-}; +- +-static struct orion_nand_data db88f6281_nand_data = { +- .parts = db88f6281_nand_parts, +- .nr_parts = ARRAY_SIZE(db88f6281_nand_parts), +- .cle = 0, +- .ale = 1, +- .width = 8, +- .chip_delay = 25, +-}; +- +-static struct platform_device db88f6281_nand_flash = { +- .name = "orion_nand", +- .id = -1, +- .dev = { +- .platform_data = &db88f6281_nand_data, +- }, +- .resource = &db88f6281_nand_resource, +- .num_resources = 1, +-}; +- + static struct mv643xx_eth_platform_data db88f6281_ge00_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(8), + }; +@@ -92,13 +64,12 @@ static void __init db88f6281_init(void) + kirkwood_init(); + kirkwood_mpp_conf(db88f6281_mpp_config); + ++ kirkwood_nand_init(ARRAY_AND_SIZE(db88f6281_nand_parts), 25); + kirkwood_ehci_init(); + kirkwood_ge00_init(&db88f6281_ge00_data); + kirkwood_sata_init(&db88f6281_sata_data); + kirkwood_uart0_init(); + kirkwood_sdio_init(&db88f6281_mvsdio_data); +- +- platform_device_register(&db88f6281_nand_flash); + } + + static int __init db88f6281_pci_init(void) +diff --git a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c +index 2f0e4ef..8bf4153 100644 +--- a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c ++++ b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c +@@ -11,8 +11,6 @@ + #include + #include + #include +-#include +-#include + #include + #include + #include +diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c +index 31e996d..31708dd 100644 +--- a/arch/arm/mach-kirkwood/rd88f6281-setup.c ++++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c +@@ -12,7 +12,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -22,7 +21,6 @@ + #include + #include + #include +-#include + #include "common.h" + #include "mpp.h" + +@@ -42,32 +40,6 @@ static struct mtd_partition rd88f6281_nand_parts[] = { + }, + }; + +-static struct resource rd88f6281_nand_resource = { +- .flags = IORESOURCE_MEM, +- .start = KIRKWOOD_NAND_MEM_PHYS_BASE, +- .end = KIRKWOOD_NAND_MEM_PHYS_BASE + +- KIRKWOOD_NAND_MEM_SIZE - 1, +-}; +- +-static struct orion_nand_data rd88f6281_nand_data = { +- .parts = rd88f6281_nand_parts, +- .nr_parts = ARRAY_SIZE(rd88f6281_nand_parts), +- .cle = 0, +- .ale = 1, +- .width = 8, +- .chip_delay = 25, +-}; +- +-static struct platform_device rd88f6281_nand_flash = { +- .name = "orion_nand", +- .id = -1, +- .dev = { +- .platform_data = &rd88f6281_nand_data, +- }, +- .resource = &rd88f6281_nand_resource, +- .num_resources = 1, +-}; +- + static struct mv643xx_eth_platform_data rd88f6281_ge00_data = { + .phy_addr = MV643XX_ETH_PHY_NONE, + .speed = SPEED_1000, +@@ -114,6 +86,7 @@ static void __init rd88f6281_init(void) + kirkwood_init(); + kirkwood_mpp_conf(rd88f6281_mpp_config); + ++ kirkwood_nand_init(ARRAY_AND_SIZE(rd88f6281_nand_parts), 25); + kirkwood_ehci_init(); + + kirkwood_ge00_init(&rd88f6281_ge00_data); +@@ -129,8 +102,6 @@ static void __init rd88f6281_init(void) + kirkwood_sata_init(&rd88f6281_sata_data); + kirkwood_sdio_init(&rd88f6281_mvsdio_data); + kirkwood_uart0_init(); +- +- platform_device_register(&rd88f6281_nand_flash); + } + + static int __init rd88f6281_pci_init(void) +diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c +index 831e4a5..93ea64c 100644 +--- a/arch/arm/mach-kirkwood/sheevaplug-setup.c ++++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c +@@ -11,7 +11,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -20,7 +19,6 @@ + #include + #include + #include +-#include + #include "common.h" + #include "mpp.h" + +@@ -40,32 +38,6 @@ static struct mtd_partition sheevaplug_nand_parts[] = { + }, + }; + +-static struct resource sheevaplug_nand_resource = { +- .flags = IORESOURCE_MEM, +- .start = KIRKWOOD_NAND_MEM_PHYS_BASE, +- .end = KIRKWOOD_NAND_MEM_PHYS_BASE + +- KIRKWOOD_NAND_MEM_SIZE - 1, +-}; +- +-static struct orion_nand_data sheevaplug_nand_data = { +- .parts = sheevaplug_nand_parts, +- .nr_parts = ARRAY_SIZE(sheevaplug_nand_parts), +- .cle = 0, +- .ale = 1, +- .width = 8, +- .chip_delay = 25, +-}; +- +-static struct platform_device sheevaplug_nand_flash = { +- .name = "orion_nand", +- .id = -1, +- .dev = { +- .platform_data = &sheevaplug_nand_data, +- }, +- .resource = &sheevaplug_nand_resource, +- .num_resources = 1, +-}; +- + static struct mv643xx_eth_platform_data sheevaplug_ge00_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(0), + }; +@@ -111,6 +83,7 @@ static void __init sheevaplug_init(void) + kirkwood_mpp_conf(sheevaplug_mpp_config); + + kirkwood_uart0_init(); ++ kirkwood_nand_init(ARRAY_AND_SIZE(sheevaplug_nand_parts), 25); + + if (gpio_request(29, "USB Power Enable") != 0 || + gpio_direction_output(29, 1) != 0) +@@ -120,7 +93,6 @@ static void __init sheevaplug_init(void) + kirkwood_ge00_init(&sheevaplug_ge00_data); + kirkwood_sdio_init(&sheevaplug_mvsdio_data); + +- platform_device_register(&sheevaplug_nand_flash); + platform_device_register(&sheevaplug_leds); + } + diff --git a/debian/patches/series/base b/debian/patches/series/base index 4e44051a2..b037afe4c 100644 --- a/debian/patches/series/base +++ b/debian/patches/series/base @@ -29,6 +29,8 @@ + features/arm/alternative-copy-user.patch + features/arm/lower_overhead_with_alternative.patch + features/arm/copy_to_user-better_threshold.patch ++ features/arm/nand-setup.patch ++ features/arm/clock_gating.patch + bugfix/all/mvsdio-platform.patch + bugfix/all/mvsdio-ignore-high-speed.patch + bugfix/all/mvsdio-config-failure.patch