linux-gpio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/9] ARM: vf610: Suspend/resume support
@ 2014-09-22 17:09 Stefan Agner
  2014-09-22 17:09 ` [PATCH 1/9] ARM: dts: vf610: Add system reset controller (SRC) Stefan Agner
                   ` (9 more replies)
  0 siblings, 10 replies; 19+ messages in thread
From: Stefan Agner @ 2014-09-22 17:09 UTC (permalink / raw)
  To: shawn.guo, kernel, linus.walleij, gnurou
  Cc: linux, jingchang.lu, b20788, linux-arm-kernel, linux-kernel,
	linux-gpio, stefan

This patchset provides suspend/resume support for Freescale Vybrid
SoC (vf610). The code is generally aligned to the implementation
for i.MX6. The subsystems SRC and GPC need some changes to support
the Vybrid specific implementation.

This patchset relies on GPIO driver to be present (in order to
provide a wakeup source) as well as using the ARM Global Timer
clock source (the Vybrid specifc PIT clock source, vf_pit_timer.c
does not support shutdown).

The implemented sleep states (LP-RUN and STOP), are not the most
power saving functions available on Vybrid. Especially for
suspend-to-memory one of the LPSTOP modes looks more appropriate.
However, the complexity is somewhat higher (we would need to move
execution path to SRAM and store IOMUX and DDRMC configuration).
Currently, I have not the resources to look into that so I hope
that this initial code qualifies as power saving functions to be
applied.

Suspend-to-memory as well as standby mode is tested on Colibri
VF61.

Power measurement (Colibri VF61, whole module):
- Idle: 540mW
- LP-RUN: 220mW (standby)
- STOP: 200mW (mem)

Stefan Agner (9):
  ARM: dts: vf610: Add system reset controller (SRC)
  ARM: dts: vf610: add global power controller (GPC)
  ARM: dts: vf610: add on-chip SRAM
  ARM: dts: vf610-colibri: GPIO power key
  gpio: vf610: Extend with wakeup support
  ARM: imx: gpc: Support vf610 global power controller
  ARM: imx: src: Support vf610 system reset controller
  ARM: imx: clk-gate2: allow custom gate configuration
  ARM: vf610: initial suspend/resume support

 arch/arm/boot/dts/vf610-colibri-eval-v3.dts |  26 ++
 arch/arm/boot/dts/vf610.dtsi                |  33 +++
 arch/arm/mach-imx/Kconfig                   |   2 +
 arch/arm/mach-imx/Makefile                  |   1 +
 arch/arm/mach-imx/clk-gate2.c               |   7 +-
 arch/arm/mach-imx/clk-vf610.c               |   6 +
 arch/arm/mach-imx/clk.h                     |  13 +-
 arch/arm/mach-imx/common.h                  |  14 +-
 arch/arm/mach-imx/gpc.c                     |  61 ++--
 arch/arm/mach-imx/mach-imx6q.c              |   2 +-
 arch/arm/mach-imx/mach-imx6sl.c             |   2 +-
 arch/arm/mach-imx/mach-vf610.c              |   9 +
 arch/arm/mach-imx/pm-vf610.c                | 428 ++++++++++++++++++++++++++++
 arch/arm/mach-imx/src.c                     |  11 +
 drivers/gpio/gpio-vf610.c                   |  16 ++
 include/dt-bindings/clock/vf610-clock.h     |   3 +-
 16 files changed, 605 insertions(+), 29 deletions(-)
 create mode 100644 arch/arm/mach-imx/pm-vf610.c

-- 
2.1.0


^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 1/9] ARM: dts: vf610: Add system reset controller (SRC)
  2014-09-22 17:09 [PATCH 0/9] ARM: vf610: Suspend/resume support Stefan Agner
@ 2014-09-22 17:09 ` Stefan Agner
  2014-09-24  9:16   ` Linus Walleij
  2014-09-22 17:09 ` [PATCH 2/9] ARM: dts: vf610: add global power controller (GPC) Stefan Agner
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Stefan Agner @ 2014-09-22 17:09 UTC (permalink / raw)
  To: shawn.guo, kernel, linus.walleij, gnurou
  Cc: linux, linux-kernel, stefan, linux-gpio, jingchang.lu, b20788,
	linux-arm-kernel

Add device tree property for system reset controller.

Signed-off-by: Stefan Agner <stefan@agner.ch>
---
 arch/arm/boot/dts/vf610.dtsi | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi
index 3a6840c..122a64956 100644
--- a/arch/arm/boot/dts/vf610.dtsi
+++ b/arch/arm/boot/dts/vf610.dtsi
@@ -366,6 +366,13 @@
 				reg = <0x40034800 0x200>;
 				clocks = <&clks VF610_CLK_USBC0>;
 			};
+
+			src: src@4006e000 {
+				compatible = "fsl,vf610-src";
+				reg = <0x4006e000 0x1000>;
+				interrupts = <0 96 IRQ_TYPE_LEVEL_HIGH>;
+				#reset-cells = <0>;
+			};
 		};
 
 		aips1: aips-bus@40080000 {
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 2/9] ARM: dts: vf610: add global power controller (GPC)
  2014-09-22 17:09 [PATCH 0/9] ARM: vf610: Suspend/resume support Stefan Agner
  2014-09-22 17:09 ` [PATCH 1/9] ARM: dts: vf610: Add system reset controller (SRC) Stefan Agner
@ 2014-09-22 17:09 ` Stefan Agner
  2014-09-22 17:09 ` [PATCH 3/9] ARM: dts: vf610: add on-chip SRAM Stefan Agner
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Stefan Agner @ 2014-09-22 17:09 UTC (permalink / raw)
  To: shawn.guo, kernel, linus.walleij, gnurou
  Cc: linux, linux-kernel, stefan, linux-gpio, jingchang.lu, b20788,
	linux-arm-kernel

Add global power controller module (GPC) to Vybrid device tree.

Signed-off-by: Stefan Agner <stefan@agner.ch>
---
 arch/arm/boot/dts/vf610.dtsi | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi
index 122a64956..67bb3b7 100644
--- a/arch/arm/boot/dts/vf610.dtsi
+++ b/arch/arm/boot/dts/vf610.dtsi
@@ -367,6 +367,11 @@
 				clocks = <&clks VF610_CLK_USBC0>;
 			};
 
+			gpc: gpc@4006c000 {
+				compatible = "fsl,vf610-gpc";
+				reg = <0x4006c000 0x1000>;
+			};
+
 			src: src@4006e000 {
 				compatible = "fsl,vf610-src";
 				reg = <0x4006e000 0x1000>;
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 3/9] ARM: dts: vf610: add on-chip SRAM
  2014-09-22 17:09 [PATCH 0/9] ARM: vf610: Suspend/resume support Stefan Agner
  2014-09-22 17:09 ` [PATCH 1/9] ARM: dts: vf610: Add system reset controller (SRC) Stefan Agner
  2014-09-22 17:09 ` [PATCH 2/9] ARM: dts: vf610: add global power controller (GPC) Stefan Agner
@ 2014-09-22 17:09 ` Stefan Agner
  2014-09-22 17:09 ` [PATCH 4/9] ARM: dts: vf610-colibri: GPIO power key Stefan Agner
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Stefan Agner @ 2014-09-22 17:09 UTC (permalink / raw)
  To: shawn.guo, kernel, linus.walleij, gnurou
  Cc: linux, linux-kernel, stefan, linux-gpio, jingchang.lu, b20788,
	linux-arm-kernel

Signed-off-by: Stefan Agner <stefan@agner.ch>
---
 arch/arm/boot/dts/vf610.dtsi | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi
index 67bb3b7..d2128e5 100644
--- a/arch/arm/boot/dts/vf610.dtsi
+++ b/arch/arm/boot/dts/vf610.dtsi
@@ -69,6 +69,27 @@
 		interrupt-parent = <&intc>;
 		ranges;
 
+		ocram0: sram@3f000000 {
+			compatible = "mmio-sram";
+			reg = <0x3f000000 0x40000>;
+		};
+
+		ocram1: sram@3f040000 {
+			compatible = "mmio-sram";
+			reg = <0x3f040000 0x40000>;
+		};
+
+		gfxram0: sram@3f400000 {
+			compatible = "mmio-sram";
+			reg = <0x3f400000 0x80000>;
+		};
+
+		/* used by L2 cache */
+		gfxram1: sram@3f480000 {
+			compatible = "mmio-sram";
+			reg = <0x3f480000 0x80000>;
+		};
+
 		aips0: aips-bus@40000000 {
 			compatible = "fsl,aips-bus", "simple-bus";
 			#address-cells = <1>;
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 4/9] ARM: dts: vf610-colibri: GPIO power key
  2014-09-22 17:09 [PATCH 0/9] ARM: vf610: Suspend/resume support Stefan Agner
                   ` (2 preceding siblings ...)
  2014-09-22 17:09 ` [PATCH 3/9] ARM: dts: vf610: add on-chip SRAM Stefan Agner
@ 2014-09-22 17:09 ` Stefan Agner
  2014-09-22 17:09 ` [PATCH 5/9] gpio: vf610: Extend with wakeup support Stefan Agner
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Stefan Agner @ 2014-09-22 17:09 UTC (permalink / raw)
  To: shawn.guo, kernel, linus.walleij, gnurou
  Cc: linux, linux-kernel, stefan, linux-gpio, jingchang.lu, b20788,
	linux-arm-kernel

