From 707aa45d2612778e2f3b6c5e1950ed9fa48974aa Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 19 Dec 2017 16:54:44 +0100 Subject: soc: renesas: rcar-sysc: Mark rcar_sysc_matches[] __initconst rcar_sysc_matches[] is used only by rcar_sysc_pd_init(), which is __init. Hence mark rcar_sysc_matches[] __initconst. This frees another 1764 bytes (arm32/shmobile_defconfig) or 1000 bytes (arm64/renesas_defconfig) of memory after kernel init. Signed-off-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- drivers/soc/renesas/rcar-sysc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index 52c25a5e2646..636872bc2416 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -254,7 +254,7 @@ finalize: pm_genpd_init(genpd, gov, false); } -static const struct of_device_id rcar_sysc_matches[] = { +static const struct of_device_id rcar_sysc_matches[] __initconst = { #ifdef CONFIG_SYSC_R8A7743 { .compatible = "renesas,r8a7743-sysc", .data = &r8a7743_sysc_info }, #endif -- cgit v1.2.3 From 8447756d1e582a401cdae33c9ed5d68fdb6e0410 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 2 Feb 2018 21:22:14 +0300 Subject: soc: renesas: identify R-Car V3H Add support for identifying the R-Car V3H (R8A77980) SoC. Signed-off-by: Sergei Shtylyov Reviewed-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- drivers/soc/renesas/renesas-soc.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/soc') diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c index 926b7fd6db2d..000834321774 100644 --- a/drivers/soc/renesas/renesas-soc.c +++ b/drivers/soc/renesas/renesas-soc.c @@ -149,6 +149,11 @@ static const struct renesas_soc soc_rcar_v3m __initconst __maybe_unused = { .id = 0x54, }; +static const struct renesas_soc soc_rcar_v3h __initconst __maybe_unused = { + .family = &fam_rcar_gen3, + .id = 0x56, +}; + static const struct renesas_soc soc_rcar_d3 __initconst __maybe_unused = { .family = &fam_rcar_gen3, .id = 0x58, @@ -212,6 +217,9 @@ static const struct of_device_id renesas_socs[] __initconst = { #ifdef CONFIG_ARCH_R8A77970 { .compatible = "renesas,r8a77970", .data = &soc_rcar_v3m }, #endif +#ifdef CONFIG_ARCH_R8A77980 + { .compatible = "renesas,r8a77980", .data = &soc_rcar_v3h }, +#endif #ifdef CONFIG_ARCH_R8A77995 { .compatible = "renesas,r8a77995", .data = &soc_rcar_d3 }, #endif -- cgit v1.2.3 From 7d7b619e16d420b723d6618c60a0aaf0ba4e3666 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 2 Feb 2018 21:27:01 +0300 Subject: soc: renesas: rcar-rst: add R8A77980 support Add support for R-Car V3H (R8A77980) to the R-Car RST driver -- this driver is needed for the clock driver to work. Signed-off-by: Sergei Shtylyov Reviewed-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- Documentation/devicetree/bindings/reset/renesas,rst.txt | 1 + drivers/soc/renesas/Kconfig | 2 +- drivers/soc/renesas/rcar-rst.c | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/soc') diff --git a/Documentation/devicetree/bindings/reset/renesas,rst.txt b/Documentation/devicetree/bindings/reset/renesas,rst.txt index a8014f3ab8ba..a55b88658446 100644 --- a/Documentation/devicetree/bindings/reset/renesas,rst.txt +++ b/Documentation/devicetree/bindings/reset/renesas,rst.txt @@ -27,6 +27,7 @@ Required properties: - "renesas,r8a7795-rst" (R-Car H3) - "renesas,r8a7796-rst" (R-Car M3-W) - "renesas,r8a77970-rst" (R-Car V3M) + - "renesas,r8a77980-rst" (R-Car V3H) - "renesas,r8a77995-rst" (R-Car D3) - reg: Address start and address range for the device. diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 09550b1da56d..6efd7bef8577 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -4,7 +4,7 @@ config SOC_RENESAS select SOC_BUS select RST_RCAR if ARCH_RCAR_GEN1 || ARCH_RCAR_GEN2 || \ ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A77970 || \ - ARCH_R8A77995 + ARCH_R8A77980 || ARCH_R8A77995 select SYSC_R8A7743 if ARCH_R8A7743 select SYSC_R8A7745 if ARCH_R8A7745 select SYSC_R8A7779 if ARCH_R8A7779 diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c index 3316b028f231..e2340eb9ea9c 100644 --- a/drivers/soc/renesas/rcar-rst.c +++ b/drivers/soc/renesas/rcar-rst.c @@ -42,6 +42,7 @@ static const struct of_device_id rcar_rst_matches[] __initconst = { { .compatible = "renesas,r8a7795-rst", .data = &rcar_rst_gen2 }, { .compatible = "renesas,r8a7796-rst", .data = &rcar_rst_gen2 }, { .compatible = "renesas,r8a77970-rst", .data = &rcar_rst_gen2 }, + { .compatible = "renesas,r8a77980-rst", .data = &rcar_rst_gen2 }, { .compatible = "renesas,r8a77995-rst", .data = &rcar_rst_gen2 }, { /* sentinel */ } }; -- cgit v1.2.3 From 69e0d1b8db8f8cc319f966ec3eb2fffce28c4f28 Mon Sep 17 00:00:00 2001 From: Fabrizio Castro Date: Tue, 13 Feb 2018 13:02:44 +0000 Subject: soc: renesas: rcar-rst: Enable watchdog as reset trigger for Gen2 This patch allows for platform specific quirks as some of the SoC need further customization for the watchdog to work properly, like for R-Car Gen2 and for RZ/G. Signed-off-by: Fabrizio Castro Signed-off-by: Ramesh Shanmugasundaram Signed-off-by: Simon Horman --- drivers/soc/renesas/rcar-rst.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c index e2340eb9ea9c..34136664ece4 100644 --- a/drivers/soc/renesas/rcar-rst.c +++ b/drivers/soc/renesas/rcar-rst.c @@ -13,8 +13,18 @@ #include #include +#define WDTRSTCR_RESET 0xA55A0002 +#define WDTRSTCR 0x0054 + +static int rcar_rst_enable_wdt_reset(void __iomem *base) +{ + iowrite32(WDTRSTCR_RESET, base + WDTRSTCR); + return 0; +} + struct rst_config { - unsigned int modemr; /* Mode Monitoring Register Offset */ + unsigned int modemr; /* Mode Monitoring Register Offset */ + int (*configure)(void *base); /* Platform specific configuration */ }; static const struct rst_config rcar_rst_gen1 __initconst = { @@ -23,6 +33,11 @@ static const struct rst_config rcar_rst_gen1 __initconst = { static const struct rst_config rcar_rst_gen2 __initconst = { .modemr = 0x60, + .configure = rcar_rst_enable_wdt_reset, +}; + +static const struct rst_config rcar_rst_gen3 __initconst = { + .modemr = 0x60, }; static const struct of_device_id rcar_rst_matches[] __initconst = { @@ -38,12 +53,12 @@ static const struct of_device_id rcar_rst_matches[] __initconst = { { .compatible = "renesas,r8a7792-rst", .data = &rcar_rst_gen2 }, { .compatible = "renesas,r8a7793-rst", .data = &rcar_rst_gen2 }, { .compatible = "renesas,r8a7794-rst", .data = &rcar_rst_gen2 }, - /* R-Car Gen3 is handled like R-Car Gen2 */ - { .compatible = "renesas,r8a7795-rst", .data = &rcar_rst_gen2 }, - { .compatible = "renesas,r8a7796-rst", .data = &rcar_rst_gen2 }, - { .compatible = "renesas,r8a77970-rst", .data = &rcar_rst_gen2 }, - { .compatible = "renesas,r8a77980-rst", .data = &rcar_rst_gen2 }, - { .compatible = "renesas,r8a77995-rst", .data = &rcar_rst_gen2 }, + /* R-Car Gen3 */ + { .compatible = "renesas,r8a7795-rst", .data = &rcar_rst_gen3 }, + { .compatible = "renesas,r8a7796-rst", .data = &rcar_rst_gen3 }, + { .compatible = "renesas,r8a77970-rst", .data = &rcar_rst_gen3 }, + { .compatible = "renesas,r8a77980-rst", .data = &rcar_rst_gen3 }, + { .compatible = "renesas,r8a77995-rst", .data = &rcar_rst_gen3 }, { /* sentinel */ } }; @@ -72,6 +87,14 @@ static int __init rcar_rst_init(void) rcar_rst_base = base; cfg = match->data; saved_mode = ioread32(base + cfg->modemr); + if (cfg->configure) { + error = cfg->configure(base); + if (error) { + pr_warn("%pOF: Cannot run SoC specific configuration\n", + np); + goto out_put; + } + } pr_debug("%pOF: MODE = 0x%08x\n", np, saved_mode); -- cgit v1.2.3 From 40d5c8e94751f4a4fa4e0e27e3805e201a4e79c0 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 16 Feb 2018 23:09:48 +0300 Subject: soc: renesas: r8a77970-sysc: fix power area parents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the figure 9.2(b) of the R-Car Series, 3rd Generation User’s Manual: Hardware Rev. 0.80 the A2IRn and A2SCn power areas in R8A77970 have the A3IR area as a parent, thus the SYSC driver has those parents wrong... Fixes: bab9b2a74fe9 ("soc: renesas: rcar-sysc: add R8A77970 support") Signed-off-by: Sergei Shtylyov Reviewed-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- drivers/soc/renesas/r8a77970-sysc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/soc') diff --git a/drivers/soc/renesas/r8a77970-sysc.c b/drivers/soc/renesas/r8a77970-sysc.c index 8c614164718e..caf894f193ed 100644 --- a/drivers/soc/renesas/r8a77970-sysc.c +++ b/drivers/soc/renesas/r8a77970-sysc.c @@ -25,12 +25,12 @@ static const struct rcar_sysc_area r8a77970_areas[] __initconst = { PD_CPU_NOCR }, { "cr7", 0x240, 0, R8A77970_PD_CR7, R8A77970_PD_ALWAYS_ON }, { "a3ir", 0x180, 0, R8A77970_PD_A3IR, R8A77970_PD_ALWAYS_ON }, - { "a2ir0", 0x400, 0, R8A77970_PD_A2IR0, R8A77970_PD_ALWAYS_ON }, - { "a2ir1", 0x400, 1, R8A77970_PD_A2IR1, R8A77970_PD_A2IR0 }, - { "a2ir2", 0x400, 2, R8A77970_PD_A2IR2, R8A77970_PD_A2IR0 }, - { "a2ir3", 0x400, 3, R8A77970_PD_A2IR3, R8A77970_PD_A2IR0 }, - { "a2sc0", 0x400, 4, R8A77970_PD_A2SC0, R8A77970_PD_ALWAYS_ON }, - { "a2sc1", 0x400, 5, R8A77970_PD_A2SC1, R8A77970_PD_A2SC0 }, + { "a2ir0", 0x400, 0, R8A77970_PD_A2IR0, R8A77970_PD_A3IR }, + { "a2ir1", 0x400, 1, R8A77970_PD_A2IR1, R8A77970_PD_A3IR }, + { "a2ir2", 0x400, 2, R8A77970_PD_A2IR2, R8A77970_PD_A3IR }, + { "a2ir3", 0x400, 3, R8A77970_PD_A2IR3, R8A77970_PD_A3IR }, + { "a2sc0", 0x400, 4, R8A77970_PD_A2SC0, R8A77970_PD_A3IR }, + { "a2sc1", 0x400, 5, R8A77970_PD_A2SC1, R8A77970_PD_A3IR }, }; const struct rcar_sysc_info r8a77970_sysc_info __initconst = { -- cgit v1.2.3 From 41d6d8bd8ae94ca9ee53720cd530168aca557db7 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Fri, 16 Feb 2018 21:28:02 +0300 Subject: soc: renesas: rcar-sysc: add R8A77980 support Add support for R-Car V3H (R8A77980) SoC power areas to the R-Car SYSC driver. Based on the original (and large) patch by Vladimir Barinov. Signed-off-by: Vladimir Barinov Signed-off-by: Sergei Shtylyov Reviewed-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- .../bindings/power/renesas,rcar-sysc.txt | 1 + drivers/soc/renesas/Kconfig | 5 +++ drivers/soc/renesas/Makefile | 1 + drivers/soc/renesas/r8a77980-sysc.c | 52 ++++++++++++++++++++++ drivers/soc/renesas/rcar-sysc.c | 3 ++ drivers/soc/renesas/rcar-sysc.h | 1 + 6 files changed, 63 insertions(+) create mode 100644 drivers/soc/renesas/r8a77980-sysc.c (limited to 'drivers/soc') diff --git a/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt b/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt index 8690f10426a3..6284a9550b3c 100644 --- a/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt +++ b/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt @@ -18,6 +18,7 @@ Required properties: - "renesas,r8a7795-sysc" (R-Car H3) - "renesas,r8a7796-sysc" (R-Car M3-W) - "renesas,r8a77970-sysc" (R-Car V3M) + - "renesas,r8a77980-sysc" (R-Car V3H) - "renesas,r8a77995-sysc" (R-Car D3) - reg: Address start and address range for the device. - #power-domain-cells: Must be 1. diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 6efd7bef8577..6caa393e3a2d 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -15,6 +15,7 @@ config SOC_RENESAS select SYSC_R8A7795 if ARCH_R8A7795 select SYSC_R8A7796 if ARCH_R8A7796 select SYSC_R8A77970 if ARCH_R8A77970 + select SYSC_R8A77980 if ARCH_R8A77980 select SYSC_R8A77995 if ARCH_R8A77995 if SOC_RENESAS @@ -60,6 +61,10 @@ config SYSC_R8A77970 bool "R-Car V3M System Controller support" if COMPILE_TEST select SYSC_RCAR +config SYSC_R8A77980 + bool "R-Car V3H System Controller support" if COMPILE_TEST + select SYSC_RCAR + config SYSC_R8A77995 bool "R-Car D3 System Controller support" if COMPILE_TEST select SYSC_RCAR diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index 845d62a08ce1..d3b7bb3284c0 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_SYSC_R8A7794) += r8a7794-sysc.o obj-$(CONFIG_SYSC_R8A7795) += r8a7795-sysc.o obj-$(CONFIG_SYSC_R8A7796) += r8a7796-sysc.o obj-$(CONFIG_SYSC_R8A77970) += r8a77970-sysc.o +obj-$(CONFIG_SYSC_R8A77980) += r8a77980-sysc.o obj-$(CONFIG_SYSC_R8A77995) += r8a77995-sysc.o # Family diff --git a/drivers/soc/renesas/r8a77980-sysc.c b/drivers/soc/renesas/r8a77980-sysc.c new file mode 100644 index 000000000000..9265fb525ef3 --- /dev/null +++ b/drivers/soc/renesas/r8a77980-sysc.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas R-Car V3H System Controller + * + * Copyright (C) 2018 Renesas Electronics Corp. + * Copyright (C) 2018 Cogent Embedded, Inc. + */ + +#include +#include + +#include + +#include "rcar-sysc.h" + +static const struct rcar_sysc_area r8a77980_areas[] __initconst = { + { "always-on", 0, 0, R8A77980_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, + { "ca53-scu", 0x140, 0, R8A77980_PD_CA53_SCU, R8A77980_PD_ALWAYS_ON, + PD_SCU }, + { "ca53-cpu0", 0x200, 0, R8A77980_PD_CA53_CPU0, R8A77980_PD_CA53_SCU, + PD_CPU_NOCR }, + { "ca53-cpu1", 0x200, 1, R8A77980_PD_CA53_CPU1, R8A77980_PD_CA53_SCU, + PD_CPU_NOCR }, + { "ca53-cpu2", 0x200, 2, R8A77980_PD_CA53_CPU2, R8A77980_PD_CA53_SCU, + PD_CPU_NOCR }, + { "ca53-cpu3", 0x200, 3, R8A77980_PD_CA53_CPU3, R8A77980_PD_CA53_SCU, + PD_CPU_NOCR }, + { "cr7", 0x240, 0, R8A77980_PD_CR7, R8A77980_PD_ALWAYS_ON }, + { "a3ir", 0x180, 0, R8A77980_PD_A3IR, R8A77980_PD_ALWAYS_ON }, + { "a2ir0", 0x400, 0, R8A77980_PD_A2IR0, R8A77980_PD_A3IR }, + { "a2ir1", 0x400, 1, R8A77980_PD_A2IR1, R8A77980_PD_A3IR }, + { "a2ir2", 0x400, 2, R8A77980_PD_A2IR2, R8A77980_PD_A3IR }, + { "a2ir3", 0x400, 3, R8A77980_PD_A2IR3, R8A77980_PD_A3IR }, + { "a2ir4", 0x400, 4, R8A77980_PD_A2IR4, R8A77980_PD_A3IR }, + { "a2ir5", 0x400, 5, R8A77980_PD_A2IR5, R8A77980_PD_A3IR }, + { "a2sc0", 0x400, 6, R8A77980_PD_A2SC0, R8A77980_PD_A3IR }, + { "a2sc1", 0x400, 7, R8A77980_PD_A2SC1, R8A77980_PD_A3IR }, + { "a2sc2", 0x400, 8, R8A77980_PD_A2SC2, R8A77980_PD_A3IR }, + { "a2sc3", 0x400, 9, R8A77980_PD_A2SC3, R8A77980_PD_A3IR }, + { "a2sc4", 0x400, 10, R8A77980_PD_A2SC4, R8A77980_PD_A3IR }, + { "a2pd0", 0x400, 11, R8A77980_PD_A2PD0, R8A77980_PD_A3IR }, + { "a2pd1", 0x400, 12, R8A77980_PD_A2PD1, R8A77980_PD_A3IR }, + { "a2cn", 0x400, 13, R8A77980_PD_A2CN, R8A77980_PD_A3IR }, + { "a3vip", 0x2c0, 0, R8A77980_PD_A3VIP, R8A77980_PD_ALWAYS_ON }, + { "a3vip1", 0x300, 0, R8A77980_PD_A3VIP1, R8A77980_PD_A3VIP }, + { "a3vip2", 0x280, 0, R8A77980_PD_A3VIP2, R8A77980_PD_A3VIP }, +}; + +const struct rcar_sysc_info r8a77980_sysc_info __initconst = { + .areas = r8a77980_areas, + .num_areas = ARRAY_SIZE(r8a77980_areas), +}; diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index 636872bc2416..72b0f4a9ad4e 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -287,6 +287,9 @@ static const struct of_device_id rcar_sysc_matches[] __initconst = { #ifdef CONFIG_SYSC_R8A77970 { .compatible = "renesas,r8a77970-sysc", .data = &r8a77970_sysc_info }, #endif +#ifdef CONFIG_SYSC_R8A77980 + { .compatible = "renesas,r8a77980-sysc", .data = &r8a77980_sysc_info }, +#endif #ifdef CONFIG_SYSC_R8A77995 { .compatible = "renesas,r8a77995-sysc", .data = &r8a77995_sysc_info }, #endif diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h index 9d9daf9eb91b..974b18619c08 100644 --- a/drivers/soc/renesas/rcar-sysc.h +++ b/drivers/soc/renesas/rcar-sysc.h @@ -59,6 +59,7 @@ extern const struct rcar_sysc_info r8a7794_sysc_info; extern const struct rcar_sysc_info r8a7795_sysc_info; extern const struct rcar_sysc_info r8a7796_sysc_info; extern const struct rcar_sysc_info r8a77970_sysc_info; +extern const struct rcar_sysc_info r8a77980_sysc_info; extern const struct rcar_sysc_info r8a77995_sysc_info; -- cgit v1.2.3 From bfd8398339ccd824a3c5dfaee2a2b489a85b132f Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Tue, 20 Feb 2018 16:12:05 +0100 Subject: soc: renesas: Identify R-Car M3-N Add support for indentifying R-Car M3-N (R8A77965) SoC. Signed-off-by: Jacopo Mondi Reviewed-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- drivers/soc/renesas/renesas-soc.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/soc') diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c index 000834321774..ea71c413c926 100644 --- a/drivers/soc/renesas/renesas-soc.c +++ b/drivers/soc/renesas/renesas-soc.c @@ -144,6 +144,11 @@ static const struct renesas_soc soc_rcar_m3_w __initconst __maybe_unused = { .id = 0x52, }; +static const struct renesas_soc soc_rcar_m3_n __initconst __maybe_unused = { + .family = &fam_rcar_gen3, + .id = 0x55, +}; + static const struct renesas_soc soc_rcar_v3m __initconst __maybe_unused = { .family = &fam_rcar_gen3, .id = 0x54, @@ -214,6 +219,9 @@ static const struct of_device_id renesas_socs[] __initconst = { #ifdef CONFIG_ARCH_R8A7796 { .compatible = "renesas,r8a7796", .data = &soc_rcar_m3_w }, #endif +#ifdef CONFIG_ARCH_R8A77965 + { .compatible = "renesas,r8a77965", .data = &soc_rcar_m3_n }, +#endif #ifdef CONFIG_ARCH_R8A77970 { .compatible = "renesas,r8a77970", .data = &soc_rcar_v3m }, #endif -- cgit v1.2.3 From a527709b78b3c9979fb47ddd4c3d3fd96182b504 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Tue, 20 Feb 2018 16:12:06 +0100 Subject: soc: renesas: rcar-sysc: Add R-Car M3-N support Add support for R-Car M3-N (R8A77965) power areas. Signed-off-by: Jacopo Mondi Reviewed-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- .../bindings/power/renesas,rcar-sysc.txt | 1 + drivers/soc/renesas/Kconfig | 5 +++ drivers/soc/renesas/Makefile | 1 + drivers/soc/renesas/r8a77965-sysc.c | 37 ++++++++++++++++++++++ drivers/soc/renesas/rcar-sysc.c | 3 ++ drivers/soc/renesas/rcar-sysc.h | 1 + include/dt-bindings/power/r8a77965-sysc.h | 30 ++++++++++++++++++ 7 files changed, 78 insertions(+) create mode 100644 drivers/soc/renesas/r8a77965-sysc.c create mode 100644 include/dt-bindings/power/r8a77965-sysc.h (limited to 'drivers/soc') diff --git a/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt b/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt index 6284a9550b3c..ab399e559257 100644 --- a/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt +++ b/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt @@ -17,6 +17,7 @@ Required properties: - "renesas,r8a7794-sysc" (R-Car E2) - "renesas,r8a7795-sysc" (R-Car H3) - "renesas,r8a7796-sysc" (R-Car M3-W) + - "renesas,r8a77965-sysc" (R-Car M3-N) - "renesas,r8a77970-sysc" (R-Car V3M) - "renesas,r8a77980-sysc" (R-Car V3H) - "renesas,r8a77995-sysc" (R-Car D3) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 6caa393e3a2d..7106a6330210 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -14,6 +14,7 @@ config SOC_RENESAS select SYSC_R8A7794 if ARCH_R8A7794 select SYSC_R8A7795 if ARCH_R8A7795 select SYSC_R8A7796 if ARCH_R8A7796 + select SYSC_R8A77965 if ARCH_R8A77965 select SYSC_R8A77970 if ARCH_R8A77970 select SYSC_R8A77980 if ARCH_R8A77980 select SYSC_R8A77995 if ARCH_R8A77995 @@ -57,6 +58,10 @@ config SYSC_R8A7796 bool "R-Car M3-W System Controller support" if COMPILE_TEST select SYSC_RCAR +config SYSC_R8A77965 + bool "R-Car M3-N System Controller support" if COMPILE_TEST + select SYSC_RCAR + config SYSC_R8A77970 bool "R-Car V3M System Controller support" if COMPILE_TEST select SYSC_RCAR diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index d3b7bb3284c0..ccb5ec57a262 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_SYSC_R8A7792) += r8a7792-sysc.o obj-$(CONFIG_SYSC_R8A7794) += r8a7794-sysc.o obj-$(CONFIG_SYSC_R8A7795) += r8a7795-sysc.o obj-$(CONFIG_SYSC_R8A7796) += r8a7796-sysc.o +obj-$(CONFIG_SYSC_R8A77965) += r8a77965-sysc.o obj-$(CONFIG_SYSC_R8A77970) += r8a77970-sysc.o obj-$(CONFIG_SYSC_R8A77980) += r8a77980-sysc.o obj-$(CONFIG_SYSC_R8A77995) += r8a77995-sysc.o diff --git a/drivers/soc/renesas/r8a77965-sysc.c b/drivers/soc/renesas/r8a77965-sysc.c new file mode 100644 index 000000000000..d7f7928e3c07 --- /dev/null +++ b/drivers/soc/renesas/r8a77965-sysc.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas R-Car M3-N System Controller + * Copyright (C) 2018 Jacopo Mondi + * + * Based on Renesas R-Car M3-W System Controller + * Copyright (C) 2016 Glider bvba + */ + +#include +#include + +#include + +#include "rcar-sysc.h" + +static const struct rcar_sysc_area r8a77965_areas[] __initconst = { + { "always-on", 0, 0, R8A77965_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, + { "ca57-scu", 0x1c0, 0, R8A77965_PD_CA57_SCU, R8A77965_PD_ALWAYS_ON, + PD_SCU }, + { "ca57-cpu0", 0x80, 0, R8A77965_PD_CA57_CPU0, R8A77965_PD_CA57_SCU, + PD_CPU_NOCR }, + { "ca57-cpu1", 0x80, 1, R8A77965_PD_CA57_CPU1, R8A77965_PD_CA57_SCU, + PD_CPU_NOCR }, + { "cr7", 0x240, 0, R8A77965_PD_CR7, R8A77965_PD_ALWAYS_ON }, + { "a3vc", 0x380, 0, R8A77965_PD_A3VC, R8A77965_PD_ALWAYS_ON }, + { "a3vp", 0x340, 0, R8A77965_PD_A3VP, R8A77965_PD_ALWAYS_ON }, + { "a2vc1", 0x3c0, 1, R8A77965_PD_A2VC1, R8A77965_PD_A3VC }, + { "3dg-a", 0x100, 0, R8A77965_PD_3DG_A, R8A77965_PD_ALWAYS_ON }, + { "3dg-b", 0x100, 1, R8A77965_PD_3DG_B, R8A77965_PD_3DG_A }, + { "a3ir", 0x180, 0, R8A77965_PD_A3IR, R8A77965_PD_ALWAYS_ON }, +}; + +const struct rcar_sysc_info r8a77965_sysc_info __initconst = { + .areas = r8a77965_areas, + .num_areas = ARRAY_SIZE(r8a77965_areas), +}; diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index 72b0f4a9ad4e..faf20e719361 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -284,6 +284,9 @@ static const struct of_device_id rcar_sysc_matches[] __initconst = { #ifdef CONFIG_SYSC_R8A7796 { .compatible = "renesas,r8a7796-sysc", .data = &r8a7796_sysc_info }, #endif +#ifdef CONFIG_SYSC_R8A77965 + { .compatible = "renesas,r8a77965-sysc", .data = &r8a77965_sysc_info }, +#endif #ifdef CONFIG_SYSC_R8A77970 { .compatible = "renesas,r8a77970-sysc", .data = &r8a77970_sysc_info }, #endif diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h index 974b18619c08..dcdc9ec8eba7 100644 --- a/drivers/soc/renesas/rcar-sysc.h +++ b/drivers/soc/renesas/rcar-sysc.h @@ -58,6 +58,7 @@ extern const struct rcar_sysc_info r8a7792_sysc_info; extern const struct rcar_sysc_info r8a7794_sysc_info; extern const struct rcar_sysc_info r8a7795_sysc_info; extern const struct rcar_sysc_info r8a7796_sysc_info; +extern const struct rcar_sysc_info r8a77965_sysc_info; extern const struct rcar_sysc_info r8a77970_sysc_info; extern const struct rcar_sysc_info r8a77980_sysc_info; extern const struct rcar_sysc_info r8a77995_sysc_info; diff --git a/include/dt-bindings/power/r8a77965-sysc.h b/include/dt-bindings/power/r8a77965-sysc.h new file mode 100644 index 000000000000..05a4b5917314 --- /dev/null +++ b/include/dt-bindings/power/r8a77965-sysc.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2018 Jacopo Mondi + * Copyright (C) 2016 Glider bvba + */ + +#ifndef __DT_BINDINGS_POWER_R8A77965_SYSC_H__ +#define __DT_BINDINGS_POWER_R8A77965_SYSC_H__ + +/* + * These power domain indices match the numbers of the interrupt bits + * representing the power areas in the various Interrupt Registers + * (e.g. SYSCISR, Interrupt Status Register) + */ + +#define R8A77965_PD_CA57_CPU0 0 +#define R8A77965_PD_CA57_CPU1 1 +#define R8A77965_PD_A3VP 9 +#define R8A77965_PD_CA57_SCU 12 +#define R8A77965_PD_CR7 13 +#define R8A77965_PD_A3VC 14 +#define R8A77965_PD_3DG_A 17 +#define R8A77965_PD_3DG_B 18 +#define R8A77965_PD_A3IR 24 +#define R8A77965_PD_A2VC1 26 + +/* Always-on power area */ +#define R8A77965_PD_ALWAYS_ON 32 + +#endif /* __DT_BINDINGS_POWER_R8A77965_SYSC_H__ */ -- cgit v1.2.3 From bf79cd635db50fab2319add2462cf803ff76d346 Mon Sep 17 00:00:00 2001 From: Jacopo Mondi Date: Tue, 20 Feb 2018 16:12:04 +0100 Subject: soc: renesas: rcar-rst: Add support for R-Car M3-N Signed-off-by: Jacopo Mondi Reviewed-by: Geert Uytterhoeven Signed-off-by: Simon Horman --- Documentation/devicetree/bindings/reset/renesas,rst.txt | 1 + drivers/soc/renesas/Kconfig | 4 ++-- drivers/soc/renesas/rcar-rst.c | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/soc') diff --git a/Documentation/devicetree/bindings/reset/renesas,rst.txt b/Documentation/devicetree/bindings/reset/renesas,rst.txt index a55b88658446..294a0dae106a 100644 --- a/Documentation/devicetree/bindings/reset/renesas,rst.txt +++ b/Documentation/devicetree/bindings/reset/renesas,rst.txt @@ -26,6 +26,7 @@ Required properties: - "renesas,r8a7794-rst" (R-Car E2) - "renesas,r8a7795-rst" (R-Car H3) - "renesas,r8a7796-rst" (R-Car M3-W) + - "renesas,r8a77965-rst" (R-Car M3-N) - "renesas,r8a77970-rst" (R-Car V3M) - "renesas,r8a77980-rst" (R-Car V3H) - "renesas,r8a77995-rst" (R-Car D3) diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 7106a6330210..3bbe6114a420 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -3,8 +3,8 @@ config SOC_RENESAS default y if ARCH_RENESAS select SOC_BUS select RST_RCAR if ARCH_RCAR_GEN1 || ARCH_RCAR_GEN2 || \ - ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A77970 || \ - ARCH_R8A77980 || ARCH_R8A77995 + ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A77965 || \ + ARCH_R8A77970 || ARCH_R8A77980 || ARCH_R8A77995 select SYSC_R8A7743 if ARCH_R8A7743 select SYSC_R8A7745 if ARCH_R8A7745 select SYSC_R8A7779 if ARCH_R8A7779 diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c index 34136664ece4..8e9cb7996ab0 100644 --- a/drivers/soc/renesas/rcar-rst.c +++ b/drivers/soc/renesas/rcar-rst.c @@ -56,6 +56,7 @@ static const struct of_device_id rcar_rst_matches[] __initconst = { /* R-Car Gen3 */ { .compatible = "renesas,r8a7795-rst", .data = &rcar_rst_gen3 }, { .compatible = "renesas,r8a7796-rst", .data = &rcar_rst_gen3 }, + { .compatible = "renesas,r8a77965-rst", .data = &rcar_rst_gen3 }, { .compatible = "renesas,r8a77970-rst", .data = &rcar_rst_gen3 }, { .compatible = "renesas,r8a77980-rst", .data = &rcar_rst_gen3 }, { .compatible = "renesas,r8a77995-rst", .data = &rcar_rst_gen3 }, -- cgit v1.2.3 From afe761f8d3e99155b76833421e76553a3ac69577 Mon Sep 17 00:00:00 2001 From: Dave Gerlach Date: Fri, 23 Feb 2018 09:43:57 -0600 Subject: soc: ti: Add pm33xx driver for basic suspend support AM335x and AM437x support various low power modes as documented in section 8.1.4.3 of the AM335x Technical Reference Manual and section 6.4.3 of the AM437x Technical Reference Manual. DeepSleep0 mode offers the lowest power mode with limited wakeup sources without a system reboot and is mapped as the suspend state in the kernel. In this state, MPU and PER domains are turned off with the internal RAM held in retention to facilitate the resume process. As part of the boot process, the assembly code is copied over to OCMCRAM so it can be executed to turn of the EMIF and put DDR into self refresh. Both platforms have a Cortex-M3 (WKUP_M3) which assists the MPU in DeepSleep0 entry and exit. WKUP_M3 takes care of the clockdomain and powerdomain transitions based on the intended low power state. MPU needs to load the appropriate WKUP_M3 binary onto the WKUP_M3 memory space before it can leverage any of the PM features like DeepSleep. This loading is handled by the remoteproc driver wkup_m3_rproc. Communication with the WKUP_M3 is handled by a wkup_m3_ipc driver that exposes the specific PM functionality to be used the PM code. In the current implementation when the suspend process is initiated, MPU interrupts the WKUP_M3 to let it know about the intent of entering DeepSleep0 and waits for an ACK. When the ACK is received MPU continues with its suspend process to suspend all the drivers and then jumps to assembly in OCMC RAM. The assembly code puts the external RAM in self-refresh mode, gates the MPU clock, and then finally executes the WFI instruction. Execution of the WFI instruction with MPU clock gated triggers another interrupt to the WKUP_M3 which then continues with the power down sequence wherein the clockdomain and powerdomain transition takes place. As part of the sleep sequence, WKUP_M3 unmasks the interrupt lines for the wakeup sources. WFI execution on WKUP_M3 causes the hardware to disable the main oscillator of the SoC and from here system remains in sleep state until a wake source brings the system into resume path. When a wakeup event occurs, WKUP_M3 starts the power-up sequence by switching on the power domains and finally enabling the clock to MPU. Since the MPU gets powered down as part of the sleep sequence in the resume path ROM code starts executing. The ROM code detects a wakeup from sleep and then jumps to the resume location in OCMC which was populated in one of the IPC registers as part of the suspend sequence. Code is based on work by Vaibhav Bedia. Signed-off-by: Dave Gerlach Acked-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- Documentation/devicetree/bindings/arm/omap/mpu.txt | 16 + drivers/soc/ti/Kconfig | 9 + drivers/soc/ti/Makefile | 1 + drivers/soc/ti/pm33xx.c | 349 +++++++++++++++++++++ 4 files changed, 375 insertions(+) create mode 100644 drivers/soc/ti/pm33xx.c (limited to 'drivers/soc') diff --git a/Documentation/devicetree/bindings/arm/omap/mpu.txt b/Documentation/devicetree/bindings/arm/omap/mpu.txt index 763695db2bd9..f301e636fd52 100644 --- a/Documentation/devicetree/bindings/arm/omap/mpu.txt +++ b/Documentation/devicetree/bindings/arm/omap/mpu.txt @@ -13,6 +13,13 @@ Required properties: Optional properties: - sram: Phandle to the ocmcram node +am335x and am437x only: +- pm-sram: Phandles to ocmcram nodes to be used for power management. + First should be type 'protect-exec' for the driver to use to copy + and run PM functions, second should be regular pool to be used for + data region for code. See Documentation/devicetree/bindings/sram/sram.txt + for more details. + Examples: - For an OMAP5 SMP system: @@ -36,3 +43,12 @@ mpu { compatible = "ti,omap3-mpu"; ti,hwmods = "mpu"; }; + +- For an AM335x system: + +mpu { + compatible = "ti,omap3-mpu"; + ti,hwmods = "mpu"; + pm-sram = <&pm_sram_code + &pm_sram_data>; +}; diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index 39e152abe6b9..92770d84a288 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -28,6 +28,15 @@ config KEYSTONE_NAVIGATOR_DMA If unsure, say N. +config AMX3_PM + tristate "AMx3 Power Management" + depends on SOC_AM33XX || SOC_AM43XX + depends on WKUP_M3_IPC && TI_EMIF_SRAM && SRAM + help + Enable power management on AM335x and AM437x. Required for suspend to mem + and standby states on both AM335x and AM437x platforms and for deeper cpuidle + c-states on AM335x. + config WKUP_M3_IPC tristate "TI AMx3 Wkup-M3 IPC Driver" depends on WKUP_M3_RPROC diff --git a/drivers/soc/ti/Makefile b/drivers/soc/ti/Makefile index 8e205287f120..a22edc0b258a 100644 --- a/drivers/soc/ti/Makefile +++ b/drivers/soc/ti/Makefile @@ -5,5 +5,6 @@ obj-$(CONFIG_KEYSTONE_NAVIGATOR_QMSS) += knav_qmss.o knav_qmss-y := knav_qmss_queue.o knav_qmss_acc.o obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA) += knav_dma.o +obj-$(CONFIG_AMX3_PM) += pm33xx.o obj-$(CONFIG_WKUP_M3_IPC) += wkup_m3_ipc.o obj-$(CONFIG_TI_SCI_PM_DOMAINS) += ti_sci_pm_domains.o diff --git a/drivers/soc/ti/pm33xx.c b/drivers/soc/ti/pm33xx.c new file mode 100644 index 000000000000..652739c7f718 --- /dev/null +++ b/drivers/soc/ti/pm33xx.c @@ -0,0 +1,349 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * AM33XX Power Management Routines + * + * Copyright (C) 2012-2018 Texas Instruments Incorporated - http://www.ti.com/ + * Vaibhav Bedia, Dave Gerlach + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define AMX3_PM_SRAM_SYMBOL_OFFSET(sym) ((unsigned long)(sym) - \ + (unsigned long)pm_sram->do_wfi) + +static int (*am33xx_do_wfi_sram)(unsigned long unused); +static phys_addr_t am33xx_do_wfi_sram_phys; + +static struct gen_pool *sram_pool, *sram_pool_data; +static unsigned long ocmcram_location, ocmcram_location_data; + +static struct am33xx_pm_platform_data *pm_ops; +static struct am33xx_pm_sram_addr *pm_sram; + +static struct device *pm33xx_dev; +static struct wkup_m3_ipc *m3_ipc; + +static u32 sram_suspend_address(unsigned long addr) +{ + return ((unsigned long)am33xx_do_wfi_sram + + AMX3_PM_SRAM_SYMBOL_OFFSET(addr)); +} + +#ifdef CONFIG_SUSPEND +static int am33xx_pm_suspend(suspend_state_t suspend_state) +{ + int i, ret = 0; + + ret = pm_ops->soc_suspend((unsigned long)suspend_state, + am33xx_do_wfi_sram); + + if (ret) { + dev_err(pm33xx_dev, "PM: Kernel suspend failure\n"); + } else { + i = m3_ipc->ops->request_pm_status(m3_ipc); + + switch (i) { + case 0: + dev_info(pm33xx_dev, + "PM: Successfully put all powerdomains to target state\n"); + break; + case 1: + dev_err(pm33xx_dev, + "PM: Could not transition all powerdomains to target state\n"); + ret = -1; + break; + default: + dev_err(pm33xx_dev, + "PM: CM3 returned unknown result = %d\n", i); + ret = -1; + } + } + + return ret; +} + +static int am33xx_pm_enter(suspend_state_t suspend_state) +{ + int ret = 0; + + switch (suspend_state) { + case PM_SUSPEND_MEM: + case PM_SUSPEND_STANDBY: + ret = am33xx_pm_suspend(suspend_state); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static int am33xx_pm_begin(suspend_state_t state) +{ + int ret = -EINVAL; + + switch (state) { + case PM_SUSPEND_MEM: + ret = m3_ipc->ops->prepare_low_power(m3_ipc, WKUP_M3_DEEPSLEEP); + break; + case PM_SUSPEND_STANDBY: + ret = m3_ipc->ops->prepare_low_power(m3_ipc, WKUP_M3_STANDBY); + break; + } + + return ret; +} + +static void am33xx_pm_end(void) +{ + m3_ipc->ops->finish_low_power(m3_ipc); +} + +static int am33xx_pm_valid(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_STANDBY: + case PM_SUSPEND_MEM: + return 1; + default: + return 0; + } +} + +static const struct platform_suspend_ops am33xx_pm_ops = { + .begin = am33xx_pm_begin, + .end = am33xx_pm_end, + .enter = am33xx_pm_enter, + .valid = am33xx_pm_valid, +}; +#endif /* CONFIG_SUSPEND */ + +static void am33xx_pm_set_ipc_ops(void) +{ + u32 resume_address; + int temp; + + temp = ti_emif_get_mem_type(); + if (temp < 0) { + dev_err(pm33xx_dev, "PM: Cannot determine memory type, no PM available\n"); + return; + } + m3_ipc->ops->set_mem_type(m3_ipc, temp); + + /* Physical resume address to be used by ROM code */ + resume_address = am33xx_do_wfi_sram_phys + + *pm_sram->resume_offset + 0x4; + + m3_ipc->ops->set_resume_address(m3_ipc, (void *)resume_address); +} + +static void am33xx_pm_free_sram(void) +{ + gen_pool_free(sram_pool, ocmcram_location, *pm_sram->do_wfi_sz); + gen_pool_free(sram_pool_data, ocmcram_location_data, + sizeof(struct am33xx_pm_ro_sram_data)); +} + +/* + * Push the minimal suspend-resume code to SRAM + */ +static int am33xx_pm_alloc_sram(void) +{ + struct device_node *np; + int ret = 0; + + np = of_find_compatible_node(NULL, NULL, "ti,omap3-mpu"); + if (!np) { + np = of_find_compatible_node(NULL, NULL, "ti,omap4-mpu"); + if (!np) { + dev_err(pm33xx_dev, "PM: %s: Unable to find device node for mpu\n", + __func__); + return -ENODEV; + } + } + + sram_pool = of_gen_pool_get(np, "pm-sram", 0); + if (!sram_pool) { + dev_err(pm33xx_dev, "PM: %s: Unable to get sram pool for ocmcram\n", + __func__); + ret = -ENODEV; + goto mpu_put_node; + } + + sram_pool_data = of_gen_pool_get(np, "pm-sram", 1); + if (!sram_pool_data) { + dev_err(pm33xx_dev, "PM: %s: Unable to get sram data pool for ocmcram\n", + __func__); + ret = -ENODEV; + goto mpu_put_node; + } + + ocmcram_location = gen_pool_alloc(sram_pool, *pm_sram->do_wfi_sz); + if (!ocmcram_location) { + dev_err(pm33xx_dev, "PM: %s: Unable to allocate memory from ocmcram\n", + __func__); + ret = -ENOMEM; + goto mpu_put_node; + } + + ocmcram_location_data = gen_pool_alloc(sram_pool_data, + sizeof(struct emif_regs_amx3)); + if (!ocmcram_location_data) { + dev_err(pm33xx_dev, "PM: Unable to allocate memory from ocmcram\n"); + gen_pool_free(sram_pool, ocmcram_location, *pm_sram->do_wfi_sz); + ret = -ENOMEM; + } + +mpu_put_node: + of_node_put(np); + return ret; +} + +static int am33xx_push_sram_idle(void) +{ + struct am33xx_pm_ro_sram_data ro_sram_data; + int ret; + u32 table_addr, ro_data_addr; + void *copy_addr; + + ro_sram_data.amx3_pm_sram_data_virt = ocmcram_location_data; + ro_sram_data.amx3_pm_sram_data_phys = + gen_pool_virt_to_phys(sram_pool_data, ocmcram_location_data); + + /* Save physical address to calculate resume offset during pm init */ + am33xx_do_wfi_sram_phys = gen_pool_virt_to_phys(sram_pool, + ocmcram_location); + + am33xx_do_wfi_sram = sram_exec_copy(sram_pool, (void *)ocmcram_location, + pm_sram->do_wfi, + *pm_sram->do_wfi_sz); + if (!am33xx_do_wfi_sram) { + dev_err(pm33xx_dev, + "PM: %s: am33xx_do_wfi copy to sram failed\n", + __func__); + return -ENODEV; + } + + table_addr = + sram_suspend_address((unsigned long)pm_sram->emif_sram_table); + ret = ti_emif_copy_pm_function_table(sram_pool, (void *)table_addr); + if (ret) { + dev_dbg(pm33xx_dev, + "PM: %s: EMIF function copy failed\n", __func__); + return -EPROBE_DEFER; + } + + ro_data_addr = + sram_suspend_address((unsigned long)pm_sram->ro_sram_data); + copy_addr = sram_exec_copy(sram_pool, (void *)ro_data_addr, + &ro_sram_data, + sizeof(ro_sram_data)); + if (!copy_addr) { + dev_err(pm33xx_dev, + "PM: %s: ro_sram_data copy to sram failed\n", + __func__); + return -ENODEV; + } + + return 0; +} + +static int am33xx_pm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + int ret; + + if (!of_machine_is_compatible("ti,am33xx") && + !of_machine_is_compatible("ti,am43")) + return -ENODEV; + + pm_ops = dev->platform_data; + if (!pm_ops) { + dev_err(dev, "PM: Cannot get core PM ops!\n"); + return -ENODEV; + } + + pm_sram = pm_ops->get_sram_addrs(); + if (!pm_sram) { + dev_err(dev, "PM: Cannot get PM asm function addresses!!\n"); + return -ENODEV; + } + + pm33xx_dev = dev; + + ret = am33xx_pm_alloc_sram(); + if (ret) + return ret; + + ret = am33xx_push_sram_idle(); + if (ret) + goto err_free_sram; + + m3_ipc = wkup_m3_ipc_get(); + if (!m3_ipc) { + dev_dbg(dev, "PM: Cannot get wkup_m3_ipc handle\n"); + ret = -EPROBE_DEFER; + goto err_free_sram; + } + + am33xx_pm_set_ipc_ops(); + +#ifdef CONFIG_SUSPEND + suspend_set_ops(&am33xx_pm_ops); +#endif /* CONFIG_SUSPEND */ + + ret = pm_ops->init(); + if (ret) { + dev_err(dev, "Unable to call core pm init!\n"); + ret = -ENODEV; + goto err_put_wkup_m3_ipc; + } + + return 0; + +err_put_wkup_m3_ipc: + wkup_m3_ipc_put(m3_ipc); +err_free_sram: + am33xx_pm_free_sram(); + pm33xx_dev = NULL; + return ret; +} + +static int am33xx_pm_remove(struct platform_device *pdev) +{ + suspend_set_ops(NULL); + wkup_m3_ipc_put(m3_ipc); + am33xx_pm_free_sram(); + return 0; +} + +static struct platform_driver am33xx_pm_driver = { + .driver = { + .name = "pm33xx", + }, + .probe = am33xx_pm_probe, + .remove = am33xx_pm_remove, +}; +module_platform_driver(am33xx_pm_driver); + +MODULE_ALIAS("platform:pm33xx"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("am33xx power management driver"); -- cgit v1.2.3