diff options
author | Olof Johansson <olof@lixom.net> | 2014-11-08 16:51:39 -0800 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2014-11-08 16:51:39 -0800 |
commit | 85b80b6bfdbdab3f489857dd850dad5a65e49895 (patch) | |
tree | 53519a62e13eeef800c0d1f32cfa7323b840fe47 | |
parent | c6c65189f9e14338533c871845ae6897a4f87c88 (diff) | |
parent | 29417fe80ad2fd4f62f00dcca96c7198870e5642 (diff) | |
download | linux-85b80b6bfdbdab3f489857dd850dad5a65e49895.tar.gz |
Merge tag 'ux500-core-for-arm-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson into next/soc
Merge "Ux500 core changes for v3.19" from Linus Walleij: "please pull in these Ux500 core changes for this kernel development cycle: mainly a generic power domain implementation from Ulf Hansson that needs to get queued up in -next and tested." Generic power domains for the Ux500 * tag 'ux500-core-for-arm-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson: ARM: ux500: Add i2c devices to the VAPE PM domain ARM: ux500: Add spi and ssp devices to the VAPE PM domain ARM: ux500: Add sdi devices to the VAPE PM domain ARM: ux500: Add DT node for ux500 PM domains ARM: ux500: Enable Kconfig for the generic PM domain ARM: ux500: Initial support for PM domains dt: bindings: ux500: Add header for PM domains specifiers dt: bindings: ux500: Add documentation for PM domains ARM: u300: Convert pr_warning to pr_warn
-rw-r--r-- | Documentation/devicetree/bindings/arm/ux500/power_domain.txt | 35 | ||||
-rw-r--r-- | arch/arm/boot/dts/ste-dbx5x0.dtsi | 22 | ||||
-rw-r--r-- | arch/arm/mach-u300/dummyspichip.c | 65 | ||||
-rw-r--r-- | arch/arm/mach-ux500/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-ux500/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm_domains.c | 79 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm_domains.h | 17 | ||||
-rw-r--r-- | include/dt-bindings/arm/ux500_pm_domains.h | 15 |
9 files changed, 203 insertions, 36 deletions
diff --git a/Documentation/devicetree/bindings/arm/ux500/power_domain.txt b/Documentation/devicetree/bindings/arm/ux500/power_domain.txt new file mode 100644 index 000000000000..5679d1742d3e --- /dev/null +++ b/Documentation/devicetree/bindings/arm/ux500/power_domain.txt @@ -0,0 +1,35 @@ +* ST-Ericsson UX500 PM Domains + +UX500 supports multiple PM domains which are used to gate power to one or +more peripherals on the SOC. + +The implementation of PM domains for UX500 are based upon the generic PM domain +and use the corresponding DT bindings. + +==PM domain providers== + +Required properties: + - compatible: Must be "stericsson,ux500-pm-domains". + - #power-domain-cells : Number of cells in a power domain specifier, must be 1. + +Example: + pm_domains: pm_domains0 { + compatible = "stericsson,ux500-pm-domains"; + #power-domain-cells = <1>; + }; + +==PM domain consumers== + +Required properties: + - power-domains: A phandle and PM domain specifier. Below are the list of + valid specifiers: + + Index Specifier + ----- --------- + 0 DOMAIN_VAPE + +Example: + sdi0_per1@80126000 { + compatible = "arm,pl18x", "arm,primecell"; + power-domains = <&pm_domains DOMAIN_VAPE> + }; diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi index 9d2323020d34..bfd3f1c734b8 100644 --- a/arch/arm/boot/dts/ste-dbx5x0.dtsi +++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi @@ -11,6 +11,7 @@ #include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/mfd/dbx500-prcmu.h> +#include <dt-bindings/arm/ux500_pm_domains.h> #include "skeleton.dtsi" / { @@ -43,6 +44,10 @@ interrupts = <0 7 IRQ_TYPE_LEVEL_HIGH>; }; + pm_domains: pm_domains0 { + compatible = "stericsson,ux500-pm-domains"; + #power-domain-cells = <1>; + }; clocks { compatible = "stericsson,u8500-clks"; @@ -636,6 +641,7 @@ clock-frequency = <400000>; clocks = <&prcc_kclk 3 3>, <&prcc_pclk 3 3>; clock-names = "i2cclk", "apb_pclk"; + power-domains = <&pm_domains DOMAIN_VAPE>; }; i2c@80122000 { @@ -651,6 +657,7 @@ clocks = <&prcc_kclk 1 2>, <&prcc_pclk 1 2>; clock-names = "i2cclk", "apb_pclk"; + power-domains = <&pm_domains DOMAIN_VAPE>; }; i2c@80128000 { @@ -666,6 +673,7 @@ clocks = <&prcc_kclk 1 6>, <&prcc_pclk 1 6>; clock-names = "i2cclk", "apb_pclk"; + power-domains = <&pm_domains DOMAIN_VAPE>; }; i2c@80110000 { @@ -681,6 +689,7 @@ clocks = <&prcc_kclk 2 0>, <&prcc_pclk 2 0>; clock-names = "i2cclk", "apb_pclk"; + power-domains = <&pm_domains DOMAIN_VAPE>; }; i2c@8012a000 { @@ -696,6 +705,7 @@ clocks = <&prcc_kclk 1 9>, <&prcc_pclk 1 10>; clock-names = "i2cclk", "apb_pclk"; + power-domains = <&pm_domains DOMAIN_VAPE>; }; ssp@80002000 { @@ -709,6 +719,7 @@ dmas = <&dma 8 0 0x2>, /* Logical - DevToMem */ <&dma 8 0 0x0>; /* Logical - MemToDev */ dma-names = "rx", "tx"; + power-domains = <&pm_domains DOMAIN_VAPE>; }; ssp@80003000 { @@ -722,6 +733,7 @@ dmas = <&dma 9 0 0x2>, /* Logical - DevToMem */ <&dma 9 0 0x0>; /* Logical - MemToDev */ dma-names = "rx", "tx"; + power-domains = <&pm_domains DOMAIN_VAPE>; }; spi@8011a000 { @@ -736,6 +748,7 @@ dmas = <&dma 0 0 0x2>, /* Logical - DevToMem */ <&dma 0 0 0x0>; /* Logical - MemToDev */ dma-names = "rx", "tx"; + power-domains = <&pm_domains DOMAIN_VAPE>; }; spi@80112000 { @@ -750,6 +763,7 @@ dmas = <&dma 35 0 0x2>, /* Logical - DevToMem */ <&dma 35 0 0x0>; /* Logical - MemToDev */ dma-names = "rx", "tx"; + power-domains = <&pm_domains DOMAIN_VAPE>; }; spi@80111000 { @@ -764,6 +778,7 @@ dmas = <&dma 33 0 0x2>, /* Logical - DevToMem */ <&dma 33 0 0x0>; /* Logical - MemToDev */ dma-names = "rx", "tx"; + power-domains = <&pm_domains DOMAIN_VAPE>; }; spi@80129000 { @@ -778,6 +793,7 @@ dmas = <&dma 40 0 0x2>, /* Logical - DevToMem */ <&dma 40 0 0x0>; /* Logical - MemToDev */ dma-names = "rx", "tx"; + power-domains = <&pm_domains DOMAIN_VAPE>; }; uart@80120000 { @@ -836,6 +852,7 @@ clocks = <&prcc_kclk 1 5>, <&prcc_pclk 1 5>; clock-names = "sdi", "apb_pclk"; + power-domains = <&pm_domains DOMAIN_VAPE>; status = "disabled"; }; @@ -851,6 +868,7 @@ clocks = <&prcc_kclk 2 4>, <&prcc_pclk 2 6>; clock-names = "sdi", "apb_pclk"; + power-domains = <&pm_domains DOMAIN_VAPE>; status = "disabled"; }; @@ -866,6 +884,7 @@ clocks = <&prcc_kclk 3 4>, <&prcc_pclk 3 4>; clock-names = "sdi", "apb_pclk"; + power-domains = <&pm_domains DOMAIN_VAPE>; status = "disabled"; }; @@ -881,6 +900,7 @@ clocks = <&prcc_kclk 2 5>, <&prcc_pclk 2 7>; clock-names = "sdi", "apb_pclk"; + power-domains = <&pm_domains DOMAIN_VAPE>; status = "disabled"; }; @@ -896,6 +916,7 @@ clocks = <&prcc_kclk 2 2>, <&prcc_pclk 2 4>; clock-names = "sdi", "apb_pclk"; + power-domains = <&pm_domains DOMAIN_VAPE>; status = "disabled"; }; @@ -911,6 +932,7 @@ clocks = <&prcc_kclk 3 7>, <&prcc_pclk 3 7>; clock-names = "sdi", "apb_pclk"; + power-domains = <&pm_domains DOMAIN_VAPE>; status = "disabled"; }; diff --git a/arch/arm/mach-u300/dummyspichip.c b/arch/arm/mach-u300/dummyspichip.c index ec0283cf9a32..131996805690 100644 --- a/arch/arm/mach-u300/dummyspichip.c +++ b/arch/arm/mach-u300/dummyspichip.c @@ -80,8 +80,8 @@ static ssize_t dummy_looptest(struct device *dev, "in 8bit mode\n"); status = spi_w8r8(spi, 0xAA); if (status < 0) - pr_warning("Siple test 1: FAILURE: spi_write_then_read " - "failed with status %d\n", status); + pr_warn("Simple test 1: FAILURE: spi_write_then_read failed with status %d\n", + status); else pr_info("Simple test 1: SUCCESS!\n"); @@ -89,8 +89,8 @@ static ssize_t dummy_looptest(struct device *dev, "in 8bit mode (full FIFO)\n"); status = spi_write_then_read(spi, &txbuf[0], 8, &rxbuf[0], 8); if (status < 0) - pr_warning("Simple test 2: FAILURE: spi_write_then_read() " - "failed with status %d\n", status); + pr_warn("Simple test 2: FAILURE: spi_write_then_read() failed with status %d\n", + status); else pr_info("Simple test 2: SUCCESS!\n"); @@ -98,8 +98,8 @@ static ssize_t dummy_looptest(struct device *dev, "in 8bit mode (see if we overflow FIFO)\n"); status = spi_write_then_read(spi, &txbuf[0], 14, &rxbuf[0], 14); if (status < 0) - pr_warning("Simple test 3: FAILURE: failed with status %d " - "(probably FIFO overrun)\n", status); + pr_warn("Simple test 3: FAILURE: failed with status %d (probably FIFO overrun)\n", + status); else pr_info("Simple test 3: SUCCESS!\n"); @@ -107,14 +107,14 @@ static ssize_t dummy_looptest(struct device *dev, "bytes garbage with spi_read() in 8bit mode\n"); status = spi_write(spi, &txbuf[0], 8); if (status < 0) - pr_warning("Simple test 4 step 1: FAILURE: spi_write() " - "failed with status %d\n", status); + pr_warn("Simple test 4 step 1: FAILURE: spi_write() failed with status %d\n", + status); else pr_info("Simple test 4 step 1: SUCCESS!\n"); status = spi_read(spi, &rxbuf[0], 8); if (status < 0) - pr_warning("Simple test 4 step 2: FAILURE: spi_read() " - "failed with status %d\n", status); + pr_warn("Simple test 4 step 2: FAILURE: spi_read() failed with status %d\n", + status); else pr_info("Simple test 4 step 2: SUCCESS!\n"); @@ -122,16 +122,14 @@ static ssize_t dummy_looptest(struct device *dev, "14 bytes garbage with spi_read() in 8bit mode\n"); status = spi_write(spi, &txbuf[0], 14); if (status < 0) - pr_warning("Simple test 5 step 1: FAILURE: spi_write() " - "failed with status %d (probably FIFO overrun)\n", - status); + pr_warn("Simple test 5 step 1: FAILURE: spi_write() failed with status %d (probably FIFO overrun)\n", + status); else pr_info("Simple test 5 step 1: SUCCESS!\n"); status = spi_read(spi, &rxbuf[0], 14); if (status < 0) - pr_warning("Simple test 5 step 2: FAILURE: spi_read() " - "failed with status %d (probably FIFO overrun)\n", - status); + pr_warn("Simple test 5 step 2: FAILURE: spi_read() failed with status %d (probably FIFO overrun)\n", + status); else pr_info("Simple test 5: SUCCESS!\n"); @@ -140,16 +138,14 @@ static ssize_t dummy_looptest(struct device *dev, DMA_TEST_SIZE, DMA_TEST_SIZE); status = spi_write(spi, &bigtxbuf_virtual[0], DMA_TEST_SIZE); if (status < 0) - pr_warning("Simple test 6 step 1: FAILURE: spi_write() " - "failed with status %d (probably FIFO overrun)\n", - status); + pr_warn("Simple test 6 step 1: FAILURE: spi_write() failed with status %d (probably FIFO overrun)\n", + status); else pr_info("Simple test 6 step 1: SUCCESS!\n"); status = spi_read(spi, &bigrxbuf_virtual[0], DMA_TEST_SIZE); if (status < 0) - pr_warning("Simple test 6 step 2: FAILURE: spi_read() " - "failed with status %d (probably FIFO overrun)\n", - status); + pr_warn("Simple test 6 step 2: FAILURE: spi_read() failed with status %d (probably FIFO overrun)\n", + status); else pr_info("Simple test 6: SUCCESS!\n"); @@ -169,18 +165,17 @@ static ssize_t dummy_looptest(struct device *dev, pr_info("Simple test 7: SUCCESS! (expected failure with " "status EIO)\n"); else if (status < 0) - pr_warning("Siple test 7: FAILURE: spi_write_then_read " - "failed with status %d\n", status); + pr_warn("Simple test 7: FAILURE: spi_write_then_read failed with status %d\n", + status); else - pr_warning("Siple test 7: FAILURE: spi_write_then_read " - "succeeded but it was expected to fail!\n"); + pr_warn("Simple test 7: FAILURE: spi_write_then_read succeeded but it was expected to fail!\n"); pr_info("Simple test 8: write 8 bytes, read back 8 bytes garbage " "in 16bit mode (full FIFO)\n"); status = spi_write_then_read(spi, &txbuf[0], 8, &rxbuf[0], 8); if (status < 0) - pr_warning("Simple test 8: FAILURE: spi_write_then_read() " - "failed with status %d\n", status); + pr_warn("Simple test 8: FAILURE: spi_write_then_read() failed with status %d\n", + status); else pr_info("Simple test 8: SUCCESS!\n"); @@ -188,8 +183,8 @@ static ssize_t dummy_looptest(struct device *dev, "in 16bit mode (see if we overflow FIFO)\n"); status = spi_write_then_read(spi, &txbuf[0], 14, &rxbuf[0], 14); if (status < 0) - pr_warning("Simple test 9: FAILURE: failed with status %d " - "(probably FIFO overrun)\n", status); + pr_warn("Simple test 9: FAILURE: failed with status %d (probably FIFO overrun)\n", + status); else pr_info("Simple test 9: SUCCESS!\n"); @@ -198,17 +193,15 @@ static ssize_t dummy_looptest(struct device *dev, DMA_TEST_SIZE, DMA_TEST_SIZE); status = spi_write(spi, &bigtxbuf_virtual[0], DMA_TEST_SIZE); if (status < 0) - pr_warning("Simple test 10 step 1: FAILURE: spi_write() " - "failed with status %d (probably FIFO overrun)\n", - status); + pr_warn("Simple test 10 step 1: FAILURE: spi_write() failed with status %d (probably FIFO overrun)\n", + status); else pr_info("Simple test 10 step 1: SUCCESS!\n"); status = spi_read(spi, &bigrxbuf_virtual[0], DMA_TEST_SIZE); if (status < 0) - pr_warning("Simple test 10 step 2: FAILURE: spi_read() " - "failed with status %d (probably FIFO overrun)\n", - status); + pr_warn("Simple test 10 step 2: FAILURE: spi_read() failed with status %d (probably FIFO overrun)\n", + status); else pr_info("Simple test 10: SUCCESS!\n"); diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 699e8601dbf0..c9ac19b24e5a 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -32,6 +32,7 @@ config UX500_SOC_DB8500 select PINCTRL_AB8540 select REGULATOR select REGULATOR_DB8500_PRCMU + select PM_GENERIC_DOMAINS if PM config MACH_MOP500 bool "U8500 Development platform, MOP500 versions" diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 9741de956b3e..4418a5078833 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -9,5 +9,6 @@ obj-$(CONFIG_MACH_MOP500) += board-mop500-regulators.o \ board-mop500-audio.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o +obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o CFLAGS_hotplug.o += -march=armv7-a diff --git a/arch/arm/mach-ux500/pm.c b/arch/arm/mach-ux500/pm.c index b80a9a2e356e..2cb587b50905 100644 --- a/arch/arm/mach-ux500/pm.c +++ b/arch/arm/mach-ux500/pm.c @@ -17,6 +17,7 @@ #include <linux/platform_data/arm-ux500-pm.h> #include "db8500-regs.h" +#include "pm_domains.h" /* ARM WFI Standby signal register */ #define PRCM_ARM_WFI_STANDBY (prcmu_base + 0x130) @@ -191,4 +192,7 @@ void __init ux500_pm_init(u32 phy_base, u32 size) /* Set up ux500 suspend callbacks. */ suspend_set_ops(UX500_SUSPEND_OPS); + + /* Initialize ux500 power domains */ + ux500_pm_domains_init(); } diff --git a/arch/arm/mach-ux500/pm_domains.c b/arch/arm/mach-ux500/pm_domains.c new file mode 100644 index 000000000000..0d4b5b46f15b --- /dev/null +++ b/arch/arm/mach-ux500/pm_domains.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2014 Linaro Ltd. + * + * Author: Ulf Hansson <ulf.hansson@linaro.org> + * License terms: GNU General Public License (GPL) version 2 + * + * Implements PM domains using the generic PM domain for ux500. + */ +#include <linux/printk.h> +#include <linux/slab.h> +#include <linux/err.h> +#include <linux/of.h> +#include <linux/pm_domain.h> + +#include <dt-bindings/arm/ux500_pm_domains.h> +#include "pm_domains.h" + +static int pd_power_off(struct generic_pm_domain *domain) +{ + /* + * Handle the gating of the PM domain regulator here. + * + * Drivers/subsystems handling devices in the PM domain needs to perform + * register context save/restore from their respective runtime PM + * callbacks, to be able to enable PM domain gating/ungating. + */ + return 0; +} + +static int pd_power_on(struct generic_pm_domain *domain) +{ + /* + * Handle the ungating of the PM domain regulator here. + * + * Drivers/subsystems handling devices in the PM domain needs to perform + * register context save/restore from their respective runtime PM + * callbacks, to be able to enable PM domain gating/ungating. + */ + return 0; +} + +static struct generic_pm_domain ux500_pm_domain_vape = { + .name = "VAPE", + .power_off = pd_power_off, + .power_on = pd_power_on, +}; + +static struct generic_pm_domain *ux500_pm_domains[NR_DOMAINS] = { + [DOMAIN_VAPE] = &ux500_pm_domain_vape, +}; + +static struct of_device_id ux500_pm_domain_matches[] = { + { .compatible = "stericsson,ux500-pm-domains", }, + { }, +}; + +int __init ux500_pm_domains_init(void) +{ + struct device_node *np; + struct genpd_onecell_data *genpd_data; + int i; + + np = of_find_matching_node(NULL, ux500_pm_domain_matches); + if (!np) + return -ENODEV; + + genpd_data = kzalloc(sizeof(*genpd_data), GFP_KERNEL); + if (!genpd_data) + return -ENOMEM; + + genpd_data->domains = ux500_pm_domains; + genpd_data->num_domains = ARRAY_SIZE(ux500_pm_domains); + + for (i = 0; i < ARRAY_SIZE(ux500_pm_domains); ++i) + pm_genpd_init(ux500_pm_domains[i], NULL, false); + + of_genpd_add_provider_onecell(np, genpd_data); + return 0; +} diff --git a/arch/arm/mach-ux500/pm_domains.h b/arch/arm/mach-ux500/pm_domains.h new file mode 100644 index 000000000000..263d3ba97177 --- /dev/null +++ b/arch/arm/mach-ux500/pm_domains.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2014 Linaro Ltd. + * + * Author: Ulf Hansson <ulf.hansson@linaro.org> + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef __MACH_UX500_PM_DOMAINS_H +#define __MACH_UX500_PM_DOMAINS_H + +#ifdef CONFIG_PM_GENERIC_DOMAINS +extern int __init ux500_pm_domains_init(void); +#else +static inline int ux500_pm_domains_init(void) { return 0; } +#endif + +#endif diff --git a/include/dt-bindings/arm/ux500_pm_domains.h b/include/dt-bindings/arm/ux500_pm_domains.h new file mode 100644 index 000000000000..398a6c0288d1 --- /dev/null +++ b/include/dt-bindings/arm/ux500_pm_domains.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2014 Linaro Ltd. + * + * Author: Ulf Hansson <ulf.hansson@linaro.org> + * License terms: GNU General Public License (GPL) version 2 + */ +#ifndef _DT_BINDINGS_ARM_UX500_PM_DOMAINS_H +#define _DT_BINDINGS_ARM_UX500_PM_DOMAINS_H + +#define DOMAIN_VAPE 0 + +/* Number of PM domains. */ +#define NR_DOMAINS (DOMAIN_VAPE + 1) + +#endif |