Enable GPIO power key on pad 41 which is routed to our default
wakeup pin SO-DIMM 45.

Signed-off-by: Stefan Agner <stefan@agner.ch>
---
 arch/arm/boot/dts/vf610-colibri-eval-v3.dts | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/arch/arm/boot/dts/vf610-colibri-eval-v3.dts b/arch/arm/boot/dts/vf610-colibri-eval-v3.dts
index 7fb3066..e707243 100644
--- a/arch/arm/boot/dts/vf610-colibri-eval-v3.dts
+++ b/arch/arm/boot/dts/vf610-colibri-eval-v3.dts
@@ -8,6 +8,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/input/input.h>
 #include "vf610-colibri.dtsi"
 
 / {
@@ -17,6 +18,20 @@
 	chosen {
 		bootargs = "console=ttyLP0,115200";
 	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_gpiokeys>;
+
+		power {
+			label = "Power";
+			gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>;
+			linux,code = <KEY_POWER>;
+			debounce-interval = <10>;
+			gpio-key,wakeup;
+		};
+	};
 };
 
 &esdhc1 {
@@ -44,3 +59,14 @@
 &uart2 {
 	status = "okay";
 };
+
+
+&iomuxc {
+	vf610-colibri {
+		pinctrl_gpiokeys: gpiokeys {
+			fsl,pins = <
+				VF610_PAD_PTB19__GPIO_41	0x219d
+			>;
+		};
+	};
+};
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 5/9] gpio: vf610: Extend with wakeup support
  2014-09-22 17:09 [PATCH 0/9] ARM: vf610: Suspend/resume support Stefan Agner
                   ` (3 preceding siblings ...)
  2014-09-22 17:09 ` [PATCH 4/9] ARM: dts: vf610-colibri: GPIO power key Stefan Agner
