Generic power domains for the Ux500

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJUVqxEAAoJEEEQszewGV1zRcQP/AxYB/o+6Zb/HgCxIT+9vujJ
 4ghuDElDUffBCXhv8IGuvzcAK+UKAqoj98vZNmI6Kl/MvXoHLcyTfu7e9i/zPFcM
 szYdlG+ui4PEhuwPgWHCpOzyWWjqBuujFyYG8Kk/akUtMntV0NXoS7snqoAw47Y1
 IAn7oov+UHFDw8ewWU+i5qrdPKOQ4IaIQcWB58EfJHfsU4f9sUB6JVSBJ3mCtAhg
 N8P3qg9WV0sqvZt1oI+naTRZL/CtNlrDYVnWVQb0WeGEI3MGEibEkWr1HScHmwko
 eNsOvTV+/3iFz/RUQtFqw4kidHiIdpTHgCLEauJ+KBz86X5sRq23CXLWnZy3h9Mw
 q/05yl0/IgTZlNCrULqmkcapjLp89nk5PGYOtuXuaYPj7y8og3LWc+bCYIXJd7Ay
 OMH9CJQpysWdyDOMt2C7xOI3/IkUjluEvOGN8iWoze9k8Dxr2+Ajmvf74lu0QtYm
 hejdKS6Jr0a43FHwJFS/oX7LAGSft76xvs9bGa033YRcNGLXYLcjlbNqynep0Hhm
 SKk67IfI+FXjo28FWlp7sXWsfhyg3tJHkAgEPZ1o+V8UNWT5Pb+Pop/DqJG6Jvjc
 +F3m+wkvcP7kOpVHdyFqY026lb0nMyDimTvqYjfDxwaElVcUSBu3/0/A9SJGqBcH
 L0mMNkBMP5HDmwy6bo2u
 =8T8T
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Olof Johansson 2014-11-08 16:51:39 -08:00
commit 85b80b6bfd
9 changed files with 203 additions and 36 deletions

View file

@ -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>
};

View file

@ -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 @@ pmu {
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 @@ i2c@80004000 {
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 @@ i2c@80122000 {
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 @@ i2c@80128000 {
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 @@ i2c@80110000 {
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 @@ i2c@8012a000 {
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 @@ ssp@80002000 {
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 @@ ssp@80003000 {
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 @@ spi@8011a000 {
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 @@ spi@80112000 {
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 @@ spi@80111000 {
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 @@ spi@80129000 {
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 @@ sdi0_per1@80126000 {
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 @@ sdi1_per2@80118000 {
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 @@ sdi2_per3@80005000 {
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 @@ sdi3_per2@80119000 {
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 @@ sdi4_per2@80114000 {
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 @@ sdi5_per3@80008000 {
clocks = <&prcc_kclk 3 7>, <&prcc_pclk 3 7>;
clock-names = "sdi", "apb_pclk";
power-domains = <&pm_domains DOMAIN_VAPE>;
status = "disabled";
};

View file

@ -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");

View file

@ -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"

View file

@ -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

View file

@ -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();
}

View file

@ -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;
}

View file

@ -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

View file

@ -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