@ 2014-09-22 17:09 ` Stefan Agner
  2014-09-24  9:19   ` Linus Walleij
  2014-09-24 10:06   ` Lucas Stach
  2014-09-22 17:09 ` [PATCH 6/9] ARM: imx: gpc: Support vf610 global power controller Stefan Agner
                   ` (4 subsequent siblings)
  9 siblings, 2 replies; 19+ messages in thread
From: Stefan Agner @ 2014-09-22 17:09 UTC (permalink / raw)
  To: shawn.guo, kernel, linus.walleij, gnurou
  Cc: linux, jingchang.lu, b20788, linux-arm-kernel, linux-kernel,
	linux-gpio, stefan

Support Vybrid GPIO's as wakeup source by requesting the parent
IRQ as wakeup IRQ.

Signed-off-by: Stefan Agner <stefan@agner.ch>
---
 drivers/gpio/gpio-vf610.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
index 5f59424..50326af 100644
--- a/drivers/gpio/gpio-vf610.c
+++ b/drivers/gpio/gpio-vf610.c
@@ -196,12 +196,28 @@ static void vf610_gpio_irq_unmask(struct irq_data *d)
 			  pcr_base);
 }
 
+static int vf610_gpio_irq_set_wake(struct irq_data *d, u32 enable)
+{
+	struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
+
+	if (enable)
+		enable_irq_wake(port->irq);
+	else
+		disable_irq_wake(port->irq);
+
+	return 0;
+}
+
+
 static struct irq_chip vf610_gpio_irq_chip = {
 	.name		= "gpio-vf610",
 	.irq_ack	= vf610_gpio_irq_ack,
 	.irq_mask	= vf610_gpio_irq_mask,
 	.irq_unmask	= vf610_gpio_irq_unmask,
 	.irq_set_type	= vf610_gpio_irq_set_type,
+#ifdef CONFIG_PM_SLEEP
+	.irq_set_wake	= vf610_gpio_irq_set_wake,
+#endif
 };
 
 static int vf610_gpio_probe(struct platform_device *pdev)
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 6/9] ARM: imx: gpc: Support vf610 global power controller
  2014-09-22 17:09 [PATCH 0/9] ARM: vf610: Suspend/resume support Stefan Agner
                   ` (4 preceding siblings ...)
  2014-09-22 17:09 ` [PATCH 5/9] gpio: vf610: Extend with wakeup support Stefan Agner
@ 2014-09-22 17:09 ` Stefan Agner
  2014-09-22 17:09 ` [PATCH 7/9] ARM: imx: src: Support vf610 system reset controller Stefan Agner
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Stefan Agner @ 2014-09-22 17:09 UTC (permalink / raw)
  To: shawn.guo, kernel, linus.walleij, gnurou
  Cc: linux, jingchang.lu, b20788, linux-arm-kernel, linux-kernel,
	linux-gpio, stefan

Support Vybrid SoC which has a similar global power controller
found in i.MX6 SoC's. The extension for the GIC interrupt
controller can be reused. However, Vybrid's GPC has no CPU
powerdown flag, hence we write this conditional.

Signed-off-by: Stefan Agner <stefan@agner.ch>
---
 arch/arm/mach-imx/Kconfig       |  1 +
 arch/arm/mach-imx/common.h      |  3 +-
 arch/arm/mach-imx/gpc.c         | 61 +++++++++++++++++++++++++++--------------
 arch/arm/mach-imx/mach-imx6q.c  |  2 +-
 arch/arm/mach-imx/mach-imx6sl.c |  2 +-
 arch/arm/mach-imx/mach-vf610.c  |  7 +++++
 6 files changed, 53 insertions(+), 23 deletions(-)

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index a566fbf3..70e6d56 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -633,6 +633,7 @@ config SOC_VF610
 	bool "Vybrid Family VF610 support"
 	select ARM_GIC
 	select PINCTRL_VF610
+	select HAVE_IMX_GPC
 	select ARM_GLOBAL_TIMER
 	select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
 	select PL310_ERRATA_769419 if CACHE_L2X0
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 1dabf43..4b753f5 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -103,7 +103,8 @@ static inline void imx_scu_map_io(void) {}
 static inline void imx_smp_prepare(void) {}
 #endif
 void imx_src_init(void);
-void imx_gpc_init(void);
+void imx6_gpc_init(void);
+void vf610_gpc_init(void);
 void imx_gpc_pre_suspend(bool arm_power_off);
 void imx_gpc_post_resume(void);
 void imx_gpc_mask_all(void);
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 82ea74e..4ac7a48 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -18,40 +18,42 @@
 #include <linux/irqchip/arm-gic.h>
 #include "common.h"
 
-#define GPC_IMR1		0x008
+#define IMX6_GPC_IMR1		0x008
+#define VF610_GPC_IMR1		0x044
 #define GPC_PGC_CPU_PDN		0x2a0
 
 #define IMR_NUM			4
 
 static void __iomem *gpc_base;
+static void __iomem *gpc_imr_base;
+static bool has_cpu_pdn;
 static u32 gpc_wake_irqs[IMR_NUM];
 static u32 gpc_saved_imrs[IMR_NUM];
 
 void imx_gpc_pre_suspend(bool arm_power_off)
 {
-	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
 	int i;
 
 	/* Tell GPC to power off ARM core when suspend */
-	if (arm_power_off)
+	if (arm_power_off && has_cpu_pdn)
 		writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
 
 	for (i = 0; i < IMR_NUM; i++) {
-		gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
-		writel_relaxed(~gpc_wake_irqs[i], reg_imr1 + i * 4);
+		gpc_saved_imrs[i] = readl_relaxed(gpc_imr_base + i * 4);
+		writel_relaxed(~gpc_wake_irqs[i], gpc_imr_base + i * 4);
 	}
 }
 
 void imx_gpc_post_resume(void)
 {
-	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
 	int i;
 
 	/* Keep ARM core powered on for other low-power modes */
-	writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN);
+	if (has_cpu_pdn)
+		writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN);
 
 	for (i = 0; i < IMR_NUM; i++)
-		writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
+		writel_relaxed(gpc_saved_imrs[i], gpc_imr_base + i * 4);
 }
 
 static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
@@ -72,23 +74,21 @@ static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
 
 void imx_gpc_mask_all(void)
 {
-	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
 	int i;
 
 	for (i = 0; i < IMR_NUM; i++) {
-		gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
-		writel_relaxed(~0, reg_imr1 + i * 4);
+		gpc_saved_imrs[i] = readl_relaxed(gpc_imr_base + i * 4);
+		writel_relaxed(~0, gpc_imr_base + i * 4);
 	}
 
 }
 
 void imx_gpc_restore_all(void)
 {
-	void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
 	int i;
 
 	for (i = 0; i < IMR_NUM; i++)
-		writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
+		writel_relaxed(gpc_saved_imrs[i], gpc_imr_base + i * 4);
 }
 
 void imx_gpc_irq_unmask(struct irq_data *d)
@@ -100,7 +100,7 @@ void imx_gpc_irq_unmask(struct irq_data *d)
 	if (d->irq < 32)
 		return;
 
-	reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
+	reg = gpc_imr_base + (d->irq / 32 - 1) * 4;
 	val = readl_relaxed(reg);
 	val &= ~(1 << d->irq % 32);
 	writel_relaxed(val, reg);
@@ -115,27 +115,48 @@ void imx_gpc_irq_mask(struct irq_data *d)
 	if (d->irq < 32)
 		return;
 
-	reg = gpc_base + GPC_IMR1 + (d->irq / 32 - 1) * 4;
+	reg = gpc_imr_base + (d->irq / 32 - 1) * 4;
 	val = readl_relaxed(reg);
 	val |= 1 << (d->irq % 32);
 	writel_relaxed(val, reg);
 }
 
-void __init imx_gpc_init(void)
+static void __init imx_gpc_init(void)
 {
-	struct device_node *np;
 	int i;
 
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
-	gpc_base = of_iomap(np, 0);
 	WARN_ON(!gpc_base);
 
 	/* Initially mask all interrupts */
 	for (i = 0; i < IMR_NUM; i++)
-		writel_relaxed(~0, gpc_base + GPC_IMR1 + i * 4);
+		writel_relaxed(~0, gpc_imr_base + i * 4);
 
 	/* Register GPC as the secondary interrupt controller behind GIC */
 	gic_arch_extn.irq_mask = imx_gpc_irq_mask;
 	gic_arch_extn.irq_unmask = imx_gpc_irq_unmask;
 	gic_arch_extn.irq_set_wake = imx_gpc_irq_set_wake;
 }
+
+void __init imx6_gpc_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
+	gpc_base = of_iomap(np, 0);
+	gpc_imr_base = gpc_base + IMX6_GPC_IMR1;
+	has_cpu_pdn = true;
+
+	imx_gpc_init();
+}
+
+void __init vf610_gpc_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,vf610-gpc");
+	gpc_base = of_iomap(np, 0);
+	gpc_imr_base = gpc_base + VF610_GPC_IMR1;
+	has_cpu_pdn = false;
+
+	imx_gpc_init();
+}
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index d51c6e9..b26dc73 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -392,7 +392,7 @@ static void __init imx6q_init_irq(void)
 	imx_init_revision_from_anatop();
 	imx_init_l2cache();
 	imx_src_init();
-	imx_gpc_init();
+	imx6_gpc_init();
 	irqchip_init();
 }
 
diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
index ed263a2..df462d6 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -66,7 +66,7 @@ static void __init imx6sl_init_irq(void)
 	imx_init_revision_from_anatop();
 	imx_init_l2cache();
 	imx_src_init();
-	imx_gpc_init();
+	imx6_gpc_init();
 	irqchip_init();
 }
 
diff --git a/arch/arm/mach-imx/mach-vf610.c b/arch/arm/mach-imx/mach-vf610.c
index ee7e57b..532f18f 100644
--- a/arch/arm/mach-imx/mach-vf610.c
+++ b/arch/arm/mach-imx/mach-vf610.c
@@ -14,6 +14,12 @@
 
 #include "common.h"
 
+static void __init vf610_init_irq(void)
+{
+	vf610_gpc_init();
+	irqchip_init();
+}
+
 static void __init vf610_init_machine(void)
 {
 	mxc_arch_reset_init_dt();
@@ -29,6 +35,7 @@ DT_MACHINE_START(VYBRID_VF610, "Freescale Vybrid VF610 (Device Tree)")
 	.l2c_aux_val	= 0,
 	.l2c_aux_mask	= ~0,
 	.init_machine   = vf610_init_machine,
+	.init_irq	= vf610_init_irq,
 	.dt_compat	= vf610_dt_compat,
 	.restart	= mxc_restart,
 MACHINE_END
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 7/9] ARM: imx: src: Support vf610 system reset controller
  2014-09-22 17:09 [PATCH 0/9] ARM: vf610: Suspend/resume support Stefan Agner
                   ` (5 preceding siblings ...)
  2014-09-22 17:09 ` [PATCH 6/9] ARM: imx: gpc: Support vf610 global power controller Stefan Agner
@ 2014-09-22 17:09 ` Stefan Agner
  2014-09-22 17:09 ` [PATCH 8/9] ARM: imx: clk-gate2: allow custom gate configuration Stefan Agner
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Stefan Agner @ 2014-09-22 17:09 UTC (permalink / raw)
  To: shawn.guo, kernel, linus.walleij, gnurou
  Cc: linux, jingchang.lu, b20788, linux-arm-kernel, linux-kernel,
	linux-gpio, stefan

Support Vybrid SoC's system reset controller (SRC). Currently we
don't register a reset controller but only support the imx_cpu_jump
and imx_cpu_arg functions.

Signed-off-by: Stefan Agner <stefan@agner.ch>
---
 arch/arm/mach-imx/Kconfig      |  1 +
 arch/arm/mach-imx/common.h     |  1 +
 arch/arm/mach-imx/mach-vf610.c |  1 +
 arch/arm/mach-imx/src.c        | 11 +++++++++++
 4 files changed, 14 insertions(+)

diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 70e6d56..f393775 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -634,6 +634,7 @@ config SOC_VF610
 	select ARM_GIC
 	select PINCTRL_VF610
 	select HAVE_IMX_GPC
+	select HAVE_IMX_SRC
 	select ARM_GLOBAL_TIMER
 	select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
 	select PL310_ERRATA_769419 if CACHE_L2X0
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 4b753f5..ca7a0d9 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -103,6 +103,7 @@ static inline void imx_scu_map_io(void) {}
 static inline void imx_smp_prepare(void) {}
 #endif
 void imx_src_init(void);
+void vf610_src_init(void);
 void imx6_gpc_init(void);
 void vf610_gpc_init(void);
 void imx_gpc_pre_suspend(bool arm_power_off);
diff --git a/arch/arm/mach-imx/mach-vf610.c b/arch/arm/mach-imx/mach-vf610.c
index 532f18f..eef3496 100644
--- a/arch/arm/mach-imx/mach-vf610.c
+++ b/arch/arm/mach-imx/mach-vf610.c
@@ -16,6 +16,7 @@
 
 static void __init vf610_init_irq(void)
 {
+	vf610_src_init();
 	vf610_gpc_init();
 	irqchip_init();
 }
diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c
index 45f7f4e..a1f5160 100644
--- a/arch/arm/mach-imx/src.c
+++ b/arch/arm/mach-imx/src.c
@@ -140,3 +140,14 @@ void __init imx_src_init(void)
 	writel_relaxed(val, src_base + SRC_SCR);
 	spin_unlock(&scr_lock);
 }
+
+void __init vf610_src_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,vf610-src");
+	if (!np)
+		return;
+	src_base = of_iomap(np, 0);
+	WARN_ON(!src_base);
+}
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 8/9] ARM: imx: clk-gate2: allow custom gate configuration
  2014-09-22 17:09 [PATCH 0/9] ARM: vf610: Suspend/resume support Stefan Agner
                   ` (6 preceding siblings ...)
  2014-09-22 17:09 ` [PATCH 7/9] ARM: imx: src: Support vf610 system reset controller Stefan Agner
@ 2014-09-22 17:09 ` Stefan Agner
  2014-09-28  2:02   ` Shawn Guo
  2014-09-22 17:09 ` [PATCH 9/9] ARM: vf610: initial suspend/resume support Stefan Agner
  2014-09-28  3:15 ` [PATCH 0/9] ARM: vf610: Suspend/resume support Shawn Guo
  9 siblings, 1 reply; 19+ messages in thread
From: Stefan Agner @ 2014-09-22 17:09 UTC (permalink / raw)
  To: shawn.guo, kernel, linus.walleij, gnurou
  Cc: linux, jingchang.lu, b20788, linux-arm-kernel, linux-kernel,
	linux-gpio, stefan

The 2-bit gates found i.MX and Vybrid SoC support different clock
configuration:

0b00: clk disabled
0b01: clk enabled in RUN mode but disabled in WAIT and STOP mode
0b10: clk enabled in RUN, WAIT and STOP mode (only Vybrid)
0b11: clk enabled in RUN and WAIT mode

For some clocks, we might want to configure different behaviour,
e.g. a memory clock should be on even in STOP mode. Add a new
function imx_clk_gate2_cgr which allow to configure specific
gate values through the cgr_val parameter.

Signed-off-by: Stefan Agner <stefan@agner.ch>
---
 arch/arm/mach-imx/clk-gate2.c           |  7 +++++--
 arch/arm/mach-imx/clk-vf610.c           |  3 +++
 arch/arm/mach-imx/clk.h                 | 13 ++++++++++---
 include/dt-bindings/clock/vf610-clock.h |  3 ++-
 4 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-imx/clk-gate2.c b/arch/arm/mach-imx/clk-gate2.c
index 84acdfd..8c22a84 100644
--- a/arch/arm/mach-imx/clk-gate2.c
+++ b/arch/arm/mach-imx/clk-gate2.c
@@ -31,6 +31,7 @@ struct clk_gate2 {
 	struct clk_hw hw;
 	void __iomem	*reg;
 	u8		bit_idx;
+	u8		cgr_val;
 	u8		flags;
 	spinlock_t	*lock;
 	unsigned int	*share_count;
@@ -50,7 +51,8 @@ static int clk_gate2_enable(struct clk_hw *hw)
 		goto out;
 
 	reg = readl(gate->reg);
-	reg |= 3 << gate->bit_idx;
+	reg &= ~(3 << gate->bit_idx);
+	reg |= gate->cgr_val << gate->bit_idx;
 	writel(reg, gate->reg);
 
 out:
@@ -110,7 +112,7 @@ static struct clk_ops clk_gate2_ops = {
 
 struct clk *clk_register_gate2(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
-		void __iomem *reg, u8 bit_idx,
+		void __iomem *reg, u8 bit_idx, u8 cgr_val,
 		u8 clk_gate2_flags, spinlock_t *lock,
 		unsigned int *share_count)
 {
@@ -125,6 +127,7 @@ struct clk *clk_register_gate2(struct device *dev, const char *name,
 	/* struct clk_gate2 assignments */
 	gate->reg = reg;
 	gate->bit_idx = bit_idx;
+	gate->cgr_val = cgr_val;
 	gate->flags = clk_gate2_flags;
 	gate->lock = lock;
 
diff --git a/arch/arm/mach-imx/clk-vf610.c b/arch/arm/mach-imx/clk-vf610.c
index a178184..1034e78 100644
--- a/arch/arm/mach-imx/clk-vf610.c
+++ b/arch/arm/mach-imx/clk-vf610.c
@@ -103,6 +103,7 @@ static struct clk_onecell_data clk_data;
 static unsigned int const clks_init_on[] __initconst = {
 	VF610_CLK_SYS_BUS,
 	VF610_CLK_DDR_SEL,
+	VF610_CLK_DDRMC,
 };
 
 static void __init vf610_clocks_init(struct device_node *ccm_node)
@@ -171,6 +172,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
 	clk[VF610_CLK_PLL4_MAIN_DIV] = clk_register_divider_table(NULL, "pll4_main_div", "pll4_main", 0, CCM_CACRR, 6, 3, 0, pll4_main_div_table, &imx_ccm_lock);
 	clk[VF610_CLK_PLL6_MAIN_DIV] = imx_clk_divider("pll6_main_div", "pll6_main", CCM_CACRR, 21, 1);
 
+	clk[VF610_CLK_DDRMC] = imx_clk_gate2_cgr("ddrmc", "ddr_sel", CCM_CCGR6, CCM_CCGRx_CGn(14), 0x2);
+
 	clk[VF610_CLK_USBPHY0] = imx_clk_gate("usbphy0", "pll3_main", PLL3_CTRL, 6);
 	clk[VF610_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll7_main", PLL7_CTRL, 6);
 
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index 4cdf8b6..d22e339 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -29,7 +29,7 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
 
 struct clk *clk_register_gate2(struct device *dev, const char *name,
 		const char *parent_name, unsigned long flags,
-		void __iomem *reg, u8 bit_idx,
+		void __iomem *reg, u8 bit_idx, u8 cgr_val,
 		u8 clk_gate_flags, spinlock_t *lock,
 		unsigned int *share_count);
 
@@ -43,7 +43,7 @@ static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
 		void __iomem *reg, u8 shift)
 {
 	return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
-			shift, 0, &imx_ccm_lock, NULL);
+			shift, 0x3, 0, &imx_ccm_lock, NULL);
 }
 
 static inline struct clk *imx_clk_gate2_shared(const char *name,
@@ -51,7 +51,14 @@ static inline struct clk *imx_clk_gate2_shared(const char *name,
 		unsigned int *share_count)
 {
 	return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
-			shift, 0, &imx_ccm_lock, share_count);
+			shift, 0x3, 0, &imx_ccm_lock, share_count);
+}
+
+static inline struct clk *imx_clk_gate2_cgr(const char *name,
+		const char *parent, void __iomem *reg, u8 shift, u8 cgr_val)
+{
+	return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
+			shift, cgr_val, 0, &imx_ccm_lock, NULL);
 }
 
 struct clk *imx_clk_pfd(const char *name, const char *parent_name,
diff --git a/include/dt-bindings/clock/vf610-clock.h b/include/dt-bindings/clock/vf610-clock.h
index d6b56b2..84c4809 100644
--- a/include/dt-bindings/clock/vf610-clock.h
+++ b/include/dt-bindings/clock/vf610-clock.h
@@ -169,6 +169,7 @@
 #define VF610_CLK_PLL7_MAIN		156
 #define VF610_CLK_USBPHY0		157
 #define VF610_CLK_USBPHY1		158
-#define VF610_CLK_END			159
+#define VF610_CLK_DDRMC			159
+#define VF610_CLK_END			160
 
 #endif /* __DT_BINDINGS_CLOCK_VF610_H */
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 9/9] ARM: vf610: initial suspend/resume support
  2014-09-22 17:09 [PATCH 0/9] ARM: vf610: Suspend/resume support Stefan Agner
                   ` (7 preceding siblings ...)
  2014-09-22 17:09 ` [PATCH 8/9] ARM: imx: clk-gate2: allow custom gate configuration Stefan Agner
@ 2014-09-22 17:09 ` Stefan Agner
  2014-09-28  3:15 ` [PATCH 0/9] ARM: vf610: Suspend/resume support Shawn Guo
  9 siblings, 0 replies; 19+ messages in thread
From: Stefan Agner @ 2014-09-22 17:09 UTC (permalink / raw)
  To: shawn.guo, kernel, linus.walleij, gnurou
  Cc: linux, jingchang.lu, b20788, linux-arm-kernel, linux-kernel,
	linux-gpio, stefan

This patch adds initial suspend/resume support for Vybrid SoC.
The standby sleep state puts the module in LP-RUN mode which
allows to the SoC to be woken by a regular interrupt. The mem
sleep state (Suspend-to-RAM) uses the STOP mode which puts the
memory in self-refresh mode but keeps the memory clock enabled.
To wake the SoC a power management wakeup IRQ need to be enabled
using irq_set_irq_wake (e.g. through a GPIO).

Signed-off-by: Stefan Agner <stefan@agner.ch>
---
 arch/arm/mach-imx/Makefile     |   1 +
 arch/arm/mach-imx/clk-vf610.c  |   3 +
 arch/arm/mach-imx/common.h     |  10 +
 arch/arm/mach-imx/mach-vf610.c |   1 +
 arch/arm/mach-imx/pm-vf610.c   | 428 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 443 insertions(+)
 create mode 100644 arch/arm/mach-imx/pm-vf610.c

diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 6e4fcd8..0f558aa 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -103,6 +103,7 @@ AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a
 obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o
 endif
 obj-$(CONFIG_SOC_IMX6) += pm-imx6.o
+obj-$(CONFIG_SOC_VF610) += pm-vf610.o
 
 obj-$(CONFIG_SOC_IMX50) += mach-imx50.o
 obj-$(CONFIG_SOC_IMX51) += mach-imx51.o
diff --git a/arch/arm/mach-imx/clk-vf610.c b/arch/arm/mach-imx/clk-vf610.c
index 1034e78..fbaa708 100644
--- a/arch/arm/mach-imx/clk-vf610.c
+++ b/arch/arm/mach-imx/clk-vf610.c
@@ -13,6 +13,7 @@
 #include <dt-bindings/clock/vf610-clock.h>
 
 #include "clk.h"
+#include "common.h"
 
 #define CCM_CCR			(ccm_base + 0x00)
 #define CCM_CSR			(ccm_base + 0x04)
@@ -131,6 +132,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
 	ccm_base = of_iomap(np, 0);
 	BUG_ON(!ccm_base);
 
+	vf610_pm_set_ccm_base(ccm_base);
+
 	clk[VF610_CLK_SLOW_CLK_SEL] = imx_clk_mux("slow_clk_sel", CCM_CCSR, 4, 1, slow_sels, ARRAY_SIZE(slow_sels));
 	clk[VF610_CLK_FASK_CLK_SEL] = imx_clk_mux("fast_clk_sel", CCM_CCSR, 5, 1, fast_sels, ARRAY_SIZE(fast_sels));
 
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index ca7a0d9..6dd360f 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -80,6 +80,13 @@ enum mxc_cpu_pwr_mode {
 	STOP_POWER_OFF,		/* STOP + SRPG */
 };
 
+enum vf610_cpu_pwr_mode {
+	VF610_RUN,
+	VF610_LP_RUN,
+	VF610_STOP,
+	VF610_LP_STOP,
+};
+
 enum mx3_cpu_pwr_mode {
 	MX3_RUN,
 	MX3_WAIT,
@@ -125,6 +132,7 @@ int imx_cpu_kill(unsigned int cpu);
 #ifdef CONFIG_SUSPEND
 void v7_cpu_resume(void);
 void imx6_suspend(void __iomem *ocram_vbase);
+void vf610_suspend(void);
 #else
 static inline void v7_cpu_resume(void) {}
 static inline void imx6_suspend(void __iomem *ocram_vbase) {}
@@ -135,6 +143,8 @@ void imx6dl_pm_init(void);
 void imx6sl_pm_init(void);
 void imx6sx_pm_init(void);
 void imx6q_pm_set_ccm_base(void __iomem *base);
+void vf610_pm_init(void);
+void vf610_pm_set_ccm_base(void __iomem *base);
 
 #ifdef CONFIG_PM
 void imx51_pm_init(void);
diff --git a/arch/arm/mach-imx/mach-vf610.c b/arch/arm/mach-imx/mach-vf610.c
index eef3496..79f0461 100644
--- a/arch/arm/mach-imx/mach-vf610.c
+++ b/arch/arm/mach-imx/mach-vf610.c
@@ -25,6 +25,7 @@ static void __init vf610_init_machine(void)
 {
 	mxc_arch_reset_init_dt();
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	vf610_pm_init();
 }
 
 static const char * const vf610_dt_compat[] __initconst = {
diff --git a/arch/arm/mach-imx/pm-vf610.c b/arch/arm/mach-imx/pm-vf610.c
new file mode 100644
index 0000000..87dbbac
--- /dev/null
+++ b/arch/arm/mach-imx/pm-vf610.c
@@ -0,0 +1,428 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2014 Toradex AG
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/genalloc.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+#include <linux/suspend.h>
+#include <linux/clk.h>
+#include <asm/cacheflush.h>
+#include <asm/fncpy.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+#include <asm/tlb.h>
+
+#include "common.h"
+
+#define CCR				0x0
+#define BM_CCR_FIRC_EN			(0x1 << 16)
+#define BM_CCR_FXOSC_EN			(0x1 << 12)
+
+#define CCSR				0x8
+#define BM_CCSR_DDRC_CLK_SEL		(0x1 << 6)
+#define BM_CCSR_FAST_CLK_SEL		(0x1 << 5)
+#define BM_CCSR_SLOW_CLK_SEL		(0x1 << 4)
+#define BM_CCSR_SYS_CLK_SEL_MASK	(0x7 << 0)
+
+#define CLPCR				0x2c
+#define BM_CLPCR_ARM_CLK_DIS_ON_LPM	(0x1 << 5)
+#define BM_CLPCR_SBYOS			(0x1 << 6)
+#define BM_CLPCR_DIS_REF_OSC		(0x1 << 7)
+#define BM_CLPCR_ANADIG_STOP_MODE	(0x1 << 8)
+#define BM_CLPCR_FXOSC_BYPSEN		(0x1 << 10)
+#define BM_CLPCR_FXOSC_PWRDWN		(0x1 << 11)
+#define BM_CLPCR_MASK_CORE0_WFI		(0x1 << 22)
+#define BM_CLPCR_MASK_CORE1_WFI		(0x1 << 23)
+#define BM_CLPCR_MASK_SCU_IDLE		(0x1 << 24)
+#define BM_CLPCR_MASK_L2CC_IDLE		(0x1 << 25)
+
+#define CGPR				0x64
+#define BM_CGPR_INT_MEM_CLK_LPM		(0x1 << 17)
+
+#define GPC_PGCR			0x0
+#define BM_PGCR_DS_STOP			(0x1 << 7)
+#define BM_PGCR_DS_LPSTOP		(0x1 << 6)
+#define BM_PGCR_WB_STOP			(0x1 << 4)
+#define BM_PGCR_HP_OFF			(0x1 << 3)
+
+#define GPC_LPMR			0x40
+#define BM_LPMR_RUN			0x0
+#define BM_LPMR_STOP			0x2
+
+#define ANATOP_PLL1_CTRL		0x270
+#define ANATOP_PLL2_CTRL		0x30
+#define ANATOP_PLL3_CTRL		0x10
+#define ANATOP_PLL4_CTRL		0x70
+#define ANATOP_PLL5_CTRL		0xe0
+#define ANATOP_PLL6_CTRL		0xa0
+#define ANATOP_PLL7_CTRL		0x10
+#define BM_PLL_ENABLE		(0x1 << 13)
+#define BM_PLL_LOCK		(0x1 << 31)
+
+#define VF610_SUSPEND_OCRAM_SIZE	0x4000
+
+#define VF_UART0_BASE_ADDR	0x40027000
+#define VF_UART1_BASE_ADDR	0x40028000
+#define VF_UART2_BASE_ADDR	0x40029000
+#define VF_UART3_BASE_ADDR	0x4002a000
+#define VF_UART_BASE_ADDR(n)	VF_UART##n##_BASE_ADDR
+#define VF_UART_BASE(n)		VF_UART_BASE_ADDR(n)
+#define VF_UART_PHYSICAL_BASE	VF_UART_BASE(CONFIG_DEBUG_VF_UART_PORT)
+
+static void __iomem *ccm_base;
+static void __iomem *suspend_ocram_base;
+
+/*
+ * suspend ocram space layout:
+ * ======================== high address ======================
+ *                              .
+ *                              .
+ *                              .
+ *                              ^
+ *                              ^
+ *                              ^
+ *                      vf610_suspend code
+ *              PM_INFO structure(vf610_cpu_pm_info)
+ * ======================== low address =======================
+ */
+
+struct vf610_pm_base {
+	phys_addr_t pbase;
+	void __iomem *vbase;
+};
+
+struct vf610_pm_socdata {
+	const char *src_compat;
+	const char *gpc_compat;
+	const char *anatop_compat;
+};
+
+static const struct vf610_pm_socdata vf610_pm_data __initconst = {
+	.src_compat = "fsl,vf610-src",
+	.gpc_compat = "fsl,vf610-gpc",
+	.anatop_compat = "fsl,vf610-anatop",
+};
+
+/*
+ * This structure is for passing necessary data for low level ocram
+ * suspend code(arch/arm/mach-imx/suspend-vf610.S), if this struct
+ * definition is changed, the offset definition in
+ * arch/arm/mach-imx/suspend-vf610.S must be also changed accordingly,
+ * otherwise, the suspend to ocram function will be broken!
+ */
+struct vf610_cpu_pm_info {
+	phys_addr_t pbase; /* The physical address of pm_info. */
+	phys_addr_t resume_addr; /* The physical resume address for asm code */
+	u32 cpu_type; /* Currently not used, leave it for alignment */
+	u32 pm_info_size; /* Size of pm_info. */
+	struct vf610_pm_base anatop_base;
+	struct vf610_pm_base src_base;
+	struct vf610_pm_base ccm_base;
+	struct vf610_pm_base gpc_base;
+	struct vf610_pm_base l2_base;
+} __aligned(8);
+
+#ifdef DEBUG
+static void uart_reinit(unsigned long int rate, unsigned long int baud)
+{
+	void __iomem *membase = ioremap(VF_UART_PHYSICAL_BASE, 0x1000);
+	u8 tmp;
+	u16 sbr, brfa;
+
+	/* UART_C2 */
+	__raw_writeb(0, membase + 0x3);
+
+	sbr = (u16) (rate / (baud * 16));
+	brfa = (rate / baud) - (sbr * 16);
+
+	tmp = ((sbr & 0x1f00) >> 8);
+	__raw_writeb(tmp, membase + 0x0);
+	tmp = sbr & 0x00ff;
+	__raw_writeb(tmp, membase + 0x1);
+
+	/* UART_C4 */
+	__raw_writeb(brfa & 0xf, membase + 0xa);
+
+	/* UART_C2 */
+	__raw_writeb(0xac, membase + 0x3);
+
+	iounmap(membase);
+}
+#else
+static void uart_reinit(unsigned long int rate, unsigned long int baud) {}
+#endif
+
+static void vf610_enable_pll(void __iomem *pll_base)
+{
+	writel_relaxed(readl_relaxed(pll_base) | BM_PLL_ENABLE, pll_base);
+}
+
+static void vf610_disable_pll(void __iomem *pll_base)
+{
+	writel_relaxed(readl_relaxed(pll_base) & ~BM_PLL_ENABLE, pll_base);
+}
+
+int vf610_set_lpm(enum vf610_cpu_pwr_mode mode)
+{
+	u32 ccr = readl_relaxed(ccm_base + CCR);
+	u32 ccsr = readl_relaxed(ccm_base + CCSR);
+	u32 cclpcr = readl_relaxed(ccm_base + CLPCR);
+	struct vf610_cpu_pm_info *pm_info = suspend_ocram_base;
+	void __iomem *gpc_base = pm_info->gpc_base.vbase;
+	u32 gpc_pgcr = readl_relaxed(gpc_base + GPC_PGCR);
+	void __iomem *anatop = pm_info->anatop_base.vbase;
+
+	switch (mode) {
+	case VF610_STOP:
+		cclpcr &= ~BM_CLPCR_ANADIG_STOP_MODE;
+		cclpcr |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
+		cclpcr &= ~BM_CLPCR_SBYOS;
+		writel_relaxed(cclpcr, ccm_base + CLPCR);
+
+		gpc_pgcr |= BM_PGCR_DS_STOP;
+		gpc_pgcr |= BM_PGCR_HP_OFF;
+		writel_relaxed(gpc_pgcr, gpc_base + GPC_PGCR);
+
+		writel_relaxed(BM_LPMR_STOP, gpc_base + GPC_LPMR);
+		/* fall-through */
+	case VF610_LP_RUN:
+		ccr |= BM_CCR_FIRC_EN;
+		writel_relaxed(ccr, ccm_base + CCR);
+
+		/* Switch internal OSC's */
+		ccsr &= ~BM_CCSR_FAST_CLK_SEL;
+		ccsr &= ~BM_CCSR_SLOW_CLK_SEL;
+		writel_relaxed(ccsr, ccm_base + CCSR);
+
+		ccsr &= ~BM_CCSR_SYS_CLK_SEL_MASK;
+		writel_relaxed(ccsr, ccm_base + CCSR);
+		uart_reinit(4000000UL, 115200);
+
+		vf610_disable_pll(anatop + ANATOP_PLL1_CTRL);
+		vf610_disable_pll(anatop + ANATOP_PLL3_CTRL);
+		vf610_disable_pll(anatop + ANATOP_PLL5_CTRL);
+		vf610_disable_pll(anatop + ANATOP_PLL7_CTRL);
+		break;
+	case VF610_RUN:
+		vf610_enable_pll(anatop + ANATOP_PLL1_CTRL);
+		vf610_enable_pll(anatop + ANATOP_PLL3_CTRL);
+		vf610_enable_pll(anatop + ANATOP_PLL5_CTRL);
+		vf610_enable_pll(anatop + ANATOP_PLL7_CTRL);
+
+		ccsr &= ~BM_CCSR_SYS_CLK_SEL_MASK;
+		ccsr |= 0x4;
+		writel_relaxed(ccsr, ccm_base + CCSR);
+		uart_reinit(83368421UL, 115200);
+
+		writel_relaxed(BM_LPMR_RUN, gpc_base + GPC_LPMR);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vf610_pm_enter(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_STANDBY:
+		vf610_set_lpm(VF610_LP_RUN);
+		imx_gpc_pre_suspend(false);
+
+		/* zzZZZzzz */
+		cpu_do_idle();
+
+		imx_gpc_post_resume();
+		vf610_set_lpm(VF610_RUN);
+		break;
+	case PM_SUSPEND_MEM:
+		vf610_set_lpm(VF610_STOP);
+		imx_gpc_pre_suspend(false);
+
+		cpu_do_idle();
+
+		imx_gpc_post_resume();
+		vf610_set_lpm(VF610_RUN);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int vf610_pm_valid(suspend_state_t state)
+{
+	return (state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM);
+}
+
+static const struct platform_suspend_ops vf610_pm_ops = {
+	.enter = vf610_pm_enter,
+	.valid = vf610_pm_valid,
+};
+
+void __init vf610_pm_set_ccm_base(void __iomem *base)
+{
+	ccm_base = base;
+}
+
+static int __init imx_pm_get_base(struct vf610_pm_base *base,
+				const char *compat)
+{
+	struct device_node *node;
+	struct resource res;
+	int ret = 0;
+
+	node = of_find_compatible_node(NULL, NULL, compat);
+	if (!node) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	ret = of_address_to_resource(node, 0, &res);
+	if (ret)
+		goto put_node;
+
+	base->pbase = res.start;
+	base->vbase = ioremap(res.start, resource_size(&res));
+
+	if (!base->vbase)
+		ret = -ENOMEM;
+
+put_node:
+	of_node_put(node);
+out:
+	return ret;
+}
+
+static int __init vf610_suspend_init(const struct vf610_pm_socdata *socdata)
+{
+	phys_addr_t ocram_pbase;
+	struct device_node *node;
+	struct platform_device *pdev;
+	struct vf610_cpu_pm_info *pm_info;
+	struct gen_pool *ocram_pool;
+	unsigned long ocram_base;
+	int ret = 0;
+
+	suspend_set_ops(&vf610_pm_ops);
+
+	if (!socdata) {
+		pr_warn("%s: invalid argument!\n", __func__);
+		return -EINVAL;
+	}
+
+	node = of_find_compatible_node(NULL, NULL, "mmio-sram");
+	if (!node) {
+		pr_warn("%s: failed to find ocram node!\n", __func__);
+		return -ENODEV;
+	}
+
+	pdev = of_find_device_by_node(node);
+	if (!pdev) {
+		pr_warn("%s: failed to find ocram device!\n", __func__);
+		ret = -ENODEV;
+		goto put_node;
+	}
+
+	ocram_pool = dev_get_gen_pool(&pdev->dev);
+	if (!ocram_pool) {
+		pr_warn("%s: ocram pool unavailable!\n", __func__);
+		ret = -ENODEV;
+		goto put_node;
+	}
+
+	ocram_base = gen_pool_alloc(ocram_pool, VF610_SUSPEND_OCRAM_SIZE);
+	if (!ocram_base) {
+		pr_warn("%s: unable to alloc ocram!\n", __func__);
+		ret = -ENOMEM;
+		goto put_node;
+	}
+
+	ocram_pbase = gen_pool_virt_to_phys(ocram_pool, ocram_base);
+
+	suspend_ocram_base = __arm_ioremap_exec(ocram_pbase,
+		VF610_SUSPEND_OCRAM_SIZE, false);
+
+	pm_info = suspend_ocram_base;
+	pm_info->pbase = ocram_pbase;
+	pm_info->pm_info_size = sizeof(*pm_info);
+
+	/*
+	 * ccm physical address is not used by asm code currently,
+	 * so get ccm virtual address directly, as we already have
+	 * it from ccm driver.
+	 */
+	pm_info->ccm_base.vbase = ccm_base;
+
+	ret = imx_pm_get_base(&pm_info->anatop_base, socdata->anatop_compat);
+	if (ret) {
+		pr_warn("%s: failed to get anatop base %d!\n", __func__, ret);
+		goto put_node;
+	}
+
+	ret = imx_pm_get_base(&pm_info->src_base, socdata->src_compat);
+	if (ret) {
+		pr_warn("%s: failed to get src base %d!\n", __func__, ret);
+		goto src_map_failed;
+	}
+
+	ret = imx_pm_get_base(&pm_info->gpc_base, socdata->gpc_compat);
+	if (ret) {
+		pr_warn("%s: failed to get gpc base %d!\n", __func__, ret);
+		goto gpc_map_failed;
+	}
+
+	ret = imx_pm_get_base(&pm_info->l2_base, "arm,pl310-cache");
+	if (ret) {
+		pr_warn("%s: failed to get pl310-cache base %d!\n",
+			__func__, ret);
+		goto pl310_cache_map_failed;
+	}
+
+	goto put_node;
+
+pl310_cache_map_failed:
+	iounmap(&pm_info->gpc_base.vbase);
+gpc_map_failed:
+	iounmap(&pm_info->src_base.vbase);
+src_map_failed:
+	iounmap(&pm_info->anatop_base.vbase);
+put_node:
+	of_node_put(node);
+
+	return ret;
+}
+
+void __init vf610_pm_init(void)
+{
+	int ret;
+
+	WARN_ON(!ccm_base);
+
+	if (IS_ENABLED(CONFIG_SUSPEND)) {
+		ret = vf610_suspend_init(&vf610_pm_data);
+		if (ret)
+			pr_warn("%s: No DDR LPM support with suspend %d!\n",
+				__func__, ret);
+	}
+}
+
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/9] ARM: dts: vf610: Add system reset controller (SRC)
  2014-09-22 17:09 ` [PATCH 1/9] ARM: dts: vf610: Add system reset controller (SRC) Stefan Agner
@ 2014-09-24  9:16   ` Linus Walleij
  2014-09-24 16:41     ` Stefan Agner
  0 siblings, 1 reply; 19+ messages in thread
From: Linus Walleij @ 2014-09-24  9:16 UTC (permalink / raw)
  To: Stefan Agner
  Cc: Shawn Guo, Sascha Hauer, Alexandre Courbot,
	Russell King - ARM Linux, jingchang.lu, Huang Yongcai-B20788,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org

On Mon, Sep 22, 2014 at 7:09 PM, Stefan Agner <stefan@agner.ch> wrote:

> Add device tree property for system reset controller.
>
> Signed-off-by: Stefan Agner <stefan@agner.ch>

Are there already device tree bindings for SRC and GRC?

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 5/9] gpio: vf610: Extend with wakeup support
  2014-09-22 17:09 ` [PATCH 5/9] gpio: vf610: Extend with wakeup support Stefan Agner
@ 2014-09-24  9:19   ` Linus Walleij
  2014-09-24 16:33     ` Stefan Agner
  2014-09-24 10:06   ` Lucas Stach
  1 sibling, 1 reply; 19+ messages in thread
From: Linus Walleij @ 2014-09-24  9:19 UTC (permalink / raw)
  To: Stefan Agner
  Cc: Shawn Guo, Sascha Hauer, Alexandre Courbot,
	Russell King - ARM Linux, jingchang.lu, Huang Yongcai-B20788,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org

On Mon, Sep 22, 2014 at 7:09 PM, Stefan Agner <stefan@agner.ch> wrote:

> Support Vybrid GPIO's as wakeup source by requesting the parent
> IRQ as wakeup IRQ.
>
> Signed-off-by: Stefan Agner <stefan@agner.ch>
> ---
>  drivers/gpio/gpio-vf610.c | 16 ++++++++++++++++

This driver is not yet upstream. Make wakeup support part
of the initial driver submission instead, it doesn't hurt.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 5/9] gpio: vf610: Extend with wakeup support
  2014-09-22 17:09 ` [PATCH 5/9] gpio: vf610: Extend with wakeup support Stefan Agner
  2014-09-24  9:19   ` Linus Walleij
@ 2014-09-24 10:06   ` Lucas Stach
  2014-09-24 16:51     ` Stefan Agner
  1 sibling, 1 reply; 19+ messages in thread
From: Lucas Stach @ 2014-09-24 10:06 UTC (permalink / raw)
  To: Stefan Agner
  Cc: shawn.guo, kernel, linus.walleij, gnurou, linux, jingchang.lu,
	b20788, linux-arm-kernel, linux-kernel, linux-gpio

Hi Stefan,

Am Montag, den 22.09.2014, 19:09 +0200 schrieb Stefan Agner:
> Support Vybrid GPIO's as wakeup source by requesting the parent
> IRQ as wakeup IRQ.
> 
> Signed-off-by: Stefan Agner <stefan@agner.ch>
> ---
>  drivers/gpio/gpio-vf610.c | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
> 
> diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
> index 5f59424..50326af 100644
> --- a/drivers/gpio/gpio-vf610.c
> +++ b/drivers/gpio/gpio-vf610.c
> @@ -196,12 +196,28 @@ static void vf610_gpio_irq_unmask(struct irq_data *d)
>  			  pcr_base);
>  }
>  
> +static int vf610_gpio_irq_set_wake(struct irq_data *d, u32 enable)
> +{
> +	struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
> +
> +	if (enable)
> +		enable_irq_wake(port->irq);
> +	else
> +		disable_irq_wake(port->irq);
> +
> +	return 0;
> +}
> +
> +
>  static struct irq_chip vf610_gpio_irq_chip = {
>  	.name		= "gpio-vf610",
>  	.irq_ack	= vf610_gpio_irq_ack,
>  	.irq_mask	= vf610_gpio_irq_mask,
>  	.irq_unmask	= vf610_gpio_irq_unmask,
>  	.irq_set_type	= vf610_gpio_irq_set_type,
> +#ifdef CONFIG_PM_SLEEP
> +	.irq_set_wake	= vf610_gpio_irq_set_wake,
> +#endif

Either you need to get rid of this #ifdef and always assign this
function or you need to wrap the function itself into the same #ifdef.
Otherwise you provoke a unused function warning with !CONFIG_PM_SLEEP.

Given that this function isn't really that big I would argue to just
drop the #ifdef.

Regards,
Lucas 

-- 
Pengutronix e.K.             | Lucas Stach                 |
Industrial Linux Solutions   | http://www.pengutronix.de/  |


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 5/9] gpio: vf610: Extend with wakeup support
  2014-09-24  9:19   ` Linus Walleij
@ 2014-09-24 16:33     ` Stefan Agner
  0 siblings, 0 replies; 19+ messages in thread
From: Stefan Agner @ 2014-09-24 16:33 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Alexandre Courbot, Russell King - ARM Linux, linux-kernel,
	linux-gpio, linux-arm-kernel, Sascha Hauer, jingchang.lu,
	Huang Yongcai-B20788, Shawn Guo

Am 2014-09-24 11:19, schrieb Linus Walleij:
> On Mon, Sep 22, 2014 at 7:09 PM, Stefan Agner <stefan@agner.ch> wrote:
> 
>> Support Vybrid GPIO's as wakeup source by requesting the parent
>> IRQ as wakeup IRQ.
>>
>> Signed-off-by: Stefan Agner <stefan@agner.ch>
>> ---
>>  drivers/gpio/gpio-vf610.c | 16 ++++++++++++++++
> 
> This driver is not yet upstream. Make wakeup support part
> of the initial driver submission instead, it doesn't hurt.

Ok, will do. 

Just realized that this patch even leads to compile errors when applying
on top of v2 of the GPIO driver; we need the irq in drivers struct here,
and I removed that in v2...  :-)

--
Stefan

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/9] ARM: dts: vf610: Add system reset controller (SRC)
  2014-09-24  9:16   ` Linus Walleij
@ 2014-09-24 16:41     ` Stefan Agner
  2014-09-25 13:08       ` Philipp Zabel
  0 siblings, 1 reply; 19+ messages in thread
From: Stefan Agner @ 2014-09-24 16:41 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Shawn Guo, Sascha Hauer, Alexandre Courbot,
	Russell King - ARM Linux, jingchang.lu, Huang Yongcai-B20788,
	linux-arm-kernel, linux-kernel, linux-gpio

Am 2014-09-24 11:16, schrieb Linus Walleij:
> On Mon, Sep 22, 2014 at 7:09 PM, Stefan Agner <stefan@agner.ch> wrote:
> 
>> Add device tree property for system reset controller.
>>
>> Signed-off-by: Stefan Agner <stefan@agner.ch>
> 
> Are there already device tree bindings for SRC and GRC?

Yes there are used in the i.MX6 world for instance, see imx6qdl.dtsi.
The SRC also has quite generic documentation, however, the GPC module
currently lacks documentation...

--
Stefan


^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 5/9] gpio: vf610: Extend with wakeup support
  2014-09-24 10:06   ` Lucas Stach
@ 2014-09-24 16:51     ` Stefan Agner
  0 siblings, 0 replies; 19+ messages in thread
From: Stefan Agner @ 2014-09-24 16:51 UTC (permalink / raw)
  To: Lucas Stach
  Cc: shawn.guo, kernel, linus.walleij, gnurou, linux, jingchang.lu,
	b20788, linux-arm-kernel, linux-kernel, linux-gpio

Am 2014-09-24 12:06, schrieb Lucas Stach:
> Hi Stefan,
> 
> Am Montag, den 22.09.2014, 19:09 +0200 schrieb Stefan Agner:
>> Support Vybrid GPIO's as wakeup source by requesting the parent
>> IRQ as wakeup IRQ.
>>
>> Signed-off-by: Stefan Agner <stefan@agner.ch>
>> ---
>>  drivers/gpio/gpio-vf610.c | 16 ++++++++++++++++
>>  1 file changed, 16 insertions(+)
>>
>> diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
>> index 5f59424..50326af 100644
>> --- a/drivers/gpio/gpio-vf610.c
>> +++ b/drivers/gpio/gpio-vf610.c
>> @@ -196,12 +196,28 @@ static void vf610_gpio_irq_unmask(struct irq_data *d)
>>  			  pcr_base);
>>  }
>>
>> +static int vf610_gpio_irq_set_wake(struct irq_data *d, u32 enable)
>> +{
>> +	struct vf610_gpio_port *port = irq_data_get_irq_chip_data(d);
>> +
>> +	if (enable)
>> +		enable_irq_wake(port->irq);
>> +	else
>> +		disable_irq_wake(port->irq);
>> +
>> +	return 0;
>> +}
>> +
>> +
>>  static struct irq_chip vf610_gpio_irq_chip = {
>>  	.name		= "gpio-vf610",
>>  	.irq_ack	= vf610_gpio_irq_ack,
>>  	.irq_mask	= vf610_gpio_irq_mask,
>>  	.irq_unmask	= vf610_gpio_irq_unmask,
>>  	.irq_set_type	= vf610_gpio_irq_set_type,
>> +#ifdef CONFIG_PM_SLEEP
>> +	.irq_set_wake	= vf610_gpio_irq_set_wake,
>> +#endif
> 
> Either you need to get rid of this #ifdef and always assign this
> function or you need to wrap the function itself into the same #ifdef.
> Otherwise you provoke a unused function warning with !CONFIG_PM_SLEEP.
> 
> Given that this function isn't really that big I would argue to just
> drop the #ifdef.
> 

Good point, thx! I will drop the #ifdef when including that patch to the
GPIO driver (as Linus Walleij suggested).

--
Stefan

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 1/9] ARM: dts: vf610: Add system reset controller (SRC)
  2014-09-24 16:41     ` Stefan Agner
@ 2014-09-25 13:08       ` Philipp Zabel
  0 siblings, 0 replies; 19+ messages in thread
From: Philipp Zabel @ 2014-09-25 13:08 UTC (permalink / raw)
  To: Stefan Agner
  Cc: Linus Walleij, Shawn Guo, Sascha Hauer, Alexandre Courbot,
	Russell King - ARM Linux, jingchang.lu, Huang Yongcai-B20788,
	linux-arm-kernel, linux-kernel, linux-gpio

Hi Stefan,

Am Mittwoch, den 24.09.2014, 18:41 +0200 schrieb Stefan Agner:
> Am 2014-09-24 11:16, schrieb Linus Walleij:
> > On Mon, Sep 22, 2014 at 7:09 PM, Stefan Agner <stefan@agner.ch> wrote:
> > 
> >> Add device tree property for system reset controller.
> >>
> >> Signed-off-by: Stefan Agner <stefan@agner.ch>
> > 
> > Are there already device tree bindings for SRC and GRC?
> 
> Yes there are used in the i.MX6 world for instance, see imx6qdl.dtsi.
> The SRC also has quite generic documentation, however, the GPC module
> currently lacks documentation...

A patch that adds GPC binding documentation is part of this i.MX6 power
domain series:

http://www.spinics.net/lists/devicetree/msg48454.html

regards
Philipp

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 8/9] ARM: imx: clk-gate2: allow custom gate configuration
  2014-09-22 17:09 ` [PATCH 8/9] ARM: imx: clk-gate2: allow custom gate configuration Stefan Agner
@ 2014-09-28  2:02   ` Shawn Guo
  0 siblings, 0 replies; 19+ messages in thread
From: Shawn Guo @ 2014-09-28  2:02 UTC (permalink / raw)
  To: Stefan Agner
  Cc: kernel, linus.walleij, gnurou, linux, jingchang.lu, b20788,
	linux-arm-kernel, linux-kernel, linux-gpio

On Mon, Sep 22, 2014 at 07:09:29PM +0200, Stefan Agner wrote:
> The 2-bit gates found i.MX and Vybrid SoC support different clock
> configuration:
> 
> 0b00: clk disabled
> 0b01: clk enabled in RUN mode but disabled in WAIT and STOP mode
> 0b10: clk enabled in RUN, WAIT and STOP mode (only Vybrid)
> 0b11: clk enabled in RUN and WAIT mode
> 
> For some clocks, we might want to configure different behaviour,
> e.g. a memory clock should be on even in STOP mode. Add a new
> function imx_clk_gate2_cgr which allow to configure specific
> gate values through the cgr_val parameter.
> 
> Signed-off-by: Stefan Agner <stefan@agner.ch>
> ---
>  arch/arm/mach-imx/clk-gate2.c           |  7 +++++--
>  arch/arm/mach-imx/clk-vf610.c           |  3 +++
>  arch/arm/mach-imx/clk.h                 | 13 ++++++++++---
>  include/dt-bindings/clock/vf610-clock.h |  3 ++-

The patch should be split into two, one for clk-gate2 and the other for
clk-vf610 driver change.  Other than that, the patch looks good to me.

Shawn

>  4 files changed, 20 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arm/mach-imx/clk-gate2.c b/arch/arm/mach-imx/clk-gate2.c
> index 84acdfd..8c22a84 100644
> --- a/arch/arm/mach-imx/clk-gate2.c
> +++ b/arch/arm/mach-imx/clk-gate2.c
> @@ -31,6 +31,7 @@ struct clk_gate2 {
>  	struct clk_hw hw;
>  	void __iomem	*reg;
>  	u8		bit_idx;
> +	u8		cgr_val;
>  	u8		flags;
>  	spinlock_t	*lock;
>  	unsigned int	*share_count;
> @@ -50,7 +51,8 @@ static int clk_gate2_enable(struct clk_hw *hw)
>  		goto out;
>  
>  	reg = readl(gate->reg);
> -	reg |= 3 << gate->bit_idx;
> +	reg &= ~(3 << gate->bit_idx);
> +	reg |= gate->cgr_val << gate->bit_idx;
>  	writel(reg, gate->reg);
>  
>  out:
> @@ -110,7 +112,7 @@ static struct clk_ops clk_gate2_ops = {
>  
>  struct clk *clk_register_gate2(struct device *dev, const char *name,
>  		const char *parent_name, unsigned long flags,
> -		void __iomem *reg, u8 bit_idx,
> +		void __iomem *reg, u8 bit_idx, u8 cgr_val,
>  		u8 clk_gate2_flags, spinlock_t *lock,
>  		unsigned int *share_count)
>  {
> @@ -125,6 +127,7 @@ struct clk *clk_register_gate2(struct device *dev, const char *name,
>  	/* struct clk_gate2 assignments */
>  	gate->reg = reg;
>  	gate->bit_idx = bit_idx;
> +	gate->cgr_val = cgr_val;
>  	gate->flags = clk_gate2_flags;
>  	gate->lock = lock;
>  
> diff --git a/arch/arm/mach-imx/clk-vf610.c b/arch/arm/mach-imx/clk-vf610.c
> index a178184..1034e78 100644
> --- a/arch/arm/mach-imx/clk-vf610.c
> +++ b/arch/arm/mach-imx/clk-vf610.c
> @@ -103,6 +103,7 @@ static struct clk_onecell_data clk_data;
>  static unsigned int const clks_init_on[] __initconst = {
>  	VF610_CLK_SYS_BUS,
>  	VF610_CLK_DDR_SEL,
> +	VF610_CLK_DDRMC,
>  };
>  
>  static void __init vf610_clocks_init(struct device_node *ccm_node)
> @@ -171,6 +172,8 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
>  	clk[VF610_CLK_PLL4_MAIN_DIV] = clk_register_divider_table(NULL, "pll4_main_div", "pll4_main", 0, CCM_CACRR, 6, 3, 0, pll4_main_div_table, &imx_ccm_lock);
>  	clk[VF610_CLK_PLL6_MAIN_DIV] = imx_clk_divider("pll6_main_div", "pll6_main", CCM_CACRR, 21, 1);
>  
> +	clk[VF610_CLK_DDRMC] = imx_clk_gate2_cgr("ddrmc", "ddr_sel", CCM_CCGR6, CCM_CCGRx_CGn(14), 0x2);
> +
>  	clk[VF610_CLK_USBPHY0] = imx_clk_gate("usbphy0", "pll3_main", PLL3_CTRL, 6);
>  	clk[VF610_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll7_main", PLL7_CTRL, 6);
>  
> diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
> index 4cdf8b6..d22e339 100644
> --- a/arch/arm/mach-imx/clk.h
> +++ b/arch/arm/mach-imx/clk.h
> @@ -29,7 +29,7 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
>  
>  struct clk *clk_register_gate2(struct device *dev, const char *name,
>  		const char *parent_name, unsigned long flags,
> -		void __iomem *reg, u8 bit_idx,
> +		void __iomem *reg, u8 bit_idx, u8 cgr_val,
>  		u8 clk_gate_flags, spinlock_t *lock,
>  		unsigned int *share_count);
>  
> @@ -43,7 +43,7 @@ static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
>  		void __iomem *reg, u8 shift)
>  {
>  	return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
> -			shift, 0, &imx_ccm_lock, NULL);
> +			shift, 0x3, 0, &imx_ccm_lock, NULL);
>  }
>  
>  static inline struct clk *imx_clk_gate2_shared(const char *name,
> @@ -51,7 +51,14 @@ static inline struct clk *imx_clk_gate2_shared(const char *name,
>  		unsigned int *share_count)
>  {
>  	return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
> -			shift, 0, &imx_ccm_lock, share_count);
> +			shift, 0x3, 0, &imx_ccm_lock, share_count);
> +}
> +
> +static inline struct clk *imx_clk_gate2_cgr(const char *name,
> +		const char *parent, void __iomem *reg, u8 shift, u8 cgr_val)
> +{
> +	return clk_register_gate2(NULL, name, parent, CLK_SET_RATE_PARENT, reg,
> +			shift, cgr_val, 0, &imx_ccm_lock, NULL);
>  }
>  
>  struct clk *imx_clk_pfd(const char *name, const char *parent_name,
> diff --git a/include/dt-bindings/clock/vf610-clock.h b/include/dt-bindings/clock/vf610-clock.h
> index d6b56b2..84c4809 100644
> --- a/include/dt-bindings/clock/vf610-clock.h
> +++ b/include/dt-bindings/clock/vf610-clock.h
> @@ -169,6 +169,7 @@
>  #define VF610_CLK_PLL7_MAIN		156
>  #define VF610_CLK_USBPHY0		157
>  #define VF610_CLK_USBPHY1		158
> -#define VF610_CLK_END			159
> +#define VF610_CLK_DDRMC			159
> +#define VF610_CLK_END			160
>  
>  #endif /* __DT_BINDINGS_CLOCK_VF610_H */
> -- 
> 2.1.0
> 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH 0/9] ARM: vf610: Suspend/resume support
  2014-09-22 17:09 [PATCH 0/9] ARM: vf610: Suspend/resume support Stefan Agner
                   ` (8 preceding siblings ...)
  2014-09-22 17:09 ` [PATCH 9/9] ARM: vf610: initial suspend/resume support Stefan Agner
@ 2014-09-28  3:15 ` Shawn Guo
  9 siblings, 0 replies; 19+ messages in thread
From: Shawn Guo @ 2014-09-28  3:15 UTC (permalink / raw)
  To: Stefan Agner
  Cc: kernel, linus.walleij, gnurou, linux, jingchang.lu, b20788,
	linux-arm-kernel, linux-kernel, linux-gpio

On Mon, Sep 22, 2014 at 07:09:21PM +0200, Stefan Agner wrote:
> This patchset provides suspend/resume support for Freescale Vybrid
> SoC (vf610). The code is generally aligned to the implementation
> for i.MX6. The subsystems SRC and GPC need some changes to support
> the Vybrid specific implementation.
> 
> This patchset relies on GPIO driver to be present (in order to
> provide a wakeup source) as well as using the ARM Global Timer
> clock source (the Vybrid specifc PIT clock source, vf_pit_timer.c
> does not support shutdown).
> 
> The implemented sleep states (LP-RUN and STOP), are not the most
> power saving functions available on Vybrid. Especially for
> suspend-to-memory one of the LPSTOP modes looks more appropriate.
> However, the complexity is somewhat higher (we would need to move
> execution path to SRAM and store IOMUX and DDRMC configuration).
> Currently, I have not the resources to look into that so I hope
> that this initial code qualifies as power saving functions to be
> applied.

So you have quite a lot of unnecessary code which is only needed by
suspend from SRAM (store IOMUX and DDRMC configuration).

Not happy with that.

Shawn

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2014-09-28  3:15 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-22 17:09 [PATCH 0/9] ARM: vf610: Suspend/resume support Stefan Agner
2014-09-22 17:09 ` [PATCH 1/9] ARM: dts: vf610: Add system reset controller (SRC) Stefan Agner
2014-09-24  9:16   ` Linus Walleij
2014-09-24 16:41     ` Stefan Agner
2014-09-25 13:08       ` Philipp Zabel
2014-09-22 17:09 ` [PATCH 2/9] ARM: dts: vf610: add global power controller (GPC) Stefan Agner
2014-09-22 17:09 ` [PATCH 3/9] ARM: dts: vf610: add on-chip SRAM Stefan Agner
2014-09-22 17:09 ` [PATCH 4/9] ARM: dts: vf610-colibri: GPIO power key Stefan Agner
2014-09-22 17:09 ` [PATCH 5/9] gpio: vf610: Extend with wakeup support Stefan Agner
2014-09-24  9:19   ` Linus Walleij
2014-09-24 16:33     ` Stefan Agner
2014-09-24 10:06   ` Lucas Stach
2014-09-24 16:51     ` Stefan Agner
2014-09-22 17:09 ` [PATCH 6/9] ARM: imx: gpc: Support vf610 global power controller Stefan Agner
2014-09-22 17:09 ` [PATCH 7/9] ARM: imx: src: Support vf610 system reset controller Stefan Agner
2014-09-22 17:09 ` [PATCH 8/9] ARM: imx: clk-gate2: allow custom gate configuration Stefan Agner
2014-09-28  2:02   ` Shawn Guo
2014-09-22 17:09 ` [PATCH 9/9] ARM: vf610: initial suspend/resume support Stefan Agner
2014-09-28  3:15 ` [PATCH 0/9] ARM: vf610: Suspend/resume support Shawn Guo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).